Web Audio API channels aren't down-mixed
-
21-12-2019 - |
Frage
I have an AAC file with 6 channels. If I open it directly in a browser, I hear all 6 channels down-mixed to play on my stereo speakers. If I play it via the Web Audio API, I only hear the left and right channels.
I'm loading the buffer, creating an AudioBufferSourceNode, assigning the buffer to it, and then connecting to the AudioContext's destination.
From my console:
> buffer.numberOfChannels
6
> source.channelCount
2
> source.channelCountMode
"max"
> source.channelInterpretation
"speakers"
> context.destination
AudioDestinationNode {maxChannelCount: 2, channelInterpretation: "speakers", channelCountMode: "explicit", channelCount: 2, numberOfOutputs: 0…}
Is this the reason that I'm not hearing the other channels, because destination.channelCountMode
is explicit
?
Is there some way to change this or get the AudioContext to use its down-mixing logic?
I've created a simple jsFiddle example showing the setup. If you download the file directly, you'll hear the 6 channels down-mixed into 2, but not if you run it through the Web Audio Context.
Lösung
Have you noticed your JSFiddle works ok in Firefox? Chrome on the other hand does not work as "expected". I am saying expected because as Web Audio is still a draft not all features may be implemented yet by all browsers supporting it (FYI see browser support here).
I have put an example that should work as you want here. As you suspected you need to implement the down mixing logic following the W3C spec you mentioned. This is done through the createScriptProcessor method in conjunction to the audioprocess event.
The code as follows (it is not production ready as such but you can take it from here :)):
<script src="http://www.html5rocks.com/en/tutorials/webaudio/intro/js/buffer-loader.js"></script>
<script type="text/javascript">
window.onload = init;
var context;
var bufferLoader;
function init() {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext();
bufferLoader = new BufferLoader(
context,
[
'http://labs.bubblefoundry.com/internet-of-cars/corsproxy.php?url=http://labs.bubblefoundry.com/internet-of-cars/sounds/5_1IDENT.m4a'
],
finishedLoading
);
bufferLoader.load();
function finishedLoading(bufferList) {
var javascriptNode = null;
var source1 = context.createBufferSource();
source1.buffer = bufferList[0];
javascriptNode = context.createScriptProcessor(2048, 6, 2); // audioContext.createScriptProcessor([bufferSize][, numberOfInputChannels][, numberOfOutputChannels]);
source1.connect(javascriptNode);
javascriptNode.connect(context.destination);
console.log(javascriptNode);
function onProcess(e) {
var in1 = e.inputBuffer.getChannelData(0); // Left input
var in2 = e.inputBuffer.getChannelData(1); // Right input
var in3 = e.inputBuffer.getChannelData(2); // Center input
var in4 = e.inputBuffer.getChannelData(3); // (??)
var in5 = e.inputBuffer.getChannelData(4); // Left Surround input
var in6 = e.inputBuffer.getChannelData(5); // Right Surround input
var leftOut = e.outputBuffer.getChannelData(0); // Left output
var rightOut = e.outputBuffer.getChannelData(1); // Right output
for (var i = 0; i < in1.length; i++) {
leftOut[i] = in1[i] + 0.7071 *(in3[i] + in5[i]); // W3C formula for Down Mixing
rightOut[i] = in2[i] + 0.7071 *(in3[i] + in6[i]); // W3C formula for Down Mixing
}
}
source1.start(0);
javascriptNode.onaudioprocess = onProcess;
}
}
</script>
I have noticed your channel 4 (marked ?? in my comment) seems to be silent. But here my knowledge of surround sound may fall short.