テンポとオクターブの処理を追加する
続いて、オクターブとテンポの処理を追加します。MMLではオクターブは「O2」、テンポは「T50」のようにそれぞれ指定します。ここまでに作ったプログラムと異なり、オクターブやテンポを処理したら次のMMLデータを解析しなければなりません。そこで、while(true){...}としてMMLの解析を無限に繰り返し実行し、オクターブやテンポの処理が済んだらcontinueで解析を継続します。
if (onkai == "O") { // オクターブ指定 octave = num; ptr++; continue; } if (onkai == "T") { // テンポ指定 tempo = num; ptr++; continue; }
オクターブやテンポ以外、つまり通常の音階であれば無限に解析する必要はないので、ループの最後でbreakを使ってループから抜けます。オクターブとテンポの処理を追加したのがサンプル3です。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>MMLを使って演奏する3</title> </head> <body> <h1>MMLを使って演奏する3</h1> <form> <input type="button" value="演奏" onclick="initMML()" /><br /> <textarea cols="20" rows="5" id="track1">T50 O4 C4 D4 E4 F4 G4 A4 B4 O2 C4</textarea> </form> <script type="text/javascript"> var freq = []; // 音階に応じた周波数を入れる配列 freq["R"] = 1; freq["C"] = 261; freq["D"] = 293; freq["E"] = 329; freq["F"] = 349; freq["G"] = 392; freq["A"] = 440; freq["B"] = 493; freq["#C"] = 277; freq["#D"] = 311; freq["#F"] = 370; freq["#G"] = 415; freq["#A"] = 466; for(i in freq) { freq[i] = freq[i] * 4; } // 演奏前の初期化を行う function initMML(){ octave = 4; // オクターブ設定(グローバル変数) tempo = 60; // テンポ設定(グローバル変数) ptr = 0; // 読み出し位置を初期化(グローバル変数) playMML(); } // 再生処理 function playMML(){ var data = document.getElementById("track1").value; var MML = data.split(" "); // 空白 while(true){ if (ptr >= MML.length) return; // 最後まで演奏が終わっていたら以後の処理はしない var sdata = MML[ptr]; var onkai = sdata.match(/[a-z]+/i)[0].toUpperCase(); if (sdata.charAt(0) == "#") { onkai = "#"+onkai; } var num = sdata.match(/\d+/); if (onkai == "O") { // オクターブ指定 octave = num; ptr++; continue; } if (onkai == "T") { // テンポ指定 tempo = num; ptr++; continue; } break; } var sec = (60 / tempo) / num; // 音長を計算 startAudio(freq[onkai]/octave, sec); } // 指定された周波数の音を指定時間出力する function startAudio(freq, sec){ var sampleRate = 44100; // 44.1kHz var audio = new Audio(); audio.mozSetup(1, sampleRate); // 1ch, 44kHz var bufferSize = Math.ceil(sampleRate * sec); // 再生秒数 var data = new Float32Array(bufferSize); var k = 2* Math.PI * freq / sampleRate; for(var i=0; i<data.length; i++){ data[i] = Math.sin(k * i); } audio.mozWriteAudio(data); setTimeout("ptr++;playMML()", sec*1000); audio.play(); } </script> </body> </html>