卡尼多隨筆

認識自我 • 感受世界 • 創造價值

0%

用一點樂理和音訊處理技術做簡單的音色轉換

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 赫茲的純音
然後我們再用一比一的比例,來調配出新的音色
新音色聽起來就像是「一個音」,但實際上卻是由兩個純音組合而成的!

泛音列&音色

泛音列與音色之間的關係

  • 基本頻率決定了一個音的音高
  • 其他泛音與基頻的音量佔比決定了一個音的音色

所以,我是怎麼做出來的呀?

分析&合成音色

  1. scipy.io.wavfile.read ,將待分析的音檔讀進來
  2. scipy.fftpack.fft ,將原本 time domain 的 data 轉換到 frequency domain 上
  3. 透過 matplotlib.pyplot.plot ,把圖給畫出來(如上圖,頻率取 0~1000)
  4. 由圖可以觀察到基頻大概是 100 赫茲左右,也可以觀察到其泛音列的數值大小
  5. 利用 max ,一個一個找出每個小區間內的最大值為何,即為圖中的明顯高起處
  6. 由求出來的所有值,可以推算出基頻及其所有泛音列的數值大小佔比
  7. 透過自己寫的 synthesizer,依照上步驟的佔比,即可合成出該音色的聲音

改變音色

以一個音框來說明,單音音樂效果較佳!

  1. scipy.fftpack.fft ,將該音框內的 data 轉換到 frequency domain 上
  2. 透過自己獨創但效果很陽春 (?) 的方法運算以後,可以粗略找到基頻
  3. 基頻及其整數倍的泛音,透過剛剛分析出來的佔比來改變數值大小,即可轉換為新音色的音樂

感想

除了學到一些音訊處理的技巧以外,最大的收穫是,「態度」才是最重要的關鍵啊!
目前在其他很多方面還是不夠及格,期望帶著這次的寶貴經驗,讓自己漸入佳境。

最後

再次感謝康明軒教授、恩衍、育浚,沒有你們,就沒有這一切!
另外,也非常感謝柏毅給予我簡報上的指點,讓我學到一些很重要也很實用的簡報技巧!


希望讀完這篇文章的您能夠有所收穫,我們下篇文見啦 😃