Tone.jsシリーズ、前回は3コード楽器のコードを拡張しやすいようにリファクタリングしました。今回は鍵盤を1オクターブ分に拡張しました。また、和音の一箇所を打ち替えるだけでメジャー調をマイナー調に変更することにも成功。それではどうぞ!
【目次】
※参考:【Tone.js】3コード楽器のコードをリファクタリング(ループとイベントと即時関数) - クモのようにコツコツと
前回のおさらい(3コード)はこちら
前回の3コード
See the Pen tone.js-3cord-6 by イイダリョウ (@i_ryo) on CodePen.
コードの詳細は前回記事を参照。
※参考:【Tone.js】3コード楽器のコードをリファクタリング(ループとイベントと即時関数) - クモのようにコツコツと
これを1オクターブに拡張したい。
メジャースケール(1オクターブ)
試行錯誤して、鍵盤を1オクターブ分増やせた。
See the Pen tone.js-12cord-1 by イイダリョウ (@i_ryo) on CodePen.
以前作った1オクターブ鍵盤と同じ見た目だが、鍵盤を弾くとメジャースケールの和音が鳴る。
※参考:【tone.js】一音鍵盤を1オクターブに拡張したらコードが冗長だったので書き直した - クモのようにコツコツと
HTLMコード
<h1>和音</h1> <p>メジャー(1オクターブ)</p> <ul id="piano"> <li id="C4" class="w_key">ド</li> <li id="Cs4" class="b_key"></li> <li id="D4" class="w_key">レ</li> <li id="Ds4" class="b_key"></li> <li id="E4" class="w_key">ミ</li> <li id="F4" class="w_key">ファ</li> <li id="Fs4" class="b_key"></li> <li id="G4" class="w_key">ソ</li> <li id="Gs4" class="b_key"></li> <li id="A4" class="w_key">ラ</li> <li id="As4" class="b_key"></li> <li id="B4" class="w_key">シ</li> <li id="C5" class="w_key">ド</li> </ul>
HTMLは1オクターブ鍵盤の時とほどんど同じ。(省略するがCSSも同じ)
次、JSコード
まずDOMの取得。
//DOM var Key = document.querySelectorAll('#piano li');
3コードの時は鍵盤一つずつID名で取得したが今回はliタグをquerySelectorAll()
で配列として取得した。鍵盤が1オクターブの12音階(白鍵8+黒鍵4)に次のオクターブのドを加え全部で12個。この方法は1オクターブ鍵盤の時と同じ方法。
次に音階の設定。
//音階 var scale = [ //休符 'null', //1オクターブ目 'C4', 'C#4', 'D4', 'D#4', 'E4', 'F4', 'F#4', 'G4', 'G#4', 'A4', 'A#4', 'B4', //2オクターブ目 'C5', 'C#5', 'D5', 'D#5', 'E5', 'F5', 'F#5', 'G5', 'G#5', 'A5', 'A#5', 'B5'];
変数scale
に2オクターブ分の音階名を入れる。これの名前はTone.jsの正式名称でC4
の4
は一番低い音から4オクターブ目を意味する。ここは前回と変わらない。
この後に細々とした設定をしている。まずルート音(和音の一番低い音)。
//ルート音 var root = {C4: 0, Cs4: 1, D4: 2, Ds4: 3, E4: 4, F4: 5, Fs4: 6, G4: 7, Gs4: 8, A4: 9, As4: 10, B4: 11, C5: 12};
まず変数root
に連想配列で和音のルート音を設定。前回の12音階に加えてC5
キーを追加。
次にメジャースケールの音程を設定。
//メジャースケール var codeM =[1,5,8];
ルート音を1とすると第二音は5、第三音は8(前回と同じ設定)
変数twelveCode
の配列にルート音を登録。
//12コード var twelveCode =[root['C4'],root['Cs4'],root['D4'],root['Ds4'],root['E4'],root['F4'],root['Fs4'],root['G4'],root['Gs4'],root['A4'],root['As4'],root['B4'],root['C5']]
前回は3コードなので3つだったが今回は13個のルート音を全て登録。
変数chords
は和音入れ場。
//和音入れ場 var chords = [];
前回はここに3コードthreeCode
の配列の値を入れたが、よく考えたらここは空っぽの器にすればいいことがわかった。
次に和音を作る。
//和音 for (var i = 0 ; i < Key.length; i++ ) { chords.push( [] ); for (var j = 0; j < codeM.length; j++){ var nmb = scale[twelveCode[i]+codeM[j]]; chords[i].push(nmb); } }
- キーボード13個分の回数
length
を繰り返す。 - 先ほどの
chords
に空の配列をここで13個追加push
する。 - 入れ子のループで
codeM
の3和音分の回数length
を繰り返す。 - 変数
nmb
でscale
のi
番目に3和音のルート、第二音、第三音を入れる。 - 和音入れ場
chords
のi
番目にnmb
の音を追加する。
シンセ音を生成
//シンセ生成 var synth = new Tone.PolySynth().toMaster();
ここは前回通り
鍵盤を叩いたときのクリックイベント
//イベントリスナ for (var i = 0; i < Key.length; i++) { (function(i) { Key[i].addEventListener('click', function () { //メジャーコードが4分音符の長さ鳴る synth.triggerAttackRelease(chords[i], '4n'); }, false); })(i); }
- 13個分の回数
length
を繰り返す。 - キーボードの
i
番目をクリックした時に chords
のI
番目の音が鳴る
JSコードの全体
//DOM var Key = document.querySelectorAll('#piano li'); //音階 var scale = [ //休符 'null', //1オクターブ目 'C4', 'C#4', 'D4', 'D#4', 'E4', 'F4', 'F#4', 'G4', 'G#4', 'A4', 'A#4', 'B4', //2オクターブ目 'C5', 'C#5', 'D5', 'D#5', 'E5', 'F5', 'F#5', 'G5', 'G#5', 'A5', 'A#5', 'B5']; //ルート音 var root = {C4: 0, Cs4: 1, D4: 2, Ds4: 3, E4: 4, F4: 5, Fs4: 6, G4: 7, Gs4: 8, A4: 9, As4: 10, B4: 11, C5: 12}; //メジャースケール var codeM =[1,5,8]; //12コード var twelveCode =[root['C4'],root['Cs4'],root['D4'],root['Ds4'],root['E4'],root['F4'],root['Fs4'],root['G4'],root['Gs4'],root['A4'],root['As4'],root['B4'],root['C5']] //和音入れ場 var chords = []; //和音 for (var i = 0 ; i < Key.length; i++ ) { chords.push( [] ); for (var j = 0; j < codeM.length; j++){ var nmb = scale[twelveCode[i]+codeM[j]]; chords[i].push(nmb); } } //シンセ生成 var synth = new Tone.PolySynth().toMaster(); //イベントリスナ for (var i = 0; i < Key.length; i++) { (function(i) { Key[i].addEventListener('click', function () { //ID名取得 var idName = this.id; //3コードが8分音符の長さ鳴る synth.triggerAttackRelease(chords[i], '4n'); }, false); })(i); }
和音をマイナーに
和音部分を打ち替えるとマイナー調になった!哀愁を帯びてる。
See the Pen tone.js-12cord-2 by イイダリョウ (@i_ryo) on CodePen.
変えた場所は1箇所!
//マイナースケール var codeM =[1,4,8];
変数codeM
の配列の2番目を5
から4
にしただけ!和音の第二音が半音下がる。
最後に
四苦八苦しながらなんとか作れました。ルート音root
の連想配列を12コードtwelveCode
の配列に登録するあたり、もう少し簡略化できたらなーと思います。普段あまり使わないけど、for...in
とか配列系のfor文がいくつかあるようなので、それを使うと簡略化できるかもしれない。成功したら記事にします。
和音を1箇所うち変えたらメジャー調がマイナー調になりました!この意気でセブンスとかナインスとかいろんな和音を作っていきたい。できればそれをボタンで一発で切り替えるところまで行きたいです。あとはアルペジオ(分散和音)など伴奏メロディに切り替えたり、シンセ音を切り替えたり。
やりたいことは果てしなく有りますが、引き続きコツコツと継続。それではまた!
※参考:Tone.jsを習得するためにやった事まとめ qiita.com