网络音频:PannerNode存在,但在iOS上可能无法正常工作

时间:2019-08-23 02:30:31

标签: ios typescript web audio

打字稿,网络音频。

我有一个播放音频的工具,一些用户报告说“平移”效果不适用于他们。基本上,有一个滑块,用户可以使用它来控制声音从最左到最右的位置(立体声位置)。这类似于“金属房间” PannerNode示例:https://mdn.github.io/webaudio-examples/panner-node/

我将在下面分享的实现可以在大多数情况下使用,但是我将概述它存在问题的特定位置。

用户最常见的问题描述是,平移效果不起作用,并且会同时影响两个扬声器,因此,当平移滑块位于最右侧时,音频将达到最大音量,而最左侧则为音频将为零。

我请遇到问题的用户解释他们在哪里看到问题,他们相当单方面地报告有关iOS各种版本和浏览器的问题。我知道某些型号的iPhone由于令人难以置信的不良设计而只具有正确的扬声器的问题,但我要求澄清一下,用户确实在使用耳机并且仍然会看到问题。我什至甚至有人亲自在iPhone 7上戴着耳机在手机上向我演示。我还让用户测试了“ Room of Metal”实施,他们看到了类似的结果-平移的工作方式与我以前不同描述。

...

检查要使用的节点类型:

if (this.audioCtx.createStereoPanner) {
    this.pannerLeft = this.audioCtx.createStereoPanner();
    this.pannerRight = this.audioCtx.createStereoPanner();
}
else if (this.audioCtx.createPanner) {
    this.pannerLeft = this.audioCtx.createPanner();
    this.pannerRight = this.audioCtx.createPanner();
}
else {
    this.forceMono = true;
}

...

设置节点:

if (this.audioCtx.createStereoPanner) {

      (this.pannerLeft as StereoPannerNode).pan.setValueAtTime(-1.0, this.audioCtx.currentTime); // Hard left

      (this.pannerRight as StereoPannerNode).pan.setValueAtTime(1.0, this.audioCtx.currentTime); // Hard right

    }
    else {

      (this.pannerLeft as PannerNode).setPosition(-5, 0, 1); // Hard left

      (this.pannerRight as PannerNode).setPosition(5, 0, 1); // Hard right

    }

    this.scriptNode = this.audioCtx.createScriptProcessor ? 
        this.audioCtx.createScriptProcessor(2048, 0, 2) : 
        this.audioCtx.createJavaScriptNode(2048, 0, 2); // 2048, 0 input channels, 2 outputs (L + R)
    this.scriptNode.onaudioprocess = this.audioProcessCallback;
    this.scriptNode.channelCountMode = 'explicit';
    this.scriptNode.channelInterpretation = 'speakers';

    this.splitter = this.audioCtx.createChannelSplitter(2);
    this.merger = this.audioCtx.createChannelMerger(2);    

    this.scriptProcessorNode.connect(this.splitter);
    this.splitter.connect(this.pannerLeft, 0);
    this.splitter.connect(this.pannerRight, 1);
    this.pannerLeft.connect(this.merger, 0, 0);
    this.pannerRight.connect(this.merger, 0, 1);
    this.merger.connect(this.audioCtx.destination);

...

音频处理回调代码段:

// Check if panning should be used - otherwise just use mono and both 
//    channels will be the same power.
    if ( !this.forceMono ) {

      // "Constant Power" panning - left audio is cos(angle), right audio is sin(angle)
      // "angle" in this context is in radians from 0 (left) to pi/2 (right)
      dataLeft[bufferIndex] += sample * Math.cos(((pan) / 100.0) * Math.PI / 2);
      dataRight[bufferIndex] += sample * Math.sin(((pan) / 100.0) * Math.PI / 2);

    } else {

      dataLeft[bufferIndex] += sample;
      dataRight[bufferIndex] += sample; //EDIT: fixed a typo where I was adding dataLeft instead of sample.

    }

在上面的代码片段中,我进行了一些检查,首先使用StereoPannerNode(在移动设备上不受支持,因此经常被跳过),然后检查是否支持PannerNodes。而这里有个问题-在我的iOS Safari移动调试器上,支持PannerNode ,但是即使初始化正常也存在问题。这意味着我无法让“ forceMono”代码段在显示此摇摄问题的上下文中运行。

请注意,当使用forceMono时,我遗漏了一些音频处理链设置不同的地方,因为问题是我们还是无法进入forceMono部分!

所以我的问题如下:

  • 这种不兼容广为人知吗?
  • 如果PannerNode 似乎可以初始化并正常工作,但实际上却无法正常工作,如何检测用户何时出现此问题?
  • 我的设置是否有问题,特别是PannerNode定位?它是模仿金属房间的例子,但我想那也可能是错误的。

0 个答案:

没有答案