2012-07-03 15 views
6

Zastanawiam się, czy używam transformacji Fouriera w MATLAB we właściwy sposób. Chcę mieć wszystkie średnie amplitudy częstotliwości w utworze. Do celów testowych używam a free mp3 download of Beethovens "For Elise", którą konwertowałem na plik fal mono 8 kHz przy użyciu Audacity.Czy używam transformacji Fouriera we właściwy sposób?

Mój kod MATLAB jest następujący:

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); 

Wyjście wówczas wygląda następująco: enter image description here

  1. Może ktoś proszę powiedzieć, czy mój kod jest poprawny? Szczególnie zastanawiam się nad pikami około 0.
  2. Dla normalizacji, czy muszę podzielić przez NFFT lub length(allSamples)?
  3. Dla mnie nie wygląda to tak naprawdę na wykresie słupkowym, ale myślę, że wynika to z wielu wartości, które knuję?

Dzięki za wszelkie wskazówki!

+1

Czy widziałeś tę stronę: [Używanie FFT do uzyskania prostych wykresów analizy spektralnej] (http://www.mathworks.com/support/tech-notes/1700/1702.html). Ma przykład z dużą ilością wyjaśnień – Amro

Odpowiedz

6
  1. W zależności od definicji "poprawne". Robię to, co myślisz, ale prawdopodobnie nie jest to zbyt użyteczne. Sugerowałbym zamiast tego użycie 2D spectrogram, ponieważ otrzymasz informację o częstotliwości w czasie.

  2. Nie ma jednego prawidłowego sposobu normalizacji wyjścia FFT; istnieje wiele różnych konwencji (patrz np. dyskusja here). Komentarz w twoim kodzie mówi, że chcesz zakres od 0 do 1; jeśli wartości wejściowe mieszczą się w zakresie od -1 do 1, wówczas zostanie to podzielone przez liczbę pojemników.

  3. No właśnie!

Polecam również wykreślenie oś y w skali logarytmicznej (w decibels), jak to jest z grubsza jak ludzkie ucho interpretuje głośność.

2

Dwie rzeczy, które wyskakują na mnie:

  1. Nie jestem pewien, dlaczego jesteś w tym (index = 1) składową stałą w swojej działce. Nic wielkiego, ale oczywiście ten bin nie zawiera danych o częstotliwościach
  2. Myślę, że podzielenie przez length(allSamples) jest bardziej prawdopodobne, że jest poprawne niż dzielenie przez NFFT. Powodem jest to, że jeśli chcesz, aby składowa stała była równa średniej danych wejściowych, dzielenie przez length(allSamples) jest właściwą rzeczą.

Jednak, jak powiedział Oli, nie można naprawdę powiedzieć, czym jest "prawidłowa" normalizacja, dopóki nie będzie wiadomo dokładnie, co próbujesz obliczyć. Używam FFT do szacowania widm mocy, więc chcę jednostek takich jak "DAC/rt-Hz", które prowadziłyby do innej normalizacji niż gdybyś chciał czegoś takiego jak "DAC/Hz".

Ostatecznie nie ma substytutu dla myślenia o egzocie, co chcesz wydostać z FFT (w tym jednostek), i wypracowanie dla siebie, jaka powinna być prawidłowa normalizacja (poczynając od definicji FFT, jeśli to konieczne).

Należy również pamiętać, że MATLAB fft nie ma potrzeby używania długości matrycy, która wynosi 2 (chociaż spowoduje to, że FFT będzie działał szybciej). Ponieważ wypełnienie zerowe wprowadzi pewne dzwonienie, musisz pomyśleć o tym, czy jest to właściwe dla twojej aplikacji.

Wreszcie, jeśli periodogram/widmo mocy jest naprawdę tym, czego potrzebujesz, MATLAB zapewnia funkcje takie jak periodogram, pwelch i inne, które mogą być pomocne.

Powiązane problemy