【问题标题】:Web Audio API: Layout to Achieve Panning for an Arbitrary Number of SourcesWeb Audio API:实现任意数量源平移的布局
【发布时间】:2019-02-08 16:18:29
【问题描述】:

我正在尝试为任意数量的同时网络音频源实现用户控制的平移。源本身是单声道的。我正在使用 Web 音频 API (https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) 使用 Javascript。

目前,我遇到的问题是我正在尝试使用多通道输出(每个源一个),但通道解释覆盖了我的平移尝试(请参阅https://developer.mozilla.org/en-US/docs/Web/API/AudioNode/channelInterpretation),导致我认为我在架构上做错了什么。

我想把事情放在一个主要是概念层面,因为我相信这就是我的问题所在。

当前设置

我的方法是让一个节点处理每个源的所有处理,这里称为“scriptNode”。创建了与音频源数量相等的通道数,并且还创建了同样数量的平移器节点。图表如下所示:

The bundle size (the '=' segments) is the number of channels, set to be equal to the number of sources.

scriptNode == splitter =+-- panner1 --+= merger == destination
                        \-- panner. --/
                        \-- panner. --/
                        \-- pannerN --/

一些杂项,我正在调用这个函数来设置 scriptNode:

scriptNode = firstPart.audioCtx.createScriptProcessor(2048, 0, numParts);

其中 numParts 是源的数量。我还将 scriptNode 的 channelCountMode 设置为“explicit”,将 channelInterpretation 设置为“speakers”。其中一项设置可能最终很重要,但在尝试修改设置时我找不到任何东西。

问题

当我用这个架构实际测试我的代码时,我会根据我选择的部件数量得到以下行为。平移滑块与每个相应源的平移器节点的“平移”值相关联。

  • numParts=1 :单声道输出,使用滑块平移不会做任何事情,只会影响输出的音量(向中间更强)。我想这是从声像器向下混音到单声道的副产品。
  • numParts=2 :立体声输出,左一硬,右一硬。使用滑块平移两个频道没有任何作用。
  • numParts=3 :与 =2 相同,但第三个通道是静默的。
  • numParts=4 :与 =2 类似,现在所有通道都重新工作了,它们按 L/R/L/R 的顺序努力平移。再次使用滑块平移没有任何作用。

这种行为似乎符合 channelInterpretation 描述,但我想要的是分别为每个源进行平移工作,而不管我使用的频道数量如何。而且我仍然希望使用通道,因为我的每个来源都希望写入单声道缓冲区。

我是否可以进行架构调整以保持这种多渠道策略并实现我的目标?

代码片段

当前代码的相关部分基于我上面的陈述以及解决问题的尝试。 编辑:感谢下面的 cmets,我设法找到了问题。我调用了单行修复,以便以后可以将此代码用作参考。

音频处理功能。只有第一个合成器(源)设置了这个回调:

function customAudioProcessCallback( audioProcessingEvent )
{
    // First synth - process audio for all synths!

    const outputBuffer = audioProcessingEvent.outputBuffer;

    for ( var i = 0; i < numParts; i++ ) {

    // Each part writes to one channel.

    synthParts[ i ].synthesize(outputBuffer.getChannelData( i ), outputBuffer.length);

    }
}

播放功能的相关sn-p:

function play()
{
    const contextClass = (window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext);
    synthParts[ 0 ].audioCtx = new contextClass();

    synthParts[ 0 ].scriptNode = synthParts[ 0 ].audioCtx.createScriptProcessor ? synthParts[ 0 ].audioCtx.createScriptProcessor(2048, 0, numParts+1) : synthParts[ 0 ].audioCtx.createJavaScriptNode(2048, 0, numParts+1); // 2048, 0 input channels, ? outputs
    synthParts[ 0 ].scriptNode.onaudioprocess = customAudioProcessCallback;
    synthParts[ 0 ].scriptNode.channelCountMode = 'explicit';
    synthParts[ 0 ].scriptNode.channelInterpretation = 'speakers';

    // Set up splitter and panners for all channels
    var splitter = synthParts[ 0 ].audioCtx.createChannelSplitter( numParts+1 );

    for ( var i = 0; i < numParts; i++ ) {

        panList[ i ] = synthParts[ 0 ].audioCtx.createStereoPanner();
        panList[ i ].pan = panValues[ i ];

    }

    // Connection:
    // scriptNode -- splitter -+-- panner1 --+- destination
    //                         \-- panner. --/
    //                         \-- pannerN --/

    synthParts[ 0 ].scriptNode.connect(splitter);

    for ( var i = 0; i < numParts; i++ ) {

        splitter.connect( panList[ i ], i);

        // This line used to read: 
        //    panList[ i ].connect( synthParts[ 0 ].audioCtx.destination, 0, i );
        // However, this was connecting multiple parts to the input of the audio context destination, which is limited to 1 input. The correct call is below.
        panList[ i ].connect( synthParts[ 0 ].audioCtx.destination );

    }
}

【问题讨论】:

    标签: javascript audio web web-audio-api


    【解决方案1】:

    A PannerNode 总是产生立体声输出。当您将声像器输出连接到合并器的一个输入时,声像器的立体声输出会下混为单声道,从而有效地消除了大部分声像效果。

    缺少一些信息,但我不明白您为什么需要合并。您可以将每个声像器的立体声输出直接发送到目的地。目的地将适当地混合来自每个声像器的立体声输出,保留声像效果。

    【讨论】:

    • 我试过了,但在尝试连接我的 panner 时出现错误。似乎以前发现过这个问题:stackoverflow.com/questions/37508035/…(甚至是你,我刚刚注意到!)。这种情况下的提议是像我目前一样使用合并,但我愿意接受建议以在不合并的情况下规避此错误以避免单声道缩混问题。
    • 与链接问题相同,即“未捕获的 IndexSizeError:无法在 'AudioNode' 上执行 'connect':输入索引 (1) 超过输入数 (1)。”当尝试使用两个源/两个通道时会看到此消息,这两个通道都直接连接到目标节点。具体来说,这是在第二个通道尝试连接到目标节点时抛出的。也许我错过了一些改变目标节点通道带宽的方法?
    • 我认为要取得进展,我需要查看导致错误的代码的简单示例。现在有点太抽象了,不知道是什么导致了问题。
    • 我在原始问题中附加了一些相关的 sn-ps。上述错误在这一行被抛出:“panList[i].connect(synthParts[0].audioCtx.destination, 0, i);”当 i > 0.
    • 我想你真的只想要panList[i].connect(synthParts[0].audioCtx.destination)。您将平移器的输出 0 连接到目标的输入 1。但是目的地只有一个输入(索引 0),所以这就是错误所在。 (控制台日志应该提供了一些关于此的信息。)此外,您通常只创建一个音频上下文,而不是每次都创建一个新上下文。 (我假设play() 被多次调用。)
    猜你喜欢
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多