第二〸章
音訊讀寫、錄製與播
放
本章重點
本章介紹 MATLAB 對於聲音訊號(Audio Signal,
簡稱「音訊」)的基本操作,包含讀檔、寫檔、錄
音與播放。與音訊相關的函數都放在下列目錄:
{matlab 根目錄}\toolbox\matlab\audio\
讀者可經由輸入「help audio」而得到完整的函數列
表。
MATLAB {]pP
20-1 音訊的基本介紹
聲音訊號(Audio Signal)簡稱音訊,泛指由人耳聽到的各種聲音的訊號。一般來說,發
音體會產生震動,此震動會對空氣產生壓縮與伸張的效果,形成聲波,以每秒大約 340 公
尺的速度在空氣中傳播,當此聲波傳遞到人耳,耳膜會感覺到一伸一壓的壓力訊號,內
耳神經再將此訊號傳遞到大腦,並由大腦解析與判讀,來分辨此訊號的意義。
音訊有些基本的特質,可說明如下:
音量(Volume):聲音的大小稱為音量,又稱為力度、強度(Intensity)或是能量
(Energy)。音量越大,代表音訊波形的震幅越大。
音高(Pitch):聲音的基本頻率(Fundamental Frequency)越高,代表音高越高(例
如女高音的歌聲);反之,聲音的基本頻率越低,代表音高越低(例如男低音的
歌聲)。(有關基本頻率的說明,將在本章其後各小節說明。)
音色(Timber):音訊波形在每個週期內的變化,就形成了此音訊的音色。不同
的音色即代表不同的音訊內容,例如不同的字有不同的發音,或是不同的歌手有
不同的特色,這些都是由於音色不同而產生。
瞭解這些特質,可使我們對音訊有更進一步的認識,並更容易瞭解本章各小節的程式範
例。
MATLAB 從第五版後,新增了對音訊檔案讀寫的功能,並能直接錄製聲音訊號與播放。
由於 MATLAB 本身就具有強大的矩陣運算與訊號處理的各種函數,因此如果你的研究
或工作和音訊相關,使用 MATLAB 來進行音訊的處理,是再方便不過了!
本章只介紹如何使用 MATLAB 來對音訊檔案(以 .wav 檔案為主)進行讀取與寫入,並
說明如何進行音訊的錄製與播放。由於篇幅有限,本章並不介紹音訊處理與辨識的各種
方法,有興趣的讀者,可進一步參考「訊號處理工具箱」(Signal Processing Toolbox)
20-2
MATLAB系列叢書
Chapter 20
音訊讀寫、錄製與播放
或「數位訊號處理方塊集」(DSP Blocksets)的手冊,或參閱相關的教科書。(或是可
以參考筆者的網頁,就有很多音訊處理與辨識的線上教材與相關 MATLAB 程式碼。)
20-2 WAV檔案的讀取
在微軟視窗平台上,聲音訊號的檔案多以 wav 為副檔名,MATLAB可直接讀取此類檔
案,所用的指令是 wavread。例如,若要讀取光碟中的檔案 welcome.wav,畫出音訊的波
形並播放出此音訊,可使用下列程式:
d 20-1G readWave01.m
[y, fs]=wavread('welcome.wav');
sound(y, fs);
% T
time=(1:length(y))/fs; % bVq
plot(time, y);
% eXbWi
在上例中,fs 是取樣頻率,其值為 11025,代表當初在錄製這個音訊檔案時,每秒鐘會
記錄下11025個聲音訊號的取樣值。而 y 是聲音訊號的向量,使用 sound(y, fs) 可播放出
此音訊,所以你會聽到我的聲音「歡迎光臨」。time 則是對應在在時間軸的向量,因此
將 y 對 time 做圖,就得到在時間軸上面的音訊波形:
清 蔚 出 版
20-3
MATLAB {]pP
事實上在錄製音訊檔案時,每一個取樣點大部分都是由8或16個位元(Bits)所代表,若
要 知 道 welcome.wav 的 取 樣 點 是 由 多 少 個 位 元 來 表 示 , 可 使 用 [y, fs,
nbits]=wavread(‘welcome.wav’)。若要知道音訊長度,則可使用 length(y)/fs。以下範例可
以印出音訊檔 welcome.wav 的各種相關資訊:
d 20-2GreadWave02.m
fileName='welcome.wav';
[y, fs, nbits]=wavread(fileName);
fprintf('T
"%s" TG
\n', fileName);
fprintf('T
= %g
\n', length(y)/fs);
fprintf('Wv
= %g I
/
\n', fs);
fprintf('R
= %g
/I
\n', nbits);
音訊檔案 "welcome.wav" 的資訊:
音訊長度 = 1.45134 秒
取樣頻率 = 11025 取樣點/秒
解析度 = 8 位元/取樣點
MATLAB系列叢書
20-4
Chapter 20
音訊讀寫、錄製與播放
讀者可能會好奇,為什麼每一個取樣點用 8 個位元來表示,但是從音訊波形來看,每一
點的值都介於 –1 和 1 之間,這中間是如何轉換的?首先要知道 wav 檔案的 8 位元是以
unsigned integer(不帶符號的整數,即正整數)的方式來儲存,因此所能表示的數值是
介於 0 和 255 (2^8-1) 之間,MATLAB 再將此值設定至變數 y 時,會自動將其數值調整
至介於 –1 和 1 之間,因此若要將 MATLAB 讀出之數值轉回原先 8 位元所表示之數值,
只要將變數 y 乘以 128,再加上 128,就可以得到原先的整數值,例如:
d 20-3G readWave03.m
fileName='welcome.wav';
[y, fs, nbits]=wavread(fileName);
y0=y*(2^nbits/2)+(2^nbits/2); % y0 OxsbT
difference=sum(abs(y0-round(y0)))
difference =
0
在上例中,變數 difference 的值是零,代表 y0 的值完全是整數。此外,為了增加程式碼
的通用性,我們用 2^nbits/2,而不直接使用128。
wavread 也可以讀取雙聲道或立體聲(Stereo)的音訊檔案,此時傳回的變數為具有兩直
行的陣列,每一直行代表一個聲道的音訊,例如:
d 20-4G readWave04.m
fileName='flanger.wav';
[y, fs]=wavread(fileName); % T
sound(y, fs);
left=y(:,1);
right=y(:,2);
% T
% nDT
% knDT
subplot(2,1,1), plot((1:length(left))/fs, left);
subplot(2,1,2), plot((1:length(right))/fs, right);
此範例會讀取雙聲道的音訊檔 flanger.wav,播放此雙聲道的音訊,並畫出兩個聲道的音
訊波形如下:
清 蔚 出 版
20-5
MATLAB {]pP
由於左右聲道的音量(即波形的震幅)相互消長,因此播放出來的效果,感覺好像音源
在左右聲道之間游移。(小問題:給你一個單聲道的聲音訊號,你如何使用 MATLAB 對
此音訊進行處理,最後產生原音訊在雙聲道之間游移的效果,如同此範例一般?)
如果音訊檔案很大,無法一次讀入記憶體,我們也可以使用 wavread 來讀出音訊檔的其
中一部份,例如:
d 20-5G readWave05.m
[y,fs]=wavread('welcome.wav', [4001 5000]); %
4001
5000 I
figure; plot(y)
畫出之圖形如下:
20-6
MATLAB系列叢書
Chapter 20
音訊讀寫、錄製與播放
這一段波形代表「歡迎光臨」中的「迎」剛開始發音的波形。由上圖可看出,聲波的外
型是很類似一個週期波,其震幅大小就代表音量大小,而其週期的倒數就是「基本頻
率」。以上述圖形而言,1000個取樣點大概包含了10個週期,所以每個週期大約包含 100
點,對應的時間是 100/fs = 100/11025 = 0.0091秒 = 9.1 ms,而基本頻率則是 1/0.0091 =
110.25 Hz,換算成鋼琴的按鍵,非常接近於中央 la (對應頻率是 440 Hz)降16度(兩
個全音階)所得到的音,也就是下圖中的 A4(左邊數來第 5 個白鍵)。
提 示 :
HnCPAOPWvCH^LA
la WvO
440 HzAK
7 P
]t
A
gUCG
la hO 880 HzACK
12 AN
5 A@
la hO 220 HzC^C@
12 b]
Semitones^AH MIDI
la bO
69AWvO
440 HzA]bMWv{i
semitone
=
69
+
log*12
2
frequency
440
清 蔚 出 版
20-7
MATLAB {]pP
提 示 :
@qnD
AbTBzWl
]Pitch Tracking^AOTBz
n@AyXBBC
若要取得 wav 檔案的更多資訊,可由 wavread 的第四個輸出變數得到,例如:
d 20-6GreadWave06.m
[y, fs, nbits, opts]=wavread('flanger.wav');
opts.fmt
ans =
wFormatTag: 1
nChannels: 2
nSamplesPerSec: 22050
nAvgBytesPerSec: 88200
nBlockAlign: 4
nBitsPerSample: 16
其中 wFormatTag 代表這個 wav 檔案的格式標記,nChannels 代表聲道數(此例是二聲道),
nSamplesPerSec 代表取樣頻率,nAvgBytesPerSec 代表每秒的位元數(雙聲道再加上每個
資料點是由兩個位元組來表示,所以在此例中,nAvgBytesPerSec 是 nSamplesPerSec 的
四倍),nBlockAlign 是 nAvgBytesPerSec 對 nSamplesPerSec 的比值,nBitsPerSample 則
是每個資料點所用到的位元數。
除了微軟的 wav 檔案外,MATLAB 亦可讀取 au 檔案,這是在 NeXT/Sun 工作站常用的
聲音檔案,所用的指令是 auread,其用法和 wavread 大致相同,在此不再贅述,讀者可
由 help auread 得到相關的線上說明。
20-3 聲音訊號的播放
20-8
MATLAB系列叢書