Controlling Web Audio API volume using the HTML5 slider element

“Hey mister! This loud monotonous tone is deafening me. Can you turn it down?”

Oops, sorry. You must have just created a sine wave with the Web Audio Api. Of course you can turn it down, and up as well if you want. To do so we have to talk to our very good friend the Gain Node. We know that we create sound by connecting a sound source to a destination (our speakers), but we can also connect things in-between these two elements. In this instance we’ll be inserting the Gain Node. The Gain Node is a simple element that lets us control the volume of the audio that’s coming into to it. We can visualise it like so:

audioContext.attr({fill: "#FFF6B6", 'stroke-width': '2px'}); sourceNode.attr({fill: "#FFF6B6", 'stroke-width': '2px'}); distortionNode.attr({fill: "#FFF6B6", 'stroke-width': '2px'}); destinationNode.attr({fill: "#FFF6B6", 'stroke-width': '2px'}); sourceToGainArrow.attr({'stroke-width': '2px'}); gainToDestinationArrow.attr({'stroke-width': '2px'}); audioContextText.attr({'font-size': '16px'}); sourceNodeText.attr({'font-size': '16px'}); distortionNodeText.attr({'font-size': '16px'}); destinationNodeText.attr({'font-size': '16px'}); });

This translates to:

var context = new webkitAudioContext(), sineWave = context.createOscillator(), gainNode = context.createGainNode(); // Declare gain node sineWave.connect(gainNode); // Connect sine wave to gain node gainNode.connect(context.destination); // Connect gain node to speakers sineWave.noteOn(0); // Play sine wave

The above code won’t sound any different to what you would hear if the Gain Node wasn’t attached. This because the Gain node has only one attribute, gain, which has the default value of 1. This is the original untouched volume of the incoming audio. Now that we’re all connected up, what better way to control the gain value with an input tag using HTML5′s range type:

In case you’re not familiar with this element, it creates a slider tied to a specific range. We’ve set the minimum value to 0, meaning that when the slider is at its most left position, our sine wave will be inaudible. The max value is set to 1, meaning the loudest right-most value. And finally, we set the default value in the middle at 0.5. The only thing we need to do now is to connect this slider to our gain node. We can do this by creating a simple event listener like so:

document.getElementById('volume').addEventListener('change', function () { gainNode.gain.value = this.value; });

This takes the value of the slider when it’s moved and assigns it to the gain value of our gain node. Beautiful.

The source for this example is available in a fiddle.