我想知道我是否正确地在MATLAB中使用傅里叶变换。我希望获得一首歌中频率的所有平均幅度。出于测试目的,我使用a free mp3 download of Beethovens "For Elise",我使用Audacity将其转换为8 kHz单波文件。
我的MATLAB代码如下:
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);
然后输出如下:
NFFT
或length(allSamples)
? 感谢任何提示!
答案 0 :(得分:6)
取决于您对“正确”的定义。我认为这是按照你的意图做的,但它可能不是很有用。我建议使用2D spectrogram,因为您将获得有关频率内容的时间本地化信息。
没有一种正确的FFT输出归一化方法;有各种不同的约定(参见例如讨论here)。代码中的注释表示您希望范围为0到1;如果您的输入值在-1到1的范围内,那么除以二进制数就可以实现。
嗯,确实!
我还建议在对数刻度(decibels)上绘制y轴,因为这大致是人耳如何解释响度。
答案 1 :(得分:2)
我突然发现了两件事:
length(allSamples)
更可能比除NFFT
更正确。原因是如果您希望DC分量等于输入数据的平均值,除以length(allSamples)
是正确的做法。然而,就像奥利所说,在你确切知道自己想要计算什么之前,你无法真正说出“正确”的标准化是什么。我倾向于使用FFT来估算功率谱,所以我想要像“DAC / rt-Hz”这样的单位,这会产生与你想要的“DAC / Hz”不同的标准化。
最终,没有什么可以替代你想要从FFT中获得什么(包括单位),并为自己确定正确的归一化应该是什么(如果需要,从FFT的定义开始)。
你还应该知道MATLAB的fft
不要求使用2的幂的数组长度(虽然这样做可能会导致FFT运行得更快)。因为零填充会引入一些振铃,所以你需要考虑是否应该为你的应用做正确的事。
最后,如果周期图/功率谱确实是您想要的,MATLAB提供的功能如periodogram
,pwelch
和其他可能有用的功能。