Skip to content
View in the app

A better way to browse. Learn more.

Opusmodus

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

AM

Members
  • Joined

  • Last visited

Everything posted by AM

  1. interesting results with <dec-to-bin-rhythm>. kind of transitions and pattern by adding "binary counting"... (defun dec-to-bin-rhythm (ilist) (let ((span (find-max (mapcar 'length (decimal-to-binary ilist))))) (loop for i in (binary-rhythm span ilist 1 :type 1) collect (loop for x in i when (< x 0) append (gen-repeat (abs x) 0) else collect x)))) ;;;;;;;; (list-plot (flatten (binary-layers (list (flatten (dec-to-bin-rhythm (gen-integer 0 5))) (flatten (dec-to-bin-rhythm (gen-integer 7 0))) (flatten (dec-to-bin-rhythm (gen-integer 1 5)))))) :join-points t :style :fill) ;;;;;;;; (list-plot (flatten (binary-layers (list (flatten (dec-to-bin-rhythm (gen-integer 0 11))) (flatten (dec-to-bin-rhythm (gen-integer 7 1))) (flatten (dec-to-bin-rhythm (gen-integer 1 7)))))) :join-points t :style :fill)
  2. I still have no idea what I could use this for in OPMO. In Max/MSP, it has interesting und usefull applications in the area of corpus-sampling. I didn’t write this code myself (Copilot), but it seems to fit. GeeksforGeeksK-Nearest Neighbor(KNN) Algorithm - GeeksforGeeksYour All-in-One Learning Portal: GeeksforGeeks is a comprehensive educational platform that empowers learners across domains-spanning computer science and programming, school education, upskilling, co;; kNN implementation in Common Lisp with weighted voting ;; ------------------------------------------------------- ;; This program classifies a new data point based on the k nearest neighbors ;; from a given dataset, giving more weight to closer neighbors. (defun euclidean-distance (vec1 vec2) "Compute the Euclidean distance between two numeric vectors." (unless (= (length vec1) (length vec2)) (error "Vectors must have the same length.")) (sqrt (reduce #'+ (mapcar (lambda (a b) (expt (- a b) 2)) vec1 vec2)))) (defun knn-classify-weighted (dataset labels query k) "Classify QUERY using weighted k nearest neighbors from DATASET with LABELS. Closer neighbors contribute more to the vote." (when (or (null dataset) (null labels)) (error "Dataset and labels cannot be empty.")) (unless (= (length dataset) (length labels)) (error "Dataset and labels must have the same length.")) (when (or (<= k 0) (> k (length dataset))) (error "Invalid k value.")) ;; Compute distances and pair with labels (let* ((distances (mapcar (lambda (point label) (list (euclidean-distance point query) label)) dataset labels)) ;; Sort by distance (sorted (sort distances #'< :key #'first)) ;; Take k nearest (neighbors (subseq sorted 0 k)) ;; Weighted label counts (label-weights (make-hash-table :test #'equal))) (dolist (n neighbors) (let ((dist (first n)) (label (second n))) ;; Weight: inverse of distance (avoid division by zero) (incf (gethash label label-weights 0) (if (zerop dist) 1e6 (/ 1.0 dist))))) ;; Return label with highest total weight (car (car (sort (loop for key being the hash-keys of label-weights collect (list key (gethash key label-weights))) #'> :key #'second))))) ;; Example usage (let* ((dataset '((1.0 2.0) (2.0 3.0) (3.0 3.0) (6.0 5.0) (7.0 8.0))) (labels '("A" "A" "B" "B" "B")) (query '(2.5 3.0)) (k 3)) (format t "Predicted class for ~a: ~a~%" query (knn-classify-weighted dataset labels query k))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; GENERATING A 2D-RND_DATASET (setf dataset_1 (loop for x from 0.0 to 0.999 by 0.001 for y in (gen-noise 1000 :seed 6235) collect (list x y))) ;; GENERATING LABELS (a scale, 7 labels) (setf labels_1 (rnd-sample 1000 (make-scale 'c4 7 :alt '(1 2)) :prob 0.5)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; EXAMPLE (let* ((dataset dataset_1) (labels labels_1) (query '(0.21 0.112)) ;; what i'm searching (2d) (k 5)) (format t "Predicted class for ~a: ~a~%" query (knn-classify-weighted dataset labels query k))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. A special form of BINARY LAYERS: each new list is applied to the 1-values of the previous list, i.e., added. The next generation is then applied to 2, the next to 3, and so on. Like structure on structure on structure. I programmed it to read a kind of sample matrix, which results in a continuous replacement process that happens generatively, kind of a tree structure. Bildschirmaufnahme 2026-04-05 um 18.59.59.mov (defun binary-layers (seqs) (append (list (car seqs)) (loop repeat (1- (length seqs)) with seq = (car seqs) with seqcnt = 1 with interf = 1 collect (setf seq (loop for i in seq with cnt = 0 when (and (= i interf) (= (nth cnt (nth seqcnt seqs)) 1)) collect (+ i 1) else collect i when (> i (1- interf)) do (incf cnt))) do (incf seqcnt) do (incf interf)))) ;;;; EXAMPLES (binary-layers '((0 1 0 1 1 0 1) (0 1 0 1 1 0 0) (1 1 0 1 1 0 0) (1 0 1 1 1 0 0))) => ((0 1 0 1 1 0 1) (0 1 0 2 1 0 2) (0 1 0 3 1 0 3) (0 1 0 4 1 0 3)) (binary-layers '((1 1 0 1 1 0 0 1 0 1 1) (0 1 1 1 0 1 1 0 1 1 0) (1 1 1 1 0 1 1 0 0 1 0) (0 1 1 0 1 1 1 1 1 0 0))) => ((1 1 0 1 1 0 0 1 0 1 1) (1 2 0 2 2 0 0 1 0 2 2) (1 3 0 3 3 0 0 1 0 3 2) (1 3 0 4 4 0 0 1 0 3 2)) (binary-layers (loop repeat 10 collect (rnd-order '(1 1 0 1 1 0 0 1 0 1 1) :seed 243))) => ((0 1 1 1 1 0 0 1 1 0 1) (0 1 2 2 2 0 0 2 1 0 1) (0 1 2 3 3 0 0 3 1 0 1) (0 1 2 3 4 0 0 4 1 0 1) (0 1 2 3 4 0 0 5 1 0 1) (0 1 2 3 4 0 0 5 1 0 1) (0 1 2 3 4 0 0 5 1 0 1) (0 1 2 3 4 0 0 5 1 0 1) (0 1 2 3 4 0 0 5 1 0 1) (0 1 2 3 4 0 0 5 1 0 1)) ;; STATIC VIEW - LISTPLOT wit lists in list (list-plot (binary-layers (loop repeat 10 collect (rnd-order '(1 1 0 1 1 0 0 1 0 1 1) :seed 243))) :join-points t) ;; RANDOM VIEW + flatten all lists -> EVAL A FEW TIMES (list-plot (flatten (binary-layers (loop repeat 10 collect (rnd-order '(1 1 0 1 1 0 0 1 0 1 1))))) :join-points t) ;; EVAL TO SEE the structures for each generation - it's a kind of REWRITE (loop repeat 10 do (list-plot (binary-layers (loop repeat 10 collect (rnd-order '(1 1 0 1 1 0 0 1 0 1 1)))) :join-points t) do (sleep 2))
  4. Slightly extended, but much more interesting/usefull... The function has been extended in a very simple way: you can now optionally specify the denominator. This means you can convert to arbitrary base units (e.g., 1/16 → 1/12) while keeping the proportions intact. Of course, there are some very special rhythms when different denominators occur within the sequence—like in this example with 1/16 and then also 1/20. Actually, it’s a tempo change. And if you were to apply the OPMO function <length-rational-quantize> as well, you could then integrate it in a usable way. (defun ratios-to-integers2 (lst &key (denom nil)) (let* ((lcm (if (null denom) (reduce #'lcm (denominators lst)) denom))) (mapcar (lambda (x) (* x lcm)) lst))) ;; EXAMPLE: for "TEMPO-CHANGE"; from 1/16- to 1/12-base ;; 1. a rhythm: take 16 as denominator => all 16,8,4 ... resulting as integers, the rest as ratios (ratios-to-integers2 '(1/8 1/16 1/16 -3/16 1/16 2/20 1/20 1/4) :denom 16) => (2 1 1 -3 1 8/5 4/5 4) ;; 2. create new rhythm with BASE 1/12 (instead of 1/16) - all proportions remain preserved, now based on 1/12. (gen-length (ratios-to-integers2 '(1/8 1/16 1/16 -3/16 1/16 2/20 1/20 1/4) :denom 16) 1/12) => (1/6 1/12 1/12 -1/4 1/12 2/15 1/15 1/3)
  5. Make a length sequence integer-valued using the least common multiple, then apply the proportions to gen-length. Another kind of augmentation/diminution. (defun ratios-to-integers (lst) (let* ((lcm (reduce #'lcm (denominators lst)))) (mapcar (lambda (x) (* x lcm)) lst))) ;; a rhythm to integers via LCM (list-plot (ratios-to-integers '(1/12 1/16 1/20 1/24 1/28)) :join-points t) ;; gen same proportions with 1/32 (list-plot (gen-length (ratios-to-integers '(1/12 1/16 1/20 1/24 1/28)) 1/32) :join-points t) ;; very strange proportions back to gen-length 1/32 (gen-length (ratios-to-integers '(1/12 -3/12 5/20 1/16 -1/20 1/24 1/28)) 1/32)
  6. i will do it more LISPian, because i want to code more then AMBITUS... so MAYBE-SECTION with lambda will fit better! Thx!
  7. How can I most easily apply the "AMBITUS function" (or any other) to specific measures? I have an OMN sequence (structured into measures) and would like to apply the function, for example, to measures 24 and 25 and to measure 31, while leaving the rest unchanged. Does anyone have a quick tip on the simplest way to do this? Thx for support André
  8. AM posted a topic in Made In Opusmodus
    ;; BY CLAUDE: ;; Aliquot-Sequenz (Summe echter Teiler, Zyklus = befreundete Zahlen) (defun aliquot-seq (n &optional acc) "Sequenz n → Σ(echte Teiler) bis 0, Fixpunkt oder Zyklus." (let ((acc (or acc (list n)))) (let ((next (reduce #'+ (proper-divisors n) :initial-value 0))) (cond ((zerop next) (append acc (list 0))) ; endet bei 0 ((member next acc) (append acc (list next))) ; Zyklus (t (aliquot-seq next (append acc (list next)))))))) (list-plot (aliquot-seq (random 100)) :join-points t) (list-plot (loop repeat 10 collect (aliquot-seq (random 100))) :join-points t)
  9. ;; BY CLAUDE: (defun happy-step (n) (reduce #'+ (mapcar (lambda (d) (* d d)) (digits n)))) (defun (n &optional acc) "Sequenz bis Fixpunkt 1 oder bis Zyklus erkannt." (let ((acc (or acc (list n)))) (let ((next (happy-step n))) (if (member next acc) (append acc (list next)) ; Zyklus: letztes Element zeigt wohin (happy-seq next (append acc (list next))))))) (happy-seq (rnd-pick (happy-numbers 100))) (list-plot (loop repeat 10 collect (flatten (happy-seq (rnd-pick (happy-numbers 300))))) :join-points t)
  10. all columns, rows, diagonals in a list... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun all-magic-square-lines (n) (let ((alist (magic-square n))) (append alist (loop for x from 0 to (1- (length (car alist))) collect (loop for i in alist collect (nth x i))) (list (loop for i in alist with cnt = 0 collect (nth cnt i) do (incf cnt))) (list (loop for i in alist with cnt = (1- (length (car alist))) collect (nth cnt i) do (decf cnt)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (all-magic-square-lines 3) => ((8 1 6) (3 5 7) (4 9 2) (8 3 4) (1 5 9) (6 7 2) (8 5 2) (6 5 4)) (all-magic-square-lines 4) => ((16 5 9 4) (2 11 7 14) (3 10 6 15) (13 8 12 1) (16 2 3 13) (5 11 10 8) (9 7 6 12) (4 14 15 1) (16 11 6 1) (4 7 10 13)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; test (loop for i in (all-magic-square-rows 7) collect (sum i)) => (175 175 175 175 175 175 175 175 175) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (all-magic-square-lines 3)
  11. Just sketching with Opusmodus and Max/MSP: Bars arranged as a matrix are read via a vector envelope and then filtered again by a cellular automaton (the bar is either played or replaced by a rest). In Max/MSP it is recorded and the sample/seq is played back in different ways. The MIDI output of Opusmodus additionally controls higher-level comb filters on it. Sounddesign with simple and cheap sounds by impulse response software (room/media simulations). sketch.MOV sketch2.MOV
  12. Dear @Cliff I find the idea genuinely interesting ... on first consideration a few issues come to mind. But maybe I’m missing something or misunderstanding certain aspects, so feel free to correct me or put things into perspective. Defining a piece through a small number of parameters feels too reductive to me, because musical dimensions are rarely independent. Things like form, harmony, rhythm, accentuation, etc. are tightly interconnected and can’t really be evaluated in isolation. So the parameters would need to be connected across different levels and hierarchically organized. A simple example would be harmony and rhythm: the way consonance and dissonance are treated is often directly linked to rhythmic structure and accent patterns, and this relationship is highly dependent on style or genre. What counts as “good” or “bad” harmonic tension only makes sense within a very specific stylistic context. This also means that any kind of rating system would have to operate within very clearly defined stylistic boundaries, both on a larger level (genre, style, compositional language) and on a smaller, more local level. On a more technical note, numerical ratings don’t really provide direction? If an algorithm generates a randomized twelve-tone row and I rate the result as “1” instead of “10”, the system has no idea why it failed or in which direction it should change — different intervals, an all-interval row, Webern-style cells, or something else entirely. Without explicit stylistic and aesthetic goals, such ratings don’t give the system much to work with? In roughly these areas, there has been research and various approaches for decades — see pioneers like David Cope or projects such as DeepBach, Bachbot, E.M.I. What I find artistically interesting about OPUSMODUS (or bach/maxmsp or ...) much more so, at least up to now, than AI or machine learning—is that it allows me to intervene very precisely in a structure or a specific aspect of a piece. I can simulate processes (sometimes randomized) and then begin with concrete, directionally guided (!) modifications, giving me specific control. This applies both on a global scale and at a very local level. In essence, it’s also a continuous generate-and-test process, but with a wider (and more specific) range of parameters—both objective and subjective—that I can consider within artistic, historical, and genre-specific contexts? Greetings André
  13. I only had a quick look/read and built something like this: at level 0 you get a random pick of the pairs, at level 1 a sequence within a pair, and at level 2 a single value from a sequence of a pair. Was that what you meant? For me, level 0 is not the whole list (i.e. the outermost parentheses), but rather all the pairs inside the outermost parentheses. If I do (length alist), I get 7 here, not 1. So there are 3 levels possible (0 to 2) ;;; (setf alist '(((c4 e4 g4) (d4 fs4 a4)) ((c4 e4 g4) (b4 d4 fs4)) ((d4 fs4 a4) (e4 g4 b4)) ((e4 g4 b4) (fs4 a4 c4)) ((fs4 a4 c4) (g4 b4 d4)) ((g4 b4 d4) (a4 c4 e4)) ((a4 c4 e4) (b4 d4 fs4)))) (defun pick-from-level (alist level) (cond ((= level 0) (nth (random (length alist)) alist)) ((= level 1) (rnd-pick (nth (random (length alist)) alist))) ((= level 2) (rnd-pick (flatten alist))))) (pick-from-level alist 0) => ((g4 b4 d4) (a4 c4 e4)) (pick-from-level alist 1) => (c4 e4 g4) (pick-from-level alist 2) => b4If you want it nested—that is, pick from pick…—then you just need to nest the function. It will then always pick within the same level, either going down or up. (pick-from-level (pick-from-level alist 0) 0) => (fs4 a4 c4) "It will then always pick within the same level,..." : PATH not LEVEL
  14. snippet-to-editor -> so nice! II really enjoy the workflow from OPUSMODUS to Sibelius. When you have some little ideas for material, you program a small function, experiment with it, then export/open it in SIBELIUS and continue working. Not generating full scores, but small units of material… exporting by snippet-to-editor. For example: (i could do it directly in SIBELIUS, but much easier via OPMO) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; binary-counting-rhythm -> counting from x to y // easy export to SIBELIUS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; to ensure the pattern is always the same length, the bit length for all decimal-to-binary conversions is adjusted to match the largest decimal number ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dec-to-bin-rhythm (ilist) (let ((span (find-max (mapcar 'length (decimal-to-binary ilist))))) (loop for i in (binary-rhythm span ilist 1 :type 1) collect (loop for x in i when (< x 0) append (gen-repeat (abs x) 0) else collect x)))) (setf bitseq (dec-to-bin-rhythm (gen-integer 23 1))) ;; 5-bit (snippet-to-editor (omn-to-measure (make-omn :pitch '(cs3) :length (gen-length bitseq '1/8) :velocity '(mf) :articulation '(stacc)) '(4/4))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; SIBELIUS opens the file -> copy/paste to the actual score ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  15. Why limit a hoquetus to just four voices? Imagine it instead for fifty guitars dispersed throughout the space—not as a mere progression, but as a finely shaped structure articulated by a vector envelope. A concept piece, perhaps best experienced on a quiet Sunday evening 😅 Have a look at the (list-plot...)... (This essentially creates spatial and sonic structures similar to those in Ligeti’s Atmosphères or XENAKIS... and on this point stochastic method would be interesting ;-)) ;; 50 GUITARISTS should play a hocket in an "specific enevelope-order" (setf 50guits (list-plot (vector-map (gen-integer 1 50) (vector-to-envelope2 '(4.2456284 7.2268248 6.4440737) '(3.682579 8.78879 10.000002) (gen-noise 356) :segment (primes 12) :type 3)))) (progn (setf mat (make-omn :pitch '(e4) :length (gen-repeat 50 's))) ;; allvoices for 50 players (gen-hocket mat :density (gen-binary-for-hocket 50guits))) i like to be guitarist number one - just 2 notes to play!
  16. everything okay with this code.... use binary... like janusz coded it... (progn (setf mat '(q c4 d4 e4 f4 g4 a4 b4 c5)) (gen-hocket mat :density '((1 0 0 0 1 0 0 0 0 0 1) (0 1 0 1 0 1 0 0 0 1 0) (0 0 1 0 0 0 1 0 1 0 0) (0 0 0 0 0 0 0 1 0 0 0))) (setf mv (merge-voices v1 v2 v3 v4))) and when you generate the binary seq with.... it's that simple. (defun gen-binary-for-hocket (alist) (let ((vlist (sort-asc (remove-duplicates alist)))) (loop for v in vlist collect (loop for i in alist when (= i v) collect 1 else collect 0)))) ;;; now with OPMO-function... (progn (setf mat '(q c4 d4 e4 f4 g4 a4 b4 c5)) (gen-hocket mat :density (gen-binary-for-hocket '(1 2 3 2 1 2 3 4 3 2 1))) (setf mv (merge-voices v1 v2 v3 v4)))
  17. the great thing about Opusmodus is that you can code your own solutions for ideas, problems, or historical models – it gives you a lot of freedom. MAX/MSP, PWGL, or CLM are/were like that too… thx @janusz for your personal support! here is another solution for the traditional hocket... take it or leave it or code it in your own personal way ;-) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; generates hocket-voice (defun gen-hocket-voice (elist omnlist) (let ((omnevents (single-events omnlist)) (elist (gen-repeat 5 elist))) (loop repeat (length (single-events omnlist)) for cnt = 0 then (incf cnt) when (= (nth cnt elist) 1) collect (nth cnt omnevents) else collect (if (length-restp (car (nth cnt omnevents))) (nth cnt omnevents) (* -1 (car (flatten (omn :length (nth cnt omnevents))))))))) ;; splits isntruments for binary.. (defun gen-binary-for-hocket (alist) (let ((vlist (sort-asc (remove-duplicates alist)))) (loop for v in vlist collect (loop for i in alist when (= i v) collect 1 else collect 0)))) ;; each number is an instrumnet -> for voices (gen-binary-for-hocket '(1 2 3 2 1 2 3 4 3 2 1))) => ((1 0 0 0 1 0 0 0 0 0 1) (0 1 0 1 0 1 0 0 0 1 0) (0 0 1 0 0 0 1 0 1 0 0) (0 0 0 0 0 0 0 1 0 0 0)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; EXAMPLE ;; rnd-omn-seq (setf omn-seq (make-omn :pitch (make-scale 'c4 23) :length '(s) :span :pitch)) ;; voices 1-4 (setf v1 (gen-hocket-voice (first (gen-binary-for-hocket '(1 2 3 2 1 2 3 4 3 2 1))) omn-seq)) (setf v2 (gen-hocket-voice (second (gen-binary-for-hocket '(1 2 3 2 1 2 3 4 3 2 1))) omn-seq)) (setf v3 (gen-hocket-voice (third (gen-binary-for-hocket '(1 2 3 2 1 2 3 4 3 2 1))) omn-seq)) (setf v4 (gen-hocket-voice (fourth (gen-binary-for-hocket '(1 2 3 2 1 2 3 4 3 2 1))) omn-seq)) ;; check -> when chromatic scale then everything is okayx (merge-voices v1 v2 v3 v4)
  18. If it weren’t exclusively stochastic, but if it were also possible to ‘filter’ the events through binary lists, then one could build interesting instrumentation matrices/trajectories (for example, using vector-envelopes that would then be mapped voice by voice into binary lists). Would that be an option?
  19. a simple hocket-function - starting with an OMN-sequence (defun gen-hocket-voice (elist omnlist) (let ((omnevents (single-events omnlist))) (loop repeat (length (single-events omnlist)) for cnt = 0 then (incf cnt) when (= (nth cnt elist) 1) collect (nth cnt omnevents) else collect (if (length-restp (car (nth cnt omnevents))) (nth cnt omnevents) (* -1 (car (flatten (omn :length (nth cnt omnevents))))))))) ;; eveluate this (progn ;(setf omnseq '(s c4 mf cs4 d4 ds4 -q s e4 f4 -1 s fs4 g4 gs4 a4)) ; simple ;(setf omnseq (flatten (gen-rnd-omn 3 8 1 3 '(c4 cs4 d4 ds4 e4 f4 fs4 g4 gs4 a4) 's nil) )) ; more complex (setf omnseq (flatten (filter-first 5 (gen-rnd-omn 8 '(8 8 12 4) 2 4 '(c4 cs4 d4 ds4 e4 f4 fs4 g4 gs4 a4) 's '(p mp f) :rotate '(-1 2 0 1) :type 2)))) (setf events1 '(0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1)) ; an eventlist (setf events2 '(1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0)) ; another eventlist (setf events3 '(1 1 1 0 1 1 0 0 1 1 1 0 1 1 1 1 1 0 1 1 0 0 1 1 1 0 1 1)) ; another eventlist (setf instr1 (gen-hocket-voice events1 omnseq)) (setf instr2 (gen-hocket-voice events2 omnseq)) (setf instr3 (gen-hocket-voice events3 omnseq)) ;; check it -> if one voice then everything okay (merge-voices instr1 instr2 instr3))
  20. some old stuff https://opusmodus.com/forums/topic/501-gen-hoquetus/
  21. packed in a function ... as many voices you want... ;; packed in a function (defun gen-omn-by-events (elist plist rlist &key (vel 'p)) (loop repeat (length elist) for cnt = 0 then (incf cnt) when (= (nth cnt elist) 1) collect (list (nth cnt rlist) (nth cnt plist) vel) else collect (* -1 (nth cnt rlist )))) (setf events1 '(1 0 1 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1 0 1)) ; an eventlist (setf events2 '(0 1 0 0 0 1 0 0 1 1 0 1 0 0 1 0 1 0 0 0 1 1 1 0)) ; another eventlist (setf events3 '(1 1 1 0 1 1 0 0 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0)) ; another eventlist (setf instr1 (gen-omn-by-events events1 plist rlist :vel 'p)) (setf instr2 (gen-omn-by-events events2 plist rlist :vel 'f)) (setf instr3 (gen-omn-by-events events3 plist rlist :vel 'ppp)) ;; ........ ;; check it (merge-voices instr1 instr2 instr3)
  22. a (very simple) more lispian version (setf l1 '(1 0 1 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1 0 1)) ; an eventlist (setf l2 '(0 1 0 0 0 1 0 0 1 1 0 1 0 0 1 0 1 0 0 0 1 1 1 0)) ; another eventlist (setf plist (gen-repeat 2 (rnd-air :type :pitch))) ;; a rnd-pitch-seq (setf rlist (rnd-sample 50 '(1/16 2/16 3/16 5/16))) ;; a rnd-length-seq ;; voice 1 (setf instr1 (loop repeat (length l1) for cnt = 0 then (incf cnt) when (= (nth cnt l1) 1) collect (list (nth cnt rlist) (nth cnt plist) 'f) else collect (* -1 (nth cnt rlist)))) ;; voice 2 (setf instr2 (loop repeat (length l2) for cnt = 0 then (incf cnt) when (= (nth cnt l2) 1) collect (list (nth cnt rlist) (nth cnt plist) 'p) else collect (* -1 (nth cnt rlist )))) ;; check by MERGE (merge-voices instr1 instr2)
  23. no problems on Version 4.0.30060 (4.0.30060) - Mac

Copyright © 2014-2026 Opusmodus™ Ltd. All rights reserved.
Product features, specifications, system requirements and availability are subject to change without notice.
Opusmodus, the Opusmodus logo, and other Opusmodus trademarks are either registered trademarks or trademarks of Opusmodus Ltd.
All other trademarks contained herein are the property of their respective owners.

Powered by Invision Community

Important Information

Terms of Use Privacy Policy

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.