# Is there an existing or planned way to *divide* a signal with another one? #1156

Closed
opened this Issue Feb 28, 2017 · 8 comments

Projects
None yet
6 participants

### JohnWeisz commented Feb 28, 2017 • edited

 I'm wondering if there is a way to divide an audio signal by another one without having to resort to scripted audio processing (which, unfortunately, is really not usable for anything slightly more complex than a tech demo, at least when doing live audio playback). I managed to implement all other basic math ops (addition, subtraction, multiplication), but I'm struggling to achieve division. Is it possible at all? For clarification about what I mean about math ops between audio signals, consider two audio 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. <20Hz) frequencies, and that their signals are used to control a single destination AudioParam, for example, the gain of a GainNode. Through various routing setups, we can define mathematical operations between these two signals. Addition If `oscA` and `oscB` are both directly connected to the destination AudioParam, their outputs are added together: ```var dest = audioCtx.createGain(); oscA.connect(dest.gain); oscB.connect(dest.gain);``` Subtraction If the output of `oscB` is first routed through another GainNode with a gain of `-1`, which is then connected to the destination AudioParam, then the output of `oscB` is effectively subtracted from that of `oscA`, because we are effectively doing an `oscA + -oscB` op. Using this setup we can subtract one signal from another one: ```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 output of `oscA` is connected to another GainNode, and the output of `oscB` is connected to the gain AudioParam of that GainNode, then `oscB` is multiplying the signal of `oscA` (amplitude-wise): ```var dest = audioCtx.createGain(); var multiplier = audioCtx.createGain(); oscA.connect(multiplier); oscB.connect(multiplier.gain); multiplier.connect(dest.gain);``` So is there a way to do division in the Web Audio API?

### pendragon-andyh commented Feb 28, 2017

 You should be able to create a waveshaper node that applies a reciprocal. The resulting signal can then be directed to the gain parameter of a gain node. I always think of waveshaper as applying "f(x)". If you need a wider range than -1 to +1 then you another gain node to scale the input signal of the waveshaper. … On 28 Feb 2017 17:17, "John White" ***@***.***> wrote: I'm wondering if there is a way to *divide* an audio signal by another one without having to resort to scripted audio processing (which, unfortunately, is really not usable for anything slightly more complex than a tech demo). I managed to implement all other basic math ops (addition, subtraction, multiplication), but I'm struggling to achieve division. Is it possible at all? ------------------------------ For clarification about what I mean about math ops between audio signals, consider two audio 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. <20Hz) frequencies, and that their signals are used to *control* a single destination AudioParam , for example, the *gain* of a GainNode . Through various routing setups, we can define mathematical operations between these two signals. *Addition* If oscA and oscB are both *directly* connected to the destination AudioParam, their outputs are *added* together: var dest = audioCtx.createGain(); oscA.connect(dest.gain);oscB.connect(dest.gain); *Subtraction* If the output of oscB is first routed through *another* GainNode with a gain of -1, which is then connected to the destination AudioParam, then the output of oscB is effectively *subtracted* from that of oscA, because we are effectively doing an oscA + -oscB op. Using this trick we can subtract one signal from another one: 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 output of oscA is connected to *another* GainNode, and the output of oscB is connected to the *gain* AudioParam of *that* GainNode, then oscB is multiplying the signal of oscA (amplitude-wise): var dest = audioCtx.createGain();var multiplier = audioCtx.createGain(); oscA.connect(multiplier);oscB.connect(multiplier.gain); multiplier.connect(dest.gain); ------------------------------ *So how to do a division?* — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#1156>, or mute the thread .
Contributor

### rtoy commented Feb 28, 2017

 Yes, using a `WaveShaperNode` is the only way. Also, in the multiplication example, you have to be sure to set the gain attribute of the gain multiplier to 0. Otherwise the output will default to 1 plus the product. (I always forget this.)

### JohnWeisz commented Mar 1, 2017 • edited

 @pendragon-andyh You should be able to create a waveshaper node that applies a reciprocal. @rtoy Yes, using a WaveShaperNode is the only way. Thank you, the help of WaveShaperNode seems to enable virtually all calculations to be done. Perfect for these use cases. EDIT: Well, not perfect, but it gets the job done. @rtoy be sure to set the gain attribute of the gain multiplier to 0 Yes, thank you, that's taken care of, but I accidentally left it out from the example.
Contributor

### rtoy commented Mar 1, 2017

 Based on the comments, I think we can close this. I don't expect that a new feature or node will be added to support division.
Member

### padenot commented Mar 7, 2017

 Tone.js used to have code to do exactly this, but it's the division is now deprecated. Here is how it used to be done: https://github.com/Tonejs/Tone.js/blob/6c0c5d77af4cc48b84a4307551d0f549b824d912/Tone/signalT/Divide.js I agree we can close this.

### mbylstra commented Jul 1, 2017 • edited

 Sure there are hacks you can do to achieve this using nodes that weren't designed for this, but why not not just provide basic math operations to the Web Audio API? What's the harm in that? Surely it would be far more performant for these operations to be done completely natively. Would this really be a controversial addition to the Web Audio API? Would it be difficult to implement? Would it not just be a couple of lines of code containing `/` to implement this?

### JohnWeisz commented Jul 3, 2017

 @mbylstra I've been looking at the code, it certainly would be trivial to implement. The committee would have to come up with the specs, however, and I'm not sure they are ready to go full-time into control signal processing (after all, there are other implications when taking this route, such as reduced sample rate for improved efficiency, as you will likely not need 44.1 kHz to automate a gain audio param).

### sgentle commented Sep 21, 2017

 There's one use case I'd like to bring up: finding the inverse of a frequency to get a wavelength. That's important if you want to delay one synth in a frequency-dependent way relative to another. When the frequencies are static, you can obviously just set them, but if you want to apply any LFO or envelope automation it gets trickier. I specifically ran into this issue trying to create a pulse wave. I originally wanted to use @pendragon-andyh's solution (sawtooth into a thresholding WaveShaper), but ran into problems with bandlimiting outlined here: pendragon-andyh/WebAudio-PulseOscillator#2. So I then went with the subtract-one-offset-saw-from-another method, but that's tricky to automate because of the above issue and I wanted vibrato. In the end, I used an inverting WaveShaper as in @padenot's Tone.js, but I'm left with lingering concerns. Looking at Inverse.js, it appears to do multiple rounds of gain and waveshaping depending on the input desired accuracy. I only did one round, and it's a bit tricky to reason about whether that's enough precision. If the current best solution to "I want to delay one oscillator by a multiple of the period of another" is to rebuild an approximation on top of an arbitrary number of WaveShapers, I think it suggests a reciprocal or division node might be useful.