An Introduction to Collective Algorithmic Music Composition

Rhythm

Perhaps of all the most basic elements of music, rhythm most directly affects our central nervous system. - George Crumb

A music composition evolves over time. In music, rhythm can be defined as the placement of sounds in time. Rhythm is also found in other arts such as dance, poetry and theater. Rhythm in music is often associated with distinctive patterns that occur over time and are often periodic.

Durations

Durations, or lengths define how long a sound, note or silence lasts. In Scripthica, there are several ways of defining the durations of notes. Symbols and numerical values can be assigned to perform musical operations. Symbols represent a numerical expression. Thus, each symbol refers to a specific numerical value.

Note Value Table

Name Integer Symbol Value
Longa 16000 L 4
Double Whole 8000 DW 2
Whole 4000 W 1
Half 2000 H 1/2
Quarter 1000 Q 1/4
Eight 500 E 1/8
Sixteenth 250 S 1/16
Thirty-second 125 T 1/32
Sixty-fourth 63 SF 1/64
Hundred Twenty-eight 31 H 1/128

Using Symbols vs Integer Values

\newthought{In Scripthica,} the most practical way to define rhythmic durations is to use integer values. If a composer chooses to use symbols, the symbols will later have to be converted to integer values by using the \textit{lengths->numbers} function.

Using Integer Values:

