December 1Dec 1 As far as I have read OMs excellent documentation, there's no function whichhelps to prepare a binary-list for driving a do-timeline to play/pause solo-instruments with occasional multiplay,where a couple of constraints like probability and max multplay can be definedand one of many possible solutions is returned.I tried with help of chat-gpt to code to do this.Although tests look plausible I believe this is not a well coded function (robustness, edge cases, seed handling, etc).Any thoughts ?;;; ;;; n solo-instruments play in a band for l periods ;;; the ratio of multiplay is defined by r ;;; max-n instruments can play together ;;; ;;; Function which supports definition ;;; of binary list which can be passed to do-timeline ;;; (defun gen-binary-solo (n l r max-n) "Generate a n binary sublists for n instruments. Each sublist has length l. Ratio r defines probaility for multiplay. Number max-n defined maximun allowed number of instruments playing together." ;; validations (unless (and (integerp n) (>= n 1) (<= n 4)) (error "n must be an integer between 1 and 4 inclusive")) (unless (and (integerp l) (> l 0)) (error "l must be a positive integer")) (unless (and (numberp r) (>= r 0.0) (<= r 1.0)) (error "r must be a number between 0 and 1")) (unless (and (integerp max-n) (>= max-n 1) (<= max-n n)) (error "max-n must be integer between 1 and n")) (let* ((max-k (min max-n n)) (multi-count (if (< max-k 2) 0 (round (* r l)))) ;; indices 0..l-1 (indices (loop for i from 0 below l collect i)) ;; choose exactly multi-count distinct positions (partial Fisher-Yates) (multi-positions (let ((vec (coerce indices 'vector))) (loop for i from 0 below multi-count do (rotatef (aref vec i) (aref vec (+ i (random (- l i)))))) (loop for i below multi-count collect (aref vec i)))) (multi-hash (let ((h (make-hash-table :test 'eql))) (dolist (pos multi-positions) (setf (gethash pos h) t)) h)) ;; rows as arrays for efficient setting (rows (loop repeat n collect (make-array l :initial-element 0))) (min-k 2)) ;; build columns for each time index (loop for time-idx from 0 below l do (let* ((is-multi (gethash time-idx multi-hash)) (k (if is-multi (if (<= max-k min-k) min-k ;; uniform integer in [2..max-k] (+ min-k (random (1+ (- max-k min-k))))) 1)) ;; choose k distinct instruments (simple partial pick) (available (loop for i below n collect i)) (chosen (loop repeat k for pick = (nth (random (length available)) available) do (setf available (remove pick available)) collect pick))) (dolist (inst chosen) (setf (aref (nth inst rows) time-idx) 1)))) ;; convert arrays back to lists and return (mapcar #'(lambda (arr) (coerce arr 'list)) rows))) ;; Tests (gen-binary-solo 4 8 1 2) => ((1 1 1 0 0 1 1 0) (1 1 0 0 0 0 0 0) (0 0 0 1 1 1 0 1) (0 0 1 1 1 0 1 1)) (gen-binary-solo 4 8 0 1) => ((1 0 1 0 0 0 0 0) (0 1 0 1 0 0 1 1) (0 0 0 0 1 0 0 0) (0 0 0 0 0 1 0 0)) (gen-binary-solo 4 8 0.5 2) => ((1 0 0 0 1 1 0 0) (0 1 0 0 0 0 1 1) (0 0 1 1 0 0 1 1) (0 1 0 1 0 0 0 0)) (gen-binary-solo 4 8 0.7 3) => ((1 0 0 0 1 0 1 0) (1 1 1 1 1 0 1 0) (0 0 0 0 0 1 1 1) (1 1 1 0 0 0 0 1)) (gen-binary-solo 4 8 0.1 3) => ((0 0 0 0 0 1 0 0) (0 1 0 1 0 0 1 1) (1 0 1 0 1 0 0 0) (0 0 1 0 0 0 0 0))
December 1Dec 1 Generally, I like using the gen-group function for this purpose because it allows you to manage whether or not you want simultaneous (unisons) lists. But your function is very interesting, thank you.
Sunday at 08:03 AM5 days Author Alternative way to generate on-off binary list for do-timeline:;; Play/pause (setf on-off (gen-binary-euclidean 2 total-span 9 15 :rotate '(0 2 3))) (list-plot (x+y (first on-off) (second on-off)) :join-points t) (do-timeline2 '(v1 v2) on-off '(gen-pause x) :time '(w.)) The plot shows the number of instruments being paused.Example:Voice v1 is RhodesVoice v2 is Marimba.2025-12_01.mp3
Sunday at 08:50 AM5 days Another excellent function for the do-timeline:(gen-binary-euclidean2 ‘(32 32 32 32) ‘(32 11 16 14))I believe the documentation is missing from the system. Janusz ?
Create an account or sign in to comment