Synthesizing Musical Sounds with Web Audio API – Part 2

Web Audio API is a system for creating, controlling, and manipulating audio in a Web browser using JavaScript.

This series of articles is intended to demonstrate the basic concepts needed to synthesize musical sounds using Web Audio API.

In part 1 of this series, we created a Web page and JavaScript code to start and stop playing a tone and to add a very short fade-in and fade-out to make the start less abrupt and prevent annoying click/pop sounds when stopping.

With that code, the tone is always at 440 Hz (Middle A) and is always a sine wave, which is a simple, pure timbre with no overtones. Now, let’s update the code to let us play tones with different frequencies and timbres.

Now, you can change the shape of the wave to be any of sine, square, sawtooth, or triangle, and you can change the frequency in a range from 20 Hz to 20000 Hz (20 kHz) which is roughly the human hearing range.

If you check the documentation for the type parameter of OscillatorNode, you will notice that there is also a “custom” value that we have not included as a selection. That value is used in conjunction with the setPeriodicWave() method to define a custom waveform, and you can read the documentation for more details on how to use that.

Like the gain property of a GainNode, the frequency property of an OscillatorNode  is a reference to an AudioParam, so we don’t assign directly to it. We’re changing the frequency value immediately though and not trying to gradually change it from one to value another, so we can simply assign to frequency’s value  property rather than scheduling a change as we did with the gain.

At this point, we’re dealing with pitch only in terms of frequency, but that’s not very useful for creating music. We generally talk abut musical pitch in terms of notes in a musical scale.

In Western music, we usually are working with an equal-tempered 12-tone scale. “Equal tempered” means that the ratio between frequencies of any 2 consecutive notes is the same as between any other consecutive notes, and 12-tone means there are 12 notes in a scale that spans 1 octave. An interval of 1 octave represents a doubling of the frequency, so with Middle A at 440 Hz, the A above Middle A is 880 Hz, and the A below Middle A is 220 Hz. The upshot of all of this is that the ratio between any consecutive notes in an equal-tempered, 12-tone scale is the 12th root of 2.

Here is an update to the code that allows the pitch to be selected in terms of octave numbers and named note values.

You have probably noticed that the sound is much louder with some of the waveforms (particularly Square and Sawtooth) than others. This is not due to any problem or bug. It is due to the fact that those waveforms have a lot more intensity than others at the same amplitude.

Any waveform can be treated as the sum of one or more sine waves, and each of those sine waves has a particular intensity depending on its amplitude and pitch. Square and sawtooth waves contain a lot of intense overtones (sine waves at multiples of the fundamental frequency) so they sound louder than the other waveforms.

That leads us to the topic of filtering which will be covered in part 3 part of this series.