In this lesson, we learn about a couple of new types of nodes and see how to chain multiple nodes together to create various special effects.
Let's look at how we can chain Web Audio nodes together to create different effects. To do this, we'll discover another type of node called a GainNode. A GainNode requires an input and has an output. It also has a gain property, which is an audio parameter, like the oscillator's frequency property.
In simple terms, the GainNode multiplies its input by its gain value, sending the result to its output.
If we insert a GainNode between our oscillator and our destination, it will multiply the output of the oscillator by whatever gain value it has before sending that to the destination. This becomes a simple volume control. If the gain value is one, then it will allow the oscillator output to pass through with no change.
Setting the gain value to 0.5 means we've cut the volume of the oscillator in half. Of course, you can go higher to one to boost the volume, but that'll just get into distortion pretty quickly.
We create a GainNode via the context by calling context.createGain(). I'm going to put all this inside a window.onload handler, because we're going to add some HTML elements, and I want to make sure they exist before trying to access them.
Then, I'll create the AudioContext, and an oscillator, and then a GainNode called vol. Now, I'll jump over to the HTML and create a slider using an input of type range. I'll set the minimum to 0, maximum to 1, a step of 0.01, and a value of 1. Back in the code, I'll get a reference to the slider calling it volControl.
Now, I can set the gain value of the volume node to be volControl.value and connect that node to the output. Then, I'll set the frequency value of the oscillator to 440 and connect it to the volume node. Now, we're all hooked up. The oscillator goes to the GainNode, and the GainNode goes to the destination.
Now, I'll need to know when the slider changes, so I'll add an event listener for the input event. Inside that, I'll reset the volume.gain.value to the current value of the volControl slider. Now all we need to do is start the oscillator.
There's our sound. When we move the slider, we change the gain to something less than one, which lowers the sound's volume all the way down to zero.
While GainNodes are great for controlling volume, they can also be used to change any other value. Remember, they're just multiplying input by a gain value value and send that to the output.
We can actually use the output of a GainNode to alter the frequency of an oscillator in real time and have another oscillator control that first GainNode.
Here, we have an oscillator running at one hertz or one cycle per second. That sends out values that go back and forth between -1 and 1 over and over every second. That gets fed into a GainNode with a base gain value of 100. This will output values that go from -100 to 100 over and over every second.
This gets attached to the main oscillator, whose base frequency is 440. The gain output will vary that frequency so that it actually cycles from 340 to 540 every second. This, then, gets piped through the volume node to the output. Let's put it all together.
Let's first make a frequency GainNode using context.createGain() and another oscillator. I'll call this LFO for low-frequency oscillator. The frequency GainNode will get a value of 100, and we'll connect that to the oscillator's frequency property. Then, we set the LFO's frequency to 1 and connect it to the frequency GainNode directly.
Finally, we start the LFO and start the main oscillator. You'll notice them starting while I'm typing, due to the type that JS Bin is reloading the whole file every time it changes. When I'm done, we have this siren sound. Note that the volume control still works. It's still controlling that last GainNode in the chain.
There's lots to experiment with here. I can change the LFO's frequency, and we get a faster siren. Or I can change the frequency gain value, and this will amount in a larger alteration to the base frequency. I can change the wave type of the LFO.
With a square wave, the tone isn't rising and falling but playing a half a second in a lower tone and a half a second in a higher tone.
Another node you can try is the PannerNode. This will allow you to pan audio left or right. We can slip that right in-between the volume GainNode and the destination. Ultimately, we could put it between the oscillator and the volume GainNode. Either one should work.
You create a PannerNode with context.createStereoPanner(). Now that I have a PannerNode, connect it to the destination, and then connect the volume gain to the panner. Now, we need something to control the panning. I'll go back into the HTML, copy and paste this slider, change its name to panner, set min to -1 and value to 0.
The panner's code values are interpreted as -1 for full left channel, plus 1 for full right, and 0 for center.
Now, we get our reference to that control and set up a listener for it. In the listener, I'll change the PannerNode's value to the panControl's pan value. Start it all up, and there's our siren. Now, we can pan it left and right and change the volume.
With five nodes chained together to produce an output, you should have a pretty good idea of how nodes work.