我正在尝试做一个项目,该项目使用 MATLAB 读取 WAV 文件,其中包含一系列音符。例如,我的 WAV 文件可能包含一系列 CDCE。将此文件输入我的程序会打印出“CDC E”。
我尝试使用 WAVREAD 将文件转换为矢量,然后使用采样对其进行下采样并制作成单通道文件。然后我能够想出一个在某些频率上有“峰值”的频谱图。
从这里,我想获得有关如何使 MATLAB 识别峰值频率的帮助,从而使我能够打印出注释。
还是我走错了路?
提前致谢!
我正在尝试做一个项目,该项目使用 MATLAB 读取 WAV 文件,其中包含一系列音符。例如,我的 WAV 文件可能包含一系列 CDCE。将此文件输入我的程序会打印出“CDC E”。
我尝试使用 WAVREAD 将文件转换为矢量,然后使用采样对其进行下采样并制作成单通道文件。然后我能够想出一个在某些频率上有“峰值”的频谱图。
从这里,我想获得有关如何使 MATLAB 识别峰值频率的帮助,从而使我能够打印出注释。
还是我走错了路?
提前致谢!
你在正确的轨道上,但这不是一个简单的问题。我建议研究的是一种叫做色谱图的东西。这将使用您从频谱图中收集的信息并将其“分箱”成钢琴音符频率。这将给出歌曲谐波内容的近似值。尽管由于音符谐波中的剩余能量,这可能并不完全准确,但这是一个开始。
请务必意识到,您正在做的转录是一项非常艰巨的任务,尚未 100% 解决。直到今天,人们仍在研究这个。我有生成色度的代码,但我将不得不挖掘它。
编辑
这是一些色度的代码
clc; close all; clear all;
% didn't have wav file, but simply replace this with the following
% [audio,fs] = wavread('audioFile.wav')
audio = rand(1,10000);
fs = 44100; % temp sampling frequency, will depend on audio input
NFFT = 1024; % feel free to change FFT size
hamWin = hamming(NFFT); % window your audio signal to avoid fft edge effects
% get spectral content
S = spectrogram(audio,hamWin,NFFT/2,NFFT,fs);
% Start at center lowest piano note
A0 = 27.5;
% all 88 keys
keys = 0:87;
center = A0*2.^((keys)/12); % set filter center frequencies
left = A0*2.^((keys-1)/12); % define left frequency
left = (left+center)/2.0;
right = A0*2.^((keys+1)/12); % define right frequency
right = (right+center)/2;
% Construct a filter bank
filter = zeros(numel(center),NFFT/2+1); % place holder
freqs = linspace(0,fs/2,NFFT/2+1); % array of frequencies in spectrogram
for i = 1:numel(center)
xTemp = [0,left(i),center(i),right(i),fs/2]; % create points for filter bounds
yTemp = [0,0,1,0,0]; % set magnitudes at each filter point
filter(i,:) = interp1(xTemp,yTemp,freqs); % use interpolation to get values for frequencies
end
% multiply filter by spectrogram to get chroma values.
chroma = filter*abs(S);
%Put into 12 bin chroma
chroma12 = zeros(12,size(chroma,2));
for i = 1:size(chroma,1)
bin = mod(i,12)+1; % get modded index
chroma12(bin,:) = chroma12(bin,:) + chroma(i,:); % add octaves together
end
这应该够了吧。它可能不是最快的解决方案,但它应该可以完成工作。
当然可以优化。
作为 MZimmerman6,这是一个非常复杂的问题。峰峰值测量可能会成功,但如果音乐变得更复杂,肯定不会成功。我之前已经解决过这个问题,并且看到其他人也尝试过,我见过的同行中最成功的项目包括以下内容:
1) 限制时间。实际上,程序可能很难确定音符何时发生变化!如果您试图将人声与乐器分开,或者例如当两个和弦按顺序播放但它们之间有一个保持相同的音符时,尤其如此。因此,通过限制时间意味着找出每段音乐何时发生,因此在您的情况下,将曲目分为四个曲目,每个音符一个。您可以利用每个音符的攻击来发挥自己的优势,自动将攻击检测为要测试的新片段的开始。
2) 限制频率。您必须使用您所知道的,否则您将需要进行特征模态比较。奇异值分解在这个领域是有效的。但是,如果您以某种方式让钢琴演奏单独的音符(单独),并且您有钢琴演奏歌曲的录音,那么您可以做的是对每个片段进行快速傅立叶变换(参见上面的时间限制),消除噪音,然后比较它们。然后,您使用减法或其他指标来确定每个音符的最佳“拟合”。
这是对这些问题的粗略解释,但相信我,对这种分析施加的限制越多越好。