Tone.jsの続きです。前回はリズム系のシンセ音でドラムパッドを作りました。今回は、パッドの音色に手を加えたく、エンベロープ設定とエフェクトを加えてみました。それではいきましょう!
【目次】
※参考:【Tone.js】リズム系のシンセ音でドラムパッドを作った - クモのようにコツコツと
※参考:Tone.jsを習得するためにやった事まとめ
qiita.com
前回のおさらい
前回作ってみたドラムパッド
See the Pen tone.js-Drum Pad by イイダリョウ (@i_ryo) on CodePen.
JSコード
//DOM const kick = document.querySelector('#kick'); const snare = document.querySelector('#snare'); const hihat = document.querySelector('#hihat'); //シンセ生成 const membrane = new Tone.MembraneSynth().toMaster(); const noise = new Tone.NoiseSynth().toMaster(); const metal = new Tone.MetalSynth().toMaster(); kick.addEventListener('click', () => { membrane.triggerAttackRelease('C0','2n'); }, false); snare.addEventListener('click', () => { noise.triggerAttackRelease('8n'); }, false); hihat.addEventListener('click', () => { metal.triggerAttackRelease('32n'); }, false);
最後のクリックイベントの中のtriggerAttackRelease()
の引数で音の長さを指定したが変わらず。それ以外の方法をとる必要がありそう。
詳細は前回の記事を参照。
※参考:【Tone.js】リズム系のシンセ音でドラムパッドを作った - クモのようにコツコツと
エンベロープ(ADSR)を変更する
エンベロープ(ADSR)とは
まずエンベロープ(ADSR)の設定を変更してみる。エンベロープとは音量の立ち上がりや減衰をコントロールする設定。以前こちらの記事でも行った(この時はメロディ再生)。
※参考:【Tone.js】メロディ再生、シンセ音源加工、エフェクター接続(マリオを打ち込んだ!) - クモのようにコツコツと
エンベロープについては以前も紹介した下記の記事がとてもわかりやすい。
※参考:AMPをエンベロープ(ADSR)でコントロールする シンセサイザー 初心者講座
A(アタック)、D(ディケイ)、S(サスティーン)、R(リリース)の4つのパラメータがあり、下記の内容を設定できる。
- A(アタック):立ち上がりから最大音量までにかかる時間
- D(ディケイ):最大音量から安定音量までにかかる時間
- S(サスティーン):安定的に楽器が鳴り続ける音量(ピアノでいえば鍵盤を押し続けている間の音量)
- R(リリース):音がなくなる(減衰)までにかかる時間(ピアノでいえば鍵盤を離したあとの時間)
エンベロープ設定後のドラムパッド
エンベロープを変更してみたものこちら
See the Pen tone.js-Drum Pad-2 by イイダリョウ (@i_ryo) on CodePen.
最初の状態より音の長さが変わった!
JSコード全体
//DOM const kick = document.querySelector('#kick'); const snare = document.querySelector('#snare'); const hihat = document.querySelector('#hihat'); // エンベロープ(キック) let optsMembrane = { pitchDecay : 0.001, envelope : { attack : 0.001 , decay : 1.5 , sustain : 0.01 , release : 0.01 }, volume: 25 } // エンベロープ(スネア) let optsNoiseSnare = { envelope : { attack : 0.001 , decay : 0.7 , sustain : 0 } } // エンベロープ(ハイハット) let optsNoiseHihat = { type : "brown", envelope : { attack : 0.001 , decay : 0.03 , sustain : 0 } } //シンセ生成 const membrane = new Tone.MembraneSynth(optsMembrane).toMaster(); const noise1 = new Tone.NoiseSynth(optsNoiseSnare).toMaster(); const noise2 = new Tone.NoiseSynth(optsNoiseHihat).toMaster(); kick.addEventListener('click', () => { membrane.triggerAttackRelease('C0','2n'); }, false); snare.addEventListener('click', () => { noise1.triggerAttackRelease('8n'); }, false); hihat.addEventListener('click', () => { noise2.triggerAttackRelease('32n'); }, false);
キックのエンベロープ
まずキック音のエンベロープ
// エンベロープ(キック) let optsMembrane = { pitchDecay : 0.001, envelope : { attack : 0.001 , decay : 1.5 , sustain : 0.01 , release : 0.01 }, volume: 25 }
- 変数
optsMembrane
に連想配列でパラメータ設定 pitchDecay
を0.001
にenvelope
の値は連想配列でattack
、decay
、sustain
、release
がある。attack
を0.001
、decay
を1.5
、sustain
を0.01
、release
を0.01
にするvolume
を25に
この項目はキック音に使っている「Tone.MembraneSynth」のオプション値を打ち替えている。
※参考:MembraneSynth
pitchDecay
は
The amount of time the frequency envelope takes.
訳「周波数エンベロープにかかる時間」
エンベロープは実際にCodePenで音を鳴らしながらいろいろ打ち替えてみたが、特にattack
だけは0
だと音がならない仕様のようだったので0.001
にした。
また、キック音は他の音より音量がちょっと小さいと感じたのでvolume
も設定した。
この設定をシンセに適用するには…
const membrane = new Tone.MembraneSynth(optsMembrane).toMaster();
MembraneSynth()
の引数にoptsMembrane
を入れる。
スネア音のエンベロープ
同じようにスネア音のエンベロープを設定する。
// エンベロープ(スネア) let optsNoiseSnare = { envelope : { attack : 0.001 , decay : 0.7 , sustain : 0 } }
- 変数
optsNoiseSnare
に連想配列でパラメータ設定 envelope
の値は連想配列でattack
、decay
、sustain
がある。attack
を0.001
、decay
を0.7
、sustain
を0
にする
スネアは「NoiseSynth」の設定値を打ち替えた。(デフォルトでrelease
の設定がなかった)
※参考:https://tonejs.github.io/docs/13.8.25/NoiseSynth
decay
の音を伸ばしてみた。
この設定をシンセに適用。
const noise = new Tone.NoiseSynth(optsNoiseSnare).toMaster();
Tone.NoiseSynth()
の引数にoptsNoiseSnare
を入れる。
ハイハットのエンベロープ
前回ハイハットはMetalSynth()
にしていたが、今回、スネアと同じNoiseSynth()
にしてみる。
const noise1 = new Tone.NoiseSynth(optsNoiseSnare).toMaster(); const noise2 = new Tone.NoiseSynth().toMaster();
- スネアの
NoiseSynth()
の変数名をnoise1
とする - ハイハットのシンセも
NoiseSynth()
にして、変数名をnoise2
とする。
MetalSynth()
の「ピシー」という音はちょっとイメージと違ったため。また、こちらの記事でも触れたようにハイハットもノイズ シンセから作れそうなので、試してみたい。
※参考:【Tone.js】シンセでリズム音を作る方法を調べた - クモのようにコツコツと
ハイハットのエンベロープ設定
// エンベロープ(ハイハット) let optsNoiseHihat = { type : "brown", envelope : { attack : 0.001 , decay : 0.03 , sustain : 0 } }
- 変数
optsNoiseHihat
に連想配列でパラメータ設定 type
をbrown
にenvelope
の値は連想配列でattack
、decay
、sustain
がある。attack
を0.001
、decay
を0.03
、sustain
を0
にする
スネアと同じく「NoiseSynth」のオプションを打ち替えている。
※参考:https://tonejs.github.io/docs/13.8.25/NoiseSynth
ノイズのタイプはデフォルトはwhite
だが他にpink
とbrown
があるようだ。
the noise type (white pink brown)
※参考:Noise
試しにbrown
に変えてみたが、正直、そんなに違いは感じなかったw
ハイハットよりもdecay
は縮めて0.03
にしてみた。
最後に、この設定をシンセに適用する。
const noise2 = new Tone.NoiseSynth(optsNoiseHihat).toMaster();
先程作ったnoise2
のNoiseSynth()
の引数にoptsNoiseHihat
を入れる。
これで音の長さが変わった!
エフェクトをかける
エフェクト適用後のドラムパッド
以前のこちらの記事でエンベロープの他にリバーブ(残響音)のエフェクトをかけたが、同様にリズムパッドでもエフェクトをかけられるか試す。
※参考:【Tone.js】メロディ再生、シンセ音源加工、エフェクター接続(マリオを打ち込んだ!) - クモのようにコツコツと
やってみたものこちら。
See the Pen tone.js-Drum Pad-3 by イイダリョウ (@i_ryo) on CodePen.
三つの音色が少し変わった!それぞれに以下のエフェクトをかけている。
- キック音にピッチシフトをかけて音の高さを下げる
- スネア音にリバーブをかけて反響を増やす
- ハイハットにディレイをかけて山彦のように繰り返す
//DOM const kick = document.querySelector('#kick'); const snare = document.querySelector('#snare'); const hihat = document.querySelector('#hihat'); // エンベロープ(キック) let optsMembrane = { pitchDecay : 0.001, envelope : { attack : 0.001 , decay : 1.5 , sustain : 0.01 , release : 0.01 }, volume: 25 } // エンベロープ(スネア) let optsNoiseSnare = { envelope : { attack : 0.001 , decay : 0.7 , sustain : 0 } } // エンベロープ(ハイハット) let optsNoiseHihat = { type : "pink", envelope : { attack : 0.001 , decay : 0.03 , sustain : 0 } } //シンセ生成 const membrane = new Tone.MembraneSynth(optsMembrane).toMaster(); const noise1 = new Tone.NoiseSynth(optsNoiseSnare).toMaster(); const noise2 = new Tone.NoiseSynth(optsNoiseHihat).toMaster(); // エフェクト(ピッチシフト) const pitchShift = new Tone.PitchShift().toMaster(); pitchShift.pitch = -3; pitchShift.windowSize = 0.1; membrane.connect(pitchShift); // エフェクト(リバーブ) const reverb = new Tone.Freeverb(0.6,500).toMaster(); noise1.connect(reverb); // エフェクト(ディレイ) const delay = new Tone.Delay(0.02).toMaster(); noise2.connect(delay); kick.addEventListener('click', () => { membrane.triggerAttackRelease('C0','2n'); }, false); snare.addEventListener('click', () => { noise1.triggerAttackRelease('8n'); }, false); hihat.addEventListener('click', () => { noise2.triggerAttackRelease('32n'); }, false);
キック音のピッチを下げる(PitchShift())
まず最初にやってみたのはキック音のピッチ音を下げること。
キック音を下げたいな、と思ったが前回、triggerAttackRelease()
でC0
と打っても変わらず
membrane.triggerAttackRelease('C0','2n');
※参考:【Tone.js】リズム系のシンセ音でドラムパッドを作った - クモのようにコツコツと
エフェクトにピッチシフトがあったので、これで下げてみる。
// エフェクト(ピッチシフト) const pitchShift = new Tone.PitchShift().toMaster(); pitchShift.pitch = -3; pitchShift.windowSize = 0.1; membrane.connect(pitchShift);
- 変数
pitchShift
でエフェクトPitchShift()
のインスタンス作成 pitchShift
のpitch
を-3
にpitchShift
のwindowSize
を0.1
にmembrane
のシンセにconnect()
でpitchShift
を繋げる
PitchShift()
の設定値はこちらを参照
※参考:PitchShift
pitch
の数値は半音階らしく12で1オクターブのようだ。
pitchShift.pitch = -12; //down one octave
pitchShift.pitch = 7; //up a fifth
今回は-3
にした。
windowSize
というのはピッチを極端に変えた時の不自然な感じを調整する処理っぽい。
The window size corresponds roughly to the sample length in a looping sampler. Smaller values are desirable for a less noticeable delay time of the pitch shifted signal, but larger values will result in smoother pitch shifting for larger intervals. A nominal range of 0.03 to 0.1 is recommended.
ウィンドウサイズは、ループサンプラーのサンプル長にほぼ対応します。 ピッチシフトされた信号の遅延時間を目立たなくするためには、値が小さいほど望ましいですが、値が大きいほど、間隔が広い場合のピッチシフトがスムーズになります。 0.03〜0.1の公称範囲をお勧めします。
今回は試しに入れてみた感じ。
最後にシンセ音に.connect()
メソッドでエフェクトを繋げる。
スネア音にリバーブをかける(Freeverb())
次にスネアにリバーブをかけてみる。
// エフェクト(リバーブ) const reverb = new Tone.Freeverb(0.6,500).toMaster(); noise1.connect(reverb);
- 変数
reverb
でエフェクトFreeverb()
のインスタンス作成。 Freeverb()
の第一引数は部屋の大きさ[ roomSize ]、第二引数は湿気[ dampening ]noise1
のシンセにconnect()
でreverb
を繋げる
これは以前の記事と同じエフェクト。お風呂や教会のように反響させる「空間系」のエフェクト。
※参考:【Tone.js】メロディ再生、シンセ音源加工、エフェクター接続(マリオを打ち込んだ!) - クモのようにコツコツと
Freeverb()
のオプション値についてはこちらも参照。
※参考:Freeverb
これで少しスネアの音に響きが加わった感じになった。
ハイハットにディレイをかける(Delay())
最後、ハイハットにも何かかけてみる。もう一つの「空間系」のエフェクト、ディレイをかけてみる。ディレイは山彦のように音を繰り返す。
// エフェクト(ディレイ) const delay = new Tone.Delay(0.02).toMaster(); noise2.connect(delay);
- 変数
delay
でエフェクトDelay()
のインスタンス作成。 Delay()
の引数は遅延時間[ delayTime ]noise2
のシンセにconnect()
でdelay
を繋げる
書き方はリバーブとほとんど一緒だな。
delayTime
は「遅延時間」
The amount of time the incoming signal is delayed.
着信信号が遅延する時間。
これが長いほど時間差が広がる。今回はわずかに遅れて鳴るようにした。
(第二引数に最大遅延時間[ maxDelay ]があったが、こちらの値は変更できないらしいので無視)
※参考:Delay
最後に
今回は、過去のメロディ打ち込みの時にやったエンベロープやエフェクト設定をドラムパッドに組み合わせる感じだったけど、これによってエンベロープとエフェクトの書き方、シンセ音への繋げ方の理解が進みました!
次回からはリズム音の打ち込みをやってみたいと思います。最終的にドラムマシンみたいなのを作れたらいいなと。それではまた!
※参考:Tone.jsを習得するためにやった事まとめ
qiita.com