20-3 T

一旦我們可以讀入音訊檔案,就可以對聲音訊號進行各種處理,例如增大或減小音量、提高或降低音高、消除雜訊等。要確認處理後的聲音訊號是否符合所需,就要能夠把音訊直接透過連到電腦的喇叭播放出來,本節就是要介紹如何使用 MATLAB 來進行音訊的播放。

Hint
另一個播放音訊的方法,是將音訊資料先寫入音訊檔案(請見本章其後說明),再用電腦的播放程式(如微軟的錄音機、Window Media Player 等)來播放,但這樣總是多了一道手續,比較麻煩。

在前一節中,我們已經知道如何讀音訊檔案,一旦 MATLAB 讀入音訊資料,並將之設定成工作空間中的變數後,我們就可以使用 sound 指令來直接播放此變數。例如:

Example 1: 20-音訊讀寫、錄製與播放/audioPlay01.mload handel.mat % 載入儲存於 handel.mat 的變數 sound(y, Fs); % 播放此音訊

在上例中,聲音訊號 y 和 取樣頻率 Fs 都事先儲存在 handel.mat 檔案中,一旦載入後,就可以使用 sound 指令來播放。

Hint
上述範例所播放的音樂,是韓德爾的神劇《彌賽亞》Hallelujah,完整版本請由此試聽:「https://www.youtube.com/watch?v=URxQby3HtWY」。

我們也可以同時播放兩種音訊,如下:

Example 2: 20-音訊讀寫、錄製與播放/audioPlay02.m[y, fs]=audioread('welcome.wav'); % 載入音訊 sound(5*y, fs); % 播放音訊 load handel.mat % 載入音訊 sound(y, Fs); % 播放音訊

這時候我的「歡迎光臨」和韓德爾的「哈利路亞」就會被同時播放出來,這種播放方式稱為非同步(asynchronous),因為 MATLAB 並不會等待播放完畢才執行下一個指令,而是將音訊送往音效卡播放後,立即非同步地執行下一個指令。

若要讓 MATLAB 在播放音訊時,先停止其他動作,直到音訊播放完畢後,才會再進行其他指令的運算,這種方式稱為同步(synchronous)播放。欲採用此播放方式,我們必須使用較複雜的 audioplayer、play 及 playblocking 指令。我們先看看一個簡單的單一音訊播放範例:

Example 3: 20-音訊讀寫、錄製與播放/audioPlay03.mload handel.mat % 載入音訊 p=audioplayer(y, Fs); % 產生播放物件 play(p); % 播放音訊

在上述範例中,我們使用 audioplayer 產生一個音訊播放物件 p,然後再使用 play 指令來播放這個物件。

若要循序播放兩個音訊,以達成同步播放,可見下列範例:

Example 4: 20-音訊讀寫、錄製與播放/audioPlay04.m[y, fs]=audioread('welcome.wav'); % 讀入音訊 p=audioplayer(y, fs); playblocking(p); % 播放音訊 load handel.mat % 載入音訊 p=audioplayer(y, Fs); playblocking(p); % 播放音訊

在上述範例中,我們使用了 playblocking 指令來達成同步循序播放的效果。

下一個範例,你會聽到一個同步播放的聲音,然後再同時聽到兩個非同步播放的聲音:

Example 5: 20-音訊讀寫、錄製與播放/playSync01.m[y, fs]=audioread('welcome.wav'); p=audioplayer(y, fs); playblocking(p); % 同步播放 1.0 倍速度的音訊 sound(y, 0.8*fs); % 非同步播放 0.8 倍速度的音訊 sound(y, 0.6*fs); % 非同步播放 0.6 倍速度的音訊

我們在第一節提到過,聲音的音量是由聲波的震幅來決定,因此我們可藉由震幅的大小來改變音量,例如:

Example 6: 20-音訊讀寫、錄製與播放/playVolume01.m[y, fs]=audioread('welcome.wav'); p=audioplayer(1*y, fs); playblocking(p); % 播放 1 倍震幅的音訊 p=audioplayer(3*y, fs); playblocking(p); % 播放 3 倍震幅的音訊 p=audioplayer(5*y, fs); playblocking(p); % 播放 5 倍震幅的音訊

