Short version
I need to split the audio signal into another (in amplitude). How could I accomplish this in a web audio API without using ScriptProcessorNode ? (with ScriptProcessorNode, the task is trivial, but it is completely unsuitable for production due to its inherent performance problems)
Long version
Consider two sound sources, two OscillatorNodes , for example, oscA and oscB :
var oscA = audioCtx.createOscillator(); var oscB = audioCtx.createOscillator();
Now consider that these oscillators are LFOs, both with low (i.e., <20 Hz) frequencies, and with their signals, which are used to control one AudioParam destination , for example, the gain GainNode . Through various routing settings, we can define the mathematical operations between these two signals.
Adding
If oscA and oscB simultaneously connected to the target AudioParam, their outputs are added together:
var dest = audioCtx.createGain(); oscA.connect(dest.gain); oscB.connect(dest.gain);
Subtraction
If the oscB first redirected through another GainNode with a gain of -1 , which then connects to the target AudioParam, then the oscB effectively subtracted from the oscA , because we are effectively doing oscA + -oscB op. Using this trick, we can subtract one signal from another:
var dest = audioCtx.createGain(); var inverter = audioCtx.createGain(); oscA.connect(dest.gain); oscB.connect(inverter); inverter.gain = -1; inverter.connect(dest.gain);
Multiplication
Similarly, if the oscA output oscA connected to another GainNode, and the oscB output oscB connected to the AudioParam gain of this GainNode, then oscB multiplies the oscA signal:
var dest = audioCtx.createGain(); var multiplier = audioCtx.createGain(); oscA.connect(multiplier); oscB.connect(multiplier.gain); multiplier.connect(dest.gain);
Department (?)
Now I want the output of oscB to split the output of oscA . How to do this without using ScriptProcessorNode?
Edit
My previous, absolutely ridiculous attempts to solve this problem:
- Using PannerNode to control the
positionZ parameter, which gave a result that decreased with increasing signal B ( oscB ), but was completely turned off (for example, it gave 12/1 = 8.5 and 12/2 = 4.2 ) - now this value can be compensated using a GainNode with a gain set to 12 / 8.48528099060058593750 (approximation), but only supports values >=1 - Using AnalyserNode to quickly select an audio signal and then use this value (LOL)
Edit 2
The reason ScriptProcessorNode is practically useless for applications more complex than the technology demo is as follows:
- it performs sound processing in the main stream (!), and hard work in the user interface will lead to system malfunctions.
- a single, dead simple ScriptProcessorNode will consume 5% of the processor power on a modern device, since it performs JavaScript processing and requires data transfer between the audio stream (or rendering stream) and the main stream (or user interface stream)