I am working on a mod player which is an audio file with 4 different tracks (channels) using webaudio/audioWorkletNode.
I got it working correctly using a 2 channel (stereo) audio node:
The problem is that I'd like to analyse and show a waveform display for each of the tracks (so there should be 4 different analysers).
I had the idea of creating an audioWorkletNode with outputChannelCount set to [4], connect an analyser to each of the node's four channels, and then use a channelMerger to mix it into 2 stereo channels.
So I used the following code, expecting it to create a node with 4 channels:
let node = new AudioWorkletNode(context, 'processor', { outputChannelCount: [4] });
But the outputChannelCount parameter seems to be ignored. No matter what I specify, it's set to 2 channels in the end.
Is there a way to do it another way, or must I handle the analyse myself, using my own analyser?
I finally found a way to mix all four channels and pass each channel to its own analyser by doing that:
this.context.audioWorklet.addModule(`js/${soundProcessor}`).then(() =>
{
this.splitter = this.context.createChannelSplitter(4);
// Use 4 inputs that will be used to send each track's data to a separate analyser
// NOTE: what should we do if we support more channels (and different mod formats)?
this.workletNode = new AudioWorkletNode(this.context, 'mod-processor', {
outputChannelCount: [1, 1, 1, 1],
numberOfInputs: 0,
numberOfOutputs: 4
});
this.workletNode.port.onmessage = this.handleMessage.bind(this);
this.postMessage({
message: 'init',
mixingRate: this.mixingRate
});
this.workletNode.port.start();
// create four analysers and connect each worklet's input to one
this.analysers = new Array();
for (let i = 0; i < 4; ++i) {
const analyser = this.context.createAnalyser();
analyser.fftSize = 256;// Math.pow(2, 11);
analyser.minDecibels = -90;
analyser.maxDecibels = -10;
analyser.smoothingTimeConstant = 0.65;
this.workletNode.connect(analyser, i, 0);
this.analysers.push(analyser);
}
this.merger = this.context.createChannelMerger(4);
// merge the channel 0+3 in left channel, 1+2 in right channel
this.workletNode.connect(this.merger, 0, 0);
this.workletNode.connect(this.merger, 1, 1);
this.workletNode.connect(this.merger, 2, 1);
this.workletNode.connect(this.merger, 3, 0);
this.merger.connect(this.context.destination);
});
I basically create a new node with 4 outputs and use the outputs as a channel. To produce a stereo output I can then use a channel merger. And voila!
Complete source code of the app can be found here: https://warpdesign.github.io/modplayer-js/