实时处理web音频api

问题描述:

我正在使用web音频api和requestAnimationFrame来显示来自麦克风的音频输入。我可以成功地将时域频率数据可视化,但问题是,由于网络音频API会以秒为单位计算时间,因此每隔一秒,我的界面就会根据输入的内容而变化。实时处理web音频api

所以我的问题是,我如何可视化声音并使图形保持在屏幕上,因此我可以在一定的时间内看到我的所有频率数据(假设我说话,同时在画布上可视化为5秒)。

我使用下面的代码(从花例子here):

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)); 

} 
+0

Rq:调整画布大小/获取每次调用的上下文是一个矫枉过正的做法:做一次并存储ctx。是否需要将声源连接到分析仪以获取频率? – GameAlchemist 2013-03-28 09:52:45

+0

输入已连接到分析仪,我也可以获取波形值可以提取或其他声音属性。主要问题是如何让他们的居民可视化? – user2039789 2013-03-28 10:07:37

getByteTimeDomainData不给你的频率信息。这些是实时的时域波形值,也称为幅度值。如果你想随着时间的推移想象它们,将它们的值附加到数组中并绘制。如果你想要真正的频率值使用getByteFrequencyData。

+0

如果getByteTimeDomainData允许创建一个有用的波形。这些例子已经将输入可视化了,但正如我所说的每秒图表消失。我怎样才能让它留在那里? – user2039789 2013-03-28 09:54:19

+1

正如我所说:将times [i]数据推送到另一个数组中,该数组存储在MicrophoneSample类中并绘制该数组。 – headchant 2013-03-28 10:33:29

+0

沿着这个线:http://jsfiddle.net/ez6R6/1/ – headchant 2013-03-28 10:46:06

OP,这是一些伪代码。仅供参考,这真的不是一个网络音频问题,更像是一个动画问题。

在您的可视化器原型函数中存储一个变量/字段,用于跟踪您想要延迟画布重绘的秒数,保留一个单独的计数器,每次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)); 
} 

只是要记住,我没有真正测试过这些。但它至少应该指向正确的方向。

+0

我试图用你的伪代码来实现一个解决方案,但没有成功。不知道是否是因为我的编程技巧或... 你能在这里或在PM中写更详细的代码吗?谢谢哥们:))) – user2039789 2013-04-01 10:23:44

+0

好吧,只是为了确保,你知道伪代码不是从字面上理解的吗?只是为了让首先和最重要的:] – 2013-04-01 10:48:14

+0

有你去。去拿他们。 – 2013-04-01 11:25:26