3

我之前已经成功使用 Web Audio API 中的JavaScriptAudioNode在 Chrome 和 Safari 6.0 中合成和混合音频。但是,最新版本的 Safari 似乎不再工作,因为它不调用onaudioprocess来填充源缓冲区。

这是一个简化的示例,它只播放静音并在每次调用onaudioprocess时将文本附加到文档正文:

<html>
<head>  
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script type="text/javascript">    
$(document).ready(function() {
  $("a").click(function() {    
    var context = new webkitAudioContext(); 
    var mixerNode=context.createJavaScriptNode(2048, 0, 2);                

    mixerNode.onaudioprocess=function(ape) {                     
      var buffer=ape.outputBuffer;
      for(var s=0;s<buffer.length;s++)
      {  
        buffer.getChannelData(0)[s]=0;      
        buffer.getChannelData(1)[s]=0;       
      }
      $("body").append("buffering<br/>");
    };               

    $("body").html("");               
    mixerNode.connect(context.destination);               
    return false;
  });                                                          
});                         
</script>    
</head>  
<body>  
<a href="#">start</a>        
</body>  
</html>

上面的示例在 Chrome 中按预期工作,但在桌面 Safari 中不起作用。iOS 版本的 Safari 也不起作用,但它一开始就对我不起作用。

调用context.createJavaScriptNode确实会返回类型为JavaScriptAudioNode的正确对象,并且将其连接到目标节点不会引发任何异常。context.activeSourceCount保持为零,但在 Chrome 中也是如此,因为它显然只计算AudioBufferSourceNode类型的活动节点。context.currentTime也按预期递增。

我在这里做错了什么还是这是一个实际的错误或 Safari 中缺少的功能?Apple 文档没有提到JavaScriptAudioNode(也没有提到新名称ScriptProcessorNode),但它在 Safari 6 的第一个版本之前确实有效。iOS Safari 对用户输入的要求似乎没有帮助,因为上面的示例应该注意那个。

简单的例子可以在这里找到,一个更复杂的例子是我的Protracker 模块播放器,它表现出相同的行为。

4

1 回答 1

4

您需要注意 Safari 的 Web Audio API 实现中的几个错误。第一个在createJavaScriptNode构造函数中......似乎将“输入通道”参数设置为0有问题。尝试将其更改为:

createJavaScriptNode(2048, 1, 2)

第二个问题与垃圾收集有关(我认为);一旦您的 mixerNode 变量超出范围,Safari 似乎停止触发onaudioprocess回调。一种解决方案是在顶级范围内引入mixerNode(即var mixerNode;在脚本顶部声明),然后将您的JavaScriptNode 存储在该顶级变量中。如果您计划动态创建多个mixerNode,则可以通过将对它们的引用存储在顶级数组变量中来实现相同的效果。

如果您进行这两项更改(输入通道参数设置为 1,保持对混合器节点的引用),那么您的脚本应该可以在 Safari 中按预期工作。

于 2013-01-25T20:42:41.427 回答