Y'all!廢話不多說。先放個 beat!。
派對聲響中,鼓是一切的基底。在規律的震動中,我們才能向上向下祈禱,chill到心底涼透。可是你說:「要多少錢買?」我就說:「用做的。」哇喔!怎麼可能?就是可能,今天就開始來講我這組鼓的合成!
在「§d7§ 全頻率震動!終於買到 CDPRO2!Web Audio API 的原力!」當中有介紹了基本的 AudioNodes
的關係。底層實作與實際的API 雖然複雜,但是原理其實相當明瞭,電吉他應該有看過吧?
所以在 Tone.js / Web Audio API 裡面,我們可以對上述每個環節進行控制。以 source 為例,我們可以直接產生的就有非常多種:
最基本一定會使用的就是 Oscillator 跟 Noise 了!Oscillator 可以產生最單純的聲響 Sine 波、方波、三角波等。而 Noise 則可以分成各種頻譜分布的類型,常見的有 Pink Noise、White Noise 等,時常用在減法合成。
大鼓聽起來是什麼樣子?他是重擊心靈的、靈魂覺醒的、沈沈的、重重的、有時候短有時候長。看起來呢?你想到的是這樣:
我想到的是這樣:
一般來說,可以用一個很簡單的步驟模型去製造這樣的波形效果:
const osc = new Tone.Oscillator(220, "sine");
如此一來假如你直接把振盪器接到 master 上面,就像是插到音響上面,就會產生一個不間斷的聲音。像是這樣。這類的 youtube 影片還真他媽不少,我想像過世界上一定有一群人 party 的時候就整理一個這樣的 youtube 清單來放歌。
const osc = new Tone.Oscillator(440, "sine").toMaster().start();
但我覺得自己不是那樣的人,所以沒有這個打算。觀察那個波形加上平常聽到的音樂,大約就可以推測出:要合成大鼓的聲音一個關鍵就是訊號會在一段時間裡面逐漸消失,通常大約是一秒之內。所以,我們需要加入 envelope 的幫忙。
envelope 是什麼東西?簡單來說他代表的就是一種類型的訊號產生器,形狀的模型就像下面的圖解釋得清清楚楚:
通常是用 trigger 的模式來啟動,也就是 trigger 一次就是產生一個波,而不會重複產生,所以雖然也是某種訊號產生器,但通常不會歸 source,像是以 Tone.js 的設計就是歸類到 Component 底下,也就是直接繼承最一般的Tone.AudioNode
。(詳細可以參考 doc)
圖中 ADSR 代表的是形塑這個波形的四個參數,A 代表的是 Attack 也就是訊號達到最高點需要的時間。其他的話,這裡只要知道他可以調整那座小山的樣子即可,因為有網路資源都有相當清楚的解釋。
這樣的訊號若是直接控制 oscillator 的音量(gain)大小,就可以達到上面提到的聲音快速變小的效果。實作上,可以使用Tone.Envelope
一個音量控制的元件上面:
const gainNode = Tone.context.createGain();
const env = new Tone.Envelope({
"attack" : 0.1,
"decay" : 0.2,
"sustain" : 1,
"release" : 0.8,
});
const.connect(gainNode.gain);
或是直接使用Tone.AmplitudeEnvelope
加到一個Tone.Oscillator
上面:
const ampEnv = new Tone.AmplitudeEnvelope({
"attack": 0.1,
"decay": 0.2,
"sustain": 1.0,
"release": 0.8
}).toMaster();
//create an oscillator and connect it
const osc = new Tone.Oscillator().connect(ampEnv).start();
//trigger the envelopes attack and release "8t" apart
ampEnv.triggerAttackRelease("8t");
聽起來怎麼還是怪怪的,因為其實若是把大鼓的訊號時間軸拉更大來看,就會看到波形會從較密集轉化為較鬆散最後停下來。這其實跟鼓皮在空氣中震動之後的特性有關:很容易可以想像剛開始強烈震動的鼓面,到最後能量再給空氣做功之後,震動的速度一定會緩慢下來,頻率也就低了。
所以在最後,除了剛剛在 oscillator 的音量上面加上Tone.AmplitudeEnvelope
,現在要在 frequency 上面也加上Tone.FrequencyEnvelope
:
// 使用剛剛前面建立好了 osc 物件
const env = new Tone.FrequencyEnvelope({
"attack" : 0.2,
"baseFrequency" : "C2",
"octaves" : 4
});
env.connect(osc.frequency);
baseFrequency
代表的是最最開始的頻率,與降低過程結束後,回到的頻率。而上升到最高的頻率就是baseFrequency
再上去octaves
個八度(四個八度)。所以上面的例子當中就會是在 0.2秒 內(attack
)從C2
上去四個八度到C6
,最後逐漸回到C2
。
大鼓已經接上麥克風,明天繼續 PA 的行程。
大家加油!
關於作者
Vibert Thio
致力於將對於技術的深度研究轉化為新型態藝術創作的能量,並思考技術的拓展/侷限與其對於藝術論述/呈現的影響。專長為數位藝術創作、音像程式設計、互動設計,喜愛即時運算的臨場感與不可預測。