純音手工特調:用 Python 做聲音加法合成
類比合成器上常可見到幾款基本波形,用以構成更複雜的聲音。事實上,只要秘方在手,全部基本波形都可以用 sine wave 純音組合而成。
之前提過一個單頻率可以產生某一個音高的聲音。其實大部份樂器發出的聲音都用一組特定頻率構成每個音高,而用上不同的組合秘方就可以產生不同音色(timbre)。
Timbre /ˈtambə/: The character or quality of a musical or vocal sound (Oxford English Dictionary)
泛音(harmonics)的比例是音色變化的重要一環。我們要找到基音/基頻(fundamental frequency)及其整數倍數頻率之間的音量比例。
小提琴的聲音
先看看一個小提琴的 A440 音,基音是 440 Hz 。在此之上聲音裏還混有一個 880 Hz (440×2), 一個 1320 Hz (440×3), 一個 1760 Hz (440×4) 如此類推。聲音分析工具可以找出下圖中的秘方:音量比例(amplitude ratio)。(先別理會震音啦)
簡單合成後,聲音是這樣的:
雖不像小提琴,但跟原來的 sine wave 純音也有一段距離。
把 sine wave 純音混合成新聲音叫「加法合成」(additive synthesis)。下面我們試用 Python 一步步製作。
Python 裏的加法合成
我們從 import library 開始。IPython
顯示聲音播放器,matplotlib
製作圖表,numpy
處理數據陣列,math
提供數學 function 。另外我們先定義取樣率 sampling rate sr
。
之前我們見過用 Python 產生純 sine wave。把其放進 makesine()
function,重複使用就方便一點。
然後我們就可以多叫 makesine()
幾次,產生指定頻率 freq
和長度 dur
的聲音了。結果可以用 numpy.concatenate()
放到一起輸出。
基本的純音聽來也像樣。接着我們可以製作整數倍數關係的音頻,再疊加起來。這裏用了 freq*i
, i
從 1
開始,每次加 1 。每個音頻都用上 amplist
裏指定的音量。疊好了就放到 out
。
用加法合成調出幾種基本音形
好了,之前說到的基本音形在此,只用簡陋的加法合成器產生,用了首 10 個泛音的音量。(我太懶,不理會第 11 之後的泛音啦)
再看看之前的小提琴音⋯⋯
同樣以 440 Hz 為基音,用上不同的泛音比例,聽起來也有明顯分別。
旋律製作
準備工夫做好,我們可以做個 pitch-frequency 轉換器:
還有個旋律播放機來處理一列音 notes
和長度 durs
的組合,再指定泛音比例 harmonics
。
旋律來了!這裏 p
是要播的音, d
是每個音的長度(放快 4 倍),而 h
是泛音音量。
大概聽起來像 80 年代?(而其實是 90 年代的產物)
加法合成也有點費時失事,連電腦也花不少功夫,以往因運算資源缺乏更甚。像拿原色顏料手工調色一樣,加法合成可以給 developer/musician 很大的自由,但現成聲音便捷得多,也更受歡迎。
下次我們再談其他編程工具和軟件,可以方便一點的用到現成的聲音再處理。