Procedural Music Tutorial — Part 1

Welcome to this tutorial series about procedural music!

We will take a deep dive into the mystery of music composition by computers with the help of Artificial Intelligence.

Here are some suggested prerequisites for this part:

It might also be good to read about music theory before diving into the procedural music rabbit hole.

But we will start with the basics first: Playing music notes

Playing Notes in the Browser

We will use the Web Audio API for playing the notes directly in the browser.

Try out the following example below by clicking on the ‘Result’ tab and then the ‘Play Some Notes!’ button:

If you get a dialog showing that your browser is not supporting Web Audio, then you probably have to switch or upgrade your browser. This example has been tested in Firefox 80, Chrome 85 and Edge 85 on Windows 10.

Example Explained

Let’s take a look at how we managed to play those notes!

Here is the basic structure of the code in that JSFiddle example:

The playNotes() function is the entry point that is executed when clicking the button. It schedules the playback of three notes starting at 0, 0.5 and 1 seconds being 1 second long each. They partially overlap and outline a single musical chord.

The setup() function creates the Web Audio context which enables the browser to generate and process audio.

The playNote() function schedules a single note to play. We use a so-called MIDI note value as input to specify the note frequency so we also need the midiNoteToFrequency() function to convert that value into a frequency (Herz) that we use to setup the sound source.

The playNote() Function

Now we take a closer look at the playNote() function in the example:

The Web Audio API uses nodes to generate and process audio. In our example, we create an oscillator node to generate the basic waveform and connect it to a gain node that controls the volume or amplitude of the note.

The ‘ctx’ variable is the Web Audio Context that we create in the setup() function (not shown here). It is an ugly global variable in this example, but it is OK.

Then we connect the note’s gain node to the master gain node (also created in the setup() function) and schedule the start and stop of the oscillator node.

The setup() Function

Here is a listing of the setup() function:

This function creates the Web Audio context and also the master gain node that we connect all the notes’ local gain node to. Finally, we connect the master gain to the context’s destination, which makes the audio come out from our speakers.

End of Part 1

This is the end of this part of the tutorial series!