使用快速傅里叶变换确定音符

信息处理 matlab fft 在家工作
2022-01-31 17:36:38

大家好,我正在学习数字滤波器和频谱分析课程。我们得到了一份课程作业/家庭作业,我完全不知道该怎么处理它。我来自数学背景,以前从未做过任何信号处理,而且由于我是大学新手,我真的没有人可以问。

问题:

在本练习中,您需要使用频谱分析技术来确定在短音频样本(采样频率为 44.1KHz)中播放的音符。该样本将包含 5 个和弦的短序列,每个和弦包含 3 或 4 个同时演奏的不同音符。每个音符包括一个基频加上一系列基频倍数的谐波。本练习中的所有音符都属于 12 音符等律音阶。

这是我到目前为止打乱的一些代码:

[x,fs] = audioread('sample1_va18535.wav');
fs % fs is the sampling frequency usually 44.1 KHz
wavplay; % Play audio
N = 4410; % 0.1 seconds at 44.1KHz
N1 = 2205; % 0.05 seconds
n = N1+1:N1+N; % 0.05 – 0.15 seconds
xn = x(n,1); % Select left channel of short clip
wavplay; % Play short clip
t = n/fs; % Time index
plot(t,xn);
xlabel('Time (s)');
ylabel('Amplitude');
window = hamming(N); % Create window
wxn = xn .* window; % Apply window
Xk = fft(wxn); % DFT
k = 0:N-1;
f=k*fs/N; % Frequency in Hz
pause;
plot(f,abs(Xk));
ylabel('Magnitude');
xlabel('Frequency (Hz)');

现在我很确定这还远远没有结束(我什至不确定这段代码是否正确)。有人会这么好心并向我解释如何生成这些频率吗?我知道我需要创建一个基频矢量并忽略任何谐波。

这是文件:https ://ufile.io/lyge5

2个回答

除非您的音频数据包含纯正弦音符源,否则原始 FFT 幅度图将为您提供音高音乐声音的所有谐波或泛音,以及任何基本音高频谱(如果有)。因此,对于最常见的复音音乐录音,如果可能的话,音高检测/估计通常涉及对任何 FFT 结果的大量后处理。不只是选择最大幅度的峰值。

倒谱处理(或计算倒谱)或谐波乘积谱算法,寻找嵌入在 FFT 谱中的泛音或谐波峰值的周期性序列,这可能指示候选源音高。(例如,在均匀间隔的频率倍数上寻找具有一定数量峰值的嵌入式序列。)但是,特别是对于复音和许多常见的和弦类型,可能会有一些误报,您必须弄清楚如何打折或忽视。

或者,您也可以尝试查看自相关峰值(或其他基于滞后的部分相似性度量),而不是使用 FFT,并查看这些峰值是否对应于适当的音高范围和复音程度。

正如 Robert BJ 已经指出的那样,对于专业的音频谐波检测,不推荐使用简单的 FFT 分析方法。尽管如此,它在某些情况下可能非常有用,我认为其中之一就是这个。请注意,正如 hotpaw2 所指出的,使用这种简单的方法,可能会检测到误报。

从您提供的文件(45000+ 个样本,持续时间为 1 秒,以 16 位,44100 Hz 拍摄),首先通过绘制它,您会注意到有 5 个(几乎)相等长度的片段,每个片段大约 9000 个样本长。这 5 个乐曲对应于问题中演奏和定义的 5 个和弦。如下图所示:

在此处输入图像描述

现在,为了简化分析,我只取了 9000 个样本的第一个弦块并计算了它的周期图()wrt 赫兹频率。结果如下图。1N|X(ω)|2

在此处输入图像描述

从这个频谱图中,您可以清楚地看到那些谐波尖峰。您需要做的是找到与每个峰值对应的频率;即,找到对应于峰值的横坐标。您可以使用多种算法(精确地)找到这些峰值频率。但是对于基本分析,您不需要科学的准确性。这是我发现存在于该频谱图上的一组(近似)频率:

f={176,221,262,350,441,525,660,700,786,874,881,1048,1101,1223,1309,1321,1398,1541,1571,1747,1762,1832,1832,1981,2094,2201,2356,2617}

(这些并不精确!有几赫兹的偏差空间)。现在您必须将它们放入一些谐波族中。您可能会假设最低频率属于基本频率。经过一番搜索,您可能会说这个和弦的一个可能组织是F 大调,上面有以下三个音符:

  • F 在 174 赫兹
  • 220 赫兹时的 A
  • 262 赫兹时的 C

我希望你能看到它们的高次谐波,并能单独区分哪个谐波属于哪个音符。另外,请注意,不同基波的某些高次谐波的频率可能会非常接近。

您可以继续对剩余的四个和弦进行此分析。代码如下:

clc; clear all; close all;

[x,Fs,Nb] = wavread('C:\PathToFile\sample1.wav',[1, 45000]);
figure,plot(x);title('signal x[n] sampled at 44100 Hz, 16 bits');

y = reshape( x, 9000, 5 );
Y = fft(y,Fs);

figure,plot((1/9000)*abs(Y(:,1)).^2);
title('Periodogram of the first chord block |X_1[k]|^2|');

请注意,我通过简单的目视检查找到了(近似)峰值频率。光谱的基本类型部分证明了这一点。