Now it is not my aim to present such a theory or even a theory of harmony, nor do I possess enough ability and knowledge to do so; I am rather simply trying to present the harmonic means of music in such a way that they can be directly applied in practice. - Arnold Schoenberg, Theory of Harmony.
When we play multiple notes at once we generate a chord. Harmony is concerned with chord construction and progressions. In Scripthica, generating chords is a simple as embedding a list of the chord notes within the musical pattern. For example if we only want to create a sequence of two chords we simply would do the following:
(define pitches '((60 62 66)(64 66 68)))
(define durations '((2000 2000 2000) (2000 2000 2000)))
(define vels '((96 96 96)(96 96 96)))
(save-midi (create-events 0 pitches durations vels 1))
We can rotate the list to get a chord inversion.
(rotate '(60 70 80) 1)
;; => (80 60 70)
The create-chord procedure allows us to construct chords. We can specify a MIDI pitche number and the type of chord we want to construct and the function will return a list with the respective numbers that construct the chord.
(create-chord 50 "maj")
;; => (50 54 57)
(create-chord 50 "min")
;; => (50 53 57)
(create-chord 50 "aug")
;; => (50 54 58)
(create-chord 50 "dom")
;; => (50 54 57 60)
(create-chord 50 "dim")
;; => (50 53 56)
(create-chord 50 "min7")
;; => (50 53 57 60)
(create-chord 50 "maj7")
;; => (50 54 57 61)
We can also specify the note and we will get a list with pitch symbols.
(create-chord "c4" "maj")
;; => (C4 E4 G4)
(create-chord "c4" "min")
;; => (C4 Eb4 G4)
(create-chord "c4" "dim")
;; => (C4 Eb4 Gb4)
(create-chord "c4" "min7")
;; => (C4 Eb4 G4 Bb4)
We are going to create a small script that generates random chord sequences.
First, lets set the tempo and set an instrument.
(set-tempo '((0 0 82)))
(set-instruments '((1 0 6)))
Lets define lists with the types of chord and lengths we want to choose.
(define chord-type '("maj" "min" "aug" "dim"))
(define chord-lengths '((3000 3000 3000)
(2000 2000 2000)
(4000 4000 4000)))
We can now create a function that will create a random chord n number of times.
(define (chord-seq n)
(if (= n 0) '()
(append (list
(list
(create-chord
(+ 60 (random-integer 15))
(list-ref chord-type (random-integer 4)))
(list-ref chord-lengths (random-integer 3))))
(chord-seq (- n 1)))))
(define seq (chord-seq 15))
Every time we call chord-seq it will return a different chord.
(chord-seq 1)
;; => (((74 77 81) (3000 3000 3000)))
(chord-seq 1)
;; => (((70 73 76) (4000 4000 4000)))
(chord-seq 1)
;; => (((73 76 79) (4000 4000 4000)))
(chord-seq 1)
;; => (((63 67 70) (4000 4000 4000)))
(chord-seq 1)
;; => (((71 75 78) (3000 3000 3000)))
We can create two new functions that will separate the list that contains the durations and the pitches. We also rotate the chord just to make it more interesting.
(define (p-seq seq)
(if (null? seq) '()
(append (list (rotate (caar seq) 1)) (p-seq (cdr seq)))))
(define (d-seq seq)
(if (null? seq) '()
(append (cdar seq) (d-seq (cdr seq)))))
Finally, we can define our pitches, durations and velocities to create the MIDI events.
;pitches
(define p (p-seq seq))
;durations
(define d (d-seq seq))
;velocities
(define v (create-constant-velocities p 127))
(save-midi (create-events 0 p d v 1))
The complete code:
(set-tempo '((0 0 82)))
(set-instruments '((1 0 6)))
(define chord-type '("maj" "min" "aug" "dim"))
(define chord-lengths '((3000 3000 3000)
(2000 2000 2000)
(4000 4000 4000)))
(define (chord-seq n)
(if (= n 0) '()
(append (list
(list
(create-chord
(+ 60 (random-integer 15))
(list-ref chord-type (random-integer 4)))
(list-ref chord-lengths (random-integer 3))))
(chord-seq (- n 1)))))
(define seq (chord-seq 15))
(define (p-seq seq)
(if (null? seq) '()
(append (list (rotate (caar seq) 1)) (p-seq (cdr seq)))))
(define (d-seq seq)
(if (null? seq) '()
(append (cdar seq) (d-seq (cdr seq)))))
;pitches
(define p (p-seq seq))
;durations
(define d (d-seq seq))
;velocities
(define v (create-constant-velocities p 127))
(save-midi (create-events 0 p d v 1))