20
音訊讀寫、錄製與播放 本章介紹 MATLAB 對於聲音訊號(Audio Signal ,簡稱「音訊」)的基 本操作,包含讀檔、寫檔、錄音與播放。

音訊讀寫、錄製與播放 - epaper.gotop.com.twepaper.gotop.com.tw/PDFSample/AEL011131.pdf · MATLAB程式設計入門 20-2 20-1 音訊的基本介紹 聲音訊號(audio signals

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

音訊讀寫、錄製與播放

本章介紹 MATLAB 對於聲音訊號(Audio Signal,簡稱「音訊」)的基

本操作,包含讀檔、寫檔、錄音與播放。

MATLAB 程式設計入門

20-2

20-1 音訊的基本介紹

聲音訊號(audio signals)簡稱音訊,泛指由人耳聽到的各種聲音的訊號。一

般來說,發音體會產生震動,此震動會對空氣產生壓縮與伸張的效果,形成

聲波,以每秒大約 340 公尺的速度在空氣中傳播,當此聲波傳遞到人耳,耳

膜會感覺到一伸一壓的壓力訊號,內耳神經再將此訊號傳遞到大腦,並由大

腦解析與判讀,來分辨此訊號的意義。

音訊有些基本的特質,可說明如下:

音量(volume):聲音的大小稱為音量,又稱為力度、強度(intensity)

或是能量(energy)。音量越大,代表音訊波形的震幅越大。

音高(pitch):音高可以由聲音的基本頻率(fundamental frequency)

越高,而基本頻率則是基本週期(fundamental period)的倒數,換句話

說,一秒內出現的基本週期個數,即是基本頻率。聲音的基本頻率越高,

代表音高越高(例如女高音的歌聲);反之,聲音的基本頻率越低,代

表音高越低(例如男低音的歌聲)。

音色(Timber):音訊波形在每個基本週期內的變化,就形成了此音訊

的音色。不同的音色即代表不同的音訊內容,例如不同的母音有不同的

發音,或是不同的歌手有不同的特色,這些都是由於音色不同所產生的

現象。

瞭解這些特質,可使我們對音訊有更進一步的認識,並更容易瞭解本章各小

節的程式範例。

MATLAB 從第五版後,新增了對音訊檔案讀寫的功能,並能直接錄製聲音訊

號與播放。由於 MATLAB 本身就具有強大的矩陣運算與訊號處理的各種函

數,因此如果你的研究或工作和音訊相關,使用 MATLAB 來進行音訊的處

理,是再方便不過了!

第 20 章 音訊讀寫、錄製與播放

20-3

本章只介紹如何使用 MATLAB 來對音訊檔案進行讀取與寫入,並說明如何

進行音訊的錄製與播放。由於篇幅有限,本章不介紹音訊處理與辨識的各種

方法,有興趣的讀者,可進一步參考下列資訊:

本人所撰寫的公開教材「Audio Signal Processing and Recognition, 音訊

處理與辨識」(http://mirlab.org/jang/books/audioSignalProcessing)。

本人所開發之工具箱「Speech and Audio Processing Toolbox」

(http://mirlab.org/jang/matlab/toolbox/sap)。

MATLAB 總公司所開發的「訊號處理工具箱」(Signal Processing

Toolbox)或「數位訊號處理方塊集」(DSP Blocksets)。

20-2 音檔的讀取

在一般電腦平台上,常見音訊檔案的附檔名有 .wav、.au、.mp3、.aif 等等,

我們都可以使用 MATLAB 來直接讀取這幾種檔案,所用的指令是 audioread。

例如,若要讀取光碟中的檔案 welcome.wav、畫出音訊的波形並播放出此音

訊,可使用下列程式:

範例 20-1:音訊讀寫、錄製與播放/audioRead01.m

[y, fs]=audioread('welcome.wav');

sound(y, fs); % 播放此音訊

time=(1:length(y))/fs; % 時間軸的向量

plot(time, y); % 畫出時間軸上的波形

MATLAB 程式設計入門

20-4

在上例中,fs 是取樣頻率(sample rate),其值為 11025,代表當初在錄製這

個音訊檔案時,每秒鐘會記錄下 11025 個聲音訊號的取樣值。而 y 是聲音訊

號的向量,使用 sound(y, fs) 可播放出此音訊,所以你會聽到我的聲音「歡迎

光臨」。time 則是對應在在時間軸的向量,因此將 y 對 time 做圖,就得到在

時間軸上面的音訊波形。

提示:

在上述範例中,音訊第一點所對應的時間是 1/fs,但我們也可以改成對應時間

是 0,此時對應的時間向量應該為 time=(0:length(y)-1)/fs。

事實上在錄製音訊檔案時,每一個取樣點大部分都是由 8 或 16 個位元(bits)

所代表,若要知道 welcome.wav 的取樣點是由多少個位元來表示,可使用

audioinfo('welcome.wav') 來回傳各種相關資訊,範例如下:

範例 20-2:音訊讀寫、錄製與播放/audioInfo01.m

fileName='welcome.wav';

info=audioinfo(fileName);

fprintf('檔案名稱 = %s\n', info.Filename);

fprintf('壓縮方式 = %s\n', info.CompressionMethod);

fprintf('通道個數 = %g 個\n', info.NumChannels);

第 20 章 音訊讀寫、錄製與播放

20-5

fprintf('取樣頻率 = %g Hz\n', info.SampleRate);

fprintf('取樣點總個數 = %g 個\n', info.TotalSamples);

fprintf('音訊長度 = %g 秒\n', info.Duration);

fprintf('取樣點解析度 = %g 位元/取樣點\n', info.BitsPerSample);

檔案名稱 = D:\users\jang\books\matlabProgramming4beginner\example\20-音訊讀寫、錄

製與播放\welcome.wav

壓縮方式 = Uncompressed

通道個數 = 1 個

取樣頻率 = 11025 Hz

取樣點總個數 = 16001 個

音訊長度 = 1.45134 秒

取樣點解析度 = 8 位元/取樣點

提示:

對於不同類別的音檔,audioinfo 所回傳的欄位可能有所不同,讀者可以試看看

另一個範例 audioInfo03.m,來看看對於 mp3 檔案的回傳結果。

讀者可能會好奇,為什麼在 welcome.wav 音訊檔案中,每一個取樣點用 8 個

位元來表示,但是從音訊波形來看,每一點的值都介於 -1 和 1 之間,這中間

是如何轉換的?首先要知道 wav 檔案的 8 位元是以 unsigned integer(不帶符

號的整數,即正整數)的方式來儲存,因此所能表示的數值是介於 0 和 255

(2^8-1)之間,MATLAB 再將此值設定至變數 y 時,會自動將其數值調整至

介於 -1 和 1 之間,因此若要將 MATLAB 讀出之數值轉回原先 8 位元所表示之

數值,只要將變數 y 乘以 128,再加上 128,就可以得到原先的整數值,例如:

範例 20-3:音訊讀寫、錄製與播放/audioRead03.m

fileName='welcome.wav';

[y, fs]=audioread(fileName);

info=audioinfo(fileName);

nbits=info.BitsPerSample;

y0=y*(2^nbits/2)+(2^nbits/2); % y0 是原先儲存在音訊檔案中的值

difference=sum(abs(y0-round(y0)))

difference =

0

MATLAB 程式設計入門

20-6

在上例中,變數 difference 的值是零,代表 y0 的值完全是整數。此外,為了

增加程式碼的通用性,我們用 2^nbits/2,而不直接使用 128。

MATLAB 對於音檔資料的正規化方式,可以列表如下:

音訊檔案內部儲存方式 數值範圍 MATLAB 正規化方式

Unsigned 8-bit integer (uint8) ]12,0[ 8 y 77 2/)2( y

Signed 16-bit integer (int16) ]12,2[ 1515 y 152/y

Signed 32-bit integer (int32) ]12,2[ 3131 y 312/y

audioread 也可以讀取雙聲道或立體聲(Stereo)的音訊檔案,此時傳回的變

數為具有兩直行的陣列,每一直行代表一個聲道的音訊,例如:

範例 20-4:音訊讀寫、錄製與播放/audioRead04.m

fileName='flanger.wav';

[y, fs]=audioread(fileName); % 讀取音訊檔

sound(y, fs); % 播放音訊

left=y(:,1); % 左聲道音訊

right=y(:,2); % 右聲道音訊

subplot(2,1,1), plot((1:length(left))/fs, left);

subplot(2,1,2), plot((1:length(right))/fs, right);

第 20 章 音訊讀寫、錄製與播放

20-7

此範例會讀取雙聲道的音訊檔 flanger.wav,播放此雙聲道的音訊,並畫出兩

個聲道的音訊波形。由於左右聲道的音量(即波形的震幅)相互消長,因此

播放出來的效果,感覺好像音源在左右聲道之間游移。(小問題:給你一個

單聲道的聲音訊號,你如何使用 MATLAB 對此音訊進行處理,最後產生原

音訊在雙聲道之間游移的效果,如同此範例一般?)

如果音訊檔案很大,無法一次讀入記憶體,我們也可以使用 audioread 來讀出

音訊檔的其中一部份,例如:

範例 20-5:音訊讀寫、錄製與播放/audioRead05.m

[y,fs]=audioread('welcome.wav', [4001 5000]); % 讀取音訊檔第 4001 至 5000 點

plot(y)

這一段波形代表「歡迎光臨」中的「迎」剛開始發音的波形。由上圖可看出,

聲波的外型是很類似一個週期波,其震幅大小就代表音量大小,而其週期的

倒數就是「基本頻率」。以上述圖形而言,1000 個取樣點大概包含了 10 個

週期,所以每個週期大約包含 100 點,對應的時間是 100/fs = 100/11025 =

0.0091 秒 = 9.1 ms,而基本頻率則是 1/0.0091 = 110.25 Hz,換算成鋼琴的按

鍵,非常接近於中央 la(對應頻率是 440 Hz)降 16 度(兩個全音階)所得

到的音,也就是下圖中的 A4(左邊數來第 5 個白鍵)。

MATLAB 程式設計入門

20-8

提示:

若要知道每個鋼琴按鍵的聲音高低,可以嘗試這個網頁:

「http://www.oliphaunts.com/pianoroll-js」。

人耳對聲音高低的感覺,是與基本頻率的對數成正比。以鋼琴的鍵盤而言,

中央 la 的頻率是 440 Hz(Hertz),高八度的中央 la 則是 880 Hz,低八度的

中央 la 則是 220 Hz。鋼琴中的每一個全音階包含 7 個白鍵與 5 個黑鍵,共有

12 個鍵,代表 12 個半音(semitones),以 MIDI 的標準而言,中央 la 的半

音值是 69,對應頻率是 440 Hz,因此半音和頻率之間的轉換程式可寫成下列

公式:

)440

(log1269 2

Hzsemitone

由一段聲音來求取其音高,在音訊處理上稱為音高追蹤(Pitch Tracking),

是音訊處理很重要的一環,相關應用有語音合成、音調辨識、哼唱選歌等。

前面說明過,audioread 會將讀到的音訊壓縮在 -1 和 +1 之間,但如果你想讀

取原來音訊儲存在音訊檔案中的原始資料,也可以,範例如下:

範例 20-6:音訊讀寫、錄製與播放/audioRead06.m

[y, fs]=audioread('welcome.wav', [1, inf], 'native');

p=audioplayer(y, fs); play(p); % 播放此音訊

time=(1:length(y))/fs; % 時間軸的向量

plot(time, y); % 畫出時間軸上的波形

class(y) % 顯示 y 的資料型態

ans =

uint8

第 20 章 音訊讀寫、錄製與播放

20-9

由上例可以看出,當我們加入 'native' 當成 audioread 的第三個參數時,所讀

出的音訊就會是以原來檔案內的資料型態為準,因此本例中的音訊資料 y 的

資料型態為 uint8,同時畫出的波形的震幅範圍也不再限於 -1 和 +1 之間。

20-3 音訊的播放

一旦我們可以讀入音訊檔案,就可以對聲音訊號進行各種處理,例如增大或

減小音量、提高或降低音高、消除雜訊等。要確認處理後的聲音訊號是否符

合所需,就要能夠把音訊直接透過連到電腦的喇叭播放出來,本節就是要介

紹如何使用 MATLAB 來進行音訊的播放。

提示:

另一個播放音訊的方法,是將音訊資料先寫入音訊檔案(請見本章其後說明),

再用電腦的播放程式(如微軟的錄音機、Window Media Player 等)來播放,

但這樣總是多了一道手續,比較麻煩。

MATLAB 程式設計入門

20-10

在前一節中,我們已經知道如何讀音訊檔案,一旦 MATLAB 讀入音訊資料,

並將之設定成工作空間中的變數後,我們就可以使用 sound 指令來直接播放

此變數。例如:

範例 20-7:音訊讀寫、錄製與播放/audioPlay01.m

load handel.mat % 載入儲存於 handel.mat 的變數

sound(y, Fs); % 播放此音訊

在上例中,聲音訊號 y 和取樣頻率 Fs 都事先儲存在 handel.mat 檔案中,一旦

載入後,就可以使用 sound 指令來播放。

提示:

上述範例所播放的音樂,是韓德爾的神劇《彌賽亞》Hallelujah,完整版本請由

此試聽:「https://www.youtube.com/watch?v=URxQby3HtWY」。

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

範例 20-8:音訊讀寫、錄製與播放/audioPlay02.m

[y, fs]=audioread('welcome.wav'); % 載入音訊

sound(5*y, fs); % 播放音訊

load handel.mat % 載入音訊

sound(y, Fs); % 播放音訊

這時候我的「歡迎光臨」和韓德爾的「哈利路亞」就會被同時播放出來,這

種播放方式稱為非同步(asynchronous),因為 MATLAB 並不會等待播放完

畢才執行下一個指令,而是將音訊送往音效卡播放後,立即非同步地執行下

一個指令。

若要讓 MATLAB 在播放音訊時,先停止其他動作,直到音訊播放完畢後,

才會再進行其他指令的運算,這種方式稱為同步(synchronous)播放。欲採

用此播放方式,我們必須使用較複雜的 audioplayer、play 及 playblocking 指

令。我們先看看一個簡單的單一音訊播放範例:

第 20 章 音訊讀寫、錄製與播放

20-11

範例 20-9:音訊讀寫、錄製與播放/audioPlay03.m

load handel.mat % 載入音訊

p=audioplayer(y, Fs); % 產生播放物件

play(p); % 播放音訊

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

play 指令來播放這個物件。

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

範例 20-10:音訊讀寫、錄製與播放/audioPlay04.m

[y, fs]=audioread('welcome.wav'); % 讀入音訊

p=audioplayer(y, fs);

playblocking(p); % 播放音訊

load handel.mat % 載入音訊

p=audioplayer(y, Fs);

playblocking(p); % 播放音訊

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

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

放的聲音:

範例 20-11:音訊讀寫、錄製與播放/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 倍速度的音訊

我們在第一節提到過,聲音的音量是由聲波的震幅來決定,因此我們可藉由

震幅的大小來改變音量,例如:

MATLAB 程式設計入門

20-12

範例 20-12:音訊讀寫、錄製與播放/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);」來試試看。

提示:

在上一個範例中,雖然我們把震幅加大 5 倍,但是耳朵所聽到的音量,並沒有

感覺加大 5 倍,這也說明了人耳對於音量的感覺並不是和音波振幅成正比,而

是和振幅的對數成正比。

如果在播放時,改變取樣頻率,就會改變整個音訊的時間長度,進而影響到

音高。在下例中,我們漸漸提高播放時的取樣頻率,聽到的聲音就會越來越

快、越來越高,最後出現像唐老鴨的聲音:

範例 20-13:音訊讀寫、錄製與播放/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 倍速度的音訊

反之,如果漸漸降低播放的頻率,聽到的聲音就會越來越慢、越來越低,最

後出現像牛叫的聲音:

第 20 章 音訊讀寫、錄製與播放

20-13

範例 20-14:音訊讀寫、錄製與播放/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 倍速度的音訊

若要維持音長但調整音高,或是維持音高但調整音長,那就要對語音波形進

行較複雜的處理,由於篇幅有限,在此略過。

如果我們將聲波訊號上下顛倒,聽到的聲音基本上是一樣的,但是如果前後

顛倒,聽到的聲音就如同錄音帶「倒放」的聲音,聽起來很像是某種外國語

音,請試試下列範例:

範例 20-15:音訊讀寫、錄製與播放/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); % 播放前後顛倒的音訊波形

提示:

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

「倒放二」!

在進行音訊播放時,音訊變數 y 的資料型態可以是下列幾種:double、single、

int16、uint8。如果變數 y 是 double 的資料型態,其值就必須介於 -1 和 1 之

間,否則超過部分就會被截掉。(y 的資料型態通常都是 double,至於其他

型態的資料,大部分是配合錄音指令應運而生,有關此細節,可參考本章其

後對於錄音指令 audiorecorder 的介紹。)

另一個類似的指令是 soundsc,此指令可針對音訊變數的數值先進行正規化

(介於 -1 和 1 中間)後,再送到喇叭播放,以達到最好的播放效果。例如:

MATLAB 程式設計入門

20-14

範例 20-16:音訊讀寫、錄製與播放/soundsc01.m

[y, fs]=audioread('welcome.wav');

p=audioplayer(y, fs);

playblocking(p);

soundsc(y, fs);

在上例中,我們會先聽到原版的「歡迎光臨」,但由於當初錄音效果不佳,

所以音量偏小。改用 soundsc 之後,第二個「歡迎光臨」的聲音就大多了,

也清楚多了。

提示:

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

20-4 音訊的錄製

我們在第一節已經說明了如何讀取音訊檔案,並在第二節說明如何播放音

訊。MATLAB 也支援直接由麥克風讀取訊號,因此可以直接進行聲音的錄

製,所使用的指令是 audiorecord 和 recordblocking,請見下列基本範例:

範例 20-17:音訊讀寫、錄製與播放/audioRecord01.m

duration=3; % 錄音時間

recObj=audiorecorder;

fprintf('按任意鍵後開始 %g 秒錄音:', duration); pause

fprintf('錄音中...');

recordblocking(recObj, duration);

fprintf('錄音結束\n');

fprintf('按任意鍵後開始播放:'); pause

play(recObj);

按任意鍵後開始 3 秒錄音:錄音中...錄音結束

按任意鍵後開始播放:

第 20 章 音訊讀寫、錄製與播放

20-15

在上述範例中,我們先使用 audiorecorder 來產生錄音物件 recObj,然後再使

用 recordblocking 指令來進行三秒的錄音。(請直接執行上述範例後,才看

得出整體的流程。)

由於在上例中,我們在使用 audiorecorder 時,並未指定任何參數,所以錄音

程式會以下列預設參數來進行錄音:取樣頻率為 8000 Hz,取樣點解析度為

8 bits,單聲道錄音。

若要使用不同的參數來進行錄音,我們可以將這些參數送到 audiorecorder 指

令,範例如下:

範例 20-18:音訊讀寫、錄製與播放/audioRecord02.m

fs=16000; % 取樣頻率

nBits=16; % 取樣點解析度,必須是 8 或 16 或 24

nChannel=1; % 聲道個數,必須是 1(單聲道)或 2(雙聲道或立體音)

duration=3; % 錄音時間(秒)

recObj=audiorecorder(fs, nBits, nChannel);

fprintf('按任意鍵後開始 %g 秒錄音:', duration); pause

fprintf('錄音中...');

recordblocking(recObj, duration);

fprintf('錄音結束\n');

fprintf('按任意鍵後開始播放:'); pause

play(recObj);

y = getaudiodata(recObj, 'double'); % get data as a double array

plot((1:length(data))/fs, y);

xlabel('Time (sec)'); ylabel('Amplitude');

按任意鍵後開始 3 秒錄音:錄音中...錄音結束

按任意鍵後開始播放:

MATLAB 程式設計入門

20-16

在上例中,有兩個重點:

我們設定不同的參數來進行錄音:

fs=16000; % 取樣頻率

nBits=16; % 取樣點解析度,必須是 8 或 16 或 24

nChannel=1; % 聲道個數,必須是 1(單聲道)或 2(雙聲道或立體音)

我們可以使用 getaudiodata 指令來取出音訊(可設定資料型態,例如

double、single、int16、uint8 等),並進行繪圖。

20-5 音訊的寫檔

我們也可以經由 MATLAB 將音訊資料直接儲存為音訊檔案,以便日後直接

在電腦播放,而不需每次都經由 MATLAB 播放。寫入音訊檔案的指令是

audiowrite,用法如下:

audiowrite(audioFile, y, fs)

第 20 章 音訊讀寫、錄製與播放

20-17

其中 audioFile 則是欲寫入資料的檔案名稱,y 是音訊變數,fs 是取樣頻率。

例如,若要將韓德爾的歌劇錄音存入 handel.wav,可用下列程式碼:

範例 20-19:音訊讀寫、錄製與播放/audioWrite01.m

load handel.mat

audioFile='handel.wav'; % 欲儲存的 wav 檔案

fprintf('Saving to %s...\n', audioFile);

audiowrite(audioFile, y, round(1.5*Fs));

%fprintf('按任意鍵後開始播放 %s...\n', audioFile); pause

system(audioFile); % 開啟與 wav 檔案對應的應用程式

Saving to handel.wav...

在上例中,我們將音訊資料儲存至 handel.wav,並用電腦對應的的應用程式

來播放此 wav 檔案。

目前在 MATLAB 8 版,audiowrite 指令所支援的輸出音訊檔案包含 WAVE

(.wav)、OGG(.ogg)、FLAC(.flac)、MPEG-4 AAC(.m4a & .mp4)。

提示:

如果你只用 MATLAB 進行音訊錄製與播放,那麼就可以直接使用 save 指令將

音訊變數儲存成 mat 檔案,再用 load 指令載入,也就夠用了,這時候就不必用

到 wavwrite、auwrite 等指令了。

以下範例整合錄音、播放、存檔於同一份程式碼:

範例 20-20:音訊讀寫、錄製與播放/audioWrite02.m

fs=16000; % 取樣頻率

nBits=16; % 取樣點解析度,必須是 8 或 16 或 24

nChannel=1; % 聲道個數,必須是 1(單聲道)或 2(雙聲道或立體音)

duration=3; % 錄音時間(秒)

recObj=audiorecorder(fs, nBits, nChannel);

fprintf('按任意鍵後開始 %g 秒錄音:', duration); pause

fprintf('錄音中...');

recordblocking(recObj, duration);

fprintf('錄音結束\n');

MATLAB 程式設計入門

20-18

fprintf('按任意鍵後開始播放:\n'); pause

y = getaudiodata(recObj, 'double'); % get data as a double array

plot((1:length(data))/fs, y); xlabel('Time (sec)'); ylabel('Amplitude');

sound(y, fs);

audioFile='myRecording.wav'; % 欲儲存的 wav 檔案

fprintf('Saving to %s...\n', audioFile);

audiowrite(audioFile, y, fs);

system(audioFile); % 開啟與 wav 檔案對應的應用程式

按任意鍵後開始 3 秒錄音:錄音中...錄音結束

按任意鍵後開始播放:

Saving to myRecording.wav...

20-19

1. 請根據下列程式碼回答問題。

[y, fs]=wavread('welcome.wav');

wavplay(y,1.0*fs,sync);

wavplay(y,1.2*fs,sync);

(a) 'sync' 代表什麼意思?

(b) 如果改為把第一個 'sync' 改為 'async',會有什麼差別?

2. 以 [y, fs]=wavread('welcome.wav') 讀入音訊資料後,請問下列哪一個敘述有

「倒放」的效果?

(a) wavplay(y, 0.5*fs, 'async'); (b) wavplay(-y, fs, 'sync');

(c) wavplay(-y, -fs, 'sync'); (d) wavplay(flipud(y), fs, 'sync');

3. 對於一段聲音訊號 y 及對應的取樣頻率 fs,若以下列方式來播放,何者造成

的音量最大且發音最尖銳?

(a) sound(y, fs) (b) sound(y, fs*2)

(c) sound(y*2, fs) (d) sound(y*2, fs*2)

4. MATLAB 使用 wavread 讀入 wav 檔案之後,會將音訊資料儲存成何種資料

型態?在哪個區間?

(a) int, [-10,10] (b) double, [-1,1]

(c) int, [-32768,32767] (d) double, [-10,10]

5. 讀入整數的音訊資料:請寫一個函數 wavRead2.m,其用法和 MATLAB 內

建的函數 wavread.m 相同,用法如下:

[y, fs, nbits] = wavread2('file.wav');

唯一不同點,是所傳回來的音訊變數 y 是整數值,如果 nbits 是 8,則 y 的

範圍必須介於 -128 到 127 之間;如果 nbits 是 16,那麼 y 的範圍就會介於

-32768 至 32767 之間。(提示:你必須先瞭解 wavread() 的用法。)

6. 取樣頻率的影響:請用 MATLAB 寫一小段程式,進行錄音兩秒,錄音的內

容是「我是某某某」,其中取樣頻率是 32 KHz,解析度是 8 位元,請將音

20-20

訊儲存成 myVoice2.wav 檔案。請對訊號進行重新取樣(Resample),讓取

樣頻率變成 16 KHz, 8 KHz, 4 KHz, 2 KHz ...等等,請問當取樣頻率掉到多

低時,你已經聽不出來原先的聲音?

7. 重新取樣:請用 interp1 指令,對 myVoice2.wav 的音訊進行重新取樣,讓

取樣頻率變成 11025 Hz,並將結果儲存成 myVoice3.wav。

8. 音訊剪接:請用 MATLAB 完成下列事項:

(a) 先進行錄音,取樣頻率為 16 KHz,解析度為 16 Bits,錄音時間三秒,

錄音內容是「清華大學資訊系」,請問檔案大小為何?如何直接由錄音

設定來計算此大小?

(b) 請觀察波形,將所有的氣音設定為靜音(訊號值為零),存檔後播放聽

看看。是否能聽出來原先的內容?

(c) 請觀察波形,將所有的母音設定為靜音(訊號值為零),存檔後播放聽

看看。是否能聽出來原先的內容?

(d) 若將「大」的前半部(ㄉ)接到「系」的後半部(ㄧ),會不會得到「低」

的聲音?剪接後存成 wav 檔,再播放出來聽看看。

(e) 若將「系」的前半部(ㄒ)接到「清」的後半部(ㄧㄥ),會不會得到

「星」的聲音?剪接後存成 wav 檔,再播放出來聽看看。

9. 音訊剪接 2:請改用 CoolEdit 來完成上一題。

10. 單聲道變雙聲道:將一個單聲道音訊檔案經過處理後,變成一個左右游移的

雙聲道音訊檔案。

(a) 請將此檔案 flanger.wav 的左右聲道波形畫出來。由於左右聲道的音量

漸進互補,因此在播放時,會產生音源在左右聲道游移的效果。

(b) 請使用 load handel.mat 來載入一個音訊 y 及取樣頻率 Fs,請仿照

flanger.wav 的方式,產生一個雙聲道的音訊檔案 handel.wav,使其聲音

游移的特性和 flanger.wav 類似。