首页 > 解决方案 > Web Audio API:实现任意数量源平移的布局

问题描述

我正在尝试为任意数量的同时网络音频源实现用户控制的平移。源本身是单声道的。我正在使用 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”。其中一个设置可能最终很重要,但是在尝试摆弄这些设置时我什么也找不到。

问题

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

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

我可以进行架构调整以保持这种多渠道策略并实现我正在寻找的东西吗?

代码片段

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

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

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);

    }
}

播放功能的相关片段:

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 );

    }
}

标签: javascriptaudiowebweb-audio-api

解决方案


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

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


推荐阅读