打字稿,网络音频。
我有一个播放音频的工具,一些用户报告说“平移”效果不适用于他们。基本上,有一个滑块,用户可以使用它来控制声音从最左到最右的位置(立体声位置)。这类似于“金属房间” 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部分!
所以我的问题如下: