Tone.jsの続きです。前回はメロディ再生、シンセ音源加工、エフェクター接続を行いました。マリオの地上面メロディを打ち込みました。今回は「Tone.Part()
」とうメソッドを使ってもう少し細かくメロディのタイミング、長さ、音量を調節しました。マリオのゲームオーバー音の三連符を再現♪それではいきましょう!
【目次】
今回作ったものはこちら。マリオのゲームオーバー音。
See the Pen Mario TheEnd 03 by イイダリョウ (@i_ryo) on CodePen.
「Play」を押すと音が鳴り「Stop」を押すと止まる。前回よりもメロディを細かく制御できている。
※前回:【Tone.js】メロディ再生、シンセ音源加工、エフェクター接続(マリオを打ち込んだ!) - クモのようにコツコツと
Tone.Sequence()だとメロディのリズムが一定になる
前回、メロディの打ち込みで活躍したTone.Sequence()
。こちらは直感的に打ち込めるメリットがある反面、リズムが一定になってしまうのが難点。例えばTone.Sequence()
でマリオのゲームオーバーと打ち込むとこうなる。
See the Pen Mario TheEnd 01 by イイダリョウ (@i_ryo) on CodePen.
「ターラーラー、ターラーラー♪」と三連符にしたいところが「タッタラ、タッタラ」とやけに歯切れの良いシンコペーションになってあまりガッカリ感がないw。最後の「タララー〜♪」と伸ばしたいところも「タララッ」と途切れてしまい、随分あっさりした印象。。
メロディ部分はこちら。
//メロディ const melodyLine = [ 'c5',null, null,'G4', null, null,'E4', null, 'A4', null,'B4','A4', 'G#4',null, 'A#4', 'G#4', 'G4', 'F#4','G4', null, null, null, null, null ]
nullが休符になる。
再生ボタンのイベント
//再生ボタン play.addEventListener("click", function () { //ボタン表示切替 play.style.display = "none"; stop.style.display = "block"; //音源 const synth = new Tone.AMSynth().toMaster(); //8分音符で再生 function setPlay(time, note) { synth.triggerAttackRelease(note,'8n', time); } //メロディをセット const melody = new Tone.Sequence(setPlay, melodyLine); //メロディ再生 melody.start(); //ループ回数 //melody.loop = 0; //テンポ Tone.Transport.bpm.value = 400; //再生実行 Tone.Transport.start(); }, false);
- DOM
play
のクリックイベント play
ボタンの非表示、stop
ボタンの表示- 音源設定(
Tone.AMSynth()
に変えてみた) - 関数
setplay()
で再生設定synth.triggerAttackRelease()
、8分音符8n
の長さ - 変数
melody
でメロディセットTone..Sequence()
。setplay()
の8分音符でmelodyLine
のメロディ。 melody
の再生start()
melody
のループ回数は指定しない(無限ループ)- テンポ
Transport.bpm.value
を400
に - 再生を実行
Transport.start()
停止ボタンのコードはいじってない。前回参照。
※参考:【Tone.js】メロディ再生、シンセ音源加工、エフェクター接続(マリオを打ち込んだ!) - クモのようにコツコツと
Tone.Part()でメロディのタイミングを調節
Tone.Sequence()
をTone.Part()
に変更することでもっと厳密にメロディのタイミングを調節できた。
See the Pen Mario TheEnd 02 by イイダリョウ (@i_ryo) on CodePen.
//メロディ const melodyLine = [ ['0:0:0','c5'], ['0:3:0','G4'], ['1:2:0','E4'], ['2:0:0','A4'], ['2:1.5:0','B4'], ['2:2.8:0','A4'], ['3:0.2:0','G#4'], ['3:1.6:0','A#4'], ['3:2.8:0','G#4'], ['4:0:0','G4'], ['4:0.75:0','F#4'], ['4:1.25:0','G4'] ];
- 先ほどのメロディは全体が一つの配列になっていたが、今回は配列の中にさらに配列が入れ子になっている。
- 入れ子の配列には値が2つずつ入っている。
- 1つ目の値がタイミング(
小節:拍:半拍
)、2つ目の値が音程。
Tone.Part()
は何小節目の何拍目と細かくタイミングを指定できたため、休符null
の指定は不要になった。「小節」が0→1→2→3→4と進んでいるのがわかると思う。また、2番目の「拍」が小数点で細かく指定できたため、今回は3番目の「半拍」の指定は使わなかった。
次、再生ボタンの変えたところ
//(前略) //メロディをセット const melody = new Tone.Part(setPlay, melodyLine); //(中略) //ループ(デフォルトでfalse) melody.loop = true; melody.loopStart = "0"; melody.loopEnd = "16"; //(後略)
- メロディセットのところ、
Tone.Sequence()
をTone.Part()
に変更 - ループを
true
に設定。(デフォルトはfalse
だった) - ループの開始位置
loopStart
、終了位置loopEnd
も細かく設定(デフォルトのloopEnd
は1秒1m
だった)
※参考:Part
なお、loopStart
とloopEnd
の値は、単位無しだと拍数、単位m
は秒数になった。
さて、これでもだいぶ自由度は上がったが、欲をいえば音符の長さも一音ずつ変えたくなる。
連想配列でさらに音の長さ、音量も調整する
メロディの中を連想配列(キーと値)にすることでさらに細かい調整(音の長さ、音量)もできた!
See the Pen Mario TheEnd 03 by イイダリョウ (@i_ryo) on CodePen.
変更したメロディ部分
//メロディ const melodyLine = [ {'time': '0:0:0', 'note': 'c5', 'duration': ' 16n','velocity': 1}, {'time': '0:3:0', "note": 'G4', 'duration': '16n','velocity': 0.75}, {'time': '1:2:0', "note": 'E4', 'duration': '16n','velocity': 0.5}, {'time': '2:0:0', "note": 'A4', 'duration': '4n','velocity': 0.75}, {'time': '2:1.5:0', "note": 'B4', 'duration': '4n','velocity': 1}, {'time': '2:2.8:0', "note": 'A4', 'duration': '4n','velocity': 0.75}, {'time': '3:0.2:0', "note": 'G#4', 'duration': '4n','velocity': 0.5}, {'time': '3:1.6:0', "note": 'A#4', 'duration': '4n','velocity': 0.75}, {'time': '3:2.8:0', "note": 'G#4', 'duration': '4n','velocity': 0.5}, {'time': '4:0:0', "note": 'G4', 'duration': '16n','velocity': 1}, {'time': '4:0.75:0', "note": 'F#4', 'duration': '16n','velocity': 0.5}, {'time': '4:1.25:0', "note": 'G4', 'duration': '1n','velocity': 0.75}, ];
- 配列の中の入れ子を連想配列(キーと値)にする。キーは4種類入れている。
time
キーはタイミング、note
キーは音程、duration
キーは長さ、velocity
は音量
time
とnote
は先ほどの値と変わらない。duration
は16n
は十六分音符、4n
は四分音符、1n
は全音符。velocity
は1
を基準に小さい音を0.5
などにしてみた。鍵盤を弾く指の強さをイメージしてみた。
ちなみに音の長さduration
は公式リファレンスでは見当たらなかったのだが、こちらの記事で実現されていた!多謝!!
※参考:Tone.jsを使用した複雑な音階の再生、和音を伴うメロディの作成 │ よねぴ
再生ボタンの変えたところ
//(前略) //再生設定 //function setPlay(time, note) { synth.triggerAttackRelease(note,'8n', time); function setPlay(time, note) { synth.triggerAttackRelease(note.note, note.duration, time, note.velocity);} //(後略)
- 関数
setPlay()
のsynth.triggerAttackRelease()
の引数をnote.note
、note.duration
、time
、note.velocity
の4つに
音程note
はnote.note
とこまかいプロパティを指定しており、音の長さ8n
はnote.duration
にしている。また、音量のnote.velocity
も追加されている。
最後に
前回よりも細かいメロディを打ち込むことができました!そしてそして、Tone.Part()
はなんと、メロディだけでなく和音も再生できそうです!次回は和音の再生に取り組みたく。それではまた!!
※参考:Tone.jsを習得するためにやった事まとめ qiita.com