Chapter 18 - Tuning Systems and Scales

In this chapter we will look at how we can explore tuning systems, scales and microtonal composition using algorithmic means to generate tunings and scales.

The SynthDefs

For this chapter we want as pure waveform as possible so we can hear the ratios between the notes.

(
// We include two envelopes to choose from.
SynthDef(\pure, {arg freq=440, pan=0.0, vol=0.5, envdur=0.5, envType=0;
	var signal, envArray, env;
	env = EnvGen.ar(Env.perc(0.01, envdur), doneAction:2);
	signal = Pan2.ar(SinOsc.ar(freq), pan) * env  * vol;
	Out.ar(0, signal);
}).add;

// and another one almost identical that plays a sample
SynthDef(\puresample, {arg bufnum, rate=1, pan=0.0, vol=0.5, envdur=0.5, envType=0;
	var signal, envArray, env;
	envArray = [	
		EnvGen.kr(Env.linen(0.05, envdur, 0.1, 1), doneAction:2), 
			EnvGen.kr(Env.perc(0.01, envdur), doneAction:2)
			];
	env = Select.kr(envType, envArray);
	signal = Pan2.ar(PlayBuf.ar(1, bufnum, rate), pan) * env * vol;
	Out.ar(0, signal);
}).add;
)

Tuning systems are generally called “temperaments”. There are many different temperaments, but since the inventon of the piano the equal temperament has become the most common temperament and is typically used in computer music software.

For a bibliography and further information on scales and tunings, visit:

http://www.huygens-fokker.org/scala/

The scales can be found here: http://www.huygens-fokker.org/docs/scales.zip

A good source for microtonal theory is the Tonalsoft Encyclopedia of Microtonal Music Theory: http://tonalsoft.com/enc/

// NOTE: Tuning systems are not scales. We can have scales in different tuning systems.

Equal Temperament

Equal temperament is the most common tuning system in Western music. The octave is divided logarithmically into series of equal steps, most commonly the twelve tone octave. Other systems are also used such as the nineteen tone equal temperament (19-TET) or the thirty one tone equal temperament (31-TET).

Indian and Arabic music often uses a twenty four tone equal temperament (24-TET), although the instruments are frequently tuned using just intonation. Javanese Gamelan music is mainly tuned in a 5-TET

About the cent: The cent is a logaritmic unit (of equal steps) where 1200 represent an octave. In a 12-TET system, the half-note (of two adjacent keys on a keyboard) is 100 cents.

The logarithmic formula for pitch (exponential) for 12 tone equal temperament can be found in the following formula: fundFreq * 2.pow(n/12); (or roughly 1.05946309)

For Equal temperament of 12 notes in an octave these are the values we multiply the fundamental key with:

1 Array.fill(12, {arg i; 2.pow(i/12);})

// -> returns : [ 1, 1.0594630943593, 1.1224620483094, 1.1892071150027, 1.2599210498949, 1.33483985417, 1.4142135623731, 1.4983070768767, 1.5874010519682, 1.6817928305074, 1.7817974362807, 1.8877486253634 ]

(
var freq, n_TET;
n_TET = 25; // try, 5 19, 24, 31, 72...
freq = 440;
~eqTempFreqlist = Array.fill(n_TET, {arg i; freq * 2.pow(i/n_TET);});

~eqTempFreqlist = ~eqTempFreqlist.add(freq*2); // let's add the octave finally

[\freqlist, ~eqTempFreqlist].postln;

Task({
	~eqTempFreqlist.do({ arg freq, i; // first arg = item in the list, next arg = the index (i)
		Synth(\pure, [\freq, freq]);
		0.5.wait;
	});
}).start;
)

// now compare the list we've got (in a 12-TET)
~eqTempFreqlist.size
// to this:
[69,70,71,72,73,74,75,76,77,78,79,80].midicps // the midi notes in an octave starting with A

// and further... you can check the MIDI notes of a say 19-TET equal temperament:
~eqTempFreqlist.cpsmidi // where we get floating point MIDI notes

NOTE (SC LANG): If you are wondering about the ~freqlist.do compare this:

1 a = [111,222,333,444,555,666,777,888];
2 
3 a.do({arg item, i; [\item, item, \i, i].postln;}) // a is the array

To this:

1 a.size.do({arg i; [\item, a[i], \i, i].postln;}) // a.size is an integer.

Just Intonation

Just intonation is a very natural system frequently used by vocalists or instrumentalists who can easily tune the pitch. Instruments tuned in just intonation will have to be retuned in order to play in a different scale. This is the case with the Hapsichord for example.

