💾 Archived View for thrig.me › blog › 2022 › 12 › 26 › tarai.gmi captured on 2023-06-16 at 16:49:16. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-04-19)
-=-=-=-=-=-=-
The 「tarai function」 recently came to my attention; the context was music composition, or the art of creating hopefully neither boring nor terrible sounds from the emissions of some algorithm.
(defun tarai (x y z) (if (<= x y) y (tarai (tarai (- x 1) y z) (tarai (- y 1) z x) (tarai (- z 1) x y))))
A first step may be to study the outputs for given inputs; x > y will avoid the obvious filter, and who knows what z will do. Given the subtractions we probably want positive values, and probably not values that are too large given all the recursion. Some experimentation yielded the following, which gets slow, and does not appear to produce anything interesting.
(dotimes (n 5) (dotimes (m 5) (let* ((y 4) (x (+ y n 1)) (z (+ y x m 1))) (format t "~&~d,~d,~d -> ~d" x y z (tarai x y z)))))
Tools to convert streams of numbers into Lilypond or MIDI might be good to have. Some of these come from my App::MusicTools module: transpose the numbers up by 54 pitches, convert to lilypond, convert lilypond to sheet music and a MIDI file. Other translations would be possible (to chords, a particular scale, a rhythm, etc).
$ sbcl --script tarai.lisp | perl -lane 'print $F[-1] + 54' | atonal-util pitch2ly --mode=absolute - | ly-fu --absolute --open -
Yeah... if something uses glorious amounts of CPU for not much if any gain, we are probably on the wrong track. Some functions work when fed sequences of integers (see Music::Voss for example) but probably not this one. Maybe you might find something to use here?
The author of the tarai function posting does not use the output of the function, but rather uses the internal x y z of each of the many recursive function calls.
(defun tarai (x y z) (format t "~d ~d ~d~&" x y z) ; log what we were called with (if (<= x y) y (tarai (tarai (- x 1) y z) (tarai (- y 1) z x) (tarai (- z 1) x y)))) (tarai 10 5 0)
This gives us 343,073 lines to work with. We might use the numbers as pitch values in some scale, or maybe the first number is the pitch, the second the note velocity, and the third duration? Plenty of things to experiment with here, as all sorts of mappings and modulus are possible.
A statistical look at the numbers may be worthwhile; this shows the numbers mostly stay around one though rarely will get up to 10. They could be mapped directlyl to a 12-note scale, or perhaps extreme values could be ignored, put into the next octave, or modulated into some smaller base scale. The columns have different values, which perhaps points to using only one of the columns, or to utilize a unique mapping for each column.
$ r-fu summary < tarai.10.5.0.txt elements 1029219 mean 1.330 range 11.000 min -1.000 max 10.000 sd 1.553 0% 25% 50% 75% 100% -1 0 1 2 10 $ r-fu colsumm - x y z < tarai.10.5.0.txt x y z Count 343073.0000000 343073.000000 343073.000000 Range 11.0000000 10.000000 10.000000 Mean 0.6855363 1.628414 1.675594 Sdev 1.5179802 1.533457 1.399214 Min. -1.0000000 0.000000 0.000000 1st Qu. 0.0000000 0.000000 0.000000 Median 0.0000000 1.000000 2.000000 3rd Qu. 2.0000000 3.000000 3.000000 Max. 10.0000000 10.000000 10.000000
Converting the first column (x) pitches to Dorian mostly results in a stepwise descent and some leaps. Nothing really too interesting. More experimentation here might turn up something usable. The original post used arpeggio which probably adds interest and may hide a weaker harmonic or melodic line.
(define-condition list-full (error) ()) (defconstant +maxn+ 64) (defparameter *nn* nil) (defparameter *mm* '((-1 . "b") (0 . "c'") (1 . "d'") (2 . "e'") (3 . "f'") (4 . "g'") (5 . "a'") (6 . "b'") (7 . "c''") (8 . "d''") (9 . "e''") (10 . "f''"))) (defun tarai (x y z) (push x *nn*) ; (push y *nn*) (push z *nn*) (when (>= (length *nn*) +maxn+) (error 'list-full)) (if (<= x y) y (tarai (tarai (- x 1) y z) (tarai (- y 1) z x) (tarai (- z 1) x y)))) (handler-case (tarai 10 5 0) (list-full () (dolist (n (nreverse *nn*)) (format t "~d~&" (cdr (assoc n *mm*))))))
By way of:
$ sbcl --script tarai.lisp | ly-fu --absolute --open -
Random code I've thrown together to wrangle music or numbers with. Probably needs a rewrite. Proably will not be rewritten.
https://metacpan.org/pod/App::MusicTools
https://metacpan.org/pod/Music::Voss
tags #lisp #music