I'm trying to get the correct FFT bin index based on the given frequency. The audio is being sampled at44.1k Hz and the FFT size is1024. Given the signal is real (capture from PyAudio, decoded throughnumpy.fromstring, windowed byscipy.signal.hann), I then perform FFT throughscipy.fftpack.rfft, and compute the decibel of the result, in whole,magnitude = 20 * scipy.log10(abs(rfft(audio_sample)))
Based onthis, andthis, 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 whereFs is the sampling rate, andN 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 therfft's result is no symmetric likefft, and provides the result, in anN 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:
To me, the result of
rffton 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?Given the lack of symmetry from the above, the frequency resolution appears to have increased, is this interpretation correct?
Because of using
rfft, my mapping function from bin indexkto frequencyFis nowF = k*Fs/(2N) for k = 0 ... N-1is this correct?Conversely, the reverse mapping function from frequency
Fto bin indexknow becomesk = 2*F*N/Fs for F = 0Hz ... Fs/2-(Fs/2/N), what about the correctness of this?
My general confusion arises from howrfft is related tofft, and how the mapping can be done correctly while usingrfft. 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.
- $\begingroup$scipy.fftpack.rfft$\endgroup$Fan Jin– Fan Jin2014-02-03 05:21:07 +00:00CommentedFeb 3, 2014 at 5:21
- $\begingroup$Just use
scipy.fftpack.rfftfreq$\endgroup$endolith– endolith2021-07-06 19:06:39 +00:00CommentedJul 6, 2021 at 19:06
1 Answer1
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.
- 1$\begingroup$Complete answer, would upvote if I could, I also found
scipy.fftpack.rfftfreqto do the mapping from k to F, which is a bit different than doingk * Fs / N$\endgroup$Fan Jin– Fan Jin2014-02-03 06:48:31 +00:00CommentedFeb 3, 2014 at 6:48
Explore related questions
See similar questions with these tags.