微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将setSinkId与stereoPanner结合使用?

如何解决将setSinkId与stereoPanner结合使用?

我正在编写一个Electron应用程序,使用Focusrite Scarlett 18i20 USB声卡将单独的音频流传输到10个音频通道。 Windows 10将输出拆分为以下立体声输出

  • 焦点1 + 2
  • 焦点3 + 4
  • 焦点5 + 6
  • 焦点7 + 8
  • 焦点9 + 10

因此,我需要该应用程序将音频发送到特定的输出,以及拆分立体声通道。示例:要将音频传递到第三输出,我需要将其发送到左声道的“ Focusrite 3 + 4”。不幸的是,我似乎无法同时做这两项。

我从一个音频对象开始:

let audio = new Audio("https://test.com/test.mp3");

我执行以下操作以获取输出的接收器ID:

let devices = await navigator.mediaDevices.enumerateDevices();
devices = devices.filter(device => device.kind === 'audiooutput');

以下用于将音频输出到特定的sinkId的方法

audio.setSinkId(sinkId).then(() => {
  audio.play();
}

工作:我只播放左声道:

let audioContext = new AudioContext();
let source = audioContext.createMediaElementSource(audio);
let panner = audioContext.createStereoPanner();
panner.pan.value = -1;
source.connect(panner);
panner.connect(audioContext.destination);

到目前为止,一切都很好。但是,当我尝试合并这些对象时,sinkId将被忽略,并且音频将被发送到认音频输出。我尝试了几种方法包括这种方法

audio.setSinkId(sinkId).then(() => {
  let audioContext = new AudioContext();
  let source = audioContext.createMediaElementSource(audio);
  let panner = audioContext.createStereoPanner();
  panner.pan.value = -1;
  source.connect(panner);
  panner.connect(audioContext.destination);
}

我还尝试了使用audioContext.createChannelMerger而不是stereoPanner的方法。它可以完美地单独运行,但不能与setSinkId结合使用。在Windows 10和Mac上,我得到相同的行为。

有什么想法吗?

解决方法

要将 AudioContext 的音频输出路由到特定输出设备,您需要将 MediaStreamAudioDestinationNode 与另一个音频元素结合使用。现有音频元素的 sinkId 路由到 AudioContext 后不再有任何影响。

所需的信号流以某种方式看起来像这样:

audio
    ↓
MediaElementAudioSourceNode
    ↓
StereoPannerNode
    ↓
MediaStreamAudioDestinationNode
    ↓
outputAudio

然后需要更改您的 AudioContext 代码以将所有内容路由到 MediaStreamAudioDestinationNode 而不是默认目的地。

let audioContext = new AudioContext();
let source = audioContext.createMediaElementSource(audio);
let panner = audioContext.createStereoPanner();
let destination = audioContext.createMediaStreamDestination();

panner.pan.value = -1;

source.connect(panner).connect(destination);

最后一部分是将 streamMediaStreamAudioDestinationNode 路由到新创建的音频元素,然后可用于设置 sinkId

const outputAudio = new Audio();

outputAudio.srcObject = destination.stream;

outputAudio.setSinkId(sinkId);
outputAudio.play();

请注意,仅使用音频元素来设置 sinkId 有点小技巧。有计划将 sinkId 设置为 AudioContext 的一项功能。

https://github.com/WebAudio/web-audio-api-v2/issues/10

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。