Chromatic Scale Example

This example plays a one-octave chromatic scale.

Sound

For this first example, let's start at the beginning with sound. Sound is a physical phenomenon caused by rapid and repeated changes in air pressure. These changes in air pressure are like waves on a pond and are called oscillations. The number of oscillations per second is called frequency, which our brains perceive as pitch.

Octave

Next, let's consider the octave. An octave is a fundamental aspect of sound that people can readily identify. From a physical perspective, each octave is a doubling of the frequency of the previous octave. There is a direct relationship between what we hear (an octave) and the underlying physics (a doubling in frequency).

Notes and Chromatic Scale

Western music divides each octave into 12 distinct pitches or notes. These 12 notes form a chromatic scale. On a piano, a chromatic scale consists of a sequence of 12 consecutive keys, counting both white (7) and black (5) keys.

var notesInChromaticScale = 12; // 12 semitones make up a complete octave

MIDI Notes

In the MIDI world, each pitch is assigned a MIDI note number from 0 to 127. This range covers the 88 keys of a standard piano and more. The first key on a standard piano is MIDI note 21. This is an A. We'll get into note names in the next example.

var first = 21; // MIDI note number for lowest note on a standard piano

To start playing a MIDI note, we turn it on by its MIDI note number. To stop playing a MIDI note, we turn it off by its MIDI note number.

Programming

Now let's move on to programming. In this JavaScript example we use ws.fire to fire events and turn MIDI notes on and off.

The object named ws is the Wildwood Soundworks JavaScript interface. The method fire is a built-in function that sends an event message to other components within the device.

For those who are not familiar with JavaScript, the letters ws represent an object name, the letters fire represent a method name, and the dot (.) separates them. A method is a function associated with an object. A function is a reusable building block: you tell it to do something, optionally pass it some parameters, it does it, and optionally returns a result.

Events

An event is a message (like a text message on your phone). It tells software components on the device to do something, or that something has happened.

The device's synthesizer listens for note_on and note_off events. When it receives note_on, it starts the sound, and when it receives note_off, it stops the sound.

The note_on event requires the channel (which of the 16 MIDI channels to use), the note number, the velocity (e.g. how fast you press the key) and a delay in milliseconds (used for "swing"). Velocity controls the volume of the note when it is played, from 0 (silent) to 127 (loud). We'll get into the details on channels in a later example.

Timing

Finally, we need to sleep a bit between starting the note and stopping the note to give the note a chance to play. We use the Wildwood Soundworks sleep method, which pauses for the specified number of milliseconds.

A millisecond is 1/1000 of a second, so 250 milliseconds is 250/1000 of a second, or 1/4 of a second.

In music terms, a song playing at 120 beats per minute (BPM) moves at 2 beats per second. That's 1/2 second per beat or 500 milliseconds per beat. If a single beat represents a quarter note, then 250 milliseconds is half of that, or an eighth note.

Example Source Code

Whew! That's a lot of background for this simple example, but hopefully it helps to fill in some missing pieces and explain why it all works the way it does.

Press the Copy button below to copy the example to the clipboard.

// Example: chromatic-scale.js - Play notes in a chromatic scale

// Here we initialize some variables to make the purpose of the numeric
// constants more understandable.

var notesInChromaticScale = 12; // 12 semitones make up a complete octave
var first = 21;     // MIDI note number for lowest note on a standard piano

var channel = 0;    // Channels in range 0 to 15 (MIDI channel 1 to 16)
var velocity = 80;  // MIDI velocity in range 0 to 127 (note volume)
var delay = 0;      // Delay in milliseconds before playing note (for swing)
var duration = 250; // 250 milliseconds is an eighth note at 120 bpm

// Define a new JavaScript function named playChromaticScale

function playChromaticScale()
{
    var last = first + notesInChromaticScale; // last note to play

    // Loop across the MIDI note range from first (21)
    // up to but not including last (33)

    for (var note = first; note < last; note++) {
        // Write the current MIDI note number to the console pane
        print("Playing note " + note);
        // Start playing the note
        ws.fire("note_on", channel, note, velocity, delay);
        // Let the note play
        ws.sleep(duration);
        // Stop playing the note
        ws.fire("note_off", channel, note);
    }
}

// Invoke the function we just defined

playChromaticScale();