Am I using the Fourier transform correctly?

I am wondering if I am using Fourier transform in MATLAB correctly. I want to have all the average amplitudes for the frequencies in the song. For testing purposes, I use the free Beethovens mp3 download "For Elise" , which I converted to a 8 kHz monaural file using Audacity .

My MATLAB code is as follows:

clear all % be careful % load file % Für Elise Recording by Valentina Lisitsa % from http://www.forelise.com/recordings/valentina_lisitsa % Converted to 8 kHz mono using Audacity allSamples = wavread('fur_elise_valentina_lisitsa_8khz_mono.wav'); % apply windowing function w = hanning(length(allSamples)); allSamples = allSamples.*w; % FFT needs input of length 2^x NFFT = 2^nextpow2(length(allSamples)) % Apply FFT fftBuckets=fft(allSamples, NFFT); fftBuckets=fftBuckets(1:(NFFT/2+1)); % because of symetric/mirrored values % calculate single side amplitude spectrum, % normalize by dividing by NFFT to get the % popular way of displaying amplitudes % in a range of 0 to 1 fftBuckets = (2*abs(fftBuckets))/NFFT; % plot it: max possible frequency is 4000, because sampling rate of input % is 8000 Hz x = linspace(1,4000,length(fftBuckets)); bar(x,fftBuckets); 

The result is as follows: enter image description here

  • Can someone please tell me if my code is correct? I am particularly interested in peaks around 0.
  • For normalization, do I need to divide by NFFT or length(allSamples) ?
  • For me, this does not look like a histogram, but I believe that this is due to the many values ​​that I draw on the screen?

Thanks for any tips!

+6
source share
2 answers
  • Depends on your definition of "correct." In my opinion, this does what you intended, but it is probably not very useful. Instead, I would suggest using a 2D spectrogram , as you will get frequency content information localized in time.

  • There is no one correct way to normalize FFT output; there are various conventions (see, for example, discussion here ). The comment in your code says that you want a range from 0 to 1; if your input values ​​are in the range from -1 to 1, then this will lead to a division by the number of bins.

  • Well, for sure!

I would also recommend drawing the y axis in a logarithmic scale (in decibels ), as it is roughly the way the human ear interprets loudness.

+6
source

Two things that jump on me:

  • I'm not sure why you include the DC component (index = 1) in your plot. It doesn’t matter, but, of course, there is no frequency data in this bunker.
  • I think dividing by length(allSamples) will be more correct than dividing by NFFT . The reason is that if you want the DC component to be equal to the average value of the input, dividing by length(allSamples) is the right thing.

However, as Olya said, you cannot say what the “normal” normalization is until you know exactly what you are trying to calculate. I tend to use FFTs to estimate power spectra, so I want units like “DAC / rt-Hz”, which would lead to a different normalization than if you wanted something like “DAC / Hz”.

Ultimately, there is no way to think about what you want to get out of the FFT (including units), and to develop for yourself what the correct normalization should be (based on the definition of the FFT, if necessary).

You should also be aware that MATLAB fft does not require the use of an array length that has a power of 2 (although this will apparently lead to FFT acceleration). Since zero padding will cause some calls, you need to consider whether this is the right thing to do for your application.

Finally, if the frequency / power spectrum is really what you want, MATLAB provides functions such as periodogram , pwelch and others that may be useful.

+2
source

Source: https://habr.com/ru/post/919572/


All Articles