FFT:当小于fs / 2样本时如何找到单面光谱

时间:2017-12-30 01:29:03

标签: matlab signal-processing fft

我正在编写一段代码来确定在一首歌的任何给定时间播放的频率(音符)(注意目前我正在测试它只抓住歌曲的第一秒)。为此,我将音频文件的第一秒打破为8个不同的块。然后我对每个块执行FFT并使用以下代码绘制它:

% Taking a second of an audio file and breaking it into n many chunks and
% figuring out what frequencies make up each of those chunks
clear all;

% Read Audio
fs = 44100;         % sample frequency (Hz)
full = audioread('song.wav');

% Perform fft and get frequencies
chunks = 8;         % How many chunks to break wave into
for i = 1:chunks
    beginningChunk = (i-1)*fs/chunks+1
    endChunk = i*fs/chunks
    x = full(beginningChunk:endChunk);
    y = fft(x);
    n = length(x);     % number of samples in chunk
    amp = abs(y)/n;    % amplitude of the DFT
    %%%amp = amp(1:fs/2/chunks); % note this is my attempt that I think is wrong
    f = (0:n-1)*(fs/n);     % frequency range
    %%%f = f(1:fs/2/chunks); % note this is my attempt that I think is wrong

    figure(i);
    plot(f,amp)
    xlabel('Frequency')
    ylabel('amplitude')
end

当我这样做时,我得到的图形如下: enter image description here enter image description here

看起来我正在绘制太多的点,因为频率在图的最右边上升,所以我认为我使用的是双面光谱。我想我只需要使用1:fs / 2的样本,问题是我没有足够大的矩阵来抓住那么多点。我尝试从1:fs / 2 / chunk开始,但我不相信那些是正确的值,所以我评论了这些。当小于fs / 2样本时,如何找到单面光谱?

作为附注,当我绘制所有图表时,我注意到给出的频率几乎完全相同。这对我来说是令人惊讶的,因为我认为我的块很小,只有在正确的时间发生的频率应该被抓住 - 因此我会得到正在播放的当前音符。如果有人知道我怎样才能在每次发出什么音符时更好地获取信息,那将非常感激。

1 个答案:

答案 0 :(得分:1)

对于单侧FT,只需采用FFT算法输出的前半部分。考虑到您的输入是实值,另一半(负频率)是多余的。

1/8秒很长。请注意,如果我记得正确(音乐不是我的专长),相关频率约为160-1600赫兹。这些将位于英国“金融时报”最左侧的区域。您计算的最高频率(在丢弃FFT的右半部分之后)是采样频率的一半,44.1 / 2 kHz。最低频率和样本之间的距离由变换长度(44.1 kHz /样本数)给出。