3

マイクからのオーディオ入力を視覚化するために、Web オーディオ API と requestAnimationFrame を使用しています。時間領域の周波数データを正常に視覚化できますが、問題は、Web オーディオ API が時間を秒単位で計算するため、入力内容に応じてインターフェイスが 1 秒ごとに変化することです。

だから私の質問は、どのように音を視覚化し、グラフを画面上にとどめることができるかということです.

私は次のコードを使用しています (こちらの例から取得):

MicrophoneSample.prototype.visualize = function() {
  this.canvas.width = this.WIDTH;
  this.canvas.height = this.HEIGHT;
  var drawContext = this.canvas.getContext('2d');

  var times = new Uint8Array(this.analyser.frequencyBinCount);
  this.analyser.getByteTimeDomainData(times);
  for (var i = 0; i < times.length; i++) {
    var value = times[i];
    var percent = value / 256;
    var height = this.HEIGHT * percent;
    var offset = this.HEIGHT - height - 1;
    var barWidth = this.WIDTH/times.length;
    drawContext.fillStyle = 'purple';
    drawContext.fillRect(i * barWidth, offset, 1, 1);

  }
  requestAnimFrame(this.visualize.bind(this));

}
4

2 に答える 2

2

getByteTimeDomainData は頻度情報を提供しません。これらは、振幅値とも呼ばれるリアルタイムの時間領域波形値です。それらを経時的に視覚化したい場合は、値を配列に追加して描画します。実際の周波数値が必要な場合は、getByteFrequencyData を使用します。

于 2013-03-28T09:46:09.650 に答える
2

OP、ここにいくつかの擬似コードがあります。参考までに、これは Web オーディオに関する質問ではなく、アニメーションに関する質問です。

キャンバスの再描画を何秒遅らせるかを追跡するビジュアライザーのプロトタイプ関数に変数/フィールドを保存し、 requestAnimFrame(...) が描画されるたびにインクリメントする別のカウンターを保持します。カウンターが遅延量に達したら、キャンバスを再描画します。

編集 今考えてみると...解決策は非常に単純なはずです。間違っている場合は訂正してください。ただし、この大まかな解決策は、アニメーション ループ内から MicrophoneSample.visualize() を呼び出していることを前提としているため、コードは毎秒実行されます。MicrophoneSample オブジェクト コード、または少なくともアニメーション ループも投稿していただければ、さらにお役に立ちます。

/* NOTE!
*
*/
// Find a way to put these into your PARENT MicrophoneSample object
var delay = 5;
// Note that I am setting delayCount initially to zero - during the loop
// the delayCount will actually get reset to 1 from thereafter (not 0)...
// this gives us a way to initially draw your visualization on the first frame.
var delayCount = 0;

// Pull var times out so it doesn't get calculated each time.
var times = new Uint8Array(MicrophoneSample.analyser.frequencyBinCount);

// Same goes for the canvas...
// I would set these values inside of the PARENT MicrophoneSample object
MicrophoneSample.canvas.width = this.WIDTH;
MicrophoneSample.canvas.height = this.HEIGHT;

// you only need to establish the drawing context once. Do it in the PARENT
// MicrophoneSample object
var drawContext = this.canvas.getContext('2d');

MicrophoneSample.prototype.visualize = function() {

      /*
      *    NOTE!
      */
      // Here's the juicy meat & potatoes:
      // only if the delayCount reaches the delay amount, should you UPDATE THE
      // TIME DOMAIN DATA ARRAY (times)
      // if your loop runs every second, then delayCount increments each second
      // and after 5 seconds will reach your designated delay amount and update your
      // times array.

      if(delayCount == 0 || delayCount == delay) {
          this.analyser.getByteTimeDomainData(times);

          // Now, it would be redundant (and totally noob-programmer of you) to 
          // redraw the same visualization onto the canvas 5 times in a row, so
          // only draw the visualization after the first pass through the loop and then
          // every 5th pass after that :]
          for (var i = 0; i < times.length; i++) {
              var value = times[i];
              var percent = value / 256;
              var height = this.HEIGHT * percent;
              var offset = this.HEIGHT - height - 1;
              var barWidth = this.WIDTH/times.length;
              drawContext.fillStyle = 'purple';
              drawContext.fillRect(i * barWidth, offset, 1, 1);
          }

          // Note: 1, not 0!
          delayCount = 1;
      } 
      else {
          delayCount++;
      } 


      requestAnimFrame(this.visualize.bind(this));
}

そして、私は実際にこれをテストしていないことに注意してください. しかし、少なくとも正しい方向に向ける必要があります。

于 2013-03-28T19:28:42.823 に答える