我正在编写一段代码来确定在一首歌的任何给定时间播放的频率(音符)(注意目前我正在测试它只抓住歌曲的第一秒)。为此,我将音频文件的第一秒打破为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 / chunk开始,但我不相信那些是正确的值,所以我评论了这些。当小于fs / 2样本时,如何找到单面光谱?
作为附注,当我绘制所有图表时,我注意到给出的频率几乎完全相同。这对我来说是令人惊讶的,因为我认为我的块很小,只有在正确的时间发生的频率应该被抓住 - 因此我会得到正在播放的当前音符。如果有人知道我怎样才能在每次发出什么音符时更好地获取信息,那将非常感激。
答案 0 :(得分:1)
对于单侧FT,只需采用FFT算法输出的前半部分。考虑到您的输入是实值,另一半(负频率)是多余的。
1/8秒很长。请注意,如果我记得正确(音乐不是我的专长),相关频率约为160-1600赫兹。这些将位于英国“金融时报”最左侧的区域。您计算的最高频率(在丢弃FFT的右半部分之后)是采样频率的一半,44.1 / 2 kHz。最低频率和样本之间的距离由变换长度(44.1 kHz /样本数)给出。