当右声道高于某个音量时使用 AudioContext 选通左声道

问题描述 投票:0回答:1

在我的 chrome 扩展中,我使用

AudioContext
AudioNode
将两个流合并为一个流,其中一个位于左通道,另一个位于右通道。当左通道音量高于某个阈值时,我还想在出于录音目的而合并之前对右通道进行选通(静音)。现实世界的用例是,左流是通过当前选项卡播放的音频的直接音频录制,右流是麦克风输入。如果用户没有戴耳机,那么麦克风输入会拾取正在播放的流的(稍微时移延迟的)流血,我想将其静音。在我的用例中,录音始终是双向对话,因此实际上不需要两个人同时讲话,在这种情况下,我仍然会优先考虑左流。

下面是我合并音频流的代码。我相信 AudioWorklet 可以帮助我在录制之前实时处理流,或者可能使用 CustomNode - 但我无法使用这些音频 API 找到足够的指导性示例。

const mergeAudioStreams = (leftStream: MediaStream, rightStream: MediaStream) => {
  // Create an AudioContext
  const audioContext = new AudioContext();

  const leftSource = audioContext.createMediaStreamSource(leftStream);
  const rightSource = audioContext.createMediaStreamSource(rightStream);
  
  const merger = audioContext.createChannelMerger(2);
  merger.channelInterpretation = 'speakers'
  merger.channelInterpretation = 'speakers';
  
  leftSource.connect(merger, 0, 0); // Left channel
  rightSource.connect(merger, 0, 1); // Right channel

  const destination = audioContext.createMediaStreamDestination();
  merger.connect(destination);

  // Create a new MediaStream from the MediaStreamDestination
  const combinedStream = destination.stream;

  return combinedStream;
};

感谢您的指导。

web-audio-api audio-worklet audioworkletprocessor
1个回答
0
投票

听起来您的问题可以通过设置来解决

echoCancellation
当请求麦克风输入时,按
true

navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true } });

如果这不起作用,您还可以使用

AudioWorklet
在流之间切换。

我设置了一个演示,它使用两个振荡器作为源节点。左声道的音量通过

GainNode
进行调制以模拟您的用例。

https://stackblitz.com/edit/vitejs-vite-jypuvr

process()
内部的
AudioWorklet
函数计算左声道的音量,并用它来决定是否应该通过左声道或右声道。

process([input], [output]) {
  if (input.length === 2) {
    let volume = 0;

    for (let i = 0; i < input[0].length; i += 1) {
      volume += input[0][i] ** 2;
    }

    volume = Math.sqrt(volume / input[0].length);

    if (volume > 0.4) {
      output[0].set(input[0]);
    } else {
      output[0].set(input[1]);
    }
  }

  return true;
}

该演示仅查看当前渲染量子的样本并执行硬切换。您可能需要对此进行调整以使结果更令人愉快。

© www.soinside.com 2019 - 2024. All rights reserved.