在 Web Audio API 中使用 ChannelSplitter 和 MergeSplitter 节点

Mor*_*des 2 javascript audio web-audio-api

我正在尝试使用 ChannelSplitter 节点将音频信号发送到 ChannelMerger 节点和目的地,然后尝试使用 ChannelMerger 节点合并两个不同的音频信号(一个来自拆分源,一个来自麦克风使用 getUserMedia ) 使用 Recorder.js 进入记录器。

我不断收到以下错误:“未捕获的语法错误:指定了无效或非法的字符串。”

错误位于以下代码行:

audioSource.splitter.connect(merger);
Run Code Online (Sandbox Code Playgroud)

其中audioSource是ThreeAudio.js库中ThreeAudio.Source的一个实例,splitter是我通过修改原型实例化自己的一个通道拆分器,merge是我的合并节点。它之前的代码是:

merger = context.createChannelMerger(2);
userInput.connect(merger);
Run Code Online (Sandbox Code Playgroud)

其中 userInput 是来自用户麦克风的流。那个连接没有抛出错误。声音从 audioSource 传到目的地(我能听到),所以似乎分离器不一定是错误的——我似乎无法连接它。

有没有人有任何见解?

Gil*_*ain 6

我正在努力理解ChannelSplitterNodeChannelMergerNodeAPI。最后我找到了缺失的部分,该方法的第二个和第三个可选参数connect()- 输入和输出通道。

connect(destinationNode: AudioNode, output?: number, input?: number): AudioNode;
Run Code Online (Sandbox Code Playgroud)

使用connect()Splitter 或 Merger 节点的方法时,请调整输入/输出通道。这就是您拆分和合并到音频数据的方式。

您可以在此示例中看到我如何加载音频数据、将其拆分为 2 个通道并控制左/右输出。注意该方法的第二个和第三个参数connect()

connect(destinationNode: AudioNode, output?: number, input?: number): AudioNode;
Run Code Online (Sandbox Code Playgroud)
const audioElement = new Audio("https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3");
    audioElement.crossOrigin = "anonymous"; // cross-origin - if file is stored on remote server

    const audioContext = new AudioContext();

    const audioSource = audioContext.createMediaElementSource(audioElement);

    const volumeNodeL = new GainNode(audioContext);
    const volumeNodeR = new GainNode(audioContext);

    volumeNodeL.gain.value = 2;
    volumeNodeR.gain.value = 2;

    const channelsCount = 2; // or read from: 'audioSource.channelCount'

    const splitterNode = new ChannelSplitterNode(audioContext, { numberOfOutputs: channelsCount });
    const mergerNode = new ChannelMergerNode(audioContext, { numberOfInputs: channelsCount });

    audioSource.connect(splitterNode);

    splitterNode.connect(volumeNodeL, 0); // connect OUTPUT channel 0
    splitterNode.connect(volumeNodeR, 1); // connect OUTPUT channel 1

    volumeNodeL.connect(mergerNode, 0, 0); // connect INPUT channel 0
    volumeNodeR.connect(mergerNode, 0, 1); // connect INPUT channel 1

    mergerNode.connect(audioContext.destination);

    let isPlaying;
    function playPause() {
      // check if context is in suspended state (autoplay policy)
      if (audioContext.state === 'suspended') {
        audioContext.resume();
      }

      isPlaying = !isPlaying;
      if (isPlaying) {
        audioElement.play();
      } else {
        audioElement.pause();
      }
    }

    function setBalance(val) {
      volumeNodeL.gain.value = 1 - val;
      volumeNodeR.gain.value = 1 + val;
    }
Run Code Online (Sandbox Code Playgroud)

PS:音轨不是真正的立体声轨道,而是同一单声道播放的左右副本。您可以通过真正的立体声播放来尝试此示例,以获得真正的平衡效果。


cwi*_*lso 5

这是一些创建乒乓延迟的工作分离器/合并代码 - 也就是说,它在立体声信号的 L 和 R 通道上设置单独的延迟,并跨越反馈。这是我在 webaudiodemos.appspot.com 上的输入效果演示(github 上的代码)。

var merger = context.createChannelMerger(2);
var leftDelay = context.createDelayNode();
var rightDelay = context.createDelayNode();
var leftFeedback = audioContext.createGainNode();
var rightFeedback = audioContext.createGainNode();
var splitter = context.createChannelSplitter(2);

// Split the stereo signal.
splitter.connect( leftDelay, 0 );

// If the signal is dual copies of a mono signal, we don't want the right channel - 
// it will just sound like a mono delay.  If it was a real stereo signal, we do want
// it to just mirror the channels.
if (isTrueStereo)
    splitter.connect( rightDelay, 1 );

leftDelay.delayTime.value = delayTime;
rightDelay.delayTime.value = delayTime;

leftFeedback.gain.value = feedback;
rightFeedback.gain.value = feedback;

// Connect the routing - left bounces to right, right bounces to left.
leftDelay.connect(leftFeedback);
leftFeedback.connect(rightDelay);

rightDelay.connect(rightFeedback);
rightFeedback.connect(leftDelay);

// Re-merge the two delay channels into stereo L/R
leftFeedback.connect(merger, 0, 0);
rightFeedback.connect(merger, 0, 1);

// Now connect your input to "splitter", and connect "merger" to your output destination.
Run Code Online (Sandbox Code Playgroud)