(define pitches '(60 62 67 72))
(define durations '(1000 500 250 2000))
(define amplitudes '(100 100 100 100))
(save-midi (create-events 0 pitches durations amplitudes 1))

Using Symbols:

(define pitches '(60 62 67 72))
(define durations (lengths->numbers '(Q 1/8 1/16 H)))
(define amplitudes '(100 100 100 100))
(save-midi (create-events 0 pitches durations amplitudes 1))

Building a drum pattern generator

We're now going to apply what we have learned about rhythm to build a drum pattern generator. This script will combine precomposed drum patterns to create a rhythmical drum line.

First, we must set the tempo. In this case we'll use 140 BPM. To set the tempo we use the set-tempo function.

;tempo
(set-tempo '((0 0 140)))

Now we can start by defining the precomposed patterns. In this case, we will keep it simple and use only a snare drum, hi hats and a bass drum. We will separate the patterns into 3 different lists.

;hi-hat patterns
(define hh-patterns
'(
  ((f#2 ab2 f#2 f#2) (Q Q Q Q))
  ((f#2 r f#2 r) (Q Q Q Q))
  ((f#2 r ab2 bb2) (Q Q Q Q))
  ((bb2 f#2 ab2 f#2) (Q Q Q Q))
  ((ab2 r f#2 r) (Q Q Q Q))
))

;snare drum patterns
(define sd-patterns
'(
  ((r d2 r d2) (Q Q Q Q))
  ((r d2 r r d2) (Q Q Q E E))
  ((r d2 r r r d2) (Q E E Q E E))
  ((r r d2 r d2) (Q E E Q Q))
  ((r d2 d2 r d2) (Q E E Q Q))
))

;bass drum patterns
(define bd-patterns
'(
  ((b1 r b1 r) (Q Q Q Q))
  ((b1 b1 r b1 r) (E E Q Q Q))
  ((b1 r b1 b1 r) (Q Q E E Q))
  ((b1 r r b1) (Q Q Q Q))
  ((b1 r r b1 b1 r) (Q Q Q E S S))
))

After defining our precomposed patterns, we are now going to define a new function that will generate a list of random numbers.

;generate a list of random numbers
(define (generate-seq l t) 
 (let loop ((n 0)) 
 (if (> n (- t 1)) '() 
 (cons (+ (+ (random-integer l) 1)) 
(loop (+ n 1))))))

Now we are going to create a recursive function that create a list of the patterns.

;creates a list of the patterns
(define (create-pattern f p s)
 (if (null? s) '()
   (append (f (list-ref p (car s))) (create-pattern f p (cdr s)))))

We will now define sequences of random numbers for the bass drum, snare, and hihats.

;create a sequence of random numbers
(define bd-seq (generate-seq (- (length bd-patterns) 1) 16))
(define sd-seq (generate-seq (- (length sd-patterns) 1) 16))
(define hh-seq (generate-seq (- (length hh-patterns) 1) 16))

Now we define our events and save as MIDI.

;snare
(define sn-p (create-pattern (lambda (x) (car x)) sd-patterns sd-seq))
(define sn-l (create-pattern (lambda (x) (cadr x)) sd-patterns sd-seq))
(define sn-v (constant-value (length sn-p) 96))
(define sn (create-events 0 (pitches->numbers sn-p) (lengths->numbers sn-l) sn-v 9))

;bass drum
(define bd-p (create-pattern (lambda (x) (car x)) bd-patterns bd-seq))
(define bd-l (create-pattern (lambda (x) (cadr x)) bd-patterns bd-seq))
(define bd-v (constant-value (length bd-l) 96))
(define bd (create-events 0 (pitches->numbers bd-p) (lengths->numbers bd-l) bd-v 9))

;hihats
(define hh-p (create-pattern (lambda (x) (car x)) hh-patterns hh-seq))
(define hh-l (create-pattern (lambda (x) (cadr x)) hh-patterns hh-seq))
(define hh-v (constant-value (length hh-l) 96))
(define hh (create-events 0 (pitches->numbers hh-p) (lengths->numbers hh-l) hh-v 9))

;save midi file
(save-midi (append sn bd hh))

The complete code:

; drum pattern generator

;tempo
(set-tempo '((0 0 140)))

;hi-hat patterns
(define hh-patterns
'(
  ((f#2 ab2 f#2 f#2) (Q Q Q Q))
  ((f#2 r f#2 r) (Q Q Q Q))
  ((f#2 r ab2 bb2) (Q Q Q Q))
  ((bb2 f#2 ab2 f#2) (Q Q Q Q))
  ((ab2 r f#2 r) (Q Q Q Q))
))

;snare drum patterns
(define sd-patterns
'(
  ((r d2 r d2) (Q Q Q Q))
  ((r d2 r r d2) (Q Q Q E E))
  ((r d2 r r r d2) (Q E E Q E E))
  ((r r d2 r d2) (Q E E Q Q))
  ((r d2 d2 r d2) (Q E E Q Q))
))

;bass drum patterns
(define bd-patterns
'(
  ((b1 r b1 r) (Q Q Q Q))
  ((b1 b1 r b1 r) (E E Q Q Q))
  ((b1 r b1 b1 r) (Q Q E E Q))
  ((b1 r r b1) (Q Q Q Q))
  ((b1 r r b1 b1 r) (Q Q Q E S S))
))

;generate a list of random numbers
(define (generate-seq l t) 
 (let loop ((n 0)) 
 (if (> n (- t 1)) '() 
 (cons (+ (+ (random-integer l) 1)) 
(loop (+ n 1)))))) 

;creates a list of the patterns
(define (create-pattern f p s)
 (if (null? s) '()
   (append (f (list-ref p (car s))) (create-pattern f p (cdr s)))))

;create a sequence of random numbers
(define bd-seq (generate-seq (- (length bd-patterns) 1) 16))
(define sd-seq (generate-seq (- (length sd-patterns) 1) 16))
(define hh-seq (generate-seq (- (length hh-patterns) 1) 16))

;snare
(define sn-p (create-pattern (lambda (x) (car x)) sd-patterns sd-seq))
(define sn-l (create-pattern (lambda (x) (cadr x)) sd-patterns sd-seq))
(define sn-v (constant-value (length sn-p) 96))
(define sn (create-events 0 (pitches->numbers sn-p) (lengths->numbers sn-l) sn-v 9))

;bass drum
(define bd-p (create-pattern (lambda (x) (car x)) bd-patterns bd-seq))
(define bd-l (create-pattern (lambda (x) (cadr x)) bd-patterns bd-seq))
(define bd-v (constant-value (length bd-l) 96))
(define bd (create-events 0 (pitches->numbers bd-p) (lengths->numbers bd-l) bd-v 9))

;hihats
(define hh-p (create-pattern (lambda (x) (car x)) hh-patterns hh-seq))
(define hh-l (create-pattern (lambda (x) (cadr x)) hh-patterns hh-seq))
(define hh-v (constant-value (length hh-l) 96))
(define hh (create-events 0 (pitches->numbers hh-p) (lengths->numbers hh-l) hh-v 9))

;save midi file
(save-midi (append sn bd hh))