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 Sonic Visualizer application)

Spectrogram 1 (256 FFT frame length

Spectrogram 2 (1024 FFT frame length

Spectrogram 3 - produces by Sonic Visualizer

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 create 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.

  • $\begingroup$ so, my problem is that "spectrogram" is a mathematically strictly definable thing, whereas "not losing any information/having all the details" is thing that only depends on what info you're looking for. So, what is it that you're looking for? Which details need to be there, which don't? I think your first and third are pretty similar, definitely with a different color scheme, and maybe with a different overlap, but it's hard for me to argue which one is better! I simply don't have your intrinsic measure of "goodness" of a visualization, so you might have to explain $\endgroup$ – Marcus Müller Nov 7 '17 at 11:04
  • $\begingroup$ @Marcus, the third spectrogram is generated by Sonic Visualizer (sonicvisualiser.org). I agree that that my first spectrogram somewhat resembles the third but it's still more grainy (but don't forget that my first spectrogram uses a 256 frame length for the FFT, whereas the third is a 1024 frame spectrogram (using smaller FFT frames leads to spectrograms look less grainy, at least in my case). I think, for now, it's best to forget about the details part an just focus on the graphics part. $\endgroup$ – dsp_user Nov 7 '17 at 11:28
  • $\begingroup$ Anyway, I'm looking for a way to smoothly transition from regions of higher magnitudes to regions with lower magnitudes, so I guess my goal is to find those regions (clusters), and then apply some sort of gradients to avoid the regions having sharp edges (which leads to graininess). I hope it's now clearer what I'm trying to achieve here. $\endgroup$ – dsp_user Nov 7 '17 at 11:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.