2013-07-24 256 views
1

我正在尝试使用MATLAB读取WAV文件中有音乐音符序列的项目。例如,我的WAV文件可能包含一系列C-D-C-E。把这个文件加入我的程序将打印出“C D C E”。用matlab识别声音的音高

我尝试使用WAVREAD将文件转换为矢量,然后 使用采样将其下采样并制作为单通道文件。 然后,我能够想出在某些频率具有“峰值”的谱图。

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

还是我在错误的轨道上?

在此先感谢!

回答

3

你是在正确的轨道上,但这不是一个简单的问题。我会建议看看是什么叫chromagram。这将使用从光谱图中收集的信息,并将其“存入”到钢琴音符频率中。这将给出歌曲谐波含量的近似值。虽然这可能不完全准确,但因为音符谐波中存在剩余能量,但这是一个开始。

是否意识到转录这是你正在做的事情,是一项非常困难的任务,并且尚未完全解决。人们至今仍在研究这一点。我有代码来产生色度,但我将不得不去挖掘它。

编辑

下面是一些代码色度

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 

这应该做的伎俩。这可能不是最快的解决方案,但它应该完成工作。

当然可以优化。

+0

谢谢! 我会查找chromagram是什么。 但无论如何要正确访问生成的频谱图数据? – Diletante

+0

是'S =谱图(x,窗口,noverlap,nfft,fs)' – MZimmerman6

+0

太棒了!我一定会尝试你的代码。谢谢 – Diletante

3

由于MZimmerman6这是一个非常复杂的问题。峰值到峰值测量可能会成功,但如果音乐变得复杂,肯定不会。之前我已经解决了这个问题,并且看到其他人也尝试了这个,我见过的最成功的项目涉及以下内容:

1)限制时间。一个程序实际上可能很难确定一个音符何时改变!如果你试图从乐器中分离人声,或者例如当两个和弦按顺序播放时,尤其如此,但是它们之间有一个音符保持不变。因此,通过限制时间来查明每一段音乐何时发生,因此在您的情况下,将音轨分成四个音轨,每个音符一个。您可以使用每个音符的攻击来获得优势,自动将攻击检测为要测试的新分段的开始。

2)限制频率。你必须使用你所知道的,否则你将需要进行本征模式比较。奇异值分解在这个领域已经很有效。但是,如果您以某种方式让钢琴演奏单独的音符(单独),并且您有钢琴演奏曲目的录音,您可以做的是对每个段进行快速傅里叶变换(参见上面的时间限制),切出噪音,并且比较它们。然后,您使用减法或其他度量来确定每个音符的最佳“适合度”。

这是对问题的粗略解释,但请相信我,对这种分析的限制越多越好。

+0

是的,我绝对需要这些限制因为这是我的第一个项目。谢谢! – Diletante