From C to C# minor - Understanding Music Theory through Programmers Eyes

Author: Ananda Kammampati

Dated: March 2021

 

01

I humbly dedicate this article to my favorite teacher Thamarai Selvi Somasundaram (now Vice Chancellor) who taught us C language back in College. As the saying goes “The best teacher is the one who makes you wanting to learn”, she is the one for many of us.

 

Never in my wildest imagination, I knew what she taught us will come handy after 3+ decades in understanding something that I have been dabbling and splitting my hair for weeks.  Seeing it though a C program cleared all the concepts in my head.

 

I am reminded on this great saying:

 

“ When you change the way you look at things, the things that you look at, change ”

 

Trust me when I say this – If you know how to traverse an array based on a given criteria (ascending, descending, reversing and such) you already have the basic foundations required to understand western music theory, scales, chord progressions and such. And same applies to South Indian Classical music as well with Swaras, Swarasthaanams, Raagas (with its own variations and nomenclature). Just like everything else out there, the scary parts are the terminologies. But once we peel the layers, microscope them under a high-level programming language, the theory reveals itself beautifully well. And all we see are patterns that emerge and all we need are our good old Data Structures and Algorithms to understand them much easier. Plain and simple.

 

After getting a little grip on Guitar chords, strumming patterns and fingers picking techniques, I ventured into understanding scales and chord progressions a little better. The more I read, the more it was confusing to me. I just couldn’t get them wrapped around my head. So, I stopped reading and started watching YouTube videos on that topic.

 

There are many fantastic teachers out there but in my humble opinion Casey Connor stands out above all like a Rock Star. His explanation on the basics of western music theory with his brilliant animation is out of this world!  As he started explaining the patterns, as weird as it may sound, I started seeing things in terms of data structures, linked lists, arrays, for/while loops and such. I couldn’t thank him enough for teaching all of this for free! (His Links are at the end).

 

For me to share the way I understood and to retro fit into IT programming lingo, I need to talk a little bit about music first, though I am absolutely not qualified to teach by any means. So please bear with me on this.

 

DISCLAIMER:

" IF ANY OF THIS EXPLANATION / CONTENT IS INACCURATE, IT IS SOLELY MY FAULT. I TAKE FULL RESPONSIBILITY AND ASK YOU FOR YOUR FORGIVENESS IN ADVANCE. IT IS POSSIBLE THAT I MIGHT HAVE GOTTEN SOME STUFF WRONG, THOUGH I HAVE DONE TO THE BEST OF MY KNOWLEDGE TO FINE COMB IT WELL FOR ACCURACY. "

 

To understand the basics of music theory, a good place to start is with the layout of all keys in a Piano or a musical Keyboard as everything is in one row and it is relatively easy to follow.

 

01

As a programmer, you can see an Array right there!  And if you notice the pattern, you can break that pattern into a single unit, define a Structure and equate it to a Linked List. Something like:

 

typedef struct octave {

int black_keys = 5;

int white_keys = 7;

int total_keys = 12;

struct octave *next;

struct octave *prev;

} octave_t;

 

I am jumping way ahead here but wanted to give you a taste of how this article is being laid out. More on this in detail as we go.

 

Rather than trying to grasp the entire keyboard’s layout at one shot, the right approach is to pick just 12 keys out of them (technical term ‘Octave’), stay focus only on those 12 keys to begin with, get familiar with the names of each key (better memorize them), and take time to understand the reasoning behind how the black keys are named after. And most importantly, pay attention to the relative locations of each key, with respect to its neighboring keys. Of course, all this takes time to sink in but these are the absolute basic building blocks to begin with.

02

When you take a closer look at the Keyboard, we see a pattern of 12 keys that keep repeating till the end. i.e., A Keyboard is made out of multiple Octaves arranged sequentially. So, when somebody says a 2 or 3 or a 5 Octave keyboard, it means that Keyboard holds that many Octaves. (Now is a good time to go back and check how many Octaves are there in the first image 🙂 )

 

What you notice is a pattern in their arrangement:

 

  • 2 black keys, followed by another 3 black keys
  • then followed by two black keys
  • then again followed by 3 more black keys and it goes on
  • each black key is separated by either one or at most two white keys in between.
  • And the pattern (i.e., the Octave) repeats

 

Question:  If the Keyboard is all a series of black and white keys, what would be the starting point of an Octave in a Keyboard ?

 

Any single Octave starts from a white key - the one on the left of the first two black keys. It goes on and ends at the white key on the right of the third black key. Hope the following image makes it clear.

03

Next comes the names of the keys, starting from the very first white key in an Octave.

 

