💾 Archived View for thrig.me › blog › 2023 › 12 › 11 › musical-lsystem.gmi captured on 2024-05-26 at 15:13:49. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-12-28)

-=-=-=-=-=-=-

Musical L-system

More information about L-systems can be found elsewhere. A good source with regard to music is the following,

"Applications of Generative String-Substitution Systems in Computer Music"

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.

lsystem-to-midi.pl

All told, this works out pretty well?

out.midi

out.mp3

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

See Also

L-system subdir for generating 2D dungeon maps

https://github.com/ology/Music/blob/master/lindenmayer-midi