FFT:当样本少于 fs/2 时如何找到单边频谱

FFT: How to find the single sided spectrum when there are less than fs/2 samples

我正在编写一段代码来确定在歌曲的任何给定时间播放的频率(音符)(注意目前我正在测试它只抓取歌曲的第一秒)。为此,我将音频文件的第一秒分成 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

当我这样做时,我得到的图表如下所示:

看起来我绘制了太多点,因为频率在图表最右侧的幅度上升,所以我认为我使用的是双面频谱。我想我只需要使用 1:fs/2 中的样本,问题是我没有足够大的矩阵来获取那么多点。我尝试从 1:fs/2/chunks 开始,但我不相信这些值是正确的,所以我将它们注释掉了。当样本少于 fs/2 个时,如何找到单边光谱?

作为旁注,当我绘制所有图表时,我注意到给出的频率几乎完全相同。这让我感到惊讶,因为我认为我把这些块做得足够小,以至于只应该抓取在确切时间发生的频率——因此我会得到当前正在播放的音符。如果有人知道我如何更好地找出每次播放的音符,将不胜感激。

对于单边 FT,只需取 FFT 算法输出的前半部分。另一半(负频率)是多余的,因为您的输入是实值的。

1/8秒很长。请注意,如果我没记错的话(音乐不是我的专长),相关频率约为 160-1600 Hz。这些将位于您的 FT 的最左侧区域。您计算的最高频率(在删除 FFT 的右半部分之后)是采样频率的一半,即 44.1/2 kHz。最低频率和样本之间的距离由变换的长度给出(44.1 kHz / 样本数)。