As you can see below, the names of the white keys are straight forward. Each White Key is named after a single Alphabet.

05

But the black keys are named differently. Each black key is referred with two names, relative to its position.

 

For now, let us focus on the very first black key in the above Octave. It is referred with two names:

  1. C# (C Sharp)
  2. Db (D Flat)

 

The reason being:

  1. Since it comes after the Key C, it is referred as ‘C Sharp’ (C#)
  2. And at the same time, it is also referred ‘D Flat’ (Db) as it comes right before the key D
  3. A rule of thumb to remember is that each Black key is referred with two names relative to the names of its adjacent White keys on both sides
  4. As to which name to be used, is based on the context

 

The above explanation applies to all black keys, and in all Octaves. Hope you got the idea. Before proceeding further, now is a good time to pause and check the names of all black keys.

 

It is also important to understand that the right most C shown in dotted lines in the above image is the starting point of the next Octave in the keyboard. (hence shown in dotted lines).

 

Everything I have said so far with regards to an Octave applies to the second, third and every other Octave that follow till the end of the Keyboard. From here onwards, when I use the term “key”, it means an Alphabet, the name of a specific key in the Keyboard (I meant musical Keyboard. Not a computer keyboard)

 

Now comes the real meat and potatoes and here is where we need to put on our programmer’s hat.

 

What we do is that we will store the details of a single Octave in a Data Structure of a high-level language (C language) and play with it. Let us see what music theory we can learn / understand out of this exercise.

 

A better Data Structure to represent all Octaves in the Keyboard could be a Linked List because of its cyclic and easily repeatable nature. But for now, we will confine ourselves with just one Octave. So, we will keep it simple and use a much simpler Data Structure - Arrays instead.

 

A Single array of size 12 is good enough to hold all keys of a single Octave:

 

Let us go ahead and create an array named Key_C[12] and fill in with all the keys in the array. And to avoid confusion, let us use only the Sharp (#) names of the black keys (ignore the Flat (b) names for now).

08

From here onwards, I will go back and forth between a musician’s lingo and a programmer’s lingo.

 

If a musician has to define the above array in the musical lingo, these are the terms he will use.

 

  1. Root
  2. Half Step
  3. Whole Step

 

And this is how we have to interpret them in the programming lingo.

 

Root is like saying "the staring location”. In the above array, the location Key_C[0] is the Root

 

Half Step is like saying “one location next to the current location” in the array

 

Whole Step is like saying “two locations next to the current location” in the array

 

In the programming lingo, we know what i++ and i+=2 ; does with regards to traversing the array

 

With that understanding, it is fair to say:

 

A Half Step is equivalent to  i++ ;

 

A Full Step is equivalent to  i+=2 ;

 

Hope you got the idea so far.

 

Let us now come back to programming and spend a few minutes to print the array in different ways that we are familiar with.

 

Say if I tell you to PRINT the array, you might write something like this:

09

If I tell you to REVERSE the array, you might write like this:

10

And if I tell you to print ALTERNATE elements in the array, you might write like this:

11

The point that I am trying to get across is this – I only used the terms PRINT, REVERSE, ALTERNATE. I did not elaborate anything more in terms of what steps you needed to carry out. All those details are implied in those terms itself I used. I can just say ASCENDING ORDER and immediately you can think of multiple nested loops and a Bubble Sort Algorithm to get the desired output.

 

When I uttered those Capitalized terms, as a programmer you know instantly what steps are to be carried out.

 

PRINT the array implies - Starting from the first location, print the element in that location, move to the next location, print the element in that location and repeat the same action till you reach the last location in the array.

 

When I said REVERSE, you know it means:

 

Start from the last location in the array, print the element in that location, move to one location prior to the current location, print the element in that location and repeat the same action till you reach the first location of the array.

 

And finally, when I said print ALTERNATE you know it means:

 

Start from the first location of the array, print the element in that location, move two locations from the current location, print the element in that location, repeat the same action till you reach the last location of the array.

 

Basically, you construct your programming logic, loops, incrementing / decrementing counters, starting locations based on the desired outcome.

 

Now when a musician says “get me the MAJOR SCALE from that array" - like a Deer in the Headlights, we are completely frozen! We have no clue what (the heck) that means. The reason being we don’t know the sequence of steps that needs to be carried out to get his designed outcome.

 

But if the Musician is giving away the Algorithm to get his Major Scale, which is:

 

Whole Step + Whole Step + Half Step + Whole Step + Whole Step + Whole Step + Half Step

 

Or another way of saying it would be:

 

2 + 2 + 1 + 2 + 2 + 2 + 1

 

Now we are getting somewhere. So, let us break it down. Let us convert the Musician's language into our High Level Language that we programmers are familiar with:

Below is the Musician's ask: PLAY only the specific keys in the keyboard in a specific order

Major-Scale-Rule

And below is Programmer's interpretation:  TRAVERSE the array applying Musician's prescriptive pattern and print the array.

programmer-view

Let us write a simple C program to get him what he wants, applying his Algorithm:

12

We will create an array named major[7] and store his formula. we will use that as an incremental factor for traversing the array. And when we print the array, this is what we get:

13

Bingo! That is what the Musician was asking for. That is the C MAJOR SCALE. How cool is that.

 

And if the Musician asks us for a MINOR SCALE, we now know what we need from him. And here is the formula for a Minor Scale.

 

Whole Step + Half Step + Whole Step + Whole Step + Half Step + Whole Step + Whole Step

 

Also, same as: 2 + 1 + 2 + 2 + 1 + 2 + 2

 

Let us go ahead and modify the program to print the MINOR SCALE

14

Let us run the program and see what we get:

15

There you go! That is the C MINOR SCALE. Easy Peazy….

 

Finally, let us go for the Whole Enchilada ! Let us print all the MAJOR and MINOR SCALES for all 12 Keys in an Octave. You up for it ? Let’s do it then. Let us use a double dimensional array this time instead. Let us dedicate one row per Key in the array.

 

Here is how the double dimensional array look:

16

If you understand the way the above double dimensional array is filled in, half of the logic is done. The rest is all having appropriate loops, counters and printing them as per the Major and Minor scale formulas.

 

Here is how we fill up a double dimensional array of size 12 x 12 named 'note[12][12]'

 

We are going to fill up the array based on the layout of an Octave. We will have 12 rows. Each row is dedicated for a single Key. And we will have that Key as it’s first element in its row.

 

Start from a key, add next key in sequence, make a loop when needed, continue till all 12 key names are added for each row

 

For row 01: start from A …. end at G# (12 elements in its row)

For row 02: start from A# ...... end at A (12 elements in its row)

For row 03: start from B ...... end at A# (12 elements in its row)

For row 04: start from C ...... end at B (12 elements in its row)

For row 05: start from C# ...... end at C (12 elements in its row)

Hope you get idea

Repeat above steps for all 12 rows - from A to G#

 

And here is the final C program, where we reuse the same logic and code that we used before to print Major and Minor scales.

17

Now let us go compile + run and see what we get:

18

What we have printed above are 24 Musical scales. 12 Major scales and 12 Natural minor scales. Now from each scale shown above be it Major or Minor, we can derive what is known as a “Chord Progression” for each of them. To derive them, it is just a matter of hand picking only a few notes/keys on each scale (or from its own array to that matter), with its own formula to spell it out. It’s no rocket science once we know what to pick and what to skip because its own formula will guide us how to traverse through its array.

 

Apart from the above 24 scales, apparently there are 24 more! 12 Harmonic Minor scales (formula: "sharpen" the 7th note in each Natural Minor scale) and 12 Melodic Minor scales. But don’t let the names or terminologies scare you anymore. As a programmer once you understand the patterns, you can retrofit them into any data structure (arrays, linked list, etc) and format (YAML, JSON, Key/Value Store) of your choice that you are comfortable with and then slice and dice them, applying their formulas. Things will get relatively easier to assimilate and digest.

 

I am hoping to write a follow up article when time permits on Chord progression and other topics from whatever little I understood from Casey Connor's videos.

 

I also wanted to make this point loud and clear. Knowing any of this will in no way make us a musician instantly by any means whatsoever. Just by knowing the ingradients and steps in a recipe alone doesn’t make us a Cook (but a good start). Any Art needs practice, be it singing or playing a music instrument, which is a life long commitment and journey till Grave.

 

But the next time when you see a bunch of people (middle aged men mostly) doing all mumbo-jumbo talk on music theory, you don’t need to shy away anymore. You can also jump in and talk in a meaningful way and throw your weight around, if you choose to.

 

I sincerely hope I managed to shed some light to people with programming background to bootstrap themselves on music theory, as much as I could. If so, I would kindly urge you to donate whatever you could to Mr. Casey Connor. He is truly sowing the seeds for future musicians to flourish on this planet.

 

His links (videos 9, 10 and 11 are an absolute must to watch)

 

https://www.youtube.com/playlist?list=PL618khw0A-t5A7TyZmxAux_v_C3O7rO2l

 

https://lacinato.com/cm/software/donate

 

Let me end this article with my favorite Tamil Poet Avvaiyar's Quote:

 

quote-1

Peace ☮️

Ananda Kammampati