最初の1音だけを処理する
最初に、音階を処理するプログラムを作ります。音の周波数は前回のピアノ演奏のプログラムと同様にfreq配列に入れ、音を生成して出力する処理は関数startAudio()に再生秒数を指定できるようにして流用しています。startAudio()関数内の処理については前回の記事を参照してください。
演奏するMMLはHTMLの入力フォームのテキストエリアに入力します。テキストエリアにはID名を割り当てておき、JavaScriptから以下のようにして内容を読み出します。
var data = document.getElementById("track1").value;
読み出した内容(MML)は半角空白で区切られているので、split()を使って分割し、1音ずつ配列データに格納します。
var MML = data.split(" "); // 空白
次に、配列に格納したデータを1音ごとに処理していきます。まず、最初の1音だけ処理してみましょう。最初の1音は以下のようにして取り出せます。
var sdata = MML[0];
sdataには「C4」や「#A16」といった文字列が入っているので、取り出した後に音階と音長に分解します。音階は正規表現を使って以下のように指定します。
var onkai = sdata.match(/[a-z]+/i)[0].toUpperCase();
これで変数onkaiに「C」や「#A」といった音階だけが入ります。同様に正規表現を使って今度は音長を取り出します。
var num = sdata.match(/\d+/);
音階には#が付いている場合があるので、sdataに#が含まれている場合は変数onkaiに#を付けます。
if (sdata.charAt(0) == "#") { onkai = "#"+onkai; }
以上で音階と音長が求められました。音長にはテンポも関係してくるので、実際に演奏する秒数を以下のようにして求めます。
var sec = (60 / tempo) / num;
あとはstartAudio()関数を呼び出すとMMLで指定した最初の音が再生されます。
startAudio(freq[onkai], sec);
実際のプログラムはサンプル1です。演奏ボタンをクリックするとテキストエリアに入力されたMMLが処理されて指定した音が出力されます。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>MMLを使って演奏する1</title> </head> <body> <h1>MMLを使って演奏する1</h1> <form> <input type="button" value="演奏" onclick="playMML()" /><br /> <textarea cols="20" rows="5" id="track1">A4</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; var tempo = 60; // テンポ設定(グローバル変数) var ptr = 0; // 読み出し位置(グローバル変数) // 再生処理 function playMML(){ var data = document.getElementById("track1").value; var MML = data.split(" "); // 空白 var sdata = MML[ptr]; var onkai = sdata.match(/[a-z]+/i)[0].toUpperCase(); var num = sdata.match(/\d+/); if (sdata.charAt(0) == "#") { onkai = "#"+onkai; } var sec = (60 / tempo) / num; // 音長を計算 startAudio(freq[onkai], 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); audio.play(); } </script> </body> </html>