I'm working on creating an application which will render a spectrogram of the audio in an MP3 file. I'm having some trouble, though - after running the audio samples through my program, the resulting magnitudes are all very close together, and don't seem to be very patterned like one would expect. I'm coloring my spectrogram using a pretty typical black/blue/purple/red/yellow/white gradient. The current result I get is this:
The steps I'm performing to get this are:
- Decode the MP3 file using libmad, getting raw signed 16-bit PCM samples back. The samples are stereo, but at this point (for debugging, mostly) I'm just ignoring the right channel. I've verified that this step works by writing the raw samples back out to a file, importing them into Audacity, and then playing the audio - and it sounds correct.
- Compute the STFT of these samples (each sample is converted to a complex number of
sample + 0i
- I realize this isn't the most efficient, but it's very simple and my understanding is that it should produce the same result). I'm not scaling the samples, or converting them from signed to unsigned, or anything else. I'm using a window size of 8192 samples, which is about 185ms of audio data (sampled at 44.1KHz). I'm also applying the Hann function to each of these windows, and overlapping them by about 800 samples. I'm using my own implementation of the FFT, however I've verified it by comparing its outputs to those from Numpy over a very large list of inputs. - Plot the result. Each column in the graph is a DFT from list of STFT results (time), and each row is a particular value in the DFT result (a frequency). I'm only plotting the results in DFT bins
[1, N/2 - 1]
, since I'm using real inputs. I'm computing the magnitude aslog10(sqrt(r*r + i*i))
.
The color range is from [minimum magnitude, maximum magnitude]
. I've tried shrinking the range, thinking that outliers may be screwing it up, but even with a range of [5.6, 5.8]
the data is still not a real spectrogram. The magnitudes seem to be more or less randomly distributed in that [5.6, 5.8]
range.
What issue might be causing this type of output?
I'd love to post code or go into more detail, but as I'm not sure what area the problem might lie in I'm not sure what to expand upon. For what it's worth (although obviously I don't expect anyone to look at all of my code and fix my bug), this project is on GitHub here.
EDIT: I generated a wave file with a single 1000Hz sine wave as suggested, and for the first time ever my application actually produces some (maybe?) useful output. Here's what I get:
Perhaps this provides some more insight as to what's going wrong?