Play Chords

The music theory content can be found at Music Fundamentals on the Web.

The playing of chords using Tone.js involves playing an array of note names or frequencies at the same time. With scales we played a single note followed by another single note. Now we need to play a small array of notes (simultaneously) followed by another small array of notes. We start with triads but the concept is easily extended to more complex chords. Our array of chords will consist of an arbitrary length array consisting of sub-arrays of length 3 (representing the three note of the triad.) In addition we'll need to have a time value for each chord so each element in our main array will be a two element array itself (time value and chord array).

Triads

Just as we defined the interval structure of a scale with an array of numbers, we can similarly define the interval structure of chords with an array of numbers. Using the definitions of the major chords as listed below you can see the equivalent structure translated into an array of numbers. The root of the chord is listed as the number 0, then a root can be defined outside of this structure and it is easy to tranpose it to any root MIDI number. The second number (4) is the number of half steps in a major third. The third number (7) is the number of half steps in a perfect fifth.

As a first demonstration we set up an array of chords that plays all four types of triads (at a constant rhythm) for any selected root. The basic array is modified by the variable root, the resulting array of numbers are translated into note names using the MIDI_NUM_NAMES translation array. This will give us the correct sounds (but not necessarily the correct names) for the triads. And because this array uses only sharp names, it will spell the Eb major triad as D#,G,A#. It will sound correct, but you wouldn't want to print it out with that spelling.


// var root; // let user choose
var familyOfTriads = [[0,4,7],[0,3,7],[0,3,6],[0,4,8]];

function makeChordArray(root, chordFormula, timeInterval) {
    var indexMIDI
    var aChord = [];
    var timeAndChord = [];
    var toneTime = 0;
    var chordArray = [];
    for(let i=0; i<chordFormula.length; i++) {
        for(let j=0; j<chordFormula[i].length; j++) {
            // add the root to each chord tone
            indexMIDI = chordFormula[i][j] + Number(root);
            // tranlate to a pitch/octave name
            aChord.push(MIDI_NUM_NAMES[indexMIDI]);
        }
        j = 0;
        // create add time and chord together
        timeAndChord.push(toneTime.toNotation());
        timeAndChord.push(aChord);
        chordArray.push(timeAndChord);
        // now calc the time value for next time
        toneTime = toneTime.add(timeInterval);
        // clear the arrays;
        aChord = [];
        timeAndChord = [];
    }
    return chordArray;
}

// assume the user selects from a menu option such as the following
<select id="root">
<option value=57>A
<option value=58>Bb
<option value=59>B
<option value=60>C
...
</select>

// root = user's selection, i.e. "C" = root=60

Now we can use some code similar to PlayScale. Well make this version specific to our one goal and call the new function playFamilyOfTriads().


//	PIANO
var piano = new Tone.PolySynth(Tone.Synth, {
    "volume" : -8,
    "oscillator" : {
        "partials" : [1, 2, 5],
    },
    "portamento" : 0.005
}).toDestination();


function playFamilyOfTriads() {
    var rootMenu = document.getElementById("root");
    var root = rootMenu.options[rootMenu.selectedIndex].value;

    // this line is hardwired to the familyOfTriads global array, 
    // that will need to change to make this a more useful function
    var myChords = makeChordArray(root, familyOfTriads, '2n');

	var chordPart = new Tone.Part(function(time, chord){
		piano.triggerAttackRelease(chord, "2n", time);
	}, myChords ).start(0);

	chordPart.loop = true;
	chordPart.loopStart = "0:0";
	chordPart.loopEnd = "2:0";

	var tempo = document.myForm.tempo.value;
	Tone.Transport.bpm.value = tempo;   
	Tone.Transport.start("+0.1");
}

| tempo:

Let's modify the function to be more general purpose. We want the user to be able to select which chords to play, even if its limited to a list from a menu. So we want a playChords() function that can play any defined array of chords. Notice that the inner loop in makeChordArray() tests if j<chordFormula[i].length, this means that it isn't restricted to only three note triads but it can process whatever length that chord sub-array is. So that part of the code is good for a variety of chord types. But to make playFamilyOfTriads() more general (i.e. playChords() ) we need to extract the hardcoded familyOfTriads array and let that be a variable whose value is determined by the user.

Diatonic Triads

