If you're new to sound design, recreating the sounds associated with telephones is a great place to start. This is because they are relatively simple to understand and can be implemented in Web Audio with just a few lines of code, but that's not to say they're completely trivial.
In this article we'll be recreating the following sounds:
There are some slight differences in how these sound from country to country but I'll be focusing on the UK versions. However, you should be able to use the techniques presented here to recreate any tone from any country.
This is the sound you hear when you pick up a landline phone. In the UK, it consists of 2 continuous sine waves at frequencies of 350 Hz and 440 Hz. So, to get things started, we'll create an Audio Context.
Now we're going to create a
Tone object that will keep all of our functions and properties nicely kept together. We'll pass in our Audio Context to be set as a property of the object. We'll also have a property called
status, which, if it equals 1, indicates the tone is playing, otherwise, if it is 0 the dial tone will be off.
Next we'll write a
setup method that creates the 2 oscillator nodes and sets their frequencies to 350 Hz and 440 Hz. Even though we could connect these directly to the output, I prefer to connect them via a gain node, so I can adjust the volume more easily. (It will also prove useful later on, when we aren't dealing with continuous tones.) For extra realness, I'm going to connect in a low pass filter too, which cuts out any high frequencies, just like a real phone line would. With that in mind, I'll create a gain node and filter in this method too, connect both oscillators to the gain, and the gain to the filter.
Now we need to think about how we can start and stop the tone. We'll create a
stop() method to allow us to do this.
Next, we'll create a basic HTML user interface, consisting of a single button.
We also need to create an instance of the
Tone object. Next, we need to
add an event listener to the button. When the button is pressed, our event listener code
will determine whether we need to call the
And that completes dial tone. You can play around with a working version of this in the CodePen embed below.
Next up, we'll begin work on the DTMF (Dual Tone Multi Frequency) tones. These are the sounds you hear when you press numbers on the keypad, and, like the dial tone, are made up of pairs of sine waves. The exact frequencies used for each number are displayed in the table below.
When it comes to actually implementing these in code, we have already done virtually all of the hard work when we created the dial tone. We just need a way to easily specify the 2 frequencies instead of having them hard coded into the setup method.
To do this, we'll modify the
Tone object to accept 2 new parameters
freq2. These will become properties of the object.
Then, we'll modify the
setup method to use the 2 new properties, instead of the hard coded frequencies we had before.
Now, once again, we need to create some sort of HTML user interface to work with our newly modified object. We're going to create 12 buttons, one for each DTMF tone.
In terms of functionality, we want to hear a tone when we click/tap and hold on one of these elements, then to switch off when we release our mouse/finger, mimicking a real dial pad.
dtmfFrequencies which contains all the 12 possible frequency combinations. When we detect a click, we'll be able to figure out which frequencies to play, by looking it up in this object. (I got the frequencies listed here from Wikipedia.)
Instead of creating 12 tone instances, we're just going to create one, and change the frequencies as required.
That completes the DTMF part of this article. You can see a working version in the codepen embed below, where I've also added a little bit of CSS to the interface.
Finally, we'll look at how to create the ringback tone. This is the sound you hear when the phone of the person you're calling is ringing. Once again, it is a tone made up of 2 sine waves (400 Hz and 450 Hz in the UK). However, unlike in previous examples, the tone is not continuous. In the UK, it has a pattern or "cadence" of 0.4s on, 0.2s off, 0.4s on, 2s off. The total length of this cycle is 3 seconds.
We can deal with this by leaving the oscillators running, but turning our gain node to 0 at the required times. There are a number of ways to do this, such as utilising some sort of timing system like the Web Audio Api Clock. However, because the pattern is quite a simple one, I'd like to use a low frequency oscillator (LFO).
If the pattern went on and off in equal times, say on for 0.5s then off for 0.5s etc, we could simply use a square wave as our LFO with frequency 1Hz to do this. However, our pattern is not quite as simple as that, so we'll have to be a bit more clever.
We're going to create our waveform data manually, and place it in a buffer (a small snippet of sound), which we'll loop continuously. The buffer needs to be 3 seconds long, and contain the following waveform.
To create the buffer, we'll need to use Web Audio's
We'll create and populate our buffer in a new method of the
Tone object called
Now that we've created our audio data and stored it in a buffer, we can load it into a buffer source node to complete the LFO. Once that's done, we need to connect the LFO to the gain param of our gain node, and and start the LFO playing to get the desired effect.
We'll also create a
stopRinging method that calls the
stop method, and also stops the LFO from playing.
Finally, as was the case with the dial tone, we'll create a toggle button, an instance of the new object, and set up an event listener which will easily allow us to start and stop the ringing.
The CodePen below demonstrates the finished demo.
If these telephone sounds have sparked your imagination, you may be interested in this Spotify playlist I'm gradually compiling of telephone sounds in popular music.