UPDATED ON: December 11, 2014
Web Audio API Oscillators is a tutorial that will give you an understanding of how to generate sounds with the Web Audio API in your browser. Web Audio API Oscillators builds on what we’ve covered in Web Audio API Basics, the first tutorial in the series. Web Audio API Oscillators will attempt to cover what oscillators are, how to create them, changing waveforms, setting frequency, and layering multiple oscillators together to create rich sounds. We’ll finish by applying what we’ve learned to create a working example. After covering the basics in this tutorial, we’ll get into some techniques for toggling oscillators on and off and even how to use the API to make a synthesizer in the browser.
Web Audio API Oscillators
The Web Audio API allows us to generate oscillating wave forms quite easily. You might be asking yourself, “Aren’t those the building blocks of a synthesizer?” Well, yes. The Web Audio API enables us to create our own synths! Before we get ahead of ourselves, let’s go over the fundamentals.
What is an Oscillator?
So, what do we need to know about oscillators? An oscillator is a circuit that produces a repetitive, oscillating signal. Along with audio filters and audio controllers, audio oscillators are one of the basic elements required for modern analog subtractive synthesizers.
Let’s Create an Oscillator
Now that we’ve covered the basics, we’ll create a simple oscillator. The OscillatorNode is the interface that represents an audio source generating a periodic waveform. Unless otherwise specified, an oscillator defaults to a sine wave at 200 hertz. Notice we must connect the oscillator to the destination in order to hear it. Also, we specify a start value of zero to play the sound instantly.
oscillator = context.createOscillator(); // Create sound source oscillator.connect(context.destination); // Connect sound to output oscillator.start(0); // Play instantly
UPDATE: As of July 2014, oscillator.start() should be used instead of oscillator.noteOn().
Specify Type and Frequency
There are four commonly used waveforms that can easily be generated. Each type is specified by a number from 0-3. If we want a square wave, we change the oscillator type to 1. If we want a triangle wave, we set the oscillator type to 3. Custom waveforms can also be specified through the use of a WaveTable PeriodicWave object, but we’ll try to keep it simple for this tutorial.
UPDATE: As of July 2014, oscillator type must be specified as Web IDL value.
Commonly Used Waveforms
- Sine wave is type = “sine”
- Square wave is type = “square”
- Sawtooth wave is type = “saw”
- Triangle wave is type = “triangle”
- Custom wave is type = “custom”
Also, we can adjust the pitch of the wave simply by setting a frequency value. The number used for the frequency value represents the actual frequency in hertz. A value of 440 would be an A because the note A4 is equal to 440 Hz. For now we won’t worry about the actual note we’re playing. We’ll just use a value of 100 to keep it simple.
oscillator.type = "square"; // Square wave oscillator.frequency.value = 100; // frequency in hertz
Double the Fun
We can layer multiple oscillators to create a thicker sound. For a dual oscillator, we create two sound sources. Oscillator1 is set to the default type and frequency, and is played instantly. Oscillator2 is set to be a square wave at half the frequency of oscillator1. This will produce a tone that is one octave below the tone of oscillator1. Oscillator2 is also routed through a gainNode to reduce it’s volume to 30 percent. And finally, oscillator2 is played after two seconds. This allows the listener to differentiate the two sounds being layered.
oscillator1 = context.createOscillator(); // Create sound source 1 oscillator2 = context.createOscillator(); // Create sound source 2 gainNode2 = context.createGain(); // Create gain node 2 oscillator1.type = "sine"; // Sine wave oscillator1.frequency.value = 200; // Default frequency in hertz oscillator1.connect(context.destination); // Connect sound source 1 to output oscillator1.start(0); // Play sound source 1 instantly oscillator2.type = "square"; // Square wave oscillator2.frequency.value = 100; // Frequency in hertz oscillator2.connect(gainNode2); // Connect sound source 2 to gain node 2 gainNode2.connect(context.destination); // Connect gain node 2 to output gainNode2.gain.value = 0.3; // Set gain node 2 to 30 percent oscillator2.start(2); // Play sound source 2 after two seconds
Now Create a Triple Oscillator on your Own
We can use the same technique to create more layers of sound. This time, see if you can figure it out before looking at the code below. Let’s create a triple oscillator. Leave oscillator1 and oscillator2 the same. Create a new sound source called oscillator3. Oscillator3 should be a triangle wave set to half the frequency of oscillator2, eighty percent volume, and is played after four seconds.
Go ahead and try it out on your own.
Did it work? Good job! If not, don’t worry. You can compare yours to the code below. The final code for your triple oscillator stack should look something like this.
var context = new AudioContext(); // Create audio container oscillator1 = context.createOscillator(); // Create sound source 1 oscillator2 = context.createOscillator(); // Create sound source 2 oscillator3 = context.createOscillator(); // Create sound source 3 gainNode2 = context.createGain(); // Create gain node 2 gainNode3 = context.createGain(); // Create gain node 3 oscillator1.type = "sine"; // Sine wave oscillator1.frequency.value = 200; // Default frequency in hertz oscillator1.connect(context.destination); // Connect sound source 1 to output oscillator1.start(0); // Play sound source 1 instantly oscillator2.type = "square"; // Square wave oscillator2.frequency.value = 100; // Frequency in hertz oscillator2.connect(gainNode2); // Connect sound source 2 to gain node 2 gainNode2.connect(context.destination); // Connect gain node 2 to output gainNode2.gain.value = 0.3; // Set gain node 2 to 30 percent oscillator2.start(2); // Play sound source 2 after two seconds oscillator3.type = "triangle"; // Triangle wave oscillator3.frequency.value = 50; // Frequency in hertz oscillator3.connect(gainNode3); // Connect sound source 3 to gain node 3 gainNode3.connect(context.destination); // Connect gain node 3 to output gainNode3.gain.value = 0.8; // Set gain node 3 to 80 percent oscillator3.start(4); // Play sound source 3 after four seconds
Well, that’s about it for Web Audio API Oscillators. Next, I’ll share some techniques for toggling oscillators on and off. I’m ready to explore the outer limits of imagination. Are you? The possibilities are endless. How are you going to use the Web Audio API to make the web awesome?
Other tutorials in this series
- Web Audio API Basics
- Web Audio API Audio Buffer
- Play a Sound with Web Audio API
- Controlling Web Audio API Oscillators
- Web Audio API BufferLoader
- Timed Rhythms with Web Audio API and JavaScript
Leave a Reply