実現したいこと
Web Audio API を用いて、時間経過に沿って一連の音階を発生させたいが
setInterval() などを使用することは望ましくないため
どうやって、一定の時刻に指定された音階の音を出させたらよいかが分からない
質問の内容 詳細
下記のコードの見本のような方法で、あらかじめ用意しておいた時系列データーの音階を再生させたい
困っている問題
Web Audio API では、指定された秒数のところで、予定どおりの音階を鳴らす設定になっている
ところが、javascript においては、指定された秒数になる前に、4つも 5つも先の音階のノード設定を待たずに実行してしまうため、
setTimeout() などの方法で、無限大の音階設定をいちいち指定しなければならないことになりそうで
LOOP を使う方法も思いつかない
下記の見本を参照してください
該当のソースコード
HTML
1<!DOCTYPE html> 2<html> 3<style> 4body { margin: 60px; } 5button, select { font-size: 20px; } 6</style> 7 8<body> 9<h1>Oscillator test 7</h1> 10<br/> 11<br/> 12<button onclick="Play200()"> 200--1000 Hz </button> 13<br/> 14<br/> 15<br/> 16<br/> 17 18<p>Freq(Hz) 19<span id="freqdisp">**</span> 20</p> 21 22 23<script> 24 25function ToneControl( f ) 26{ 27 osc.type = "Triangle" ; 28 osc.frequency.value = f-0 ; // REAL f 29 30 WriteFreq( f ) ; 31} 32function WriteFreq( f ) { document.getElementById("freqdisp").innerHTML = f ; 33} 34 35function Play200() 36{ 37 var audioctx = new AudioContext(); 38 var t0 = audioctx.currentTime; 39 40 osc = new OscillatorNode(audioctx); 41 osc.connect(audioctx.destination); 42 43 ToneControl(200) ; 44 45 osc.start(t0 + 1 ); 46 osc.stop (t0 + 1.5); // この行が実行されるのは、 47 // この行を読み込んでから 1.5秒後であるため 48 49 // これより下のコマンドが、上の行の実行開始前にどんどん読み込まれて 50 // 次々と先回りしたノードが生成されてしまうと思われるため 51 // 大量のデーター処理をする場合に、メモリー内部などで 52 // 相当な混乱が起きるのではないかと懸念される 53 54 osc = new OscillatorNode(audioctx); 55 osc.connect(audioctx.destination); 56 ToneControl(300) ; 57 58 osc.start(t0 + 2 ); 59 osc.stop (t0 + 2.5); 60 61 osc = new OscillatorNode(audioctx); 62 osc.connect(audioctx.destination); 63 ToneControl(400) ; 64 65 osc.start(t0 + 3 ); 66 osc.stop (t0 + 3.5); 67 68 69 osc = new OscillatorNode(audioctx); 70 osc.connect(audioctx.destination); 71 ToneControl(500) ; 72 73 osc.start(t0 + 4 ); 74 osc.stop (t0 + 4.5); 75 76 77 osc = new OscillatorNode(audioctx); 78 osc.connect(audioctx.destination); 79 ToneControl(600) ; 80 81 osc.start(t0 + 5 ); 82 osc.stop (t0 + 5.5); 83 84 osc = new OscillatorNode(audioctx); 85 osc.connect(audioctx.destination); 86 ToneControl(700) ; 87 88 osc.start(t0 + 6 ); 89 osc.stop (t0 + 6.5); 90 91 osc = new OscillatorNode(audioctx); 92 osc.connect(audioctx.destination); 93 ToneControl(800) ; 94 95 osc.start(t0 + 7 ); 96 osc.stop (t0 + 7.5); 97} 98 99</script> 100</body> 101</html> 102
参考資料
オシレーターのタイミング制御
https://www.g200kg.com/jp/docs/webaudio/generatesound.html
g200kg > Web Audio API 解説 > 03.オシレーターの使い方
実用的なものを作ろうとした場合、リズムがヨタらない演奏をするには
時刻を指定する事が推奨されます。
というのも
この時刻による制御によらないとすると Javascript の setInterval() などでタイミングを決める事になりますが、
これだと処理が重くなって発音が遅れたりすることが普通に起こります。