;;; ;;; Lorenz ;;; ;;; defines where the program is located: (defparameter lorenz-path "/usr/ccrma/web/html/courses/220b/topics/chaosfractals/examples/cbn/code/bin/lorenz") ;;; this function calls the "lorenz" program as a separate process ;;; and grabs and parses the results into three returned values, ;;; each one a list of the 5000 coordinate points. Run the "lorenz" ;;; program from a terminal with no arguments to view the 3d curve... (defun lorenz () (let* ((process (extensions:run-program lorenz-path (list "-data") :wait nil :input :stream :output :stream :error :output))) (if (not process) (error "could not run ~s~%" lorenz-path) (let* ((stream (extensions:process-output process)) (input (extensions:process-input process))) (format t ";; running ~s with process=~s~%" lorenz-path process) (multiple-value-bind (x y z) (loop with xs = '() with ys = '() with zs = '() for line = (read-line stream nil nil) while line do (multiple-value-bind (x y0) (read-from-string line :preserve-whitespace t) (setf line (subseq line y0 (length line))) (multiple-value-bind (y z0) (read-from-string line :preserve-whitespace t) (setf line (subseq line y0 (length line))) (multiple-value-bind (z end) (read-from-string line :preserve-whitespace t) (setf xs `(,.xs ,x) ys `(,.ys ,y) zs `(,.zs ,z))))) finally (return (values xs ys zs))) (extensions:process-wait process) (values x y z)))))) ;;; a with-sound that gets the 2 lists of coordinates from "lorenz" ;;; and maps them to three parameters on the generated notes: (with-sound(:srate 44100) (multiple-value-bind (x y z) ;; get 3d coords from the lorenz curve... (lorenz) (let* (;; get range of each returned coordinate (xlimits (loop for xi in x maximize xi into maxx minimize xi into minx finally (return (list minx maxx)))) (ylimits (loop for yi in y maximize yi into maxy minimize yi into miny finally (return (list miny maxy)))) (zlimits (loop for zi in z maximize zi into maxz minimize zi into minz finally (return (list minz maxz))))) (format t "xl=~s, yl=~s, zl=~s~%" xlimits ylimits zlimits) (loop ;; change this to get more notes generated... repeat 200 for xi in x for yi in y for zi in z for time = 0 then (+ time (* 0.3 (/ (- xi (first xlimits)) (- (second xlimits)(first xlimits))))) for freq = (+ 100 (* 2000 (/ (- yi (first ylimits)) (- (second ylimits)(first ylimits))))) for brightness = (+ 0.2 (* 5 (/ (- zi (first zlimits)) (- (second zlimits)(first zlimits))))) do (format t "~s:~s " time freq) (fm-violin time 0.4 freq 0.05 :fm-index brightness))))) ;;; a version with different mappings... (with-sound(:srate 44100) (multiple-value-bind (x y z) ;; get 3d coords from the lorenz curve... (lorenz) (let* ((notes 200) ;; get range of each returned coordinate (xlimits (loop for xi in x repeat notes maximize xi into maxx minimize xi into minx finally (return (list minx maxx)))) (ylimits (loop for yi in y repeat notes maximize yi into maxy minimize yi into miny finally (return (list miny maxy)))) (zlimits (loop for zi in z repeat notes maximize zi into maxz minimize zi into minz finally (return (list minz maxz))))) (format t "xl=~s, yl=~s, zl=~s~%" xlimits ylimits zlimits) (loop repeat notes for xi in x for yi in y for zi in z for rhythm = (+ 0.05 (* 0.4 (/ (- xi (first xlimits)) (- (second xlimits)(first xlimits))))) for time = 0 then (+ time rhythm) for freq = (floor (+ 24 (* 48 (/ (- yi (first ylimits)) (- (second ylimits)(first ylimits)))))) for brightness = (+ 0.2 (* 5 (/ (- zi (first zlimits)) (- (second zlimits)(first zlimits))))) do (format t "~s:~s [~s]~%" time freq xi) (fm-violin time (* 1.1 rhythm) (hertz freq) 0.05 :fm-index brightness)))))