2020 升大三的暑假,和康明軒教授、恩衍、育浚一起做了「音訊處理」的專題。
(康明軒教授提供數學上的幫助、恩衍做降噪、育浚做其他也很有趣的聲音處理)
成果
先給大家聽聽看我最後上台發表的成果吧!
分析&合成音色
樂器 | 待分析的音檔 | 合成出來 | 演奏音階 |
---|---|---|---|
小號 | 01 | 02 | 03 |
雙簧管 | 04 | 05 | 06 |
管風琴 | 07 | 08 | 09 |
改變音色
音樂 | 原音檔 | 小號 | 雙簧管 | 管風琴 |
---|---|---|---|---|
生命之名 | 10 | 11 | 12 | |
New Thang | 13 | 14 |
預備知識
音訊預處理
為何要數位化
電腦如何將聲音訊號由類比轉成數位呢?
先講為什麼要轉成數位好了。
「電腦處理聲音」這件事情,其實就是在對聲音做運算,
和類比也就是連續訊號相比,離散訊號的運算量小多了!
所以在電腦處理聲音之前,必須先讓聲音變成離散資料。
那該怎麼轉成數位呢?
只要讓聲音經過 取樣 (sampling) 以及 量化 (quantization) 的過程就可以囉!
音檔參數
在介紹取樣、量化之前,先給大家認識一下聲音檔案的重要參數。
- 持續時間 (duration):音檔總共有多少秒
- 持續時間 (duration):音檔總共有多少秒
- 取樣頻率 (sampling rate):一秒鐘要取多少個取樣點(聲音檔案通常會採用 48000 或 44100 赫茲,跟取樣定理有關)
- 位元深度 (bit depth):一個取樣點要用多少個位元紀錄(位元深度越大的話,會越精準,但相對而言,資料量也就越大!)
- 聲道數 (channel):其實就是我們常聽到的單聲道、雙聲道等等的
取樣&量化
- 取樣 (sampling):透過取樣頻率,也就是一秒鐘要取多少個取樣點,將時間軸上的資料離散化,得到一串取樣點(如上圖)
- 量化 (quantization):依照位元深度,也就是一個取樣點要用多少個位元紀錄,分別對每個取樣點做四捨五入,將振幅軸上的資料離散化,最後就會得到一串數列(如下圖)
聲音訊號如何被處理
訊號轉成數位了,那電腦如何處理聲音訊號呢?
打個比方好了:
在開始進行一個大任務之前,我們通常會先拆解成多個小行動,然後再各個擊破!
處理聲音也是同樣道理,
我們只要把一段音訊切成一個一個小音框,乘上窗函數重疊以後,就可以開始做後續的處理。
切取音框
在分析一段音訊的時候,我們通常是以短時距分析為主,
因為聲音訊號在短時間之內是相對穩定的!
所以我們通常會將音訊切成比較短的單位,稱為音框 (frame)。
那為了方便使用快速傅立葉轉換,我們通常會取 2 的 n 次方個取樣點當作一個音框。
然後要注意,音框不能切太大或太小,這樣才能充分擷取音訊的特徵!
那為了避免相鄰兩音框的特徵變化過大,一般會讓音框之間有一段重疊的區域,
當然重疊的部分越多,對應的運算量也就越大!
音框參數
帶大家認識一下切取音框的重要參數。
- 音框大小 (frame size):每一個音框內所含有的取樣點個數
- 音框重疊量 (frame overlap):兩音框間重疊的取樣點個數
- 音框跳距 (hop size):兩音框起點距離的取樣點個數,相當於 音框大小 - 音框重疊量
- 音框率 (frame rate):每秒出現的音框數目,相當於 取樣頻率 / 音框跳距
套上窗函數
原本完整的聲音波形,被音框硬生生地截斷,頻譜將會產生誤差,該怎麼辦呢?
我們只要透過乘上一個中央高、兩側低的窗函數 (window function),
讓音框內兩端的訊號達到 fade-in、fade-out 的效果,就可以增加音框左右兩端的連續性了!
音色
聲音三要素
什麼是音色
音色是一個可以讓聆聽者分辨出聲音聽起來不同的聲音特性,
藉由音色資訊,我們可以分辨出究竟現在聽到的聲音是人聲還是某種樂器聲,
不受音高不同及音量大小的影響!
影響聲音的要素
哪些要素影響著音色呢?
- ADSR Envelope
- Tremolo & Vibrato
- 泛音列
- 可能還有其他 (?)
ADSR Envelope
它是什麼呢?
它是描述 Attack、Decay、Sustain、Release 四階段的一個包絡!
這樣講其實蠻抽象的,
可以把它想像成聲音的 schedule,讓聲音的某個參數隨著時間做改變。
那 Attack、Decay、Sustain、Release 又分別是什麼呢?
觀察上圖:
- Attack:一個參數從 0 到最大值所需要的時間
- Decay:一個參數從最大值降到 Sustain 所需要的時間
- Sustain:它比較特別,它是一個程度的參數,代表在 Release 之前維持的一個量
- Release:一個參數從 Sustain 降回 0 所需要的時間
這樣可能還是很抽象,沒關係,到 Ableton Live 的合成器教學頁面玩玩吧!
Tremolo & Vibrato
- Tremolo:讓音量呈現忽大忽小的顫音效果,可以讓長音有起伏變化不再呆板,也可以讓每個音符呈現若隱若現的效果
- Vibrato:讓音高呈現忽高忽低的顫音效果,比方擦弦樂器可以靠揉弦來達到這種效果
泛音列
泛音列是一系列頻率為基音頻率 (fundamental frequency) 整數倍的聲音,
這些聲音都是純音,可以分別用正弦波來表示。
那和音色有什麼關係呢?
強烈推薦大家看 NiceChord (好和弦) 的 一次搞懂「泛音列」!
看完了一切都豁然開朗了呢 😎
波形
波形何以如此多元?
不同樂器,組成「一個音」的泛音列佔比都不太一樣。
那剛剛提過,泛音列上的每個音都是純音,可以分別用正弦波來表示,
然後再根據波的疊加原理,依照泛音列佔比,疊加出新的波形,
疊加後的波形就是我們最後觀察到的波形!
如上圖。
感受聲音
再用聽的和看的來感受一次吧!
以基頻為 220 赫茲的音來說明好了:
先給大家聽 220 赫茲的純音。
接著是 440 赫茲的純音。
然後我們再用一比一的比例,來調配出新的音色。
新音色聽起來就像是「一個音」,但實際上卻是由兩個純音組合而成的!
泛音列&音色
泛音列與音色之間的關係:
- 基本頻率決定了一個音的音高
- 其他泛音與基頻的音量佔比決定了一個音的音色
所以,我是怎麼做出來的呀?
分析&合成音色
- 用
scipy.io.wavfile.read
,將待分析的音檔讀進來 - 用
scipy.fftpack.fft
,將原本 time domain 的 data 轉換到 frequency domain 上 - 透過
matplotlib.pyplot.plot
,把圖給畫出來(如上圖,頻率取 0~1000) - 由圖可以觀察到基頻大概是 100 赫茲左右,也可以觀察到其泛音列的數值大小
- 利用
max
,一個一個找出每個小區間內的最大值為何,即為圖中的明顯高起處 - 由求出來的所有值,可以推算出基頻及其所有泛音列的數值大小佔比
- 透過自己寫的 synthesizer,依照上步驟的佔比,即可合成出該音色的聲音
改變音色
以一個音框來說明,單音音樂效果較佳!
- 用
scipy.fftpack.fft
,將該音框內的 data 轉換到 frequency domain 上 - 透過自己獨創但效果很陽春 (?) 的方法運算以後,可以粗略找到基頻
- 該基頻及其整數倍的泛音,透過剛剛分析出來的佔比來改變數值大小,即可轉換為新音色的音樂
感想
除了學到一些音訊處理的技巧以外,最大的收穫是,「態度」才是最重要的關鍵啊!
目前在其他很多方面還是不夠及格,期望帶著這次的寶貴經驗,讓自己漸入佳境。
最後
再次感謝康明軒教授、恩衍、育浚,沒有你們,就沒有這一切!
另外,也非常感謝柏毅給予我簡報上的指點,讓我學到一些很重要也很實用的簡報技巧!
希望讀完這篇文章的您能夠有所收穫,我們下篇文見啦 😃