Blog

Representing Music in Code: Pitch

Category: Programming
By: Sam Matucheski
12/18/18



If you are writing a program that involves music such as a music generator or a music theory analysis tool you’re going to run into the problem of how to represent music in whatever programming language you’re using. (For the purposes of this article, when I talk about music I am talking about music represented as notation, not recorded music as in sound files.) Basically I’m going to be talking about ways to represent this:

When you’re programming.

The first property of music I’m going to talk about is pitch. Pitch is probably the easiest property to represent. The way that I like to do it the most is to represent them numerically using an existing system, the MIDI standard. The MIDI specification represents all 12 notes in the chromatic scale as numbers between 0 -127 (the range of a signed byte) and sets note 60 as middle C. The value of all other notes are based off of this, so 61 is the C# above middle C, 59 is the B below middle C, 72 is the C an octave above middle C.

The music above in MIDI values would be 67, 71, 74, 69, 66, 67.

Here’s a chart with all of MIDI note values with their corresponding note name and octave.

Octave Note
C C# D Eb E F F# G Ab A Bb B
-1 0 1 2 3 4 5 6 7 8 9 10 11
0 12 13 14 15 16 17 18 19 20 21 22 23
1 24 25 26 27 28 29 30 31 32 33 34 35
2 36 37 38 39 40 41 42 43 44 45 46 47
3 48 49 50 51 52 53 54 55 56 57 58 59
4 60 61 62 63 64 65 66 67 68 69 70 71
5 72 73 74 75 76 77 78 79 80 81 82 83
6 84 85 86 87 88 89 90 91 92 93 94 95
7 96 97 98 99 100 101 102 103 104 105 106 107
8 108 109 110 111 112 113 114 115 116 117 118 119
9 120 121 122 123 124 125 126 127

Now there are different ways to notate note names with octaves. I personally like scientific pitch potation where middle C is C4. When combined with MIDI with note 60 as C4 the first 12 numbers (0 - 11) are octave -1 which looks a little weird when you write it out. The MIDI spec is nice because you have plenty of notes to work with (recall that a standard grand piano has 88 keys) and when you have access to all notes and octaves of the chromatic scale you can do some quick math to alter notes.

Want to increase the octave of a note? Simply add 12 times the amount of octaves you want to increase it by. Note += (12 x number of octaves) So to go from A3 to A5: 57 + (12 x 2) = 81

Want to build a major triad up from one note?

//We'll do this example in something C like with an array
int note = 60; //C4
int triad[3];

triad[0] = note;
triad[1] = note + 4; //64 = E4
triad[2] = note + 7; //67 = G4

Pretty neat, right? The only real problem I experience is when I'm doing something like making diatonic music. For example if I'm generating notes only found in C major with MIDI numbers it can be easiy to make something outside of C major and then you have to put some extra work into figuring out what notes belong in what key. One way is to translate the note into it's scientific pitch notation form but without the octave (so 48, 60, 72 ect. will be both C) and checking that against an array that holds just the notes for whatever key you're checking.

// Also we're in Javascript now because why not?

// Reduces MIDI note numbers to their smallest possible values (0 - 11)
// This makes it easier to put them in an array to get the name of the note
// instead of having an array of 127 elements with tons of redudent elements
function ReducePitch(pitch)
{
    if(pitch < 12)
    {
        return pitch;
    }
    else
    {
        return ReducePitch(pitch - 12);
    }
}
// Two arrays to deal with enharmonics spellings (disregarding double sharps and flats to keep things simple)
const NotesSharp = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "Ab", "B"];
const NotesFlat  = ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Ab", "Cb"];

// We're going to check if a note belongs in G Major
const GMajorNotes = ["G", "A", "B", "C", "D", "E", "F#"];

// Here's a note not in G major
var noteNumber  = 63 // D#/Eb
// G Major is a sharp key so we'll grab the sharp verson of the note if it's enharmonic
var noteText = NotesSharp[noteNumber];

// Ideally you'd have a function that would take the note and array to compare
// it against as arguments but I'm trying to keep it simple
var noteFound = false;
for(var i = 0; i < GMajorNotes.length; i++)
{
    if(noteText == GMajorNotes[i])
    {
        noteFound = true;
    }
}

So that's some things you can do when you represent pitch as MIDI numbers. Hope ya liked it and maybe found it useful. If you have any suggestions for me to write about like this contact info is on the about page, drop me an email and let me know what you think.

"But what about rhythm?" you may be asking. Don't worry, I'll cover it next time. Spoiler warning: it's trickier than pitch!

Till next time folks.