I'm trying to do something similar to Shazam (paper here) in Python. Basically the idea is to use FFT with sliding window to transform both WAV files and recorded audio to the same spectral representations for recognition purposes.
The only problem is the spectrograms I extract from certain songs just seem to generate lots of useless peaks that become false positives when heard in other songs. They look a lot like noise. Examples below.
Spectrogram of SONG_1 [channel 1]:
Spectrogram of SONG_2 (dominates and generates WAY more peaks) [channel 1]:
Spectrogram of SONG_3 [channel 1]:
Spectrogram of SONG_1, recorded through my laptop mic (looks like noise) [channel 1]:
Here's the code I use to generate the spectrograms:
import pylab
from scipy.io import wavfile
fs, frames = wavfile.read("song1.wav")
channels = [
np.array(frames[:, 0]),
np.array(frames[:, 1])
]
# generate specgram
Pxx, freqs, t, plot = pylab.specgram(
channels[0],
NFFT=4096,
Fs=44100,
detrend=pylab.detrend_none,
window=pylab.window_hanning,
noverlap=int(4096 * 0.5))
I've implemented the hashing, storage, recognition, etc as well but they are rather useless unless the extracted peaks are distinct to the song heard.
I should mention my peak extraction algorithm is not just a threshold - I find points in Pxx
that are the highest value in a neighborhood of around 15-20 adjacent points.
What am I doing wrong? How can I get more distinctive spectrograms out of audio sample channels?
Pxx
2d array (amplitude as function of freq bin and time window) I have above is hard - just finding peaks usingscipy
ndimage package can find peaks in arbitrarily sized neighboorhoods. $\endgroup$