Just intonation is a method of tuning intervals based exclusively on rational numbers (integers). It is based on the intervals of the harmonic series. Depending on context, the ratio might be different for the same note. (e.g. 9/8 and 10/9 for the major second). Any interval tuned as ratio of whole numbers is a just interval, but usually it is only ratios with small numbers.

Examples of intervals:

2/1 = octave 3/2 = fifth 4/3 = fourth 5/4 = major third 6/5 = minor third

Many composers (e.g. La Monte Yong and Terry Riley) prefer to compose for just intonation tuned instruments.

A major scale ~justIntFreqlist8 = [1, 9/8, 5/4, 4/3, 3/2, 5/3, 15/8];

A whole 12 note octave

1 ~justIntFreqlist = [1/1, 135/128, 9/8, 6/5, 5/4, 4/3, 45/32, 3/2, 8/5, 27/16, 9/5, 15/8, 2/\
2 1];

And we put in a fundamental note (A)

1 ~justIntFreqlist = ~justIntFreqlist * 440

Let’s play the scale:

(

Task({
	~justIntFreqlist.do({ arg freq, i; // 1st arg is the item in the list, 2nd is the index (i)
		Synth(\pure, [\freq, freq]);
		0.7.wait;
	});
}).start;
)

// test some versions of just intonation

~justIntFreqlist1 = [1/1, 135/128, 9/8, 6/5, 5/4, 4/3, 45/32, 3/2, 8/5, 27/16, 9/5, 15/8, 2\
/1];
~justIntFreqlist2 = [1/1, 16/15, 9/8, 6/5, 5/4, 4/3, 45/32, 3/2, 8/5, 5/3, 16/9, 15/8, 2/1]
~justIntFreqlist3 = [1/1, 25/24, 9/8, 6/5, 5/4, 4/3, 45/32, 3/2, 8/5, 5/3, 9/5, 15/8, 2/1];
~justIntFreqlist4 = [1/1, 16/15, 9/8, 6/5, 5/4, 4/3, 17/12, 3/2, 8/5, 5/3, 9/5, 15/8, 2/1];

~justIntFreqlist1 = ~justIntFreqlist1 * 440
~justIntFreqlist2 = ~justIntFreqlist2 * 440
~justIntFreqlist3 = ~justIntFreqlist3 * 440
~justIntFreqlist4 = ~justIntFreqlist4 * 440

// here we listen to different tunings in parallel and we can hear the difference:

(
Task({
	13.do({ arg freq, i; // first arg is the item in the list, next arg is the index (i)
		Synth(\pure, [\freq, ~justIntFreqlist1[i], \envdur, 1.56]);
		Synth(\pure, [\freq, ~justIntFreqlist2[i], \envdur, 1.56]);
		//Synth(\pure, [\freq, ~justIntFreqlist3[i], \envdur, 1.56]); // try these as well
		//Synth(\pure, [\freq, ~justIntFreqlist4[i], \envdur, 1.56]);
		1.4.wait;
	});
}).start;
)

Pythagorean tuning

Pythagorean tuning was invented by the Greek Philosopher Pythagoras in the 6th century BC. He was interested in harmony, geometry and beans. The Pythagorean tuning is based on perfect fifths, fourths and octaves.

~pythFreqlist8 = [1, 9/8, 81/64, 4/3, 3/2, 27/16, 243/128, 2/1]; // a major scale

~pythFreqlist = [1, 256/243, 9/8, 32/27, 81/64, 4/3, 729/512, 3/2, 128/81, 27/16, 16/9, 243\
/128, 2/1];

~pythFreqlist = ~pythFreqlist * 440;

(

Task({
	~pythFreqlist.do({ arg freq, i; // first arg is the item in the list, next arg is the inde\
x (i)
		Synth(\pure, [\freq, freq]);
		0.7.wait;
	});
}).start;
)

Now let’s compare Equal Temperament to the Pythagorean tuning.

First we make the equal temperament scale array

~eqTempFreqlist = Array.fill(12, {arg i; 440 * 2.pow(i/12);});
~eqTempFreqlist = ~eqTempFreqlist.add(440*2); // let's add the octave finally

(
Task({
	12.do({ arg freq, i; // first arg is the item in the list, next arg is the index (i)
		Synth(\pure, [\freq, ~pythFreqlist[i], \envdur, 1]);
		Synth(\pure, [\freq, ~eqTempFreqlist[i], \envdur, 1]);
		1.4.wait;
	});
}).start;
)

// and here we compare Just Intonation with Pythagorean tuning.