On a musical level when we are in the context of a scale such as the major scale, you also have an entire family of diatonic chords from that scale. We label those chords with roman numerals: I II III IV V VI VII with each root being the scale degree of that roman numeral. For example in the key of C major the roots of the roman numeral chords are (respectively) C D E F G A B. For the major scale the quality of the chords (major, minor, diminished or augmented) has a consistent order for all major scales.

For major scales: Diatonic triads

NOTE: there are no augmented triads created with notes from only a major scale. Also, many people use lowercase roman numerals for minor and diminished triads. If that style of notation is used then the diatonic triads are labeled: I ii iii IV V vi vii. However, I'll use capital roman numerals for ALL chord types (without it defining chord quality) because we'll be switching between major and minor keys while using the same roman numeral chord progression.

While it might be tempting to create an array of these structures to use in the context of major scale there is a more general method that will also work for the three form of minor. The diatonic triads are created by combining a interval of a diatonic third and fifth above any of the scale tones (which is labeled as the 'root' of the triad). So for C major:

The major scale always has the order of quality: major, minor, minor, major, major, minor, diminished. But a different scale will have different quality chords at those specific roman numerals. Each of the three forms of minor has its own unique series of chords. For A harmonic minor:

So a general approach to diatonic chords is to calculate a root, third, fifth on each scale degree on whichever scale we are working with. This approach allows us to explore, for example, the I V VI IV chord progression in major or three forms of minor using the same underlying code. In fact why limit ourselves to just root, third and fifth patterns from the scale. We can design it so that ANY combination of notes from the scale can be used to create a chord.

Inversions

Triads and other chords can be played in the basic voicing from low to high: root, third, fifth (known as root position). But they also can be voiced with either the third or the fifth as the lowest note. These addition voicings are known as inversions of the triad.

Root Position
The basic voicing from low to high: root, third, fifth (usually). Even if the third is above the fifth, as long as the root is the lowest tone it's in root position.
First Inversion
When the third of the chord is the lowest note it is called 1st inversion.
Second Inversion
When the fifth of the chord is the lowest note it is called 2nd inversion.

If we use inversions on some of the roman numerals we can voice all of diatonic (I II III IV V VI VII) triads within a single octave.

Before we get to creating our diatonic chords in major and each of the three forms of minor, I want to emphasise an important characteristic of minor keys: Any of these three forms can be used during a phrase in a minor key. A common minor key chord progression is [ Am - G - F - E ]=[ I VII VI V ] This chord progression is sometimes referred to as the Andalusian Cadence, but I know it as 'Hit the Road Jack' and others recognize it as 'Stray Cat Strut'. Bach has some hits using this progression also. This chord progression shows the mixture of both natural minor and harmonic minor. The G chord lives in A natural minor (but not A harmonic minor [G#dim]) and the E chord lives in A harmonic minor (but not A natural minor [Em]) The Am and F chords are in both the natural and harmonic minor forms. So in addition to having diatonic chords of each minor type we need some way of mixing the types within a single chord progression. One common approach is to modify the V chord of the natural minor form to become a major triad (in natural minor the V chord is minor). That would allow for the Andalusian Cadence to be used when the scale type is natural minor. This seems like a good feature to be able to turn on and off with a checkbox. We'll incorporate that idea into the next section.

Again we can use the remainer operator (%), this time to help keep our triads within an octave range. Assume we have a scale formula like major [0,2,4,5,7,9,11,12]. our triads are created by starting at any of the scale degrees and taking every other value for a total of 3 values. The pattern is [index,index+2,index+4]. For example, the I chord uses the values at indices 0,2,4, II chord use the values at indices 1,3,5 etc. But if we try to build a triad starting on index 4 of this array our last note's index will try to access something out-of-bounds (4,6,8). The remainder operator (%) provides a solution. There are seven different letter names in the scale. If we use (indexNumber %7) we'll force the index number to stay within our scale boundary. In many cases the resulting chord will be an inversion of the triad.

These voicing are a limited set and they don't allow us the kind of voiceleading that we would want. But as a first iteration of chord progressions code we'll select chords from a diatonic family that have these voicings. We'll allow the user to select from a menu a roman numeral chord progression and a key and scale type. Plus our check box that will modify the V chord in natural minor so that the third of the chord is raised a half step (one MIDI number) which will make the V chord a major quality chord (instead of minor). The chords are the correct notes but many times there is a preferred different voiceleading. We'll work on that in a later version.

chord progression | | tempo: Scale type:

Back to the Tone.js Setup page.