;;; ;;; "Logistics" function, a simple example that illustrates ;;; how a simple change in parameter space can alter the ;;; behavior from simple repetitive selections to chaotic ;;; behavior ;;; ;;; The function itself (defun logistics (x p) (* p x (- 1 x))) ;;; A function that runs logistics a given number of times (defun run-logistics (x p &key (times 200)) (loop repeat times collect (setf x (logistics x p)))) ;;; NOTE: for this work you have to compile and load the ;;; plotter functions... (plot-data (run-logistics (random 1.0) 3.857 :times 1000) :style "points") (plot-data (run-logistics (random 1.0) 4 :times 1000) :style "points") (plot-data (run-logistics (random 1.0) 2.6 :times 100) :style "points") ;;; Simple mapping of output to pitch (with-sound() (let* ((data (run-logistics (random 1.0) 3 :times 50))) ;; (plot-data data :style "points") (loop for d in data for time from 0 by 0.1 do (fm-violin time 0.1 (hertz (floor (* 100 d))) 0.05)))) ;;; Hummm, let's package the behavior into a function ;;; first one maps numbers into pitches: ;;; first try gets back just very high notes... wrong parameter scaling! (defun try (parameter &key (times 50)(rhythm 0.1)) (let* ((data (run-logistics (random 1.0) parameter :times times))) ;; (plot-data data :style "points") (format t "repeated ~s times~%" (length data)) (loop for d in data for time from 0 by rhythm do (format t " ~s" time) (fm-violin time 0.4 (hertz (min 90 (+ 40 (floor (* 100 d))))) 0.05)))) ;;; Let's try again and map to the min and max values found ;;; setup parameters so that we can control the mapping (scaler and offset) ;;; this one works fine... (defun try (parameter &key (times 50)(rhythm 0.1) (scaler 40) (offset 20)) (let* ((data (run-logistics (random 1.0) parameter :times times)) (min (loop for d in data minimize d)) (max (loop for d in data maximize d))) ;; (plot-data data :style "points") (format t "repeated ~s times, min=~f, max=~f~%" (length data) min max) (loop for d in data for time from 0 by rhythm do (format t " ~s" time) (fm-violin time 0.4 (hertz (floor (+ offset (* scaler (/ (- d min)(- max min)))))) 0.05)))) ;; (defun try (parameter &key (times 50)(rhythm 0.1)(transfer-function '(0 40 1 80))) (let* ((data (run-logistics (random 1.0) parameter :times times)) (min (loop for d in data minimize d)) (max (loop for d in data maximize d))) (format t "max is ~f and min is ~f~%" max min) ;; (plot-data data :style "points") (format t "repeated ~s times, min=~f, max=~f~%" (length data) min max) (loop for d in data for time from 0 by rhythm do (format t " ~s" time) (fm-violin time 0.4 (hertz (floor (interpl d transfer-function))) 0.05)))) (defun map-notes (note-list) (let* ((n (/ (length note-list))) (prev 0)) `(,@(loop for note in note-list for x from 0 by n collect x collect prev collect x collect note do (setf prev note)) 1 ,(first (last note-list))))) ;;; (with-sound()(try 3.7 :times 20 :transfer-function '(0 50 0.5 53 0.51 80 1 83))) (defun try (parameter &key (times 50)(rhythm 0.1)(transfer-function '(0 40 1 80))) (let* ((data (run-logistics (random 1.0) parameter :times times)) (min (loop for d in data minimize d)) (max (loop for d in data maximize d))) (format t "max is ~f and min is ~f~%" max min) ;; (plot-data data :style "points") (format t "repeated ~s times, min=~f, max=~f~%" (length data) min max) (loop for d in data for time from 0 by rhythm do (format t " ~s" time) (fm-violin time 0.4 (interpl d transfer-function) 0.05)))) ;;; or: second function maps numbers directly into frequencies: (defun try (parameter &key (times 50)(rhythm 0.1)) (let* ((data (run-logistics 0.1 parameter :times times))) ;; (plot-data data :style "points") (format t "repeated ~s times~%" (length data)) (loop for d in data for time from 0 by rhythm do (fm-violin time 0.4 (+ 60 (* 1000 d)) 0.05)))) ;;; different calls for different value of the logistics parameter: (with-sound()(try 3.5 :times 100)) (with-sound()(try 2.9)) (with-sound()(try 3)) (with-sound()(try 3.2)) (with-sound()(try 3.4)) (with-sound()(try 3.5)) (with-sound()(try 3.55)) (with-sound()(try 3.57)) (with-sound()(try 3.7)) (with-sound()(try 3.8)) (with-sound()(try 3.857)) ;;; on this function we put an envelope in the parameter of the ;;; logistics funcion, that is, we change the behavior over ;;; time: (defun try (parameter &key (times 50) (index 1.0)) (if (numberp parameter) (setf parameter (list 0 parameter 1 parameter))) (let* ((x (random 1.0)) (rhythm 0.1) (duration (* rhythm times)) (norm (clm::x-norm parameter duration))) (loop repeat times for time from 0 by rhythm for x = (random 1.0) then (logistics x (envelope-interp time norm)) collect x into output do (fm-violin time 0.4 (hertz (floor (* 100 x))) 0.05 :fm-index index)))) ;; finally ;; (plot-data output :style "points")))) ;; A simple example: (with-sound()(try '(0 2 0.5 3 1 3.7))) ;;; three logistic functions control three different parameters ;;; of each generated note: (defun try (parameter &key (times 50) (index 1.0) (index-p 3.5) (index-a 3.6) (index-offset -0.2)) (if (numberp parameter) (setf parameter (list 0 parameter 1 parameter))) (let* ((x (random 1.0)) (rhythm 0.1) (duration (* rhythm times)) (norm (clm::x-norm parameter duration))) (loop repeat times for time from 0 by rhythm for x = (random 1.0) then (logistics x (envelope-interp time norm)) for y = (random 1.0) then (logistics y index-p) for z = (random 1.0) then (logistics z index-a) collect z into output do (fm-violin time 0.4 (hertz (floor (* 100 x))) (* 0.1 z) :fm-index (max 0 (* 10 (+ y index-offset))))))) ;; obviously this function could use normalizing of the parameter space... ;; finally ;; (plot-data output :style "points")))) (with-sound()(try '(0 3 1 3) :times 100 :index-p 3.7)) (with-sound() (try '(0 2 0.3 3.857 0.5 3.856 0.6 3 1 3.2) :times 100) (try '(0 3.2 0.3 3.857 0.5 3.856 0.6 3 1 3.4) :times 100) (try '(0 3.5 0.3 3.857 0.5 3.856 0.6 3 1 3.45) :times 100)) (with-sound() (try '(0 2 0.3 3.857 0.5 3.856 0.6 3 1 3.2) :times 100 :index 0.3) (try '(0 3.2 0.3 3.857 0.5 3.856 0.6 3 1 3.4) :times 100 :index 2) (try '(0 3.5 0.3 3.857 0.5 3.856 0.6 3 1 3.45) :times 100 :index 4))