<?xml version="1.0"?>
<rss version="2.0"><channel><title>User Extensions Source Code Latest Topics</title><link>https://opusmodus.com/forums/forum/17-user-extensions-source-code/</link><description>User Extensions Source Code Latest Topics</description><language>en</language><item><title>Save-current-section</title><link>https://opusmodus.com/forums/topic/4112-save-current-section/</link><description><![CDATA[<p>Hello everyone,</p><p></p><p>I would like to share a small utility function I recently developed for Opusmodus that may be useful for people working with long-form generative or multi-section compositions.</p><p></p><p>The idea is very simple:</p><p></p><p>The function automatically captures the output of <code>pprint-last-score</code>, creates a file if necessary, and appends the generated <code>def-score</code> into that file while allowing automatic or manual section naming.</p><p></p><p>For example:</p><p></p><p><code>(save-current-section</code></p><p><code> :file "/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp")</code></p><p></p><p>Automatically generates:</p><p></p><p><code>(def-score section001 ...)</code></p><p><code>(def-score section002 ...)</code></p><p><code>(def-score section003 ...)</code></p><p></p><p>Or with a custom name:</p><p></p><p><code>(save-current-section</code></p><p><code> :file "/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp"</code></p><p><code> :name 'coda)</code></p><p></p><p>One particularly useful aspect is the possibility to store metadata alongside each section:</p><p></p><p><code>(save-current-section</code></p><p><code> :file "/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp"</code></p><p><code> :metadata `((:seed ,*gseed*)</code></p><p><code>             (:tempo 72)</code></p><p><code>             (:mode octatonic)</code></p><p><code>             (:algorithm score212)))</code></p><p></p><p>This allows the score file to become not only a collection of sections, but also a compositional archive containing informations on each section.</p><p>I have found this especially useful for:</p><ul><li><p>large algorithmic works,</p></li><li><p>iterative composition,</p></li><li><p>and building long-form modular pieces.</p></li></ul><p>The function automatically:</p><ul><li><p>creates the file if needed,</p></li><li><p>appends new sections without overwriting,</p></li><li><p>detects the next available section number,</p></li><li><p>renames the internal <code>def-score</code>,</p></li><li><p>and optionally stores metadata comments.</p></li></ul><p>I am sharing the full code below in case it may be useful to others.</p><p></p><p><code>(in-package :opusmodus)</code></p><p><code>;;; ------------------------------------------------------------</code></p><p><code>;;; CAPTURE DU DERNIER SCORE</code></p><p><code>;;; ------------------------------------------------------------</code></p><p><code>(defun capture-pprint-last-score ()</code></p><p><code>  "Capture le texte produit par pprint-last-score sans la ligne pprint-last-score."</code></p><p><code>  (let* ((txt (with-output-to-string (*standard-output*)</code></p><p><code>                (pprint-last-score)))</code></p><p><code>         (pos (search "(def-score" txt :test #'char-equal)))</code></p><p><code>    (unless pos</code></p><p><code>      (error "Aucun (def-score ...) trouvé dans pprint-last-score."))</code></p><p><code>    (subseq txt pos)))</code></p><p><code>;;; ------------------------------------------------------------</code></p><p><code>;;; REMPLACEMENT DU NOM DU DEF-SCORE</code></p><p><code>;;; ------------------------------------------------------------</code></p><p><code>(defun replace-def-score-name (score-string new-name)</code></p><p><code>  "Remplace le nom du premier def-score par NEW-NAME."</code></p><p><code>  (let* ((new-name-string (string-downcase (string new-name)))</code></p><p><code>         (pos (search "(def-score" score-string :test #'char-equal)))</code></p><p><code>    (unless pos</code></p><p><code>      (error "Aucun (def-score ...) trouvé dans le texte capturé."))</code></p><p><code>    (let* ((start (+ pos (length "(def-score")))</code></p><p><code>           (after-space</code></p><p><code>            (position-if-not</code></p><p><code>             #'(lambda (c)</code></p><p><code>                 (member c '(#\Space #\Tab #\Newline)))</code></p><p><code>             score-string</code></p><p><code>             :start start))</code></p><p><code>           (end-name</code></p><p><code>            (position-if</code></p><p><code>             #'(lambda (c)</code></p><p><code>                 (member c '(#\Space #\Tab #\Newline #\()))</code></p><p><code>             score-string</code></p><p><code>             :start after-space)))</code></p><p><code>      (concatenate 'string</code></p><p><code>                   (subseq score-string 0 after-space)</code></p><p><code>                   new-name-string</code></p><p><code>                   (subseq score-string end-name)))))</code></p><p><code>;;; ------------------------------------------------------------</code></p><p><code>;;; UTILITAIRES</code></p><p><code>;;; ------------------------------------------------------------</code></p><p><code>(defun read-file-as-string (file)</code></p><p><code>  "Lit FILE sous forme de string. Renvoie une string vide si le fichier n'existe pas."</code></p><p><code>  (if (probe-file file)</code></p><p><code>      (with-open-file (in file :direction :input)</code></p><p><code>        (let ((contents (make-string (file-length in))))</code></p><p><code>          (read-sequence contents in)</code></p><p><code>          contents))</code></p><p><code>      ""))</code></p><p><code>(defun zero-pad-number (number width)</code></p><p><code>  "Convertit NUMBER en string avec des zéros à gauche."</code></p><p><code>  (let ((s (write-to-string number)))</code></p><p><code>    (concatenate 'string</code></p><p><code>                 (make-string (max 0 (- width (length s)))</code></p><p><code>                              :initial-element #\0)</code></p><p><code>                 s)))</code></p><p><code>(defun collect-auto-section-numbers (text prefix)</code></p><p><code>  "Collecte tous les numéros trouvés dans des noms du type PREFIX001, PREFIX002, etc."</code></p><p><code>  (let* ((prefix-string (string-downcase prefix))</code></p><p><code>         (prefix-length (length prefix-string))</code></p><p><code>         (text-lower (string-downcase text))</code></p><p><code>         (numbers '())</code></p><p><code>         (start 0))</code></p><p><code>    (loop</code></p><p><code>      for pos = (search prefix-string text-lower :start2 start)</code></p><p><code>      while pos do</code></p><p><code>        (let* ((num-start (+ pos prefix-length))</code></p><p><code>               (num-end num-start))</code></p><p><code>          (loop</code></p><p><code>            while (and (&lt; num-end (length text-lower))</code></p><p><code>                       (digit-char-p (char text-lower num-end)))</code></p><p><code>            do (incf num-end))</code></p><p><code>          (when (&gt; num-end num-start)</code></p><p><code>            (push (parse-integer text-lower</code></p><p><code>                                 :start num-start</code></p><p><code>                                 :end num-end)</code></p><p><code>                  numbers))</code></p><p><code>          (setf start num-end)))</code></p><p><code>    numbers))</code></p><p><code>(defun next-section-number (file prefix)</code></p><p><code>  "Trouve le prochain numéro disponible pour PREFIX dans FILE."</code></p><p><code>  (let* ((text (read-file-as-string file))</code></p><p><code>         (numbers (collect-auto-section-numbers text prefix)))</code></p><p><code>    (if numbers</code></p><p><code>        (1+ (apply #'max numbers))</code></p><p><code>        1)))</code></p><p><code>(defun make-auto-section-name (file prefix digits)</code></p><p><code>  "Crée un nom automatique du type section001."</code></p><p><code>  (intern</code></p><p><code>   (string-upcase</code></p><p><code>    (format nil "~a~a"</code></p><p><code>            prefix</code></p><p><code>            (zero-pad-number</code></p><p><code>             (next-section-number file prefix)</code></p><p><code>             digits)))))</code></p><p><code>;;; ------------------------------------------------------------</code></p><p><code>;;; FONCTION PRINCIPALE</code></p><p><code>;;; ------------------------------------------------------------</code></p><p><code>(defun save-current-section (&amp;key</code></p><p><code>                               file</code></p><p><code>                               name</code></p><p><code>                               (prefix "section")</code></p><p><code>                               (digits 3)</code></p><p><code>                               (separator t)</code></p><p><code>                               (comment-date nil)</code></p><p><code>                               metadata)</code></p><p><code>  "Sauvegarde le dernier score Opusmodus dans FILE.</code></p><p><code>Si NAME est fourni, le def-score prendra ce nom.</code></p><p><code>Si NAME est NIL, un nom automatique sera généré :</code></p><p><code>section001, section002, section003, etc.</code></p><p><code>Exemples :</code></p><p><code>  (save-current-section</code></p><p><code>   :file \"/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp\")</code></p><p><code>  (save-current-section</code></p><p><code>   :file \"/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp\"</code></p><p><code>   :name 'introduction)</code></p><p><code>  (save-current-section</code></p><p><code>   :file \"/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp\"</code></p><p><code>   :prefix \"part\"</code></p><p><code>   :digits 2)</code></p><p><code>  (save-current-section</code></p><p><code>   :file \"/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp\"</code></p><p><code>   :metadata '((:seed 12345)</code></p><p><code>               (:mode octatonic-1)</code></p><p><code>               (:tempo 72)))"</code></p><p><code>  (unless file</code></p><p><code>    (error "Tu dois fournir un chemin avec :file."))</code></p><p><code>  (let* ((score-name</code></p><p><code>          (or name</code></p><p><code>              (make-auto-section-name file prefix digits)))</code></p><p><code>         (raw-score</code></p><p><code>          (capture-pprint-last-score))</code></p><p><code>         (renamed-score</code></p><p><code>          (replace-def-score-name raw-score score-name)))</code></p><p><code>    (ensure-directories-exist file)</code></p><p><code>    (with-open-file (out file</code></p><p><code>                         :direction :output</code></p><p><code>                         :if-exists :append</code></p><p><code>                         :if-does-not-exist :create)</code></p><p><code>      (when separator</code></p><p><code>        (format out "~%~%;;; ------------------------------------------------------------~%")</code></p><p><code>        (format out ";;; SCORE: ~a~%" score-name)</code></p><p><code>        (when comment-date</code></p><p><code>          (format out ";;; Exported: ~a~%" (get-universal-time)))</code></p><p><code>        (when metadata</code></p><p><code>          (format out ";;; Metadata: ~s~%" metadata))</code></p><p><code>        (format out ";;; ------------------------------------------------------------~%~%"))</code></p><p><code>      (format out "~a~%" renamed-score))</code></p><p><code>    score-name))</code></p><p><code>#|USAGE</code></p><p><code>Utilisation automatique :</code></p><p><code>(save-current-section</code></p><p><code> :file "/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp")</code></p><p><code>Cela écrit automatiquement :</code></p><p><code>(def-score section001 ...)</code></p><p><code>Puis au prochain appel :</code></p><p><code>(def-score section002 ...)</code></p><p><code>Avec un nom manuel :</code></p><p><code>(save-current-section</code></p><p><code> :file "/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp"</code></p><p><code> :name 'coda)</code></p><p><code>Avec métadonnées :</code></p><p><code>(save-current-section</code></p><p><code> :file "/Users/stephaneboussuge/Opusmodus/Scores/my-piece.lisp"</code></p><p><code> :metadata `((:seed ,*gseed*)</code></p><p><code>             (:tempo 72)</code></p><p><code>             (:material "octatonic")))</code></p><p><code>|#</code></p><p></p><p></p><p></p><p></p><p></p><p>Best,<br>Stéphane</p><p></p>]]></description><guid isPermaLink="false">4112</guid><pubDate>Tue, 12 May 2026 20:05:56 +0000</pubDate></item><item><title>A useful function : Export-to-Dorico</title><link>https://opusmodus.com/forums/topic/4111-a-useful-function-export-to-dorico/</link><description><![CDATA[<p>Hi dear Opusmodus users,</p><p></p><p>If you’re like me and use Dorico to compose with Opusmodus, you’ve probably noticed that the dynamics notation like pp, mf, and ff aren’t imported into Dorico when you import an XML file from Opusmodus.</p><p></p><p>Here’s a function that solves this problem. It’s probably not perfect, but I’m sharing it here in case it helps some Opusmodus/Dorico users.</p><p></p><p>Be careful not to forget to change the path for your own path in the first parameter inside the Lisp document to make it work properly.</p><p>Best,</p><p></p><p>Stéphane</p><p></p><p></p><p></p><p></p><p></p>]]></description><guid isPermaLink="false">4111</guid><pubDate>Mon, 11 May 2026 10:06:51 +0000</pubDate></item><item><title>Csound-Opusmodus-Framework</title><link>https://opusmodus.com/forums/topic/4102-csound-opusmodus-framework/</link><description><![CDATA[<p>Hi dear Opusmodus friends,</p><p></p><p>I’m sharing my personal framework for generating algorithmically Csound files directly from Opusmodus.</p><p></p><p>I’m sharing it « as is » and I know it can be improved, but it works well for my actual use. You can use it as a starting point for building your own framework.</p><p></p><p>There are some personal choices in the design of this framework, such as a very simple signal flow. After testing more complex routing like Csound mixers and send FX, I decided to return to a simpler workflow that aligns more closely with my usual Csound practice.</p><p></p><p>Disclaimer: This tool is intended for individuals who are already proficient in Csound.</p><p></p><p>Hope you will enjoy it !</p><p></p><figure data-og-url="https://github.com/Nanotk303/csound-opusmodus-framework" data-og-description="Contribute to Nanotk303/csound-opusmodus-framework development by creating an account on GitHub." data-og-title="GitHub - Nanotk303/csound-opusmodus-framework" data-og-site_name="GitHub" data-og-favicon_url="https://github.githubassets.com/favicons/favicon.svg" data-og-user_text="https://github.com/Nanotk303/csound-opusmodus-framework" class="ipsEmbedded_og ipsEmbedded"><div class="ipsEmbedded_og__site-name"><img class="ipsEmbedded_og__favicon" src="https://github.githubassets.com/favicons/favicon.svg" alt=""><h5>GitHub</h5></div><figcaption><h3 class="ipsEmbedded_og__title">GitHub - Nanotk303/csound-opusmodus-framework</h3><div class="ipsEmbedded_og__description">Contribute to Nanotk303/csound-opusmodus-framework development by creating an account on GitHub.</div></figcaption></figure>]]></description><guid isPermaLink="false">4102</guid><pubDate>Fri, 17 Apr 2026 14:04:10 +0000</pubDate></item><item><title>binary-layers - alternative version</title><link>https://opusmodus.com/forums/topic/4091-binary-layers-alternative-version/</link><description><![CDATA[<p>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.</p><p></p><p>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.</p><p></p><p><video class="ipsEmbeddedVideo ipsRichText__align--block" data-controller="core.global.core.embeddedvideo" controls="" title="" preload="metadata"><source src="https://opusmodus.com/forums/uploads/monthly_2026_04/Bildschirmaufnahme2026-04-05um18_59_59.mov.7159becab3ac5977cfb36da5e0d9908d.mov#t=0" type="video/quicktime"><a href="https://opusmodus.com/forums/applications/core/interface/file/attachment.php?id=4391" class="ipsAttachLink" data-fileid="4391" data-fileext="mov" rel="">Bildschirmaufnahme 2026-04-05 um 18.59.59.mov</a></source></video></p><p></p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>(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 (&gt; 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)))
=&gt; ((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)))
=&gt; ((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)))
=&gt; ((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 -&gt; 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))</code></pre><p></p>]]></description><guid isPermaLink="false">4091</guid><pubDate>Sun, 05 Apr 2026 17:02:10 +0000</pubDate></item><item><title>kNN-algorithm</title><link>https://opusmodus.com/forums/topic/4092-knn-algorithm/</link><description><![CDATA[<p>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.</p><p></p><figure data-og-url="https://www.geeksforgeeks.org/machine-learning/k-nearest-neighbours/" data-og-description="Your 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" data-og-title="K-Nearest Neighbor(KNN) Algorithm - GeeksforGeeks" data-og-site_name="GeeksforGeeks" data-og-favicon_url="https://www.geeksforgeeks.org/wp-content/uploads/gfg_200X200.png" data-og-user_text="https://www.geeksforgeeks.org/machine-learning/k-nearest-neighbours/" class="ipsEmbedded_og ipsEmbedded"><div class="ipsEmbedded_og__site-name"><img class="ipsEmbedded_og__favicon" src="https://www.geeksforgeeks.org/wp-content/uploads/gfg_200X200.png" alt=""><h5>GeeksforGeeks</h5></div><figcaption><h3 class="ipsEmbedded_og__title">K-Nearest Neighbor(KNN) Algorithm - GeeksforGeeks</h3><div class="ipsEmbedded_og__description">Your 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</div></figcaption></figure><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>;; 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 (&lt;= k 0) (&gt; 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 #'&lt; :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)))
                    #'&gt;
                    :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)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
