Search code examples
javascriptmathsignal-processingweb-audio-api

WebAudioAPI: Dividing two AudioNodes' outputs


Context: I am trying to implement an ADSR envelope in WebAudioAPI where Attack, Decay, Sustain and Release are all AudioParams, and the 'note on' and 'note off' is represented by an input value of 1 and 0 respectively. I'm using four DynamicCompressor nodes and a lot of gain manipulation to achieve this, since compressors are technically Attack-Release envelopes.

Everything is going fine, except for the fact that I need to divide the level of one signal by the level of another signal to get the amount of gain to achieve the level offset combined with the DynamicCompressor that produces the decay gradient.

If it helps, here's the formula:

decayOffsetY = (1 - sustainLevel) * (attackDur + decayDur) / decayDur

Note that sustainLevel, attackDur and decayDur are all AudioParams.

Addition, subtraction and multiplication are all rather easily achievable using some ConstantSourceNodes and GainNodes, but how do I go about division?

Note: I've thought about using another DynamicCompressorNode to perform the division, since compressors technically divide the signal by a ratio, but this ratio is in the logarithmic scale, and I end up with a compression ratio of

log(decayDur) / 5

to achieve the value of 1 / decayDur which will be connected to another GainNode. But is it even possible to perform a Math.log using just AudioNodes?


Solution

  • Use a WaveShaperNode to compute either the inverse or the log. You'll have to figure out how to handle the case where the input is near zero and also how long to make the wave shaper curve array, but this should work.