我正在尝试对任意数量的同时Web音频源实现用户控制的平移。来源本身是单声道的。我正在使用Javascript和网络音频API(https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)。
当前,我遇到的问题是我正在尝试使用多通道输出(每个源一个),但是通道解释覆盖了我平移的尝试(请参见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”。这些设置之一可能最终很重要,但是当尝试摆弄这些设置时,我什么也找不到。
问题
当我使用这种架构实际测试代码时,基于选择的部件数量,我将得到以下行为。平移滑块与每个相应源的平移节点的“ pan”值相关联。
此行为似乎与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 );
}
}
答案 0 :(得分:1)
PannerNode
总是产生立体声输出。当将Panner输出连接到合并的输入之一时,来自Panner的立体声输出将缩混为单声道,从而有效地消除了大部分Panning效果。
缺少某些信息,但是我不明白为什么需要合并。您可以将每个声相器的立体声输出直接发送到目的地。目的地将适当地混合每个声相器的立体声输出,以保持声相效果。