</code></pre><p></p><p></p>]]></description><guid isPermaLink="false">4092</guid><pubDate>Sun, 05 Apr 2026 20:48:32 +0000</pubDate></item><item><title>ratios-to-integers and back</title><link>https://opusmodus.com/forums/topic/4090-ratios-to-integers-and-back/</link><description><![CDATA[<p>Make a length sequence integer-valued using the least common multiple, then apply the proportions to gen-length. Another kind of augmentation/diminution.</p><p></p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>(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)</code></pre>]]></description><guid isPermaLink="false">4090</guid><pubDate>Fri, 03 Apr 2026 21:32:19 +0000</pubDate></item><item><title>Slonimsky Patterns</title><link>https://opusmodus.com/forums/topic/4070-slonimsky-patterns/</link><description><![CDATA[<p>Hi,</p><p></p><ul><li><p>I’ve experimented with Opusmodus GPT and created this tool for my personal use. However, I thought it might be helpful for some of you, so I’m sharing it.</p><h2><code>GEN-SLONIMSKY-PATTERN</code></h2><p><strong>Synopsis</strong></p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>(gen-slonimsky-pattern octaves divisions
  &amp;key
    interpolation infrapolation ultrapolation
    root direction
    dedupe dedupe-mode dedupe-tolerance
    limit-to-octave
    trim-with-gen-trim
    interpolation-permutation
    remove-consecutive-repeats
    transpose
    rotate)</code></pre><h2>Description</h2><p><code>GEN-SLONIMSKY-PATTERN</code> generates a <em>Slonimsky-like</em> procedural pitch pattern as an <strong>Opusmodus pitch list</strong>.</p><p>Conceptually, the function builds a chain of “principal tones” across a span of <code>octaves</code> (converted to a total chromatic span), subdivided into <code>divisions</code>. For each principal tone, it can optionally insert:</p><ul><li><p>an <strong>infrapolation</strong> pitch (below the principal tone),</p></li><li><p>one or more <strong>interpolation</strong> pitches (offsets around each principal tone),</p></li><li><p>an <strong>ultrapolation</strong> pitch (above the principal tone).</p></li></ul><p>After construction, the pattern can be octave-wrapped, de-duplicated (exactly or with a tolerance), trimmed to a target size, filtered for repeats, then optionally transposed and rotated.</p><p>The function returns either <strong>one pitch list</strong> or <strong>a list of pitch-lists</strong>, depending on <code>:interpolation-permutation</code>.</p><h2>Parameters</h2><h3>Required</h3><ul><li><p><code>octaves</code><br>Number of octaves covered by the pattern. Internally, the chromatic span is <code>(* 12 octaves)</code>.</p></li><li><p><code>divisions</code><br>Number of divisions across the total span. The step size is computed as:</p><ul><li><p><code>step = (/ (* 12 octaves) divisions)</code></p></li></ul><p>The principal-tone loop iterates <code>i = 0 .. divisions</code> (inclusive), so endpoints are included.</p></li></ul><h3>Keyword options</h3><h4>Pattern content</h4><ul><li><p><code>:interpolation</code> <em>(default: </em><code>NIL</code><em>)</em><br>A list of numeric offsets (in MIDI units) inserted after each principal tone. Each <code>k</code> produces an inserted pitch at <code>pt + (dir-sign * k)</code>.</p></li><li><p><code>:infrapolation</code> <em>(default: </em><code>NIL</code><em>)</em><br>If non-<code>NIL</code>, inserts one pitch <em>below</em> each principal tone: <code>pt - infrapolation</code> (respecting direction sign as implemented).</p></li><li><p><code>:ultrapolation</code> <em>(default: </em><code>NIL</code><em>)</em><br>If non-<code>NIL</code>, inserts one pitch <em>above</em> each principal tone: <code>pt + (dir-sign * ultrapolation)</code>.</p></li><li><p><code>:root</code> <em>(default: </em><code>'c4</code><em>)</em><br>Root pitch (Opusmodus pitch symbol). Converted to MIDI via <code>PITCH-TO-MIDI</code>. </p></li><li><p><code>:direction</code> <em>(default: </em><code>:up</code><em>)</em><br>Either <code>:up</code> or <code>:down</code>. Controls the sign of principal-tone stepping and of interpolation offsets.</p></li></ul><h4>De-duplication</h4><ul><li><p><code>:dedupe</code> <em>(default: </em><code>NIL</code><em>)</em><br>Enables de-duplication after optional octave-wrapping.</p></li><li><p><code>:dedupe-mode</code> <em>(default: </em><code>:consecutive</code><em>)</em></p><ul><li><p><code>:consecutive</code> removes only consecutive duplicates.</p></li><li><p><code>:all</code> removes duplicates globally (first occurrence kept).</p></li></ul></li><li><p><code>:dedupe-tolerance</code> <em>(default: </em><code>0</code><em>)</em><br>If <code>0</code>, duplicates are detected by exact MIDI equality.<br>If <code>&gt; 0</code>, two MIDI values are considered equal if their absolute difference is <code>&lt;= dedupe-tolerance</code>.</p></li></ul><h4>Octave limiting</h4><ul><li><p><code>:limit-to-octave</code> <em>(default: </em><code>NIL</code><em>)</em></p><ul><li><p><code>NIL</code>: no wrapping</p></li><li><p><code>T</code>: wraps every MIDI value into the octave <code>[root, root+12)</code> (relative to the MIDI value of <code>root</code>), then converts back to pitches.</p></li></ul></li></ul><h4>Trimming / sizing</h4><ul><li><p><code>:trim-with-gen-trim</code> <em>(default: </em><code>NIL</code><em>)</em><br>If true, calls <code>GEN-TRIM</code> to force a computed target size. <code>GEN-TRIM</code> trims or extends a list to the requested length. </p><p>The internal <strong>target size</strong> is computed as:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>target-size = divisions
            + (length interpolation)
            + (if infrapolation 1 0)
            + (if ultrapolation 1 0)</code></pre><p>(Note: principal tones are generated with endpoints included, but the trimming target is computed as shown above.)</p></li></ul><h4>Interpolation permutation</h4><ul><li><p><code>:interpolation-permutation</code> <em>(default: </em><code>NIL</code><em>)</em><br>Controls <em>only</em> the ordering/selection of the <code>:interpolation</code> list; principal tones remain fixed.</p><p>Supported values:</p><ul><li><p><code>NIL</code> → uses <code>interpolation</code> as given.</p></li><li><p><code>:all</code> → generates <strong>all permutations</strong> of <code>interpolation</code> via <code>PERMUTE</code> and returns <strong>a list of pitch-lists</strong> (one per permutation). </p></li><li><p><code>:messiaen</code> → applies <code>MESSIAEN-PERMUTATION</code> to the interpolation list. For length 2, the code forces <code>:type :open</code>by default. (<code>MESSIAEN-PERMUTATION</code> is documented with <code>:type</code> options such as <code>:open</code> / <code>:closed</code>.) </p></li><li><p><code>(:messiaen type)</code> → uses <code>MESSIAEN-PERMUTATION</code> with an explicit <code>:type</code>. </p></li><li><p><code>(:nth n)</code> → takes the <code>n</code>th permutation from <code>(permute interpolation)</code> and builds a single pattern.</p></li></ul></li></ul><h4>Repeat filtering</h4><ul><li><p><code>:remove-consecutive-repeats</code> <em>(default: </em><code>NIL</code><em>)</em><br>If true, applies <code>(filter-repeat 1 ...)</code> to the trimmed pitch list. <code>FILTER-REPEAT</code> limits repetitions; with <code>n = 1</code> it removes consecutive repeats. </p></li></ul><h4>Post transforms (new)</h4><ul><li><p><code>:transpose</code> <em>(default: </em><code>NIL</code><em>)</em><br>If non-<code>NIL</code>, applies <code>(pitch-transpose transpose sequence)</code> to the final pitch list.</p></li><li><p><code>:rotate</code> <em>(default: </em><code>NIL</code><em>)</em><br>If non-<code>NIL</code>, applies <code>(pitch-rotate rotate sequence)</code> to the (optionally transposed) result. <code>PITCH-ROTATE</code> supports <code>rotation-number</code> as a number or list, and has keyword options such as <code>:chord</code> (default <code>T</code>). </p></li></ul><h2>Return value</h2><ul><li><p>If <code>:interpolation-permutation</code> is <code>:all</code> → returns <strong>a list of pitch-lists</strong> (one per permutation variant).</p></li><li><p>Otherwise → returns a <strong>single pitch list</strong>.</p></li></ul><p>Pitch conversion uses <code>MIDI-TO-PITCH</code> for the final MIDI list back to pitch symbols. </p><h2>Examples</h2><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>;; Basic example + consecutive de-dupe + target trimming
(gen-slonimsky-pattern 1 2 :root 'c4 :direction :up
                       :interpolation '(1 6)
                       :dedupe t :dedupe-mode :consecutive
                       :trim-with-gen-trim t)
;; target-size = 2 + 2 = 4


;; With infra + ultra, trimmed to target size
(gen-slonimsky-pattern 1 2 :root 'c4 :direction :up
                       :interpolation '(1 6)
                       :infrapolation 1
                       :ultrapolation 2
                       :trim-with-gen-trim t)
;; target-size = 2 + 2 + 1 + 1 = 6


;; Messiaen permutation of interpolations (principal tones unchanged)
(gen-slonimsky-pattern 1 2
                       :root 'c4 :direction :up
                       :interpolation '(1 6)
                       :trim-with-gen-trim nil
                       :interpolation-permutation :messiaen)


;; Messiaen permutation + remove consecutive repeats
(gen-slonimsky-pattern 1 2
                       :root 'c4 :direction :up
                       :interpolation '(1 6)
                       :trim-with-gen-trim nil
                       :interpolation-permutation :messiaen
                       :remove-consecutive-repeats t)


;; Transpose then rotate (melodic rotation)
(gen-slonimsky-pattern 1 2
                       :root 'c4 :direction :up
                       :interpolation '(1 6)
                       :interpolation-permutation :messiaen
                       :remove-consecutive-repeats t
                       :transpose 2
                       :rotate 1)


;; Rotation with a longer interpolation set
(gen-slonimsky-pattern 1 2
                       :root 'c4
                       :interpolation '(1 6 8)
                       :trim-with-gen-trim t
                       :rotate 2)


;; Random interpolation offsets + random rotation amount
(gen-slonimsky-pattern 1 2
                       :root 'c4
                       :interpolation (rndn (rndn 1 2 5) 1 11)
                       :trim-with-gen-trim nil
                       :rotate (rndn 1 0 11))</code></pre><h2>Related documented functions (used internally)</h2><ul><li><p><code>PITCH-TO-MIDI (list &amp;key quantize remain)</code></p></li><li><p><code>MIDI-TO-PITCH (values &amp;key quantize remain)</code></p></li><li><p><code>GEN-TRIM (n sequence ...)</code> (trims/extends to length) </p></li><li><p><code>FILTER-REPEAT</code> (repeat limiting / consecutive control) </p></li><li><p><code>PERMUTE (sequence)</code> (all permutations) </p></li><li><p><code>MESSIAEN-PERMUTATION ... :type ...</code> (permutation strategies, e.g., <code>:open</code>, <code>:closed</code>) </p></li><li><p><code>PITCH-ROTATE (rotation-number sequence &amp;key chord section exclude ambitus)</code></p></li></ul></li></ul><p>
<a class="ipsAttachLink" href="https://opusmodus.com/forums/applications/core/interface/file/attachment.php?id=4362&amp;key=68888319f067cb3e76a9c09fe1791952" data-fileExt='lisp' data-fileid='4362' data-filekey='68888319f067cb3e76a9c09fe1791952'>gen-slonimsky-pattern.lisp</a></p>]]></description><guid isPermaLink="false">4070</guid><pubDate>Fri, 27 Feb 2026 20:21:12 +0000</pubDate></item><item><title>Cellular Automaton filters Chord</title><link>https://opusmodus.com/forums/topic/3933-cellular-automaton-filters-chord/</link><description><![CDATA[<p>Here’s a small technical idea... just with a "random-chord"</p><p></p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>(progn
  (setf chord  (rnd-sample-seq 10 (gen-sieve '(c3 g7) '(1 2 4 7 4 2) :type :pitch)))
  
  
  (setf rule30 (cellular-automaton 30 200 '(0 0 0 1 0 1 0 0 0 0)))
  (setf positions (loop for i in rule30
                        collect (position-item 1 i)))
  
  (setf chords (loop for i in positions
                     collect (chordize (position-filter i chord))))

  (pitch-list-plot (flatten chords)  :join-chords t))</code></pre><p><a rel="external nofollow" href="https://plato.stanford.edu/entries/cellular-automata/supplement.html">https://plato.stanford.edu/entries/cellular-automata/supplement.html</a></p>]]></description><guid isPermaLink="false">3933</guid><pubDate>Sat, 28 Jun 2025 13:03:51 +0000</pubDate></item><item><title>anti-oscil</title><link>https://opusmodus.com/forums/topic/3827-anti-oscil/</link><description><![CDATA[<p>Hi folks,</p><p> </p><p>here's a function I find useful for my work and sharing it here.</p><p>This is an anti oscillation function to remove aba type patterns when working on algorithmically generated material.</p><p> </p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>(defun anti-oscil (lst)
  "Supprime les éléments formant des oscillations de type x _ x dans LST.
   Exemple : (anti-oscil '(a b a a c)) =&gt; (a b c)"
  (labels
      ((rec (remaining result)
         (if (null remaining)
             ;; Plus rien à traiter, on renvoie le résultat tel quel
             result
           (let ((x (car remaining)))
             (if (and (&gt;= (length result) 2)
                      (equal x (nth (- (length result) 2) result)))
                 ;; x forme une oscillation x _ x : on l'ignore
                 (rec (cdr remaining) result)
               ;; Sinon, on l'ajoute à la fin du résultat
               (rec (cdr remaining) (append result (list x))))))))
    ;; On démarre la récursion avec la liste complète et un résultat vide
    (rec lst '())))

#| Usage examples
 (filter-repeat
  1
  (anti-oscil
   (vector-to-pitch
    '(c3 c5)
    (vector-smooth 0.2 (gen-noise 128 :seed 42)))
   ))

(tonality-map
 '(messiaen-mode2 :map 'step)
 (filter-repeat
  1
  (anti-oscil
   (vector-to-pitch
    '(0 20)
    (vector-smooth 0.2 (gen-noise 128)))
   )))
|#
</code></pre>]]></description><guid isPermaLink="false">3827</guid><pubDate>Sat, 11 Jan 2025 18:11:37 +0000</pubDate></item><item><title>Multi-state Cellular Automata</title><link>https://opusmodus.com/forums/topic/3799-multi-state-cellular-automata/</link><description><![CDATA[<p>
	I'm new to Opusmodus and Lisp programming. It will be awhile before I can implement some of the ideas that I have. In the meantime I've discovered that the Opusmodus GPT can do some programming for me. Here are two functions that it generated for me. A one dimensional totalistc CA with an arbitrary number of states, and a function to generate random rule sets. It took some prompting to get them to this stage. Totalistic CA rules are symmetrical, so if your initial state is a palindrome all generations will be.
</p>

<p>
	 
</p>

<pre class="ipsCode">(defun totalistic-cellular-automaton (states rules initial-state generations)
  "Generates a multi-state totalistic cellular automaton.
   STATES: the number of possible states (e.g., 0, 1, 2, ...).
   RULES: a list of rules that map the sum of neighborhood states to a new state.
   INITIAL-STATE: a list representing the initial state of the automaton.
   GENERATIONS: the number of generations to evolve.
   Returns a list of all generations."
  (let* ((length (length initial-state))  ; Calculate the length from the initial-state
         (current-state initial-state)
         (next-state (make-list length))
         (all-generations (list current-state))) ; Initialize list with initial state
    (loop for gen from 1 to (1- generations)
          do (progn
               (loop for i from 0 below length
                     do (let* ((left (nth (mod (- i 1) length) current-state))  ; Left neighbor (wrap-around)
                               (center (nth i current-state))                 ; Current cell
                               (right (nth (mod (+ i 1) length) current-state)) ; Right neighbor (wrap-around)
                               (neighborhood-sum (+ left center right)))      ; Calculate the sum of neighbors
                          ;; Apply the totalistic rule based on the neighborhood sum
                          (setf (nth i next-state) (nth neighborhood-sum rules))))
               ;; Append the new state to the list of all generations
               (push (copy-list next-state) all-generations)
               ;; Move to the next state
               (setf current-state (copy-list next-state))))
    ;; Return the list of all generations
    (reverse all-generations)))  ; Return in the correct order

(defun generate-random-rule-set (states &amp;key seed)
  "Generates a random rule set for a totalistic cellular automaton with the given number of STATES.
   The rule set maps sums (from 0 to 3 * (states - 1)) to a random state.
   The SEED parameter allows reproducibility of random output."
  (let ((max-sum (* 3 (1- states))))
    ;; Generate the entire rule set in one go using rndn with the seed parameter
    (rndn (1+ max-sum) 0 (1- states) :seed seed)))  ;; Generate integers between 0 and states-1

;; usage
(setf states 8)
(setf rule (generate-random-rule-set states :seed 12))
(totalistic-cellular-automaton states rule '(0 1 2 7 7 2 1 0) 4)
=&gt; ((0 1 2 7 7 2 1 0)
    (7 3 6 2 2 6 3 7)
    (2 2 6 6 6 6 2 2)
    (3 6 7 4 4 7 6 3))</pre>

<p>
	 
</p>
]]></description><guid isPermaLink="false">3799</guid><pubDate>Sun, 03 Nov 2024 15:42:31 +0000</pubDate></item><item><title>omn-rnd-vars</title><link>https://opusmodus.com/forums/topic/3678-omn-rnd-vars/</link><description><![CDATA[<p>
	here's a useful function (for me at least) who use unfold internally to apply some variations from a reservoir to some OMN material. This function can surely be much improved (adding seed etc...) but actually I'm using it like this...
