2013-07-24 213 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