用matlab识别声音的音高



我正在尝试使用MATLAB读取一个WAV文件,该文件中有一系列音符。例如,我的WAV文件可能包含C-D-C-E序列。把这个文件输入我的程序会打印出"C D C E"

我尝试使用WAVREAD将文件转换为矢量,然后使用采样对其进行下采样,并制作成一个单通道文件。然后,我能够得出一个在特定频率下具有"峰值"的谱图。

从这里,我想得到关于如何使MATLAB识别峰值频率的帮助,从而使我能够打印出注释。

还是我走错了路?

提前感谢!

您正处于正确的轨道上,但这不是一个简单的问题。我建议研究一种叫做chromatram的东西。这将使用你从声谱图中收集的信息,并将其"分类"为钢琴音符频率。这将给出一首歌曲谐波内容的近似值。由于音符谐波中的残余能量,这可能并不完全准确,但这只是一个开始。

要意识到转录,这就是你正在做的,是一项非常困难的任务,还没有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) 约束频率。你必须使用你所知道的,否则你将需要进行本征模比较。奇异值分解在这个领域是有效的。但是,如果你以某种方式让钢琴(单独地)演奏单独的音符,并且你有钢琴演奏歌曲的录音,你可以做的是对每个片段进行快速傅立叶变换(见上面的时间限制),去掉噪音,并进行比较。然后你使用减法或其他度量来确定每个音符的最佳"适合度"。

这是对这些担忧的粗略解释,但相信我,你对这类分析的约束越多越好。

最新更新