</p>

<p>
	Example of usage is at the end of the function definition file, a short string quartet example.
</p>

<p>
	 
</p>

<pre class="ipsCode" id="ips_uid_1925_5">;;; OMN-RND-VAR
;;; Base sur ma vieille pratique
;;; avec omn-rnd-variations1.

(defun generate-variation (max-length num-measures)
  "Generate a sorted list of unique random numbers based on num-measures."
  (sort-asc (find-unique (rnd-number num-measures 1 max-length :norep t))))

(defun omn-rnd-var (variations measures omn-sequence &amp;key (uset 'om))
  "Application de variations via unfold avec une liste de variations et mesures correspondantes."
  (let ((max-length (length omn-sequence))
        (variation-list '()))
    (dolist (pair (mapcar #'cons variations measures))
      (let ((var (car pair))
            (num-measures (cdr pair)))
        (push (list var (generate-variation max-length num-measures)) variation-list)))
    (unfold uset (reverse variation-list) omn-sequence )))

#!
;; Exemple d'appel de l a fonction
;; Note: Le nombre de mesure n'est pas toujours exact
;; en raison de l'appel de find unique dans la fonction
;; generate variations afin de generer les index aleatoires
;; de mesure sans repetition, find-unique donc qui peut entrainer
;; la suppression de certains index qui etaient repetes. 

;; Attention, pour que la fonction fonctionne bien,
;; Les 2 listes variations et measures doivent etre
;; de la meme longueur (meme nombre d'elements).

;; Possibilite d'utiliser un unfold set personel avec uset.
(setf omn-mat (gen-trim 8 '((e c4 fs4 d4 a4 c5 g4 d4 e4))))
(omn-rnd-var '(ld12 ld42 d) '(2 4 3) omn-mat)
(omn-rnd-var '(ld12 ld42 d) '(2 5 3) omn-mat :uset 'om) ;replace 'om by your own unfold set.

;; Exemple d'utilisation:
(setf mat1 '((s c4 d4 e4 fs4 q b4)))
(setf vars1.n 24)
(setf vars1 (length-legato
             (omn-rnd-var 
              '(ad da d ld12mx ld22mx i ri ra rr4 pf2 rop 7-15 stacc dl1)
              '(3   8 3  4     4      2  2  2 8   8   8   8    11    12)
              (gen-repeat vars1.n mat1)) 
             ))

(setf idx1 (vector-round 1 vars1.n (gen-noise vars1.n)))
(setf idx2 (vector-round 1 vars1.n (gen-noise vars1.n)))
(setf idx3 (vector-round 1 vars1.n (gen-noise vars1.n)))
(setf idx4 (vector-round 1 vars1.n (gen-noise vars1.n)))

(setf line1 (vector-map vars1 idx1))
(setf line2 (vector-map vars1 idx2))
(setf line3 (vector-map vars1 idx3))
(setf line4 (vector-map vars1 idx4))

(setf vn1 (ambitus 'violin (pitch-transpose 8 line1)))
(setf vn2 (ambitus 'violin (pitch-transpose 0 line2)))
(setf vla (ambitus 'viola (pitch-transpose -8 line3)))
(setf vlc (ambitus 'cello (pitch-transpose -18 line4)))

(ps 'gm :sq (list vn1 vn2 vla vlc))
!#


</pre>

<p>
	 
</p>
]]></description><guid isPermaLink="false">3678</guid><pubDate>Sun, 02 Jun 2024 07:10:55 +0000</pubDate></item><item><title>position-insert-seq</title><link>https://opusmodus.com/forums/topic/3025-position-insert-seq/</link><description><![CDATA[<p>
	kind of ... "position-insert" with OVERWRITE
</p>

<p>
	 
</p>

<pre class="ipsCode">(defun position-insert-seq (&amp;key alist insert item)
  (let ((pos (car (position-item item alist))))
    (position-replace (gen-integer pos (+ pos (1- (length insert)))) insert alist)))


(setf alist '(0 0 0 0 0 0 1 0 2 0 0 0 3 5 7))
(setf insert '(a b c d))

(position-insert-seq :alist '(0 0 0 0 0 0 1 0 2 0 0 0 3 5 7)
                 :insert '(a b c d)
                 :item 2)

=&gt; (0 0 0 0 0 0 1 0 a b c d 3 5 7)</pre>

<p>
	 
</p>
]]></description><guid isPermaLink="false">3025</guid><pubDate>Fri, 20 Oct 2023 18:30:41 +0000</pubDate></item><item><title>function to rnd-order  length, pitch,velocity etc of a omn-list</title><link>https://opusmodus.com/forums/topic/2979-function-to-rnd-order-length-pitchvelocity-etc-of-a-omn-list/</link><description><![CDATA[<p>
	Edit: Thanks to Janusz and Stephane I could correct and improve the function .    See below.
</p>

<p>
	 
</p>

<p>
	This is an earlier version:
</p>

<p>
	For the fun of it and hopefully some use I wrote this simple function:
</p>

<p>
	;;;;;;;;;
</p>

<p>
	(defun rk_rnd-order-omn (inomnl &amp;key (exclude nil) seed  (flat nil))<br />
	"to exclude use l for :length, p for :pitch, v for :velocity; d for :duration, a for :articulation, <br />
	 leg for :leg, ped for :ped;   i.e :exclude '(p leg)<br />
	  To be even more random flatten the omn with :flat t"<br />
	  (let* ( <br />
	          (state *init-seed* )<br />
	          (vseed (rnd-seed seed))<br />
	          (omnl (if flat (flatten inomnl) inomnl))<br />
	          (len (if (member 'l exclude) (omn :length omnl) (rnd-order (omn :length omnl) :seed vseed) )) <br />
	          (pit (if (member 'p exclude) (omn :pitch omnl) (rnd-order (omn :pitch omnl) :seed vseed) )) <br />
	          (vel (if (member 'v exclude) (omn :velocity omnl) (rnd-order (omn :velocity omnl) :seed vseed) )) <br />
	          (dur (if (member 'd exclude) (omn :duration omnl) (rnd-order (omn :duration omnl) :seed vseed) )) <br />
	          (arti (if (member 'a exclude) (omn :articulation omnl) (rnd-order (omn :articulation omnl) :seed vseed) )) <br />
	          (vleg (if (member 'leg exclude) (omn :leg omnl) (rnd-order (omn :leg omnl) :seed vseed) )) <br />
	          (vped (if (member 'ped exclude) (omn :ped omnl) (rnd-order (omn :ped omnl) :seed vseed) ))<br />
	          (x )<br />
	       )<br />
	       (progn<br />
	         (init-state state) <br />
	         (make-omn :length len :pitch pit :velocity vel :duration dur :articulation arti  :leg vleg :ped vped)<br />
	       )<br />
	  )<br />
	)  ;end rk_rnd-order-omn
</p>

<p>
	 
</p>

<p>
	(setf mat2 '((q e5 leg e fs5 leg gs5 q a5 ten cs6 ten)<br />
	  (h cs6 leg q b5 e d6 leg cs6 leg)<br />
	  (q a5 cs6 marc+leg gs5 cs6 leg)<br />
	  (h. fs5)))
</p>

<p>
	(gen-loop 10 (rk_rnd-order-omn mat2 :seed 10 ))<br />
	(gen-loop 10 (rk_rnd-order-omn mat2 :flat t :seed 10 ))<br />
	(gen-loop 10 (rk_rnd-order-omn mat2 :exclude '(p ) :flat t :seed 10))
</p>

<p>
	(gen-loop 10 (rk_rnd-order-omn mat2  ))<br />
	(gen-loop 10 (rk_rnd-order-omn mat2 :exclude '(p ) ))<br />
	(gen-loop 10 (rk_rnd-order-omn mat2 :exclude '(l a leg) :seed 60))<br />
	(gen-loop 10 (rk_rnd-order-omn mat2 :flat t ))<br />
	 
</p>

<p>
	;;;;;;;;
</p>

<p>
	 
</p>

<p>
	I find the results interesting to create variations with selected similarities.
</p>

<p>
	 
</p>

<p>
	If there is already a function like this or another easy way to get the same results please let me know.
</p>
]]></description><guid isPermaLink="false">2979</guid><pubDate>Tue, 15 Aug 2023 10:26:23 +0000</pubDate></item><item><title>brownian bridge</title><link>https://opusmodus.com/forums/topic/2958-brownian-bridge/</link><description><![CDATA[<p>
	i like the concept of "brownian bridge" to produce complex curves from a to b, but not completely randomized or controlled. in the video you see all the generations for one evaluation...
</p>

<p>
	 
</p>

<p>
	how it could sound - mapped on different tonalities
</p>

<p>
	 
</p>

<div class="ipsEmbeddedOther" contenteditable="false">
	<iframe allowfullscreen="" data-embedid="embed1557210654" src="https://opusmodus.com/forums/index.php?app=core&amp;module=system&amp;controller=embed&amp;url=https://soundcloud.com/andr-meier-1/brownian-bridge-mapped-on-different-tonalities-algorithmic-study" style="height:415px;" loading="lazy"></iframe>
</div>

<p>
	 
</p>

<p>
	 
</p>

<div class="ipsRichEmbed" style="max-width:500px;border:1px solid rgba(0,0,0,0.1);">
	<div class="ipsRichEmbed_masthead ipsRichEmbed_mastheadBg ipsType_center">
		<a href="https://de.wikipedia.org/wiki/Brownsche_Br%C3%BCcke" rel="external nofollow" style='background-image:url("https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Brownsche_Bruecken.png/640px-Brownsche_Bruecken.png");background-position:center;background-repeat:no-repeat;background-size:cover;height:160px;'><img alt="640px-Brownsche_Bruecken.png" class="ipsHide" src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Brownsche_Bruecken.png/640px-Brownsche_Bruecken.png" loading="lazy"> </a>
	</div>

	<div style="padding:10px;">
		<h3 class="ipsRichEmbed_itemTitle ipsTruncate ipsTruncate_line ipsType_blendLinks">
			<span><img alt="wikipedia.ico" style="width:16px;height:16px;border:0;" src="https://de.wikipedia.org//static/favicon/wikipedia.ico" loading="lazy"></span> <a href="https://de.wikipedia.org/wiki/Brownsche_Br%C3%BCcke" rel="external nofollow" style="text-decoration:none;margin-bottom:5px;" title="Brownsche Brücke – Wikipedia">Brownsche Brücke – Wikipedia</a>
		</h3>

		<div class="ipsType_light">
			DE.WIKIPEDIA.ORG
		</div>
	</div>
</div>

<p>
	 
</p>

<p>
	<strong>for understanding in OPMO:</strong>
</p>

<p>
	 
</p>

<p>
	axiom: start end
</p>

<p>
	(50 23)
</p>

<p>
	 
</p>

<p>
	gen1 =&gt; 1 step
</p>

<p>
	(50 <strong>8 </strong>23)
</p>

<p>
	 
</p>

<p>
	gen2  =&gt; 3 steps
</p>

<p>
	(50 <em>15 </em><strong>8 </strong><em>-3</em> 23)
</p>

<p>
	 
</p>

<p>
	gen3 =&gt; 7 steps
</p>

<p>
	(50 <em><strong>40</strong></em> <em>15</em> 13 <strong>8 </strong>-14 <em>-3</em> <em><strong>29</strong></em> 23)
</p>

<p>
	 
</p>

<p>
	gen4 =&gt; 15 steps
</p>

<p>
	(50 58 <em><strong>40</strong></em> 33 <em>15 </em>22 13 4 <strong>8 </strong>4 -14 -16<em> -3</em> 17 <em><strong>29</strong></em> 17 23)
</p>

<p>
	 
</p>

<p>
	...and so on
</p>

<p>
	 
</p>

<p>
	-------------------------------------------------------------------------------
</p>

<p>
	 
</p>

<p>
	some evaluations with same AXIOM:
</p>

<p>
	 
</p>

<p>
	</p><video class="ipsEmbeddedVideo" controls="" data-controller="core.global.core.embeddedvideo" preload="metadata">
		<source type="video/quicktime" src="https://opusmodus.com/forums/uploads/monthly_2023_07/Bildschirmaufnahme2023-07-08um11_09_51.mov.0490fa550c858e17969bfb0b974066f3.mov"><a class="ipsAttachLink" data-fileext="mov" data-fileid="3532" href="https://opusmodus.com/forums/applications/core/interface/file/attachment.php?id=3532&amp;key=3b5b84bdfaa4dc151de7bdfb1ecbddd0" rel="">Bildschirmaufnahme 2023-07-08 um 11.09.51.mov</a>
	</source></video>


<p>
	 
</p>

<p>
	 
</p>

<pre class="ipsCode">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; BROWNIAN BRIDGE -&gt; could be use as a rnd-process from A to B (integers or pitches)
;;; if you have a look to example with ":all-gen t", you will see the process with all generations, how it works

;;; or take a look to:
;;; https://de.wikipedia.org/wiki/Wiener-Prozess#/media/File:BrownscheBewegung.png
;;; https://de.wikipedia.org/wiki/Brownsche_Brücke
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; SUB

(defun pick (a b &amp;key (span 5))
  (let ((rnd1 (car (rnd-number 1 (+ a span) (- a span))))
        (rnd2  (car (rnd-number 1 (+ b span) (- b span))))
        (n))
    (progn
      (setf n (car (rnd-number 1 rnd1 rnd2)))     
      (if (or (= n a) (= n b))
        (+ (rnd-pick '(1 -1)) n)
        n))))


(pick 2 3)


;;; MAIN

;;; MAIN

(defun gen-brownian-bridge (n startend &amp;key (all-gen nil) (output 'integer) (span 5))
  (let ((seq))
    (progn
      (setf seq (append (list startend)
                        (loop repeat n
                          with liste = startend
                          do (setf liste (filter-repeat 1 (loop repeat (1- (length liste))
                                                            for cnt = 0 then (incf cnt)
                                                            append (append (list (nth cnt liste) 
                                                                                 (pick (nth cnt liste) 
                                                                                       (nth (1+ cnt) liste) 
                                                                                       :span span)
                                                                                 (nth (1+ cnt) liste))))))
                          collect liste)))

      (setf seq (if (equal all-gen t)
                  seq
                  (car (last seq))))
      (if (equal output 'pitch)
        (integer-to-pitch seq)
        seq))))
  

;;; EXAMPLES


;; SPAN influence -&gt; span 2
(loop repeat 20
      do (list-plot (gen-brownian-bridge 5 '(1.2 5.4) :span 2 :all-gen t)
                    :zero-based t
                    :point-radius 3
                    :join-points t)
         
        do (sleep 2))  
         

;; SPAN influence -&gt; span 10
(list-plot (gen-brownian-bridge 5 '(50 23) :span 20 :all-gen t)
           :zero-based t
           :point-radius 3
           :join-points t)

;;; SPAN default (5)
(list-plot (gen-brownian-bridge 5 '(50 23) :all-gen t)
           :zero-based t
           :point-radius 3
           :join-points t)

(list-plot (gen-brownian-bridge 5 '(50 23))
           :zero-based t
           :point-radius 3
           :join-points t)


(gen-brownian-bridge 5 '(50 23) :all-gen t :output 'pitch)
(gen-brownian-bridge 5 '(50 23) :output 'pitch)</pre>

<p>
	 
</p>
]]></description><guid isPermaLink="false">2958</guid><pubDate>Sat, 08 Jul 2023 09:24:00 +0000</pubDate></item><item><title>ITERATE build in 1.2.20405</title><link>https://opusmodus.com/forums/topic/618-iterate-build-in-1220405/</link><description><![CDATA[
<p>
	The <strong><span style="font-family:Courier New,Courier,monospace;">ITERATE</span></strong> library is build in version 1.2.20405, therefore there is no need to load the library with <strong><span style="font-family:Courier New,Courier,monospace;">QUICKLISP</span></strong> anymore.
</p>

<p>
	 
</p>

<p>
	About <strong><span style="font-family:Courier New,Courier,monospace;">ITERATE</span></strong> library:
</p>

<p>
	<a href="https://common-lisp.net/project/iterate/" rel="external nofollow">https://common-lisp.net/project/iterate/</a>
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">618</guid><pubDate>Fri, 26 Aug 2016 06:35:55 +0000</pubDate></item><item><title>Poor man's playlist</title><link>https://opusmodus.com/forums/topic/2814-poor-mans-playlist/</link><description><![CDATA[<p>
	Inspired by the example from this thread but I could not find the related function been shipped with the OM application.
</p>
<iframe allowfullscreen="" data-embedauthorid="1" data-embedcontent="" data-embedid="embed176924805" src="https://opusmodus.com/forums/topic/1973-live-coding-midi-loop/?do=embed&amp;comment=6772&amp;embedComment=6772&amp;embedDo=findComment" style="height:290px;max-width:502px;" loading="lazy"></iframe>

<p>
	 
</p>

<p>
	The code requires OM3.0 because of LispWorks specific API but the concept should be simple enough to be implemented in Clozure CL.
</p>

<p>
	 
</p>

<p>
	After some midi objects has been compiled and inserted to the playlist one can use <span style="font-family:'Courier New', Courier, monospace;">run-playlist</span> to start play. While it is still playing one
</p>

<p>
	can feed more midi objects queued to the playlist. When the playlist is empty and after the specified seconds of timeout, the player process would exit.
</p>

<p>
	 
</p>

<pre class="ipsCode">(setq midi1 (compile-score 'score1))
(setq midi2 (compile-score 'score2))
(setq midi3 (compile-score 'score3))

(defparameter *playlist* (mp:make-mailbox))

(defun push-to-list (item)
  (let ((midi (cond ((eq (type-of item) 'midi:midi)
                     item)
                    ((symbolp item)
                     (compile-score item))
                    ((or (stringp item) (pathnamep item))
                     (midi:read-midi-file item)))))
    (mp:mailbox-send *playlist* midi)))

(defun run-playlist (&amp;key (timeout 5) (ignore-ports nil))
  (mp:process-run-function
   "Playing..." ()
   (lambda ()
     (loop
        (let ((current (mp:mailbox-read *playlist* "Wait for feed tracks" timeout)))
          (if current
              (mp:process-join (start-midi current :ignore-ports ignore-ports))
            (return)))))))

(push-to-list midi1)
(push-to-list midi2)

(run-playlist 5)

(push-to-list midi3)</pre>

<p>
	 
</p>
]]></description><guid isPermaLink="false">2814</guid><pubDate>Tue, 20 Dec 2022 00:46:59 +0000</pubDate></item><item><title>gen-hoquetus</title><link>https://opusmodus.com/forums/topic/501-gen-hoquetus/</link><description><![CDATA[<pre class="ipsCode" id="ips_uid_4296_5">
;; gen-hoquetus.4
 
https://en.wikipedia.org/wiki/Hocket

;;; andré meier / 27-4-2016
;;; write a instrumentation-list (instrument + techniques + velocity), pitch-list 
;;; and length-list. the gen-hoquetus-function will split the melody 
;;; off... in any possibilities, techniques/articulations/velocities will be added
;;; this is only a function i coded for my actual work... perhaps you could use
;;; it or code it properly :-)
;;; HAVE FUN! regards, andré

(setq instrumentation '(((pno ponte ppp))
                       ((vn pizz p)) 
                       ((vn pizz f) (va ponte f))
                       ((pno tasto ff))
                       ((pno pizz fff))
                       ((vn tasto mf) (pno ord ff) (vc tasto mf) (trp ord pp))
                       ((trp mute pp) (vn ponte mf))))
 
;; mainfuction:
 
(defun gen-hoquetus.4 (filtered-instrument &amp;key pitch length  instrument-list)
  (let ((events (generate-events.4 length pitch :optional_data instrument-list)))
    (filtering-color.4 filtered-instrument events)))
(gen-hoquetus.4 'vn :pitch '(c4 d4 e5 f6) :length '(1/32 2/32 3/32 4/32) :instrument-list instrumentation)

;; subfunctions
 
(defun generate-events.4 (durations pitches &amp;key (velocity '(mf))
                                    (articulation '(-)) (optional_data 'nil))
  (loop repeat (length durations)
    with cnt-d = 0
    with cnt-rest = 0
    when (&gt; (nth cnt-d durations) 0)
    collect (list (nth cnt-d durations) 
                  (nth cnt-rest pitches) 
                  (nth cnt-rest velocity)
                  (nth cnt-rest articulation) 
                  (nth cnt-rest optional_data))
    and do (incf cnt-rest)
    and do (incf cnt-d)
    else collect (list (nth cnt-d durations) 
                  'nil 
                  'nil
                  'nil 
                  'nil)
    and do (incf cnt-d)))
(generate-events.4 '(1 2 -3 4) '(60 61 62) :optional_data instrumentation)

(defun filtering-color.4 (selected-color event-stream)
  (loop for i in event-stream
    with match = 0
    append (loop for x in (fifth i)             
             when (equal (first x) selected-color)
             do (setq articulation (second x)
                      velocity (third x))
             and do (setq match 1))
    when (and (= match 1)  (&gt; (first i) 0))
    append (list (first i) (second i) velocity articulation)
    else collect (* -1 (abs (first i)))
    do (setq match 0)))

(filtering-color.4 'vn (generate-events.4
                        (gen-length '(1 -100 2 3 4 5) 1/32) '(c4 d4 e4 e5)
                        :optional_data instrumentation))

;; OMN_EXAMPLE:

(setq pitches (midi-to-pitch '(60 61 62 63 64 65 66 67 68 69 70))) ; only an example
(setq lengths (gen-length '(1 2 3 -4 5 6 5 -4 3 -2 1) 1/16)) ; only an example
(setq instrumentation (loop repeat 10 collect
                        (rnd-pick '(((pno ponte ppp)) ; only an example
                                    ((vn pizz p)) 
                                    ((vn pizz f) (va ponte f))
                                    ((pno tasto ff))
                                    ((pno pizz fff))
                                    ((vn tasto mf) (pno ord ff) (vc tasto mf) (trp ord pp))
                                    ((trp mute pp) (vn ponte mf))))))

 
(def-score hoquetus.4
           (:key-signature '(c maj)
                           :time-signature '(4 4)
                           :tempo '(120)
                           :layout (bracket-group
                                    (trumpet-layout 'trumpet)
                                    (piano-grand-layout 'piano)
                                    (violin-layout 'violin)
                                    (viola-layout 'viola)
                                    (violoncello-layout 'violoncello)))
  
  (trumpet :omn (gen-hoquetus.4 'trp
                                :pitch pitches
                                :length lengths
                                :instrument-list instrumentation)
           :channel 1)
  
  (piano :omn (gen-hoquetus.4 'pno
                              :pitch pitches
                              :length lengths
                              :instrument-list instrumentation)
         :channel 1)
  
  (violin :omn (gen-hoquetus.4 'vn
                               :pitch pitches
                               :length lengths
                               :instrument-list instrumentation)
          :channel 1)
  
  (viola :omn (gen-hoquetus.4 'va
                              :pitch pitches
                              :length lengths
                              :instrument-list instrumentation)
         :channel 1)
  
  (violoncello :omn (gen-hoquetus.4 'vc
                                    :pitch pitches
                                    :length lengths
                                    :instrument-list instrumentation)
               :channel 1))</pre>

<p>
	 
</p>]]></description><guid isPermaLink="false">501</guid><pubDate>Wed, 27 Apr 2016 16:34:18 +0000</pubDate></item><item><title>Generation of appoggiatura and accacciatura</title><link>https://opusmodus.com/forums/topic/2514-generation-of-appoggiatura-and-accacciatura/</link><description><![CDATA[<p>
	In many scores, Pierre Boulez use a lot of accacciatura or appoggiatura , for exemple like in Dérive (1984), a score composed for and based on the name SACHER (famous hexachord used also in "Message esquisse").
</p>

<p>
	 
</p>

<p>
	Here's a function to help to add such appoggiature in your score based on a list of rhythmic values.
</p>

<p>
	There is a draft doc in French joined to the function definition.
</p>

<p>
	 
</p>

<p>
	Hope it could be useful for some of us and may be improved and better coded and refined.
</p>

<p>
	 
</p>

<p>
	My best to all of Opmo users.
</p>

<p>
	 
</p>

<p>
	SB.
</p>

<p>
	 
</p>
<p>
<a class="ipsAttachLink" href="https://opusmodus.com/forums/applications/core/interface/file/attachment.php?id=3146&amp;key=d9c127bb309ee0f5e09a78635635c860" data-fileExt='lisp' data-fileid='3146' data-filekey='d9c127bb309ee0f5e09a78635635c860'>gen-ornament.lisp</a> 
<a class="ipsAttachLink" href="https://opusmodus.com/forums/applications/core/interface/file/attachment.php?id=3147&amp;key=6cc346cc3764e49c26d76744909d3700" data-fileExt='zip' data-fileid='3147' data-filekey='6cc346cc3764e49c26d76744909d3700'>gen-ornament.rtfd.zip</a></p>]]></description><guid isPermaLink="false">2514</guid><pubDate>Sat, 28 May 2022 20:15:58 +0000</pubDate></item><item><title>split-point</title><link>https://opusmodus.com/forums/topic/1701-split-point/</link><description><![CDATA[
<p>
	Hi,
</p>

<p>
	 
</p>

<p>
	here's a function i've made for my own usage and i think could be useful for others.
</p>

<p>
	It is a split point function which divide an OMN flux according to a list of split points.
</p>

<p>
	 
</p>

<p>
	Attached, you will find the French doc of the function <span class="ipsEmoji">😉</span></p>

<pre class="ipsCode ipsCopyInit" id="ips_uid_1295_6">
;;; SPLIT-POINT
;;; SB. 2020
;;; Fonction utile pour séparer les 2 mains pour une partie de piano
;;; renvoie une liste de listes


(defun split-point (split-points omn-seq)
  (do-verbose ("split-point")
  (let* (
         (spltconvert (if (numberp (car split-points))
                        split-points
                        (pitch-to-integer split-points)))
         (spltp (gen-trim (length omn-seq) spltconvert))
         (p1 (loop for sp in spltp
               for l in omn-seq
               collect (ambitus-filter `(,sp 128) l)
               ))
         (p2 (loop for sp in spltp
               for l in omn-seq
               collect (ambitus-filter `(-128 ,(- sp  1)) l)
               ))
         )
    (list p1 p2))))

#|
(split-point '(c4 d4) '((e a3d4 c4e4 f4c5 q g3d4 e4)(e a3d4 c4e4 f4c5 q g3d4 e4)))
=&gt; (((e d4 c4e4 f4c5 q d4 e4)(q d4 e4 f4c5 d4 e4)) ((e a3 - - q g3 -)(e a3 c4 - q g3 -)))


;;; Example
(setf pmat (make-scale 'c2 32 :alt '(2 1 2 3)))
(setf pch (rnd-sample 128 pmat))
(setf chrd (chordize-list (gen-divide (rnd-number 8 1 4) pch)))
(setf mat (length-legato (gen-filter-euclidean 8 16 4 16 chrd 's '(mf))))
(setf split (split-point '(c4) mat))
(setf piano-rh (ambitus-chord 12 (first split)))
(setf piano-lh (ambitus-chord 12 (second split)))

(ps 'gm
    :p (list piano-rh piano-lh)
    )


|#</pre>

<p>
	 
</p>

<p>
	SB.
</p>

<p>
	<a class="ipsAttachLink" data-fileext="zip" data-fileid="2413" href="https://opusmodus.com/forums/applications/core/interface/file/attachment.php?id=2413" rel="">split-point.rtfd.zip</a>
</p>
]]></description><guid isPermaLink="false">1701</guid><pubDate>Mon, 13 Apr 2020 10:46:30 +0000</pubDate></item><item><title>mapping a 2d-field to chords</title><link>https://opusmodus.com/forums/topic/2364-mapping-a-2d-field-to-chords/</link><description><![CDATA[<p>
	here is a function to MAP a 2d-field to chords (via intervals) // an idea i got from "Nierhaus - Algorithmic Composition" - Cellular Automata (p. 198). so you can "import/map" some GAME-OF-LIFE configurations or whatelse (a pixel photo?)  // the PITCH-MAPPING is like in Miranda's CAMUS.
</p>

<p>
	 
</p>

<p>
	 
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted"><span class="pln">;; FUNCTION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun 2d-field-to-chord (matrix &amp;key (start 'c4) (merge-chords nil))
  (let* ((int-horizontal
         (x+b (loop for x in (loop for i in matrix 
                               collect (position-item 1 i))
                when (not (null x))
                collect x)
              1))
  
        (int-vertical
         (x+b (loop repeat (length matrix)
                for n = 0 then (incf n)
                
                when (not (null (position-item 1 (nth n matrix))))
                collect n)
              1))

        (chords (loop 
                  for h in int-horizontal
                  for v in int-vertical
                  append (loop for z in h
                           collect (chordize (interval-to-pitch (list z v) :start start))))))

    (if (null merge-chords)
      chords
      (chord-pitch-unique (chordize (flatten chords))))))




;; interval-matrix ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; numbers are intervals (inverted order then in the book)
;; (different sizes are possible)

(setf matrix 
              #|1 2 3 4 5 6 7 8 9 etc..|#

       #|1|# '((1 0 0 0 0 0 0 0 0 0 0 0) 
       #|2|#   (0 1 0 0 0 0 0 0 0 0 0 0) 
       #|3|#   (0 0 1 0 0 0 0 0 0 0 0 0) 
       #|4|#   (0 0 0 0 0 0 0 0 0 0 0 0) 
       #|5|#   (0 0 0 0 0 0 0 0 0 0 0 0) 
       #|6|#   (0 0 0 0 0 0 0 0 0 0 0 0)
       #|7|#   (0 0 0 0 0 0 0 0 0 0 0 0)
   #|etc..|#   (0 0 0 0 0 0 0 0 0 0 0 0)
               (0 0 0 0 0 0 0 0 1 0 0 0)
               (0 0 0 0 0 0 0 0 0 0 0 0)
               (0 0 0 0 0 1 0 0 0 0 0 0)
               (0 0 0 0 0 0 0 0 0 0 0 0)))
      
              
(2d-field-to-chord matrix)
(2d-field-to-chord matrix :start 'd4)
(2d-field-to-chord matrix :merge-chords t)
(2d-field-to-chord matrix :merge-chords t :start 'd4)

;; as a scale
(sort-asc (melodize (2d-field-to-chord matrix :merge-chords t)))


;; with rnd-generated field (by probability)

(progn
  (setf matrix (loop repeat 32
                 collect (loop repeat 32 
                           collect (prob-pick '((0 0.97) (1 0.03))))))
  (2d-field-to-chord matrix))

(progn
  (setf matrix (loop repeat 32
                 collect (loop repeat 32 
                           collect (prob-pick '((0 0.99) (1 0.01))))))
  (2d-field-to-chord matrix :merge-chords t))</span></pre>

<p>
	 
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="3109" href="https://opusmodus.com/forums/uploads/monthly_2022_04/IMG_2723.jpg.3ccc1b2c9fd5eab864ec63e2bcd4f4e7.jpg" rel=""><img alt="IMG_2723.thumb.jpg.1baf02361f7661b675b67b37ef809dd7.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="3109" width="1000" src="https://opusmodus.com/forums/uploads/monthly_2022_04/IMG_2723.thumb.jpg.1baf02361f7661b675b67b37ef809dd7.jpg" loading="lazy" height="750"></a>
</p>

<p>
	 
</p>

<p>
	 
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">2364</guid><pubDate>Sat, 09 Apr 2022 16:59:15 +0000</pubDate></item><item><title>pitch-trajectory</title><link>https://opusmodus.com/forums/topic/2183-pitch-trajectory/</link><description><![CDATA[<p>
	Hi,
</p>

<p>
	 
</p>

<p>
	here's a function I've made for my personal usage.
</p>

<p>
	May be it could be useful for some users...
</p>

<p>
	Best
</p>

<p>
	 
</p>

<p>
	Stéphane
</p>

<p>
	 
</p>

<pre class="ipsCode" id="ips_uid_4816_5">;;;===================================
;;; PITCH-TRAJECTORY
;;;===================================
;;; SB 1.11.21
;;;===================================
(defun pitch-trajectory (nbpitch range tendency 
                                 &amp;key 
                                 (variance 0.5) 
                                 (type :around) 
                                 (quantize 1/2) 
                                 (smooth 1)
                                 filter-repeat
                                 seed
                                 )
  (setf seed (rnd-seed seed))
  (do-verbose ("pitch-trajectory :seed ~s" seed)
  (let* ((values (gen-tendency nbpitch tendency :variance variance :type type 
                           :seed (seed)))
         (smoothedval (vector-smooth smooth values))
         (out (vector-to-pitch range smoothedval :quantize quantize))
         )
    (if filter-repeat 
      (filter-repeat filter-repeat out)
      out))))


#|
;;; Tests divers
(pitch-trajectory 32 '(c4 g5) '(0.1 1 0.1) :seed 1234)
(pitch-trajectory 32 '(c4 g5) '(0.1 1 0.1) :seed 1234 :filter-repeat 1)
(pitch-trajectory 32 '(c4 g5) '(0.1 1 0.1) :seed 1234 
                  :filter-repeat 1
                  :variance 1
                  )
(pitch-trajectory 32 '(c4 g5) '(0.1 1 0.1) :seed 1234 
                  :filter-repeat 1
                  :variance 0.1
                  )
(pitch-trajectory 32 '(c4 g5) '(0.1 1 0.1) :seed 1234 
                  :filter-repeat 1
                  :smooth 0.1
                  )
(pitch-trajectory 32 '(c4 g5) '(0.1 1 0.1) :seed 1234 
                  :filter-repeat 1
                  :quantize 1/4
                  )
(pitch-trajectory 32 '(c4 g5) '(0.1 1 0.1) :seed 1234 
                  :filter-repeat 1
                  :quantize 1/8
                  )
(pitch-trajectory 32 '(c4 g5) '(0.1 1 0.1) :seed 1234 
                  :filter-repeat 1
                  :variance 1
                  :quantize 1/8
                  )



(gen-filter-change 
 (pitch-trajectory 
  32 '(c4 g5) '(0.1 1 0.1) :seed 1234)
 's)


|#

</pre>

<p>
	 
</p>
]]></description><guid isPermaLink="false">2183</guid><pubDate>Sat, 06 Nov 2021 11:16:20 +0000</pubDate></item><item><title>Jean Barraqu&#xE9; - "s&#xE9;ries prolif&#xE9;rantes"</title><link>https://opusmodus.com/forums/topic/1959-jean-barraqu%C3%A9-s%C3%A9ries-prolif%C3%A9rantes/</link><description><![CDATA[<p>
	here  a function... to barraqué's techniques
</p>

<p>
	 
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted"><span class="pln">
(defun serie-proliferantes (row)
  (let* ((ri_row (pitch-invert (gen-retrograde row)))
         (row (loop for z in (loop for x in (pitch-to-midi ri_row)
                          collect (or (position x (pitch-to-midi row))
                                      (position (- x 12)
                                                (pitch-to-midi row)) 
                                      (position (+ x 12) 
                                                (pitch-to-midi row))))
           
                collect (nth z ri_row))))

    row))


(serie-proliferantes '(c5 ab4 g4 db5 e4 d4 bb4 eb4 b4  f4 fs4 a4))
=&gt; (fs4 a4 g4 cs5 d5 c5 eb5 gs4 b4 f4 e5 bb4)</span></pre>

<p>
	 
</p>

<div class="ipsRichEmbed" style="max-width: 500px;  border: 1px solid rgba(0,0,0,0.1); ">
	<div style="padding: 10px;">
		<h3 class="ipsRichEmbed_itemTitle  ipsTruncate ipsTruncate_line  ipsType_blendLinks">
			<span><img alt="wikipedia.png" style="width: 16px; height: 16px; border: 0;" src="https://fr.wikipedia.org//static/apple-touch/wikipedia.png" loading="lazy"></span> <a href="https://fr.wikipedia.org/wiki/Jean_Barraqu%C3%A9" rel="external nofollow" style="text-decoration: none; margin-bottom: 5px;" title="Jean Barraqué — Wikipédia">Jean Barraqué — Wikipédia</a>
		</h3>

		<div class="ipsType_light">
			FR.WIKIPEDIA.ORG
		</div>
	</div>
</div>

<p>
	 
</p>

<p>
	seen here:
</p>

<p>
	<a href="https://www.amazon.de/Jean-Barraqu%C3%A9-Musik-Konzepte-Heinz-Klaus-Metzger/dp/3883774499" rel="external nofollow">https://www.amazon.de/Jean-Barraqué-Musik-Konzepte-Heinz-Klaus-Metzger/dp/3883774499</a>
</p>

<p>
	 
</p>

<p>
	page 19-20
</p>

<p>
	 
</p>

<p>
	 
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpeg" data-fileid="2704" href="https://opusmodus.com/forums/uploads/monthly_2021_01/IMG_9474.jpeg.c59d9fd163fd78411ec6276667f8469d.jpeg" rel=""><img alt="IMG_9474.jpeg" class="ipsImage ipsImage_thumbnailed" data-fileid="2704" data-unique="v96vjamcb" width="563" src="https://opusmodus.com/forums/uploads/monthly_2021_01/IMG_9474.thumb.jpeg.e480453f174dbb199b8c551f630d48ca.jpeg" loading="lazy" height="748.79"></a>
</p>

<p>
	 
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpeg" data-fileid="2703" href="https://opusmodus.com/forums/uploads/monthly_2021_01/IMG_9475.jpeg.f7e9964ad2442fa192712292dbf69754.jpeg" rel=""><img alt="IMG_9475.jpeg" class="ipsImage ipsImage_thumbnailed" data-fileid="2703" data-unique="5tcgtvkha" width="563" src="https://opusmodus.com/forums/uploads/monthly_2021_01/IMG_9475.thumb.jpeg.a27a50729d9b89b9f91ef5803697a255.jpeg" loading="lazy" height="748.79"></a>
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">1959</guid><pubDate>Sat, 30 Jan 2021 19:56:35 +0000</pubDate></item><item><title>Version Control</title><link>https://opusmodus.com/forums/topic/493-version-control/</link><description><![CDATA[<p>
	I'm new to the OpusModus IDE and project/file structure. As a senior programmer my version control system (mainly GIT and TFVC) with a proper version control / branching strategy is an import friend.
</p>

<p>
	 
</p>

<p>
	Any ideas/experience in applying version control on OpusModus scripts while composing?
</p>

<p>
	 
</p>

<p>
	Big hug,
</p>

<p>
	 
</p>

<p>
	Wim Dijkgraaf
</p>]]></description><guid isPermaLink="false">493</guid><pubDate>Thu, 21 Apr 2016 23:04:07 +0000</pubDate></item><item><title>Opusmodus convention: documentation of the libraries I presented</title><link>https://opusmodus.com/forums/topic/1949-opusmodus-convention-documentation-of-the-libraries-i-presented/</link><description><![CDATA[
<p>
	After our recent Opusmodus Convention I have been asked whether there would be any Opusmodus tutorials for the libraries I shared. 
</p>

<p>
	While there is no bespoke Opusmodus tutorial for any of them (you might consider my presentation at he Opusmodus convention as that tutorial, and additionally there are some nods to Opusmodus in the docs here and there), these libraries are all documented. For all libraries I write I tend to create detailed reference documentation for my own good <span class="ipsEmoji">🙂</span>  Much of the documentation is simply at the Common Lisp level, but that means in Opusmodus it would be largely used the same way. 
</p>

<p>
	<br>
	 
</p>

<p>
	<strong>Fenv (Function Envelopes)</strong>
</p>

<p>
	 
</p>

<p>
	There is some short intro doc at the github project page of this library at <a href="https://github.com/tanders/fenv" rel="external nofollow">https://github.com/tanders/fenv</a> for plain Common Lisp but with a few Opusmodus-specific notes. In the fenv library, pretty much every definition has a very short docstring (e.g., see <a href="https://github.com/tanders/fenv/blob/master/sources/fenv.lisp" rel="external nofollow">https://github.com/tanders/fenv/blob/master/sources/fenv.lisp</a> ). These docstrings were also used for creating some HTML documentation. Check out the doc directory in this library. Further, there is a test file, which can also be considered a file with a bunch of examples, though without further documentation (see <a href="https://github.com/tanders/fenv/blob/master/tests/test-fenv.lisp" rel="external nofollow">https://github.com/tanders/fenv/blob/master/tests/test-fenv.lisp</a> ).
</p>

<p>
	 
</p>

<p>
	 
</p>

<p>
	 
</p>

<p>
	<strong>Cluster Engine and Cluster Rules</strong>
</p>

<p>
	 
</p>

<p>
	Concerning the constraint libraries, the situation is a bit more complex. The Github landing page of Cluster Engine (https://github.com/tanders/cluster-engine ) also starts with something like a mini tutorial and some very brief consideration of Opusmodus, like the fenv library. Nevertheless, these libraries where originally written for PWGL and they are still best documented when used from within PWGL.
</p>

<p>
	 
</p>

<p>
	You might want start looking into these libraries by watching some video tutorial I did for my students (as part of a collection/playlist of videos on PWGL) where I am showing them how to get started with these libraries in PWGL at
</p>

<div class="ipsEmbeddedVideo">
	<div>
		<iframe allowfullscreen="" frameborder="0" height="113" width="200" src="https://www.youtube.com/embed/xPXIRmH9rZc?feature=oembed" loading="lazy"></iframe>
	</div>
</div>

<p>
	 
</p>

<p>
	Both libraries feature some PWGL tutorial that consists of a number of PWGL patches accessible from the PWGL docs menu after installing and loading them.  These PWGL tutorials go much further than I do in the above-mentioned video.
</p>

<p>
	 
</p>

<p>
	Beyond these PWGL tutorials, there is also some reference doc for the top-level Cluster Engine functions (e.g.,  the rule applicators) and the predefined rules in Cluster Rules, again written as docstrings but also part of HTML docs of these libraries, but these are best understood after you followed the PWGL tutorials.
</p>

<p>
	 
</p>

<p>
	So, unfortunately I have to encourage you to check these libraries out in PWGL first, that is still more easy. You can then rather easily port your first PWGL Cluster Engine patches to Opusmodus, as the boxes in PWGL and the functions for Opusmodus at called the same, as long as you only used definitions from the Cluster Engine package.
</p>

<p>
	 
</p>

<p>
	Note that unfortunately, the original PWGL site is meanwhile down (this software is not developed any further), but it seems that some version of the software can still be downloaded at
</p>

<div class="ipsRichEmbed" style="max-width:500px;border:1px solid rgba(0,0,0,.1);">
	<div style="padding:10px;">
		<h3 class="ipsRichEmbed_itemTitle ipsTruncate ipsTruncate_line ipsType_blendLinks">
			<span><img alt="favicon_2.ico" style="width:16px;height:16px;border:0;" src="https://ssl.gstatic.com/atari/images/favicon_2.ico" loading="lazy"></span> <a href="https://sites.google.com/site/fdsdbmascagni/code/fdsdb_xxth_ct-per-pwgl," rel="external nofollow" style="text-decoration:none;margin-bottom:5px;" title="fdsdbmascagni">fdsdbmascagni</a>
		</h3>

		<div class="ipsType_light">
			SITES.GOOGLE.COM
		</div>
	</div>
</div>

<p>
	 
</p>

<p>
	Apologies that there are no bespoke Opusmodus tutorials. Janusz already also mentioned some interest in these libraries, so I may give some dedicated talk on those at some later stage (e.g., as part of our next convention). I would likely cover largely what is already covered in the above-mentioned docs, only from within Opusmodus then.
</p>

<p>
	 
</p>

<p>
	<br><strong>TOT</strong>
</p>

<p>
	 
</p>

<p>
	Again, this library has a github landing page with some initial documentation (https://github.com/tanders/tot ) and some detailed reference documentation in HTML in the doc folder (https://tanders.github.io/tot/ ). This reference documentation features many examples that can be directly executed within Opusmodus. In some earlier version of Opusmodus, the HTML doc files could also be directly opened and the code could be evaluated without copying, but that is currently not possible any more (due to some changes by Apple as I understand, sigh). 
</p>

<p>
	<br>
	Note that all of these libraries might have some problems here and there. I try to test all my definitions carefully (for Cluster Engine I even defined a suit of regression tests), but things on which these libraries depends can change (e.g., some updates of Opusmodus break some TOT code every now and then). Anyway, if case you run into problems just get in touch. I have currently rather little time to look into these matters and thus may not be very response, but I will try to help at some stage... 
</p>

<p>
	 
</p>

<p>
	Best,<br>
	Torsten
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">1949</guid><pubDate>Sun, 17 Jan 2021 13:58:00 +0000</pubDate></item><item><title>filling 'time-points'?</title><link>https://opusmodus.com/forums/topic/215-filling-time-points/</link><description><![CDATA[<p>Hi,</p><p>Is there a way to fill in distances between 'time-points' like in the example? Thanks for help!</p><p>best</p><p>ole</p><pre class="prettyprint lang-html ipsCode" data-pbcklang="html" data-pbcktabsize="4">(setf time-points '(e b5 f - - -  b5 - -  b5 - - - - b5 -  b5 - - b5 - - - 
                      b5 - - - - a5 - - - - - a5 - - - a5 - - - -
                      a5 - - -  a5 - - - a5 - - - - a5 - - - a5 - - - - a5))

(omn :length time-points)

;is there a way to achive this:
(setf filled '(4/8 3/8 5/8 2/8 3/8 4/8 5/8 6/8 4/8 5/8 4/8 4/8 5/8 4/8 5/8 1/8))

(setf time-points-filled (make-omn :length filled
          :pitch (pitch-transpose -12 (omn :pitch time-points))
          :velocity (omn :velocity time-points)))

(def-score tp
            (:key-signature '(c maj)
             :time-signature '(4 4)  
             :tempo 50)             
            
  (voice1 :omn time-points :channel 1 :sound 'gm :program 0)
  (voice2 :omn time-points-filled :channel 2 :sound 'gm :program 0))
</pre><p><a rel="external nofollow" href="https://opusmodus.com/forums/uploads/monthly_02_2015/post-116-0-96589600-1425066532.jpg"><img data-fileid="108" alt="post-116-0-96589600-1425066532_thumb.jpg" src="https://opusmodus.com/forums/uploads/monthly_02_2015/post-116-0-96589600-1425066532_thumb.jpg" width="100" loading="lazy" height="14"></a></p>]]></description><guid isPermaLink="false">215</guid><pubDate>Fri, 27 Feb 2015 19:49:00 +0000</pubDate></item></channel></rss>
