14
$\begingroup$

I'm calculating FFT from microphone input. I notice that lower frequencies always seems to have more power (higher dB) than higher frequencies.

  1. I cut the data into frames of 24576 bytes (4096*6).
  2. Apply Hamming window: input[i] *= (0.54d - 0.46d*(double) Math.Cos((2d*Math.PI*i)/fs));
  3. Run it through FFTW Process1D().
  4. Convert from complex numbers: output[i] = 10.0 * Math.Log10((fout[i * 2] * fout[i * 2]) + (fout[i * 2 + 1] * fout[i * 2 + 1]));
  5. Average out 6 values to get a complete FFT of 4096 bytes.
  6. Paint pretty picture (colors mapped to a palette).

The averaging (pt. 5) is done to lower FFT noise.

As the image shows both with sound and with mic off there is more energy (and more noise) in the lower frequencies. This indicates its more than just a mic/sub problem.

My questions:
1. Is this expected? Why?
2. Any standard way of fixing this? Almost looks like some Math.Tan() magic could lift it up where it belongs.

My goal is to be able to identify the top 5 frequencies without lower frequencies winning by default.

FFT

$\endgroup$

migrated from stackoverflow.com Oct 30 '11 at 5:10

This question came from our site for professional and enthusiast programmers.

  • $\begingroup$ Please try the correct Hamming window first to see if a broken window fragment is what is causing this low frequency noise. $\endgroup$ – hotpaw2 Oct 30 '11 at 17:47
  • $\begingroup$ @Tedd Hansen, how did you end up "identifying the top 5 frequencies without lower frequencies" -- top 5 from weighted 1/3 octave bands ?? $\endgroup$ – denis Sep 15 '13 at 13:04
12
$\begingroup$

Yes, this is very much expected. What you see is a "pink" spectrum, i.e. constant energy per relative bandwidth, as compared to "white" which is constant energy per absolute bandwidth. For pink signals the energy between 1-2kHz is the same as from 2-4kHz (each represents a doubling of bandwidth or an "octave".

Most natural audio signals (Speech, music, movies, etc.) have a pink-like spectrum. Also most acoustic background noises (microphone noise, HVAC noise, air pressure fluctuations, generic background) tend to be pink or even more skewed towards lower frequencies.

The human auditory systems works that way, too. In the inner ear the audio signals are broken down into bands of constant relative bandwidth (called "Critical Bands") which are roughly the same as a third octave spectrum.

The best way to look at audio spectrum data is to plot it on a logarithmic frequency scale.

$\endgroup$
  • $\begingroup$ The statement that "natural audio signals have a pink-like spectrum", leaves out consideration of time scale. Over a long time (~10s of seconds) I agree, and certainly over several minutes that statement tends to be true. But the spectra here are calculated over 0.55 sec. If the input is e.g., music, I'd expect a much more tonal structure. $\endgroup$ – mtrw Nov 2 '11 at 5:23
  • 2
    $\begingroup$ "tonality" affects more the fine structure of the spectrum. The overall shape (in terms of energy per octave) will still be mostly pink for music unless it's something like "solo for triangle and crash cymbal" $\endgroup$ – Hilmar Nov 3 '11 at 16:41
  • 1
    $\begingroup$ @mtrw: A square wave is certainly a tone, but the high frequency harmonics still fall off at a 1/f rate. $\endgroup$ – endolith Sep 28 '12 at 16:09
8
$\begingroup$

In step 2, the formula should be input[i] *= (0.54d - 0.46d*(double) Math.Cos((2d*Math.PI*i)/N));, where N is the number of samples in the buffer, in your case 24576.

In steps 4 & 5, I would do the bin-wise averaging on the squared magnitude values, not the dB values. Say you have the squared magnitudes [4,6]. Their average is 5, 10*log10(5) ~= 6.99. The average of 10*log10(4) and 10*log10(6) is 6.90.

The first problem might be the cause the of the bias towards low frequencies, as it will cause spectral leakage, and the low frequencies will get more contamination from the DC line (which is inevitably a poor estimate). The second problem is probably not going to make a difference on the low frequencies, but I think gets closer to the intent of your measurement.

$\endgroup$
  • $\begingroup$ While averaging the dB values is very likely not the best thing to do, it is not immediately obvious to me that averaging the magnitudes is significantly better. I would suggest averaging the squared magnitudes instead, which I think are (if I understand the code fragments correctly) being computed already via fout[i * 2] * fout[i * 2]) + (fout[i * 2 + 1] * fout[i * 2 + 1]. I think the $4$ and $6$ used by mtrw are in fact the squared magnitudes since he suggests using their average in $10\log_{10}(5)$ instead of averaging $(10\log_{10}(4) + 10\log_{10}(6))/2$ as the OP does $\endgroup$ – Dilip Sarwate Oct 31 '11 at 13:54
  • $\begingroup$ In your explanation above, I believe you want a window width (N) of 4096, since this is the width of the FFT being applied. This window would need to be applied to the 4096 samples being transformed before each fft. $\endgroup$ – Jacob Nov 14 '11 at 16:47
  • $\begingroup$ @Jacob - the OP is calculating the FFT of 6*4096 points, then averaging 6 adjacent bins to reduce down to 4096 points. $\endgroup$ – mtrw Nov 14 '11 at 21:39
5
$\begingroup$

1/f noise occurs in many physical, biological and economic systems. Some researchers describe it as being ubiquitous.

pink and white noises

Pink noise (left) and white noise (right) on an FFT spectrogram with linear frequency vertical axis (on a typical audio or similar spectrum analyzer the pink noise would be flat, not downward-sloping, and the white noise rising)

$\endgroup$
  • 6
    $\begingroup$ The noise on the left is definitely pink but the one on the right looks a bit orange :-) $\endgroup$ – Guy Sirton Oct 29 '11 at 22:32
  • $\begingroup$ While it's true that 1/f noise is ubiquitous, a well designed analog front end for audio generally has low levels of 1/f noise above, say 10 Hz. White noise dominates in the bands of interest. $\endgroup$ – mtrw Oct 30 '11 at 3:39
