Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 实时处理web音频api_Javascript_Html5 Canvas_Html5 Audio_Web Audio Api - Fatal编程技术网

Javascript 实时处理web音频api

Javascript 实时处理web音频api,javascript,html5-canvas,html5-audio,web-audio-api,Javascript,Html5 Canvas,Html5 Audio,Web Audio Api,我正在使用web音频api和requestAnimationFrame来可视化麦克风的音频输入。我可以成功地可视化时域频率数据,但问题是,由于web audio api以秒为单位计算时间,因此每秒钟我的界面都会根据输入内容而改变 所以我的问题是,我如何可视化声音并使图形停留在屏幕上,这样我就可以在一定的时间限制内看到我所有的频率数据(比如说我说话,同时在画布上可视化5秒钟) 我正在使用以下代码(摘自示例): MicrophoneSample.prototype.visualize=functio

我正在使用web音频api和requestAnimationFrame来可视化麦克风的音频输入。我可以成功地可视化时域频率数据,但问题是,由于web audio api以秒为单位计算时间,因此每秒钟我的界面都会根据输入内容而改变

所以我的问题是,我如何可视化声音并使图形停留在屏幕上,这样我就可以在一定的时间限制内看到我所有的频率数据(比如说我说话,同时在画布上可视化5秒钟)

我正在使用以下代码(摘自示例):

MicrophoneSample.prototype.visualize=function(){
this.canvas.width=this.width;
this.canvas.height=this.height;
var drawContext=this.canvas.getContext('2d');
var时间=新的UINT8阵列(此分析仪频率BINCOUNT);
此.analyzer.getByteTimeDomainData(次);
对于(var i=0;i
getByteTimeDomainData不提供频率信息。这些是实时的时域波形值,也称为振幅值。如果要随时间可视化这些值,请将其附加到数组中并绘制该数组。如果需要真实频率值,请使用getByteFrequencyData。

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

在visualizer prototype函数中存储一个变量/字段,用于跟踪要延迟画布重画的秒数,保留一个单独的计数器,该计数器将在每次绘制requestAnimFrame(…)时递增。一旦计数器达到延迟量,则重新绘制画布

编辑 现在我想起来了…解决方案应该很简单。如果我错了,请纠正我,但这个粗略的解决方案是假设您正在从动画循环中调用microhonesample.visualize(),因此,其中的代码每秒执行一次。如果您也发布麦克风示例对象代码,或者至少发布动画循环,我可以提供更多帮助

/* 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));
}
/*注意!
*
*/
//找到一种方法将它们放入父microhoneSample对象中
var延迟=5;
//请注意,在循环过程中,我最初将delayCount设置为零
//delayCount将从之后实际重置为1(而不是0)。。。
//这为我们提供了一种在第一帧上最初绘制可视化效果的方法。
var-delayCount=0;
//拉出var超时,这样就不会每次都计算它。
var时间=新UINT8阵列(麦克风采样、分析仪、频率BINcount);
//画布也是如此。。。
//我将在父MicrophoneSample对象内设置这些值
MicrophoneSample.canvas.width=this.width;
microhonesample.canvas.height=this.height;
//只需建立一次图形上下文。在家长那里做
//麦克风采样对象
var drawContext=this.canvas.getContext('2d');
MicrophoneSample.prototype.visualize=函数(){
/*
*注意!
*/
//这是多汁的肉和土豆:
//仅当delayCount达到延迟量时,才应更新
//时域数据阵列(次)
//如果循环每秒运行一次,则delayCount每秒递增
//5秒后将达到您指定的延迟量并更新您的
//时间数组。
如果(delayCount==0 | | delayCount==delay){
此.analyzer.getByteTimeDomainData(次);
//现在,这将是多余的(完全是你的noob程序员)
//连续5次在画布上重新绘制相同的可视化效果,因此
//仅在第一次通过循环后绘制可视化,然后
//此后每隔5次通过:]
对于(var i=0;i

请记住,我还没有真正测试过这些。但它至少应该为您指明正确的方向。

Rq:调整画布的大小/获取每次调用的上下文是一种过分的做法:只做一次,然后存储ctx。难道不需要将声源连接到分析仪以获取频率吗?输入已经连接到分析仪,我还可以获取波形值或其他声音属性。主要问题是如何使它们的可视化常驻?如果getByteTimeDomainData能够创建一个波形,这也很有帮助。这个示例已经可视化了输入,但正如我所说的,每一秒图形都会消失。我怎样才能让它留在那里呢?正如我所说的:将times[I]数据推送到另一个存储在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));
}