15 Microtonality, Tunings and Modes

Interaction 15-1. Computing a harmonic series based on 100 Hz.

cm> (loop with f = 100 for h from 1 to 12
          collect (* f h))
(100 200 300 400 500 600 700 800 900 1000 1100 1200)
cm>

Example 15-1. Playing the harmonic series.

(define (play-harms frq low high rate)
  (process for h from low to high
           for f = (* frq (/ h low))
           for k = (keynum f :hz)
           output (new midi :time (now)
                       :keynum k
                       :duration (* rate .9))
           wait rate))

Interaction 15-2. Playing the harmonic series.

cm> (events (play-harms 440 8 16 .4) "micro.mid"
            :channel-tuning true)
"micro-1.mid"
cm> (events (play-harms 440 8 16 .4) "micro.mid"
            :channel-tuning 108)
"micro-2.mid"
cm> (events (play-harms 440 8 16 .4) "micro.mid"
            :channel-tuning false)
"micro-3.mid"
cm>

Example 15-2. Clearing pitchbends.

(define (clearbends )
  (process for c below 16
           output (new midimsg :time (now) 
                       :msg (make-pitch-bend c 0))))

Example 15-3. Playing the harmonic series.

(define (play-harms2 octs)
  (process with hz = (hertz 'c3)
           for h from 1 to (* 12 octs)
           for k = (keynum (* h hz) :hz)
           output (new midi time (now) 
                       duration 1.0 
                       amplitude (between 0.4 0.6) 
                       keynum (+ 48 (mod k 12)))
           wait .15))

Interaction 15-3. Playing four octaves of a normalized harmonic series.

cm> (events (play-harms2 4) "harms.mid" :channel-tuning 108)
"harms-1.mid"
cm> (events (clearbends ) "clearbends.mid")
"clearbends-1.mid"
cm>

Interaction 15-4. Converting cents to scaler values.

cm> (cents->scaler 1200)
2.0
cm> (scaler->cents 3/2)
702
cm> (scaler->cents 5/4)
386
cm> (scaler->cents 6/5)
316
cm> (cents->scaler 700)
1.4983070768766815
cm>

Example 15-4. Playing microtonal intervals.

(define (midi-ratio at note ratio dur)
  (let ((fkey (keynum (* (hertz note) ratio) :hz)))
    (list (new midi :time at :keynum note :duration dur)
          (new midi :time at :keynum fkey :duration dur))))

(define (compare-ratios note rat1 rat2 dur)
  (append (midi-ratio 0 note rat1 dur)
          (midi-ratio (+ dur .5) note rat2 dur)))

(define ct8 (list true 1 9))

Interaction 15-5. Playing and comparing ratios.

cm> (events (midi-ratio 0 'c4 5/4 3) "rat.mid"
            :channel-tuning true)
"rat-1.mid"
cm> (events (compare-ratios 'c4 5/4 (expt 2 4/12) 3)
            "rat.mid" :channel-tuning ct8)
"rat-2.mid"
cm>

Example 15-5. A process to play tuning examples.

(define (play-tuning tuning low high rate amp)
  (let* ((rise (loop for i from low below high collect i))
         (fall (loop for i downfrom high downto low collect i))
         (ran1 (shuffle (rest rise)))
         (ran2 (shuffle (rest rise)))
         (coda (loop for i from low to high collect i))
         (all (append rise fall ran1 ran2 coda)))
    (process for k in all
             for x = (keynum k :from tuning)
             output (new midi :time (now)
                         :keynum x
                         :amplitude amp
                         :duration (* rate .95))
             wait rate)))

Example 15-6. Converting harmonic numbers to ratios.

(define (harms->ratios low high)
  (loop for h from low to high collect (/ h low)))

(new tuning :name 'jmaj
     :ratios (harms->ratios 8 16))

(new tuning :name 'jmin
     :ratios (harms->ratios 9 18))

Interaction 15-6. A process to play microtonal examples.

cm> (hertz 40 :in #&jmaj)
261.6255653005986
cm> (hertz 45 :in #&jmin)
261.6255653005986
cm> (keynum 40 :from #&jmaj)
60.0
cm> (keynum 41 :from #&jmaj)
62.039100017307746
cm> (events (play-tuning #&jmaj 40 56 .25 .6) 
            "hscale.mid" :channel-tuning 108)
"hscale-1.mid"
cm> (events (play-tuning #&jmin 45 63 .25 .6)
            "hscale.mid" :channel-tuning 108)
"hscale-2.mid"
cm>

Example 15-7. Tuning definition for the Pythagorean Diatonic Scale

(new tuning :name 'pyth-d
     :ratios '(1 9/8 81/64  4/3  3/2  27/16 243/128 2))

Interaction 15-7. Converting key numbers to and from a tuning.

cm> (keynum 60 :to #&pyth-d)
35
cm> (keynum 36 :from #&pyth-d)
62.039100017307746
cm>

Interaction 15-8. Playing the Pythagorean diatonic scale.

cm> (events (play-tuning #&pyth-d 35 49 .3 .7) "pyth.mid"
            :channel-tuning 108)
"pyth-1.mid"
cm>

Interaction 15-9. The Big Lie.

cm> (expt 3/2 12)
531441/4096
cm> (expt 2 7)
128
cm> (= 531441/4096 128)
#f
cm> (/ 531441/4096 128.0)
1.0136432647705078
cm> (scaler->cents 1.0136432647705078)
23
cm>

Interaction 15-10. Comparing major thirds, minor thirds and minor seconds.

cm> (events (compare-ratios 'c4 5/4 81/64 3) 
            "maj3.mid" :channel-tuning '(#t 1 3))
"maj3-1.mid"
cm> (events (compare-ratios 'c4 6/5 32/27 3)
            "min3.mid" 
            :channel-tuning '(#t 1 3))
"min3-1.mid"
cm> (events (compare-ratios 'c4 256/243 2187/2048 3) 
            "min2.mid"
            :channel-tuning '(#t 1 3))
"min2-1.mid"
cm>

Example 15-8. Pythagorean chromatic scale.

(new tuning :name 'pyth-c
     :cents '(114 90 90 114 90 114 90 114 90 90 114 90))

Interaction 15-11. Listening to the Pythagorean chromatic scale.

cm> (events (play-tuning #&pyth-c 60 84 .3 .7) 
            "pyth.mid" :channel-tuning 108)
"pyth-2.mid"
cm>

Example 15-9. Alternate equal tempered scales.

(new tuning :name '5-tone
     :cents (loop repeat 5 collect (/  1200 5)))

(new tuning :name '24-tone
     :cents (loop repeat 24 collect 50))

(new tuning :name 'bohlen-pierce
     :ratios (loop for i to 13 collect (expt 3.0 (/ i 13))))

Example 15-10. A two octave version of the Pelog scale.

(new tuning :name 'pelog 
     :lowest 220.0
     :octaves #f
     :cents '((0    nem0)
              (125  barang0)
              (266  bem0)
              (563  gulu0)
              (676  dada0)
              (800  pelog0)
              (965  lima0)
              
              (1220 nem1)
              (1360 barang1)
              (1503 bem1)
              (1778 gulu1)
              (1905 dada1)
              (2021 pelog1)
              (2225 lima1)
              
              (2447 nem2)))

Example 15-11. Young's scale.

(new tuning :name 'young
     :ratios '((1 ef)
               (567/512 e)
               (9/8 f)
               (147/128 fs)
               (1323/1024 gs)
               (21/16 g)
               (189/128 a)
               (3/2 bf)
               (49/32 b)
               (441/256 cs)
               (7/4 c)
               (63/32 d)
               2)
     :octaves '(-1 10)
     :lowest (* (hertz 'a-1) 128/189))

Interaction 15-12. Values in Young's scale.

cm> (note 0 :in #&young)
ef-1
cm> (hertz 'a4 :in #&young)
440.0
cm> (keynum 'c4 :in #&young)
70
cm>

Example 15-12. A process to preview Young's scale.

 
(define (arp-chord notes rate dur amp)
  ;; arpeggiate a list of notes.
  (process with transp = 0
           for n in notes
           for k = (keynum n :from #&young)
           output (new midi :time (now)
                       :keynum (+ transp k)
                       :duration dur
                       :amplitude amp)
           wait rate))

Example 15-13. Scale and septimal interval relations.

(define youngs-scale 
   '(ef4 e4 f4 fs4 gs4 g4 a4 bf4 b4 cs5 c5 d5 ef5))
(define sept-7th         ; 7/4 seventh
   '(ef4 c5))
(define sept-min-3rds    ; 7/6 thirds
   '(e4 gs4 f4 g4 a4 cs5))
(define sept-maj-3rds    ; 9/7 thirds
   '(fs4 a4 b4 d5 cs5 e5 c5 f5))

Interaction 15-13. Listening to the scale and intervals.

cm> (events (arp-chord youngs-scale 0.4 2 .6)
            "young.mid" :channel-tuning (list true 0 8))
"young-1.mid"
cm> (events (play-tuning #&young 48 96 .15 .5) 
            "young.mid")
"young-2.mid"
cm> (events (arp-chord sept-7th 0 3 .6)
            "young.mid")
"young-3.mid"
cm> (events (arp-chord sept-min-3rds 0 2 .6)
            "young.mid")
"young-4.mid"
cm> (events (arp-chord sept-maj-3rds 0 2 .6)
            "young.mid")
"young-5.mid"
cm>

Example 15-14. Chords from The Well Tuned Piano.

(define opening-chord
   '(ef3 bf3 c4 ef4 f4 bf4))
(define magic-chord
   '(e3 fs3 a3 b3 d4 e4 g4 a4))
(define gamelan-chord
   '(fs3 a3 c4 e4))
(define tamiar-dream-chord
   '(b2 d3 g3 a3 b3 d4 g4 a4))
(define lost-lake-chord
  '(g2 b2 d3 fs3 g3 a3))
(define brook-chord
   '(bf3 c4 ef4 f4 g4 bf4 c5 ef5 f5 bf5))
(define pool-chord
   '(ef3 f3 fs3 bf3 c4 ef4 f4 bf4))

Interaction 15-14. Sonorities from The Well Tempered Piano.

cm> (events (arp-chord opening-chord 0.25 3 .6) 
            "young.mid" :channel-tuning (list true 0 8))
"young-6.mid"
cm> (events (arp-chord magic-chord 0.25 3 .6)
            "young.mid")
"young-7.mid"
cm> (events (arp-chord gamelan-chord 0.25 3 .6)
            "young.mid")
"young-8.mid"
cm> (events (arp-chord tamiar-dream-chord 0.25 3 .6)
            "young.mid")
"young-9.mid"
cm> (events (arp-chord lost-lake-chord 0.25 3 .6)
            "young.mid")
"young-10.mid"
cm> (events (arp-chord brook-chord .15 5 .6)
            "young.mid")
"young-11.mid"
cm> (events (arp-chord pool-chord .15 5 .6)
            "young.mid")
"young-12.mid"
cm>

Interaction 15-15. Transposing modes.

cm> (new mode :name 'dorian :steps '(d e f g a b c d))
#<mode: "dorian" (on d)>
cm> (keynum 'd4 :in #&dorian)
35
cm> (loop for i from 35 to 42
          collect (note i :in #&dorian))
(d4 e4 f4 g4 a4 b4 c5 d5)
cm> (transpose #&dorian 'cs)
#<mode: "dorian" (on cs)>
cm> (loop for i from 35 to 42
          collect (note i :in #&dorian))
(cs4 ds4 e4 fs4 gs4 as4 b4 cs5)
cm>

Example 15-15. Messiaen's Modes of Limited Transposition.

(new mode :name 'mode1 :steps '(c d e fs gs bf c))
(new mode :name 'mode2 :steps '(c df ef e fs g a bf c))
(new mode :name 'mode3 :steps '(c d ef e fs g af bf b c))
(new mode :name 'mode4 :steps '(c df d f fs g af b c))
(new mode :name 'mode5 :steps '(c df f fs g b c))
(new mode :name 'mode6 :steps '(c d ef fs gs as b c))
(new mode :name 'mode7 :steps '(c df d ef f fs g af a b c))

(define chords '((0 2 4 5) (0 1 3 5) (0 2 3 4)))

(define (messiaen mode start end rate)
  (let ((num (length chords)))
    (process for m from start to end
             for c = (list-ref chords (random num))
             for l = (note (transpose c m) :in mode)
             each n in l
             output (new midi :time (now)
                         :keynum n 
                         :duration (* rate 2))
             wait (odds .15 (* rate .5) rate))))

Interaction 15-16. Listening to Messiaen's Modes

cm> (events (messiaen #&mode2 35 50 .4)
            "messiaen.mid")
"messiaen-1.mid"
cm> (events (messiaen #&mode6 35 50 .4)
             "messiaen.mid")
"messiaen-2.mid"
cm>

Chapter Source Code

The source code to all of the examples and interactions in this chapter can be found in the file scales.cm located in the same directory as the HTML file for this chapter. The source file can be edited in a text editor or evaluated inside the Common Music application.