(
Task({
	12.do({ arg freq, i; // first arg is the item in the list, next arg is the index (i)
		Synth(\pure, [\freq, ~pythFreqlist[i], \envdur, 1]);
		Synth(\pure, [\freq, ~justIntFreqlist[i], \envdur, 1]);
		1.4.wait;
	});
}).start;
)

Scales

Scales are usually but not necessarily designated for an octave - so they repeat themselves over all octaves. There are countless scales with different note count, the most common in Western music is the diatonic scale. Other common scales (defined by note count) are chromatic (12 notes), whole tone (6 notes), pentatonic (5 notes) and octatonic (8 notes)

A dictinary of Scales

James McCartney wrote this dictionary of scales. (they are MIDI notes - no microtones and all are equal tempered)

(
z = (
// 5 note scales
	minorPentatonic: [0,3,5,7,10],
	majorPentatonic: [0,2,4,7,9],
	ritusen: [0,2,5,7,9], // another mode of major pentatonic
	egyptian: [0,2,5,7,10], // another mode of major pentatonic
	
	kumoi: [0,2,3,7,9],
	hirajoshi: [0,2,3,7,8],
	iwato: [0,1,5,6,10], // mode of hirajoshi
	chinese: [0,4,6,7,11], // mode of hirajoshi
	indian: [0,4,5,7,10],
	pelog: [0,1,3,7,8],
	
	prometheus: [0,2,4,6,11],
	scriabin: [0,1,4,7,9],
	
// 6 note scales
	whole: (0,2..10),
	augmented: [0,3,4,7,8,11],
	augmented2: [0,1,4,5,8,9],
	
	// hexatonic modes with no tritone
	hexMajor7: [0,2,4,7,9,11],
	hexDorian: [0,2,3,5,7,10],
	hexPhrygian: [0,1,3,5,8,10],
	hexSus: [0,2,5,7,9,10],
	hexMajor6: [0,2,4,5,7,9],
	hexAeolian: [0,3,5,7,8,10],
	
// 7 note scales
	ionian: [0,2,4,5,7,9,11],
	dorian: [0,2,3,5,7,9,10],
	phrygian: [0,1,3,5,7,8,10],
	lydian: [0,2,4,6,7,9,11],
	mixolydian: [0,2,4,5,7,9,10],
	aeolian: [0,2,3,5,7,8,10],
	locrian: [0,1,3,5,6,8,10],
	
	harmonicMinor: [0,2,3,5,7,8,11],
	harmonicMajor: [0,2,4,5,7,8,11],
	
	melodicMinor: [0,2,3,5,7,9,11],
	bartok: [0,2,4,5,7,8,10], // jazzers call this the hindu scale
	
	// raga modes
	todi: [0,1,3,6,7,8,11], // maqam ahar kurd
	purvi: [0,1,4,6,7,8,11],
	marva: [0,1,4,6,7,9,11],
	bhairav: [0,1,4,5,7,8,11],
	ahirbhairav: [0,1,4,5,7,9,10],
	
	superLocrian: [0,1,3,4,6,8,10],
	romanianMinor: [0,2,3,6,7,9,10], // maqam nakriz
	hungarianMinor: [0,2,3,6,7,8,11],	
	neapolitanMinor: [0,1,3,5,7,8,11],
	enigmatic: [0,1,4,6,8,10,11],
	spanish: [0,1,4,5,7,8,10],
	
	// modes of whole tones with added note:
	leadingWhole: [0,2,4,6,8,10,11],
	lydianMinor: [0,2,4,6,7,8,10],
	neapolitanMajor: [0,1,3,5,7,9,11],
	locrianMajor: [0,2,4,5,6,8,10],
	
// 8 note scales
	diminished: [0,1,3,4,6,7,9,10],
	diminished2: [0,2,3,5,6,8,9,11],
	
// 12 note scales
	chromatic: (0..11)
);
)
z.at('chromatic').postln;

// now we try one of those scales

(
x = z.at('hirajoshi').copy; // test the scales above by replacing the name
x = x.add(12); // add the octave
x = x.mirror;

Task({
	x.do({ arg ratio, i; // first arg is the item in the list, next arg is the index (i)
		Synth(\pure, [\freq, (69+ratio).midicps, \envdur, 0.94]);
		0.41.wait;
	});
}).start;
)

(
// do we get a nice melody?
Task({
	x.mirror.do({ arg ratio, i; // first arg is the item in the list, next arg is the index (i)
		Synth(\pure, [\freq, (69+x.choose).midicps, \envdur, 0.84]);
		0.18.wait;
	});
}).start;
)