4
$\begingroup$

Is this expected? Why?

A lot of natural sounds have harmonics, so there will be a lower fundamental frequencies and then less energy in higher multiples of the fundamental. There may be a DC bias which would mean a lot of energy at the very left. Another influence is your windowing function which distorts the frequency response.

Any standard way of fixing this? Almost looks like some Math.Tan() magic could lift it up where it belongs.

You can deal with the DC bias by using a high-pass filter. A simple implementation is to subtract the long term average from every sample (EDIT: or even simpler, discard the lower frequencies, e.g. <50Hz from your FFT result). You can also experiment with different window functions. make sure (as @mtrw points out) that you're applying the window properly. Any other non-linearities in the response can be corrected by measuring some ideal input and normalizing to that curve.

$\endgroup$
  • $\begingroup$ The windowing function shouldn't affect the frequency response, should it? $\endgroup$ – endolith Sep 28 '12 at 16:18
  • $\begingroup$ @endolith : It does- you multiply your data by the windowing function and the combined function has a different response. Read the linked Wikipedia article which discusses this in more depth. The reality of dealing with real world samples is that there's usually some window (e.g. a rectangle) and you can only approximate the frequency response of the (infinite) source signal because of that. $\endgroup$ – Guy Sirton Oct 2 '12 at 6:23
  • $\begingroup$ Maybe we're thinking of "frequency response" differently. If a signal is stationary, and you apply a window function to it, the spectrum should have the same amplitudes at the same frequencies, no matter what window function you use, differing only by a scale factor that affects all frequencies equally. The width of each frequency spike will be different, but the height of the spikes will be the same relative to each other. The windowing function doesn't act like a filter that attenuates some frequencies more than others. $\endgroup$ – endolith Oct 2 '12 at 14:45
  • $\begingroup$ @endolith: Imagine an infinite sine wave, now multiply by a cos^2 window. You'll still have a component at the original frequency but its amplitude will be "off" and you will have new frequency components coming from the window. See the first paragraph here: en.wikipedia.org/wiki/Spectral_leakage $\endgroup$ – Guy Sirton Oct 2 '12 at 20:02
  • $\begingroup$ Yes, but the "off" amplitude will be the same no matter what the frequency of the infinite sine wave, no? $\endgroup$ – endolith Oct 2 '12 at 21:39

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.