GNOME Bugzilla – Bug 787238
Spectrum plugin shows magnitudes that are way too small
Last modified: 2018-11-03 15:21:52 UTC
Created attachment 359057 [details] Source code to reproduce the issue The spectrum plugin shows extremely inaccurate values for the magnitudes of the audio. I have created an example application (file attached) which is a modified copy of the spectrum example from https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good/html/gst-plugins-good-plugins-spectrum.html The changes I've made: - Exchange the fakesink for a filesink and export a wavefile - Only show bands which have a magnitude > threshold / 2 - Set spectrum bands to 1024, audio frequency to 48000 - Globally defined threshold The messages I receive look consistently like this: New spectrum message, endtime 0:01:20.800000000 band 255 (freq 5988.28): magnitude -17.337473 dB phase 0.785320 band 256 (freq 6011.72): magnitude -13.766866 dB phase -2.356143 band 257 (freq 6035.16): magnitude -25.419439 dB phase 0.785200 One can see that the max. magnitude is -13.8 dB @ 6012 Hz. Now importing the wave file into Audacity and using its spectrum visualizer, one can see that the magnitude of the wave file is actually about -0.6 dB @ 6033 Hz. So the dominant frequency is fairly accurate, but the max. magnitude by far is not. Since the spectrum plugin does its job in real time and the Audacity feature does not, I don't expect the same result, but the difference is too large nonetheless.
This indeed sounds like a bug in how the magnitude is calculated from the FFT results, and/or the windowing function. It should be fairly close to what Audacity shows, especially if you use the same number of bands and windowing function.
According to https://github.com/GStreamer/gst-plugins-good/blob/master/gst/spectrum/gstspectrum.c#L774 the spectrum plugin uses the Hamming Window. Using Hamming with 1024 bands in Audacity results in -0.7 dB @ 6015 Hz. Quite similar to the result I posted before.
I looked into this issue and noticed the following: In https://github.com/GStreamer/gst-plugins-good/blob/master/gst/spectrum/gstspectrum.c#L782 the magnitude for each band gets calculated by ((real part)^2 + (imaginary part)^2) / (fft length^2). The part over the fraction is the squared absolute value of the complex number. Don't we just want the absolute value? If I change this: val /= nfft * nfft; to this: val = sqrt(val); val /= nfft; the resulting magnitude is at least linearly dependent of the input magnitude. Since the values are smaller than 1, calculating the sqrt makes them bigger. However it's still smaller than the input magnitude by a factor that was about 3.9 for all tests with 16, 32, ..., 1024, 2048 bands and about 5.8 for all tests with 4096 bands. Very strange.
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/issues/400.