# Python scipy.fftpack.rfft frequency bin mapping

I'm trying to get the correct FFT bin index based on the given frequency. The audio is being sampled at 44.1k Hz and the FFT size is 1024. Given the signal is real (capture from PyAudio, decoded through numpy.fromstring, windowed by scipy.signal.hann), I then perform FFT through scipy.fftpack.rfft, and compute the decibel of the result, in whole, magnitude = 20 * scipy.log10(abs(rfft(audio_sample)))

Based on this, and this, I originally had my mapping from the FFT bin index, k, to any frequency, F, as:

F = k*Fs/N for k = 0 ... N/2-1 where Fs is the sampling rate, and N is the FFT bin size, in this case, 1024. And the reverse as:

k = F*N/Fs for F = 0Hz ... Fs/2-Fs/N

However, realizing that the rfft's result is no symmetric like fft, and provides the result, in an N size array. I now have some questions in regarding the mapping and the function. Documentation unfortunately did not provide much information as I'm novice in this area.

My questions:

1. To me, the result of rfft on an audio sample can be used directly from the first bin to the last bin, as no symmetry occurs in the output, is that correct?

2. Given the lack of symmetry from the above, the frequency resolution appears to have increased, is this interpretation correct?

3. Because of using rfft, my mapping function from bin index k to frequency F is now F = k*Fs/(2N) for k = 0 ... N-1 is this correct?

4. Conversely, the reverse mapping function from frequency F to bin index k now becomes k = 2*F*N/Fs for F = 0Hz ... Fs/2-(Fs/2/N), what about the correctness of this?

My general confusion arises from how rfft is related to fft, and how the mapping can be done correctly while using rfft. I believe my mapping is offset by a small amount, and that is crucial in my application. Please point out the mistake or advise on the matter if possible, thank you very much.

• scipy.fftpack.rfft Feb 3 '14 at 5:21
• Just use scipy.fftpack.rfftfreq Jul 6 at 19:06

I don't use scipy, but the documentation link you provided is very similar to other real-only FFT's. So regarding your questions:

1) Note that there is a y(0) in the output, but no Im(y(0)). That's because for even N and real-only inputs (ie: all imaginary inputs are zero), then both the Im(y(0)) and Im(y(n/2)) outputs are going to be zero, and need not be represented in the output. So you can't just run a loop from the first to last bin. And note the difference of output sequence between odd/even numbered N (ie: you have an Im(y(n/2)) for odd N, but it will be zero for an even N).

2) There is no increase in frequency resolution. For N complex inputs, the FFT returns N complex outputs. When the N inputs are real-only, you only need return N/2 numbers because of the symmetry and the knowledge that one or two of them will be zero.

3) No, you'll still be off because of the single y(0) output (ie: no Im(y(0)). See point 1 above.

4) To go from k to F, I just multiply the bin number 'k' by sample_rate/N. I rarely ever have to do the inverse.

Don't make it more complicated than it is. Just follow the documentation's description of the outputs. After doing a few FFT's, you might start doing a lot of that mapping stuff in your head.

• Complete answer, would upvote if I could, I also found scipy.fftpack.rfftfreq to do the mapping from k to F, which is a bit different than doing k * Fs / N Feb 3 '14 at 6:48