在上例中,我們逐次增加震幅,因此播放出來的音量就會越來越大。要特別注意的是:audioplayer 假設 y 的值是介於 –1 和 1 之間,超過這個範圍的數值,其超過部分會被截除後再播放,這時候就會出現「破音」的現象,讀者可以執行「p=audioplayer(5*y, fs); playblocking(p);」來試試看。

Hint
在上一個範例中,雖然我們把震幅加大5倍,但是耳朵所聽到的音量,並沒有感覺加大5倍,這也說明了人耳對於音量的感覺並不是和音波振幅成正比,而是和振幅的對數成正比。

如果在播放時,改變取樣頻率,就會改變整個音訊的時間長度,進而影響到音高。在下例中,我們漸漸提高播放時的取樣頻率,聽到的聲音就會越來越快、越來越高,最後出現像唐老鴨的聲音:

Example 7: 20-音訊讀寫、錄製與播放/playFs01.m[y, fs]=audioread('welcome.wav'); p=audioplayer(y, fs); p.SampleRate=1.0*fs; playblocking(p); % 播放 1.0 倍速度的音訊 p.SampleRate=1.2*fs; playblocking(p); % 播放 1.2 倍速度的音訊 p.SampleRate=1.5*fs; playblocking(p); % 播放 1.5 倍速度的音訊 p.SampleRate=2.0*fs; playblocking(p); % 播放 2.0 倍速度的音訊

反之,如果漸漸降低播放的頻率,聽到的聲音就會越來越慢、越來越低,最後出現像牛叫的聲音:

Example 8: 20-音訊讀寫、錄製與播放/playFs02.m[y, fs]=audioread('welcome.wav'); p=audioplayer(y, fs); p.SampleRate=1.0*fs; playblocking(p); % 播放 1.0 倍速度的音訊 p.SampleRate=0.9*fs; playblocking(p); % 播放 0.9 倍速度的音訊 p.SampleRate=0.8*fs; playblocking(p); % 播放 0.8 倍速度的音訊 p.SampleRate=0.6*fs; playblocking(p); % 播放 0.6 倍速度的音訊

Hint
若要維持音長但調整音高,或是維持音高但調整音長,那就要對語音波形進行較複雜的處理,由於篇幅有限,在此略過。

如果我們將聲波訊號上下顛倒,聽到的聲音基本上是一樣的,但是如果前後顛倒,聽到的聲音就如同錄音帶「倒放」的聲音,聽起來很像是某種外國語音,請試試下列範例:

Example 9: 20-音訊讀寫、錄製與播放/playReverse01.m[y, fs]=audioread('welcome.wav'); p=audioplayer(y, fs); playblocking(p); % 播放正常的音訊波形 p=audioplayer(-y, fs); playblocking(p); % 播放上下顛倒的音訊波形 p=audioplayer(flipud(y), fs); playblocking(p); % 播放前後顛倒的音訊波形

Hint
你能由「倒放」的聲音得知原來正常播放的聲音內容嗎?試看看「倒放一」及「倒放二」!

在進行音訊播放時,音訊變數 y 的資料型態可以是下列幾種: double、single、int16、uint8。如果變數 y 是 double 的資料型態,其值就必須介於 –1 和 1 之間,否則超過部分就會被截掉。(y 的資料型態通常都是 double,至於其他型態的資料,大部分是配合錄音指令應運而生,有關此細節,可參考本章其後對於錄音指令 audiorecorder 的介紹。)

另一個類似的指令是 soundsc,此指令可針對音訊變數的數值先進行正規化(介於 –1 和 1 中間)後,再送到喇叭播放,以達到最好的播放效果。例如:

Example 10: 20-音訊讀寫、錄製與播放/soundsc01.m[y, fs]=audioread('welcome.wav'); p=audioplayer(y, fs); playblocking(p); soundsc(y, fs);

在上例中,我們會先聽到原版的「歡迎光臨」,但由於當初錄音效果不佳,所以音量偏小。改用 soundsc 之後,第二個「歡迎光臨」的聲音就大多了,也清楚多了。

Hint
在影像顯示方面,對應的命令是 imagesc。


MATLAB程式設計:入門篇