On my never-ending search for new things to try, I wanted to see if a browser could play music. A simple Google search brought me to the Web Audio API.

Web Audio API

First a Web Audio API Context object needs to be made as so

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

Sound is basically a waveform of some frequency. The pleasant sounding notes of a piano are just certain specific frequencies.

Without going into much depth, the first thing one needs is an OscillatorNode. An OscillatorNode basically represents a periodic waveform, like a sine wave or a square wave. It can be made using the createOscillator method of an AudioContext. Here’s an example

//Create OscillatorNode
var oscillator = audioCtx.createOscillator();

oscillator.type = 'sine';
oscillator.frequency.value = 1000; // value in hertz

The AudioContext is then linked to an input for a destination such as headphones or a speaker and the OscillatorNode is connected to it.

oscillator.connect(audioCtx.destination);
oscillator.start();

This will simply play a 1000 Hz tone which can be stopped using oscillator.stop();.

Seeing all this I had an idea to make the browser play a random tune selecting from notes of certain frequencies. However this leads to several pitfalls.

When you reuse an oscillator object for different notes, the frequency transition causes an audible sliding noise. The solution is to use different oscillators for each note played.

The second issue is that you may notice a clipping sound when you end the note. This might not seem like much of an issue but will definitely cause problems when many notes are played back to back relatively quickly. Here’s a demo.

Band.js

Band.js is a library based on the Web Audio API which makes playing rhythmic notes and different time signatures very easy. It’s greatest advantage over the bare API is the ease of timing notes. Here’s a nice tutorial I found on Band.js.

To set a tempo, all you have to do is

var music = new BandJS();
music.setTimeSignature(4,4);
music.setTempo(116);

Then you make an “instrument” using the createInstrument() method and adding notes is as simple as using the note() method. It has the time and key as arguments.

instrument.note('quarter', 'D4'); //D key of the 4th octave

Once that is done, we let Band.js know the music is finished after which we can play, pause or stop it.

instrument.finish();
music.end();

music.play();
music.stop();

My Random Tune Generator

The first approach was to play the notes at random. I chose all the major notes of the 4th quadrant and played each as a quarter note. It worked but sounded a bit too random.

Then I assigned weights (probabilities of being played next) to each of the notes depending on the current note being played. For example, if the current note being played is F, then E and G will have the most weight and it decreases as we go further from the current note. This sounds much better as there is often a continuous string of notes being played rather than random jumps. The timing is also chosen at random between a quarter note and eighth note.

You can find my random tune generator here. Here is the source code for it. I plan on improving the weight algorithm further to make it sound even more natural.