I'm working on a simple sound analyzer application and a main feature of this program is the spectrogram display. I want this spectrogram to render fast and to be good looking while preserving all the necessary details. What I have so far is shown below.
The 3 spectrograms below are of the same sound file (the first 2 are 256 and 1024 frame spectrograms produced by my application whereas the third is generated by the
As you can see, it's far from impressive and ideally I'd want my spectrogram to look something like the one in picture #3. The reason that my spectrogram doesn't look good is that I just draw what is calculated in subsequent FFT frames without trying to average, interpolate or normalize data in any way (I'm talking about the pixel data here, not magnitudes).
The spectrograms look better when using smaller frame lengths (e.g 256, 128 etc) because the actual frame width is smaller and thus the image looks less grainy. For small files (1-2 seconds or less), there are only a handful of frames and the problem is even worse.
I've considered using either
image segmentation (https://en.wikipedia.org/wiki/Image_segmentation) or
colour normalization ( https://en.wikipedia.org/wiki/Color_normalization ) but given that each of these technologies has so many algorithms best suited for a particular purpose, I'm kind of lost as to what to use or what would be best in terms of performance while still producing good looking results.
Marcus' comment prompted me to further explain my problem so let's just briefly go over a simple example. As I already said, the problem is most evident with small files.
If, for instance, my file is
1 sec long, sampled at
8000 Hz (mono) and I choose a frame length to be
1024 samples, the resulting spectrogram will have
8000/1024 = 7 (7 frames). Yes, I actually
7*2=14 overlapping frames but they're averaged (3 consecutive frames are averaged into a single frame except for the first frame and the last frame where only two frames are averaged )
So, there are 7 frames from which I create the spectrogram but given this small number of frames, the frame width (the width in pixels that corresponds to a single frame) is large. The frame width is
obtained by just diving the spectrogram image width by the number of frames (e.g frameWidth =
1000px / 7 = 142 px
Now, it should be fairly obvious that this kind of approach leads to spectrograms look grainy, especially for small files and ( relatively ) large frame lengths.
Any help is much appreciated.