Here is another view of the tonality functions in Opusmodus. This time the objective is to model a piece of jazz piano. Think Vijay Iyer!
The composition starts by defining two tonalities:
(create-tonality slo '(c4 cs4 fs4 g4)) (create-tonality ait '(b3 c4 cs4 f4))
slo is also PCS 4-9, or Slonimsky pattern #1. The second, ait, is the all-interval tetrachord. If you think of this as '(0 1 4 6) you can generate all intervals from different combinations of it and its inversions.
(combination 2 '(0 1 4 6))
The next data list is a sequence of roots for the chords we are going to generate. This list contains the root notes of the chords to John Coltrane's Giant Steps, a song known to work well with the all-interval tetrachord.
(setf path (tonality-series '(slo ait slo ait slo slo ait) :root root-list))
Using TONALITY-MAP we can order the change of tonality and include the root-list. Now we have the path we can do the mapping of chord tone to a list of integers generated by RND-NUMBER. Notice there isn’t a random seed set in this expression so don’t expect this list below to match up with the one you’ve just evaluated.
=> ((b4 fs4 f4 b4) (d5 gs4 d5 e4) (g4 gs3 g4 d4) (c4 c4 e4 e4) . . .)
And the same with this expression we group the pitches into chords:
(setf chords (chord-pitch-unique (chordize pitch-lists))) => ((b4fs4f4) (d5gs4e4) (g4gs3d4) (c4e4) . . .
Now we'll put the root-note of Giant Steps alongside the chords using GEN-COMBINE and apply GEN-RETROGRADE to get that classic modern jazz 'bass chord' pattern.
Notice there's lots of flattening and dividing to make sure we keep the list organisation in place.
Now for the rhythm. The left hand chord rhythm is very easy, but for the 'improvised' right hand we're going to create rhythmic variables again, only this time enable their position to be randomised.
(setf rh-rhy (flatten (rnd-sample 32 (apply-eval '(r1 r2 r3 r4 r5 r6 r7 r8))))) => (1/8 1/4 1/8 1/4 1/8 1/8 -1/4 1/4 -1/4 1/4 . . .)
With both right hand rhythms and melody we won't set random seeds, so that every time the score-script is compiled you'll hear a different performance.
To create the right hand 'improvised' melody we'll create a scale that is a composite of PCS 4-9 and the all-interval tetrachord, then in the i-pitch expression transpose it to each degree of its scale. There are two different wave expressions to try out using VECTOR-TO-PITCH and VECTOR-MAP respectively. The first wave-1 outputs a chromatic stream, the second wave-2 outputs the i-scale stream.
(setf wave-2 (vector-map i-pitch gen-sine p-value 2 '(0.2 0.7)))) => (g5 gs5 g5 fs5 gs5 b5 as5 fs5 as5 gs5 f5 c6 f5 . . .)
Like the rh-rhy this is in a single list, which allows for the use of the function FILTER-TIE, which adds tied notes into the improvisation.
Finally, the dynamics of the right hand part take the contours of the GEN-SINE 'wave' generation.
(setf i-dyn (vector-to-velocity 0.27 0.87 (gen-sine p-value 2 '(0.2 0.7))))
Try playing the piece through a few times, and experiment with changing the wave content from wave-2 to wave-1.
(init-seed 35) (create-tonality slo '(c4 cs4 fs4 g4)) (create-tonality ait '(b3 c4 cs4 f4)) (setf root-list '(b3 d4 g3 bb3 eb4 b3 d4 g3 bb3 eb4 fs4 bb3 f4 bb3 eb4 eb4 a3 d4 g3 cs4 fs4 bb3 bb3 f4 bb3 eb4 cs4 fs4)) ;Giant Steps! (setf root-list-t (mclist (pitch-transpose -12 root-list))) (setf path (tonality-series '(slo ait slo ait slo slo ait) :root root-list :seed 31)) (setf pitch-list (integer-to-pitch (rnd-number (* (length root-list) 4) 0 12))) (setf pitch-lists (tonality-map path (gen-divide 4 pitch-list))) (setf chords (chord-pitch-unique (chordize pitch-lists))) (setf chords-i (gen-divide 2 (flatten (gen-combine root-list-t chords)))) (setf chords-r (gen-retrograde chords-i :section (gen-integer-step 0 14 '(2)))) (setf chords-ri (gen-divide 4 (flatten chords-r))) ;; Rhythm (chords & improvisation) (setf chd-rhy (gen-repeat 4 '((q q q q) (q q q q) (h h) (q q q q)))) (setf r1 '(q q) r2 '(3q = = = = =) r3 '(e = s = e) r4 '(-e = = =) r5 '(e q e) r6 '(e = q) r7 '(-q =) r8 '(q e =)) (setf rh-rhy (flatten (rnd-sample 32 (apply-eval '(r1 r2 r3 r4 r5 r6 r7 r8))))) ;; Solo melody (improvisation) (setf i-scale '(bb3 b3 c4 e4 f4 g4)) (setf i-pitch (flatten (pitch-transpose 15 (pitch-transpose (pitch-to-integer i-scale) (gen-repeat 5 (list i-scale)))))) (setf p-value (get-count rh-rhy :sum t)) (setf wave-1 (vector-to-pitch '(fs4 fs6) (gen-sine p-value 2 '(0.2 0.7)))) (setf wave-2 (vector-map i-pitch (gen-sine p-value 2 '(0.2 0.7)))) (setf i-dyn (vector-to-velocity 0.27 0.87 (gen-sine p-value 2 '(0.2 0.7)))) (setf dyn (span chd-rhy '((mf f ff mf) (mf f ff mf) (f ff) (mf f mf mp)))) (setf rh-rhy-ft (filter-tie (list wave-2 rh-rhy))) (setf ferm (append (gen-repeat 15 '((- - - -))) '((- - - fermata2)))) (setf rh-1 (make-omn :length (2~ rh-rhy-ft) :pitch (1~ rh-rhy-ft) :velocity i-dyn)) (setf lh-1 (make-omn :length chd-rhy :pitch chords-ri :velocity dyn :articulation ferm)) (def-score lesson-25 (:key-signature 'chromatic :time-signature '((1 1 1 1) 4) :tempo 100 :flexible-clef t :layout (piano-layout 'piano-rh 'piano-lh :ignore-velocity t)) (piano-rh :omn rh-1 :channel 1 :sound 'gm :program 'acoustic-grand-piano) (piano-lh :omn (respell lh-1 :type :chord)) ) ;; Setting random back to NIL (init-seed nil)
Next page Lesson 26. Chords to Parts
Go back to Reference page.