Table of Contents

 • 1. Introduction
 • 2. Modulate Modulation
 • 3. Polyphony? No problem
 • 4. General composition structure
     □ 4.1. Multi-track length alignment
     □ 4.2. Snap to the scale
 • 5. Quick music theory
     □ 5.1. Major keys

1. Introduction

Once upon a time, there were many music composition software packages, mostly
written in Common LISP. To name a few I know, Common Music, Symbolic Composer
(not related to the Symbolics Lisp Machine). Common Music is still available in
source code but I doubt if anyone is still able to setup that. Symbolic
Composer just vaporized decades ago, which some archived programs scattered
over the Internet. The package is also a 32bit Intel program so newer macOS
versions would not support it and it is license protected anyway. Yet another
is Patchwork, a more graphic oriented composing program, and I'd be surprise if
it is able to survive from bit rot.

The one I actually uses is Opusmodus, similar in the spirit of Symbolic
Composer. Opusmodus has release 3.0 based on LispWorks on Dec 2022 which has
Apple M1 support, and the Windows port is on the way.

2. Modulate Modulation

Before introducing all the fancy terms about algorithm composition, let's first
see a brief example that generates melody from modulation of sin wave.

 |(setq pitch
 |      (filter-repeat 1 (quarter-tone-closest
 |                        (vector-to-pitch
 |                         '(g3 g5)
5 |                         (add-sine-waves
 |                            12 120 9 4.2 :phase 7
 |                            :modulation (gen-sine 120 1 0.4 :phase 60))
 |                         :quantize 1/2))))

Plot of the generated sine wave
Figure 1. Visualized waveform.

Then add some classic euclidean rhythm. Since this is a randomized process, a
:seed argument is provided to produce consistent result.

 |(setq rythm
 |      (euclidean-rhythm (gen-repeat 18 8) 1/2 8 1/16 :seed 9941))

The music score of generated snippet.
Figure 2. The generated piece.

3. Polyphony? No problem

Sometimes it is just desirable to have some polyphonic^1 part playing. This
time, we could add some variation by changing velocity a bit. The basic idea is
still sine wave modulation.

  |(setq rythm
  |      (quantize
  |       (add-sine-waves 17 120 9 0.3
  |                       :phase 44
5 |                       :modulation (gen-sine 120 3 0.4 :phase 60))
  |       '(1 2 3 4) :type :ratio))
  |(setq pitch
  |      (chord-inner-remove
  |       '(5 1)
10 |       (harmonic-progression
  |      (filter-repeat 2 (mapcar #'floor
  |              (add-sine-waves 12 120 9 1
  |                              :phase 9
  |                              :modulation
15 |                              (gen-sine 120 1 0.3 :phase 3))))
  |      '(c major))
  |       :seed 564))
  |
  |(setq score (make-omn :pitch pitch :length rythm
20 |                      :velocity '(f mf p mp)))

Indication of the chords.
Figure 3. Generated polyphony chords.

4. General composition structure

4.1. Multi-track length alignment

To start composing music it is important to first decide how many sections one
would like to have. Which that settled one can use get-span to acquire the
length information, then use length-span to fill other materials like
percussion generated by gen-euclidean-omn into the desirable length.

✎︎
Note

Instead of specify a very long count number to gen-euclidean-omn, which would
cause a long time to compute, length-span takes much less time to since it just
repeats materials.

4.2. Snap to the scale

Now we have some method to generate wave forms and quantize them to twelve
tones. But just playing these pitches won't make you feel right. The thing is,
you have to decide an interesting scale and map the generated notes to it.

To do that, we have tonality-map.

  |(setq pitch
  |      (quarter-tone-closest
  |       (vector-to-pitch
  |        '(g3 g5)
5 |        (add-sine-waves
  |         12 120 9 4.2 :phase 7
  |         :modulation (gen-sine 120 1 0.4 :phase 60))
  |        :quantize 1/2))))
  |
10 |(filter-repeat 3 (tonality-map '(c4e4a4f4e5) pitch))

Sine wave mapped to a scale.
Figure 4. Generated score

5. Quick music theory

5.1. Major keys

Major keys are of the '(0 2 4 5 7 9 11 12) interval^2. The key signatures are
hard to remember, but one trick is for sharp keys the name is one half step
higher than last sharp; for flat keys the name is the second to last flat. The
reason why it works is demonstrated below. The name is just from the first note
in each scale.

From C major to B major
Figure 5. A list of major keys

This is produced by OMN generated by this lisp loop:

 |(loop for i from 0 to 11
 |  collect (append '(q)
 |                  (integer-to-pitch (x+b '(0 2 4 5 7 9 11 12) i))))

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
^1

When I say polyphony I mean playing different pitch at same time.

^2

Apparently, some majors of different names are sound the same.