Musical L-system
More information about L-systems can be found elsewhere. A good source with regard to music is the following,
as it has pratical details on how to convert random bits of L-system generated strings into cromulent musical events. Some dabbling around with the rules and axiom
F F+G
G F-G
F
which yields the output that a LOGO turtle might usually draw
1 F
2 F+G
3 F+G+F-G
4 F+G+F-G+F+G-F-G
5 F+G+F-G+F+G-F-G+F+G+F-G-F+G-F-G
6 F+G+F-G+F+G-F-G+F+G+F-G-F+G-F-G+F+G+F-G+F+G-F-G-F+G+F-G-F+G-F-G
...
but instead can be turned into music.
The method here is to use two sets of pitches that the observant may note as being a tonic and a dominant,
$ atonal-util ly2pitch e g b
52 55 59
$ atonal-util ly2pitch b fis d
59 54 50
and then "F" turns into a rest (of some duration), "G" turns into a note (of some pitch), "+" shifts the note selection, and "-" shifts the rest duration selection. There's an additional complication to shift the pitch set selected from after a certain number of notes have gone by.
All told, this works out pretty well?
Mapping
Many different mappings from a L-System to music (or turtle motions in LOGO, or whatever) are possible. Statistics may help: if an L-System has a lot more "+" than "-" in it, and those symbols are used to change the pitch or velocity, the notes may run off the scale, or the music may become too loud. This may be desirable in a shorter fragment, to get an upards arc.
Where the symbols appear is also important and may contradict a statistical summary; if there is a "++++++" run at the end of the string, then that pitch leap or volume change may not appear in the output. Looking at the statistics is however a good step to get the general lay of the land, so to speak. The frequency of the symbols would be a good place to start.
(defun plusone (n) (1+ (if (numberp n) n 0)))
(defun charstats (string &aux (seen (make-hash-table)) seq (total 0))
(declare (inline plusone))
(loop for ch across string do
(incf total)
(setf (gethash ch seen) (plusone (gethash ch seen))))
(maphash (lambda (k v) (push (cons k v) seq)) seen)
(sort seq #'< :key #'cdr)
(dolist (c seq)
(format t "~&~a ~d ~$~&" (car c) (cdr c)
(coerce (/ (cdr c) total) 'long-float))))
(charstats "F+G+F-G+F+G-F-G+F+G+F-G-F+G-F-G+F+G+F-G+F+G-F-G-F+G+F-G-F+G-F-G")
This particular string is pretty boring, though.
- 15 0.24
G 16 0.25
+ 16 0.25
F 16 0.25