1
$\begingroup$

I am creating an Android app which records sound for t seconds at a sampling rate of 44.1kHz with a buffer size of 8192 (16 bit mono samples). I need to plot a graph of amplitude against frequency, and so first I need to run an FFT over the buffer each time it is full (which happens multiple times every second, more so with an increasing sampling rate). However, after I run the FFT I understand I need to 'bin' the frequencies and then apply an A-weighting to each bin. From the Nyquist criterion, I understand that I only need to look at the first half of the frequencies, and disregard the first corresponding to the DC component. However, I am unsure of what 'binning' actually means and would like some clarification as to what it is, and how to choose what goes in what bin.

Please advise :) .

$\endgroup$
  • 3
    $\begingroup$ Why are you a-weighting the bins? $\endgroup$ – Bjorn Roche Mar 3 '14 at 17:54
  • 4
    $\begingroup$ "From the Nyquist criterion, I understand that I only need to look at the first half of the frequencies" You are confusing some concepts here. Yes you only need to look at the first half, but that's because you are taking an FFT of real numbers (and thus the second half of the data is a mirror image of the first), not because of the Nyquist theorem. $\endgroup$ – Bjorn Roche Mar 3 '14 at 17:56
  • 1
    $\begingroup$ @BjornRoche I am A-weighting as I am trying to model what us humans actually hear. $\endgroup$ – Keir Simmons Mar 15 '14 at 13:42
  • 1
    $\begingroup$ @BjornRoche I've looked at your blog, thanks - it's very helpful. Basically, what I am doing is trying to record audio, FFT the data after each buffer read (8192 bytes per buffer read), display on a graph, update on next buffer read. I assume this will give the nice 'jumping bars' plot. $\endgroup$ – Keir Simmons Mar 15 '14 at 13:52
  • 2
    $\begingroup$ Depending on your application, you may be better served with a time-domain bandpass filter-bank. If you are lumping many bands together or trying to do, for example, a 1/3 octave RTA, this is what you want. $\endgroup$ – Bjorn Roche Mar 15 '14 at 22:57
2
$\begingroup$

In its simplest form, the 'binning' process consists in summing the energies (squared magnitude) within groups of adjacent FFT values. This will give you the total energy in a set of disjoint frequency bands.

A more elaborate form consists in using overlapping triangle filter banks - you compute a weighted sum of the energy in a range of FFT bins to get a number which can be interpreted as the energy measured at the output of a band-pass filter of a given center frequency/width. For example, one can use this technique to build a visualization which uses a 1/3 octave scale on the frequency axis.

$\endgroup$
1
$\begingroup$

If you desire to plot a graph with other than 4096 points (half the FFT length) on the frequency axis, then you will have to resample the FFT result. This re-binning may have to composite several FFT magnitude bins into each plot point bin, depending on your desired x axis plot resolution.

$\endgroup$
  • 1
    $\begingroup$ This doesn't answer my question (at least I don't think it does). Let's say I have my 8192 samples and I perform an FFT on them. From my understanding, this will return an array of 8192 values, of which I can disregard the latter half and the first value, leaving 4095 values (I presume the DC component is useless?). Now I have these values, what is the binning process? $\endgroup$ – Keir Simmons Mar 3 '14 at 17:11
1
$\begingroup$

If all you need to plot the FFT spectrum (ie plot amplitude vs frequency), then just get an array with the discrete FFT bin frequencies and plot it against the amplitudes.The frequencies only exist at the discrete locations given by

$$ f = n\frac{f_s}{N} - \frac{f_s}{2} \hspace{2mm} \text{where n } \hspace{0.5mm} = 0, 1, 2,...N $$

and the amplitudes A are given by

$$ A = \text{Magnitude(Data[n])} \hspace{2mm} \text{where n } \hspace{0.5mm} = 0, 1, 2,...N $$

If you have a 8192 long Audio signal for example, you would do something similar to what I have done in the small dirty pseudo code / C# code sample I have written below.

N = 8192;
Sample_Rate = 44100;
float[] myAudio = new Float[N];
myAudio = getAudio();
Complex[] myFFT_Audio = FFT(myAudio);  //Returns N complex values

//Get Array of frequency Values
float[] frequencies = new float[N]
for( i = 0 ; i < N; i++)
   { frequencies[i] = i * (Sample_Rate / N) - (Sample_Rate / 2); }

//Get Amplitudes
float[] Amplitudes = new float[N]
for( i = 0; i < N; i++)
  { Amplitudes[i] = myFFT_Audio[i].Magnitude(); }

//Plot Frequencies vs Amplitudes - will plot for frequencies -fs/2 to fs/2
PLOT(frequencies , Amplitudes);

If you want to only plot the values from $0$ to $f_s/2$ instead of from $-f_s/2$ to $f_s/2$ you can discard the first half of the values and just plot the second half.

You also need to make sure you know what sort of data FFT samples your FFT algorithm is returning as algorithms can either return FFT samples corresponding to either frequencies ranging from $-f_s / 2$ to $f_s/2$ or from $0$ to $f_s$.The code sample above assumes the former is true but that isn't always the case.

Matlab, for example, usually gives FFT samples corresponding to frequencies ranging from $0$ to $f_s$ so your frequencies in this case would just be

$$ f = n\frac{f_s}{N} $$

you can still get a plot from $-f_s/2$ to $f_s/2$ fairly easily though because the Fourier transform is periodic with period equal to $f_s$.

$\endgroup$

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.