- (**)
計算ACF:
請寫一個函數 myFrame2acf,將一個音框轉換成 ACF,其用法如下:
acf = myFrame2acf(frame);
其中 acf 的長度應該是和 frame 一樣。
(提示:請直接參考 SAP Toolbox 裡面的 frame2acf.m。你也可以使用 Signal Processing Toolbox 中的 xcorr 函數來完成此題。)
- (**)
計算AMDF:
請寫一個函數 myFrame2amdf,將一個音框轉換成 AMDF,其用法如下:
amdf = myFrame2amdf(frame);
其中 amdf 的長度應該是和 frame 一樣。
(提示:請直接參考 SAP Toolbox 裡面的 frame2acf.m。)
- (**)
計算AMDF/ACF:
請寫一個函數 myFrame2amdfOverAcf,將一個音框轉換成 AMDF/ACF,其用法如下:
amdfOverAcf = myFrame2amdfOverAcf(frame);
其中 amdfOverAcf 的長度應該是和 frame 一樣。請利用此函數,畫出類似此範例的圖,看看此方法是否能夠比單獨使用 ACF 或是 AMDF 更有用。若此方法不適合用來進行音高追蹤,請問有何改進方法?
(提示:請直接參考 SAP Toolbox 裡面的 frame2acfOverAmdf.m。)
- (**)
由ACF計算音高:
請寫一個函數 myAcf2pitch,由一個 ACF 向量來計算音高,其用法如下:
pitch = myAcf2pitch(acf, fs, plotOpt);
其中 acf 是一個 ACF 向量,fs 則是取樣頻率,pitch 則是音高(以 Semitone 為單位),plotOpt 則決定是否畫圖,若其值不等於 0,則必須畫出 ACF 及你的程式所選出來的「ACF音高點」。
(提示:建議你在使用 frame2acf.m 計算 ACF 時,使用的方法是 method=1,然後設定 ACF 的前十點等於 0,再用 max() 函數來抓出最大值的位置,就可以計算音高。你會用到 SAP Toolbox 的 freq2pitch.m。畫圖部份,可以參考此範例。)
- (**)
由AMDF計算音高:
請寫一個函數 myAmdf2pitch,由一個 AMDF 向量來計算音高,其用法如下:
pitch = myAmdf2pitch(amdf, fs, plotOpt);
其中 amdf 是一個 AMDF 向量,fs 則是取樣頻率,pitch 則是音高(以 Semitone 為單位),plotOpt 則決定是否畫圖,若其值不等於 0,則必須畫出 AMDF 及你的程式所選出來的「AMDF音高點」。
(提示:你會用到 Utility Toolbox 的 localMin.m/localMax.m,以及 SAP Toolbox 的 freq2pitch.m。)
- (**)
由一個音框計算一點音高:
請寫一個函數 myFrame2pitch,由一個音框來計算音高,其用法如下:
pitch = myFrame2pitch(frame, fs, method, plotOpt);
其中 frame 是一個音框向量,fs 是取樣頻率,method 則是代表使用的方法('acf' 代表使用 ACF,'amdf' 代表使用 AMDF,依此類推),pitch 則是音高(以 Semitone 為單位),plotOpt 則決定是否畫圖,若其值不等於 0,則必須畫出音框、ACF(或是AMDF等)及你的程式所選來計算音高的最佳點。另:你的函數必須要有 selfdemo 的功能,以便展示,請參考 SAP Toolbox 裡面的 frame2acf.m 或 frame2amdf.m 等函數。
(提示:你會用到 SAP Toolbox 裡面的 freq2pitch.m、frame2acf.m、frame2amdf.m 等函數,以及前面幾題的 myAcf2pitch.m、myAmdf2pitch.m 等函數。)
- (***)
音高的計算、顯示及播放之一:
請寫一段 MATLAB 程式 showPitch01.m,其功能如下:
- 讀入檔案 DoReMi.wav。
- 切出音框,其中音框大小是 256 點,相鄰音框不重疊。
- 對每一個音框計算音量,並使用之前所學的端點偵測的方法,求出音量門檻值。
- 對每一個音框計算下列任一個向量:ACF、AMDF、ACF/AMDF、AMDF/ACF。
- 根據上一步驟,算出每一個音框所對應的音高值,並轉成以 semitone 為單位。(提示:第一次進行時,可以直接抓出 ACF 或是 ACF/AMDF 的最大值所在的索引,或是 AMDF 或 AMDF/ACF 最小值所在的索引,看看效果如何。後續修正時,可以抓取數個最大值或最小值,然後再各種方法從這些候選者中選出最可能的答案。)
- 對音高向量進行後處理,使音高曲線是一段平滑的曲線,同時在音高不存在時,其值為零,可能方法如下:
- 若某一個音框的音量低於音量門檻值,可直接將此音框的音高設定為0。可以使用前幾章所學的「端點偵測」的各種方法來設定音量門檻值。
- 若某一點音高偏離人聲的音高範圍,表示可能是雜訊或是氣音,此時可以將音高設定為零。
- 對於單獨暴增或暴減的音高點,可將其值設為左右點的平均值。
- 對音高向量進行平滑化,可用 Median Filter,相關的指令是 median。
- 其他你可以想到的各種方法。
- 畫出結果,圖形視窗內必須有三個圖,第一個圖是原始聲音訊號,第二個圖是音量圖,第三個圖是音高圖,這三個圖的 X 軸必須都是以秒為單位。
- 播放你所找到的音高。(可使用 SAP Toolbox 的 pvPlay.m。)
你所畫出來的音高向量必須盡量連續,而播放出來的音高也必須盡量接近原歌者的音高。
- (***)
音高的計算、顯示及播放之二:
請寫一段 MATLAB 程式 showPitch02.m,功能和前一題一樣,但是改用蘇豐文老師的歌聲。
- (***)
由一段聲音來計算音高向量:
請寫一個函數 myWave2pitch,由一段聲音來計算音高向量,其用法如下:
pitch = myWave2pitch(wave, fs, frameSize, overlap, method);
其中 wave 是一段音訊向量,fs 是取樣頻率,frameSize 是音框點數,overlap 是相鄰音框的重疊點數,method 則是代表使用的方法('acf' 代表使用 ACF,'amdf' 代表使用 AMDF),而 pitch 則是音高(以 Semitone 為單位)。請注意,你找出來的音高向量應該是一段連續的曲線,你可以使用各種方法來修整 pitch,使得所找出來的 pitch 合於常理,請見上題的方法說明。
(提示:你會用到 SAP Toolbox 以及前面所寫的函數!)
- (***)
音高的播放:
請寫一個函數 myPitchPlay.m,可輸入一段音高向量,然後計算以正弦波重現此音高向量的波形,以便播放,用法如下:
wave = myPitchPlay(pitch, frameRate, fs);
其中 pitch 是音高向量(若有元素為零,代表靜音),frameRate 是每秒鐘的音框個數(每個音框會產生一個音高點),fs 則是合成訊號 wave 的取樣頻率。此函數同時會以 sound(wave, fs) 來播放合成的聲音。請特別注意,在連接正弦波時,必須盡量讓波形連續,否則會出現規律性的雜音。
- 請用此函數來合成一段「Do, Re, Mi, Fa, So, La, Si, Do」的聲音。(提示:通常一秒有兩拍,而上述音階對應到的半音差是「60, 62, 64, 65, 67, 69, 71, 72」。)
- 請使用此函數來播放前一題所計算出來的音高向量。