{language= JavaScript, line-numbers=off}

The Scala Library

For a proper exploration of scales we will use the Scala project and the SCL class written in SuperCollider to use the Scala files.

The Scale Archive can be found here (with over 3000 scales): http://www.huygens-fokker.org/docs/scales.zip

And a SuperCollider class that interfaces with the archive can be found here (XiiScala.sc) https://github.com/thormagnusson/TuningTheory

Note that you have to provide the path to where you install your Scala libaray for example “~/scwork/scl/”

a = XiiScala(“bohlen-p_9”); a.tuning.octaveRatio a.degrees a.semitones a.pitchesPerOctave

z = x.degrees.mirror;

( Task({ z.do({ arg ratio, i; // first arg is the item in the list, next arg is the index (i) Synth(\pure, [\freq, 440*ratio]); 0.3.wait; }); }).start; )

( x = SCL.new(“cairo.scl”.standardizePath, 440); z = x.getRatios.mirror;

Task({ z.do({ arg ratio, i; // first arg is the item in the list, next arg is the index (i) Synth(\pure, [\freq, 440*ratio]); 0.3.wait; }); }).start; )

( x = SCL.new(“kayolonian_s.scl”.standardizePath, 440); z = x.getRatios.mirror;

Task({ z.do({ arg ratio, i; // first arg is the item in the list, next arg is the index (i) Synth(\pure, [\freq, 440*ratio]); 0.3.wait; }); }).start; )

Using Samples

We can of course control the pitch of sampled sounds too, and here the playback rate will control the pitch o f the sample.

First we load a sound and we get a sound with a simple tone (replace this sound with your own)

1 b = Buffer.read(s, "sounds/xylo/02.aif");

The pythagorean scale:

~pythFreqlist8 = [1, 9/8, 81/64, 4/3, 3/2, 27/16, 243/128, 2/1]; // a major scale

~pythFreqlist8 = ~pythFreqlist8.mirror;

(
{
	~pythFreqlist8.do({arg item;
		Synth(\puresample, [\bufnum, b.bufnum, \rate, item, \envType, 1]);
		Synth(\pure, [\freq, 752*item]); // 752 is just rough freq of the 02.aif sample
		0.5.wait;
	});
}.fork
)

x = SCL.new("degung5.scl".standardizePath, 440);

x = SCL.new("diaconv6144.scl".standardizePath, 440);

x = SCL.new("bagpipe1.scl".standardizePath, 440);

x.name
x.steps // how many notes are there in the scale
x.getRatios


Synth(\puresample, [\bufnum, b.bufnum, \rate, 1, \envType, 0]);
Synth(\pure, [\freq, 752]);


// p is our scale
p = x.getRatios
p.size

p = p.mirror // up and down again! (See Array helpfile for .mirror)

(
{
	p.do({arg item;
		Synth(\puresample, [\bufnum, b.bufnum, \rate, item, \envType, 1]);
		Synth(\pure, [\freq, 752*item]); // 752 is just rough freq of the 02.aif sample
		0.5.wait;
	});
}.fork
)

The Scale and Tuning Classes

SSuperCollider comes with Scale and Tuning classes. They make encapsulate and simplify the things we have done above in easy to use methods of the Scale and Tuning libraries.

An example - we choose a minor scale:

a = Scale.minor;
a.degrees; 
a.semitones;	
a.cents;	
a.ratios;	

d = Pdef(\minor_et12, Pbind(\scale, a, \degree, Pseq((0..7) ++ (6..0), inf), \dur, 0.5, \am\
p, 0.1)).play;

// we choose a tuning:
t = Tuning.just; // just intonation
a.tuning_(t);

e = Pdef(\minor_just, Pbind(\scale, a, \degree, Pseq((0..7) ++ (6..0), inf), \dur, 0.5, \am\
p, 0.1)).play;


// So let's listen to equal tempered and just intonation together. You can hear the beating
(
a = Scale.minor;
t = Tuning.et12; // equal tempered tuning 
a.tuning_(t);
d = Pdef(\minor_et12, Pbind(\scale, a, \degree, Pseq((0..7) ++ (6..0), inf), \dur, 0.5, \am\
p, 0.1)).play;

b = Scale.minor;
t = Tuning.just; // just intonation
b.tuning_(t);
e = Pdef(\minor_just, Pbind(\scale, b, \degree, Pseq((0..7) ++ (6..0), inf), \dur, 0.5, \am\
p, 0.1)).play;
)

Check the scale directory

1 Scale.directory

And the available tunings

1 Tuning.directory