Jump 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

Posts posted by AM

  1. A small further development – separate sequences for note values and rests (positive and negative integers).

    ;; subfunction to test the end of the loop
    (defun pos-neg (lst +val -val)
      (let ((pos 0)
            (neg 0))
        (dolist (x lst (list (* +val pos) (* -val neg)))
          (cond ((> x 0) (incf pos))
                ((< x 0) (incf neg))))))
    
    ;; main function
    (defun gen-acc/rit* (alist length rest)
      (loop while (not (equal (sum (abs! alist)) (sum (abs! (pos-neg alist length rest)))))
            collect (setf alist (loop for i in alist
                                        when (or (= i length) (= i rest))
                                          collect i
                                          else collect (if (> i 0)
                                                      (if (> i length)
                                                          (- i 1)
                                                        (+ i 1))
                                                    
                                                    (if (< i rest)
                                                        (+ i 1)
                                                      (- i 1)))))))
    
    ;; example
    (length-list-plot
     (gen-length
      (gen-acc/rit* '(3 -11 2 -13 23 5 -5 17 -2) 7 -3) ;; list with pos and neg integers + endval pos + endval neg
      '1/12)
     :join-points t
     :point-radius 0
     :style :fill)

    pic.png

  2. There is a variable 'r inside your OMN — but what is it bound to? Within the OMN format, r doesn’t work as a proper length value; must be e replaced by a negative length value, otherwise you get an error...

    => (1/4 c4 pp stacc 1/8 r 1/8 c6 pp marc 1/16 d4 pp ten 1/4 cs4 pp stacc 1/8 c4 pp leg 1/8 b5 pp marc 1/16 eb4 pp ten 1/4 c6 pp stacc 1/8 r 1/8 r ...

    When i replace the variable 'r by -1/4 it works...

    => (1/4 c4 pp stacc 1/8 -1/4 1/8 c6 pp marc 1/16 d4 pp ten 1/4 cs4 pp stacc 1/8 c4 pp leg 1/8 b5 pp marc 1/16 eb4 pp ten 1/4 c6 pp stacc 1/8 -1/4 1/8 -1/4 ...

    (setf flute-omn
          (replace-map '((r -1/4))
                       (build-omn-with-rests
                        flute-pitches
                        flute-rhythms
                        flute-velocities
                        flute-articulations))

    Personally, I wouldn’t use the variable "p", beause in the system it’s used for “piano” (which is why it’s highlighted in red). Also, it’s probably clearer and easier not to generate the OMN using a LOOP, but instead to use "make-omn". That way, you can also replace specific variables (like your 'r) more easily/more organized.

    (make-omn :pitch
              :length
              :velocities
              :articulation 

    greetings

    andré

  3. The following function generates symmetrical structures based on sequences of tones, which can evolve over multiple generations, resulting in nested symmetries. Here are a few examples mapped to pitches, integers, and rhythms.

    
    (defun gen-symmetrical-structure (&key row gen)
      (let* ((seq1 (filter-repeat 1 (loop repeat gen
                                         for i in (rnd-sample '(3 5 7 11) :norep t)
                                         append (progn
                                                  (setf r1 (filter-first 11 row))
                                                  (setf r2 (filter-last 11 row))
                                                  (setf n i)
                                                  (setf rev (probp 0.5))
                                                  (setf r1 (if (null rev)
                                                               r1
                                                             (reverse r1)))
                                                  (setf r2 (if (null rev)
                                                               r2
                                                             (reverse r2)))
    
                                                  (flatten (gen-rotate (random 2) (list (filter-first n r1)
                                                                                        (filter-last n r2))))))))
    
             
            (seq2 (flatten (gen-rotate (random 2) (list (filter-first (length seq1) seq1)
                                                        (pitch-invert-start 'fs4 (reverse (filter-first (length seq1) seq1))))))))
            (filter-repeat 1 (flatten seq2))))
    
    
    ;; with one GEN
    (pitch-list-plot
     (gen-symmetrical-structure :row (rnd-air :type :pitch) :gen 1)
     :join-points t :style :fill)
    
    ;; with x GEN
    (pitch-list-plot
     (gen-symmetrical-structure :row (rnd-air :type :pitch) :gen (+ 2 (random 10)))
     :join-points t :style :fill)
    
    
    ;; remapped to integer
    (list-plot
     (pitch-to-integer (gen-symmetrical-structure :row (rnd-air :type :pitch) :gen (+ 2 (random 10))))
     :join-points t :style :fill)
    
    => (9 5 7 1 10 11 4 8 3 2 0 6 9 5 7 1 10 11 4 8 3 2 0 2 3 8 4 1 7 5 9 6 0 2 3 8 4 11 10 11 10 1 7 5 9 6 3 7 5 11 2 1 2 1 8 4 9 10 12 6 3 7 5 11 8 4 9 10 12 10 9 4 8 1 2 11 5 7 3 6 12 10 9 4 8 1 2 11 5 7 3)
    
    ;; remapped to lengths
    (length-list-plot
     (gen-length (pitch-to-integer (gen-symmetrical-structure :row (rnd-air :type :pitch) :gen (+ 2 (random 10))))
                 '1/32)
     :join-points t :style :fill)
    
    => (11/32 3/32 9/32 5/16 3/8 3/16 1/16 7/32 5/32 1/8 1/16 7/32 5/32 1/8 1/32 1/4 11/32 3/32 9/32 5/16 3/8 3/16 1/16 7/32 5/32 1/8 1/32 1/4 11/32 3/32 9/32 5/16 1/16 3/32 9/32 1/32 1/8 11/32 1/4 7/32 5/32 5/16 3/16 -1/32 1/16 3/32 9/32 1/32 1/8 11/32 1/4 7/32 5/32 5/16 1/4 7/32 5/32 5/16 3/16 -1/32 1/16 3/32 9/32 1/32)

    symm.png

  4. With the following functions, you can run a background process (e.g., a loop function that constantly reloads data, for example from a text file) and do other things in parallel, such as modifying functions, etc. This is helpful when working with LISP/Opusmodus to process data in real time. I’ve tested this for a few days now, and it seems to run well and stable — at least as stable as the background process functions are free of bugs.

    Starting the process: Give the process a name and "add" your function (Here’s an example I made) -> process name “mididateien-generieren”, and my function within it is called “gen_1.midi”

    (mp:process-run-function "mididateien-generieren" nil #'gen_1.midi)

    Stopping the background process

    (progn
      (print "mididateien-generieren gestoppt")
      (mp:map-processes
       (lambda (proc)
         (when (string= (mp:process-name proc) "mididateien-generieren")
           (mp:process-kill proc)))))

    If anyone has better solutions for this, I’d be happy to hear them!

    Greetings

    André

  5. One more small (improved) function: a starting rhythm (pattern) gradually changes its values towards a constant pulse/value (endvalue).

    Other possible applications: An initial pitch sequence evolves into a steady, constant pitch. A start pattern for velocity gradually shifts towards a fixed velocity.

    (defun gen-acc/rit (alist endvalue) ;; startpattern + endvalue
      (loop while (not (equal alist (gen-repeat (length alist) endvalue))) 
              collect (setf alist (loop for i in alist
                                        when (/= i endvalue)
                                          collect (if (> i endvalue)
                                                         (- i 1)
                                                      (+ i 1))
                                     else collect i))))
    
    
    (list-plot (flatten (gen-acc/rit '(1 7 4 2 11 9 5 3) 3)) :join-points t :style :fill)
    
    => ((2 6 3 3 10 8 4 3) (3 5 3 3 9 7 3 3) (3 4 3 3 8 6 3 3) (3 3 3 3 7 5 3 3) (3 3 3 3 6 4 3 3) (3 3 3 3 5 3 3 3) (3 3 3 3 4 3 3 3) (3 3 3 3 3 3 3 3))
    
    
    (list-plot (flatten (gen-acc/rit '(1 7 4 2 11 9 5 3) 15)) :join-points t :style :fill)
    
    => ((2 8 5 3 12 10 6 4) (3 9 6 4 13 11 7 5) (4 10 7 5 14 12 8 6) (5 11 8 6 15 13 9 7) (6 12 9 7 15 14 10 8) (7 13 10 8 15 15 11 9) (8 14 11 9 15 15 12 10) (9 15 12 10 15 15 13 11) (10 15 13 11 15 15 14 12) (11 15 14 12 15 15 15 13) (12 15 15 13 15 15 15 14) (13 15 15 14 15 15 15 15) (14 15 15 15 15 15 15 15) (15 15 15 15 15 15 15 15))
    
    
    (list-plot (flatten (gen-acc/rit '(1 2 3 1 5 7 11 3 13 ) 6)) :join-points t :style :fill)
    
    => (((4 6 2 6 2 12 3 4 10) (5 6 3 6 3 11 4 5 9) (6 6 4 6 4 10 5 6 8) (6 6 5 6 5 9 6 6 7) (6 6 6 6 6 8 6 6 6) (6 6 6 6 6 7 6 6 6) (6 6 6 6 6 6 6 6 6))

    plot.png

  6. a simple small function I had to write for a project: it generates a kind of accelerando towards the value 1

    (defun gen-acc (alist)
      (loop while (not (equal alist (gen-repeat (length alist) 1))) 
              collect (setf alist (loop for i in alist
                                   when (> i 1)
                                     collect (- i 1)
                                     else collect i))))
    
    
    
    (gen-acc (rnd-order (primes 11)))
    
    => ((30 2 6 12 10 18 28 1 4 16 22) (29 1 5 11 9 17 27 1 3 15 21) (28 1 4 10 8 16 26 1 2 14 20) (27 1 3 9 7 15 25 1 1 13 19) (26 1 2 8 6 14 24 1 1 12 18) (25 1 1 7 5 13 23 1 1 11 17) (24 1 1 6 4 12 22 1 1 10 16) (23 1 1 5 3 11 21 1 1 9 15) (22 1 1 4 2 10 20 1 1 8 14) (21 1 1 3 1 9 19 1 1 7 13) (20 1 1 2 1 8 18 1 1 6 12) (19 1 1 1 1 7 17 1 1 5 11) (18 1 1 1 1 6 16 1 1 4 10) (17 1 1 1 1 5 15 1 1 3 9) (16 1 1 1 1 4 14 1 1 2 8) (15 1 1 1 1 3 13 1 1 1 7) (14 1 1 1 1 2 12 1 1 1 6) (13 1 1 1 1 1 11 1 1 1 5) (12 1 1 1 1 1 10 1 1 1 4) (11 1 1 1 1 1 9 1 1 1 3) (10 1 1 1 1 1 8 1 1 1 2) (9 1 1 1 1 1 7 1 1 1 1) (8 1 1 1 1 1 6 1 1 1 1) (7 1 1 1 1 1 5 1 1 1 1) (6 1 1 1 1 1 4 1 1 1 1) (5 1 1 1 1 1 3 1 1 1 1) (4 1 1 1 1 1 2 1 1 1 1) (3 1 1 1 1 1 1 1 1 1 1) (2 1 1 1 1 1 1 1 1 1 1) (1 1 1 1 1 1 1 1 1 1 1))
    
    
    
    (length-list-plot 
     (omn-to-time-signature
      (flatten
       (gen-length 
        (gen-acc (rnd-order (primes 11)))
        1/32))
      '(4 4))
    :join-points t :style :fill :line-width 0.5)
    
    ;; press: cmd1

    Here are two practical examples in combination with GEN-SORT

    (progn
      (setf pitchseq (vector-to-pitch '(fs3 g5) (gen-noise 8)))
      (make-omn :pitch (setf pitches (flatten (gen-sort pitchseq)))
                :length  (filter-last (length pitches) (gen-length 
                                                        (gen-acc (rnd-sample (length pitchseq) (primes 11)))
                                                        1/32))))
                       
    
    (progn
      (setf pitchseq (vector-to-pitch '(fs3 g5) (gen-noise 11)))
      (make-omn :pitch (setf pitches (flatten (gen-sort pitchseq)))
                :length  (length-staccato (filter-last (length pitches) (gen-length 
                                                        (gen-acc (rnd-sample (length pitchseq) (primes 11)))
                                                        1/32))
                                          :value 1/32)))
  7. Real-Time Pitch Memory: Compositional Feedback System Using MaxMSP and OPUSMODUS

    This text outlines a specific aspect of a larger project I am developing for live electronics and instruments. Since the work heavily involves live electronic processing in real time, it is based on a MaxMSP patch that I am currently building.

    An important component of this system involves integrating OPUSMODUS for certain compositional processes—specifically, the processing of pitch material collected in real time via a pitch follower from an improvising musician.

    In MaxMSP, this means that every few seconds, the most recently played pitches (as MIDI note numbers) are saved into a .txt file. Meanwhile, in OPUSMODUS, I run a routine that checks once per second whether a new pitch list has been saved (i.e., a list that differs from the previous one). If a new list is detected, I generate an OMN sequence based on this list and export it as a MIDI file.

    Only ten MIDI files are generated and continuously overwritten in a rotating manner. These MIDI files can then be precisely triggered within MaxMSP (e.g., when a specific pitch is detected, a stored MIDI file is played back) and integrated into the live electronic performance.

    Essentially, the system acts as a memory/archive that is generated from the live improvisation of the performer. Through a specific grammar created in OPUSMODUS, this musical material can then be re-injected into the live setting, forming a loop between improvisation, analysis, and compositional feedback.

    Another development step would be to replace the current .txt-based communication with a direct OSC (Open Sound Control) connection, streamlining the entire process.

    could sound like this: electric feedbacker guitar (live and improvised) + this system (in a test setup)

  8. i'm close to the OSC solution... i can not read the DATA? but start/stop listening :-D any help possible?

    -> how do i read *empfangene-osc-werte* ? or is there a bug in the code

    (defvar *empfangene-osc-werte* '())  ;; Liste zur Speicherung der empfangenen OSC-Daten
    (defvar *stop-osc-empfang* nil)
    
    (defun osc-receive-test (&key (port 7500))
      (let* ((host #(127 0 0 1))
             (s (usocket:socket-connect nil port
                                     :protocol :datagram
                                     :element-type '(unsigned-byte 8)))
             (buffer (make-array 1024 :element-type '(unsigned-byte 8))))
        (format t "Lausche auf OSC-Port ~A...~%" port)
        (unwind-protect
             (loop
                ;; Hier prüfen wir das Abbruch-Flag
                until *stop-osc-empfang*
                do (multiple-value-bind (size from-host from-port)
                        (usocket:socket-receive s buffer (length buffer))
                     (let* ((message (subseq buffer 0 size))
                            (decoded (handler-case
                                        (osc:decode-message message)
                                      (error (e) (format t "Fehler bei der Dekodierung: ~A~%" e) nil))))
                       (if decoded
                           (progn
                             ;; Wenn dekodiert, speichern wir die Nachricht in der Liste
                             (push decoded *empfangene-osc-werte*)
                             (format t "~&Empfangen: ~S~%" decoded))
                           (format t "Ungültige Nachricht empfangen: ~S~%" message)))))
          (when s (usocket:socket-close s)))))
    
    
    (osc-receive-test) ;; start
    (setf *stop-osc-empfang* t) ;; stop
    
    

  9. at the moment i'm trying other solutions to receive (more or less) live-data from MaxMSP (i can't figure it out in OSC) to do something with it - and do not block through "loops that read the new data" my automated-/live-coding

    1. in MaxMSP: i write/store my data as txt-file (by WRITE) - every x seconds

    2. i read it by a background-process in OPUSMODUS by the following code

    ;;; THE FUNCTION to read the txt-file
    (defun read-text ()
       (loop
          do (setf x (with-open-file (stream "/Users/...../pitch_list.txt" :direction :input)
             (let ((content (make-string (file-length stream))))
               (read-sequence content stream)
               content)))
          do (sleep 3)))
    
    ;; BACKGROUND PROCESS proceeding the function
    (mp:process-run-function "Mein-Prozess" nil #'read-text)
    1. so i'm generating mini-scores/snippets (with all the possibilities of OPUSMODUS) and send it back or store it as/in a midi-file-library to play them on a specific CUE (bang) in MaxMSP to coordinate and trigger them with other things i only can do in MaxMSP.

    2. in this way you could also feed your LIVE-CODING-PERFORMANCE - under the hood - by external datasets. reading the new/other set all x-seconds.

      the advantage (?) is that you do not have to read the values with a loop or constant new evaluation, which is always updated automatically in the background

  10. this is the working example for send. very basic, i can send all in my FORMAT, i used i for several pieces... (but just SEND)

     

    ;; the function
    
    (defun osc-send (&rest args)
      (let*
          ((host #(127 0 0 1)) ;; host
           (port 7500) ;; port
           (s (usocket:socket-connect host port
                               :protocol :datagram
                               :element-type '(unsigned-byte 8)))
            (b (apply' osc:encode-message args)))
        (format t "sending to ~a on port ~A~%~%" host port)
        (unwind-protect
             (usocket:socket-send s b (length b))
          (when s (usocket:socket-close s)))))
    
    ;; the examples - i'm sending the data the receiver needs / open, a non-pretermined ... 
    
    (osc-send  "/player" "120" 1 1 1)
    (osc-send "/beat" "defer" 0 "duration" 1 "pattern" 12)
    
    ;; could also be/new?:  (osc-send '(1 2 3 4 5))

     

     

    RECEIVE VALUES - for me, two main ideas

     

    ;;; DATA RECEIVE - with port host
    ;;;(osc-receive)
    ;; for example: 
    ;; sended in OSC: "1 4.5 5000 n" => comes in in OM as '(1 4.5 5000 n) or as a string "1 4.5 5000 n"
    ;;;(setf alist (osc-receive))
    
    ;;; EVAL RECEIVE - with port host
    ;;; for example when sended in OSC "eval", then the function OM inside evaluates...
    ;;; (osc-eval (gen-sort '(rnd-order '(3 3 6 5 4 3 1)))
    ;;; => 

     

    such a formated datastructure  is too restrective to use OSC really "OPEN"... it makes sense for some "reaktor"... it is interesting too keep it open?

    "
    ...
    :time '(1/2 1/4 1/12 1/12 1/12)
                                  :min 0.0
                                  :max 1.0
                                  :bpm 120))
    
    ...
    "

     

  11. A convulsive example could be: I have a process running in Max MSP (pulse in constantly changing current values), these are influenced via an audio signal. If a certain value is reached (threshold value), MaxMSP should send the last 20 values to OM. OM then sorts these values in a new sequence, sends them back to Max and reads them again as a current values.

     

    Instead of sorting, other complex functions of OM could also be applied to these values and then reinterpreted.

    I think you could use the specific skills of the platforms and have them interacted.

     

    just sending LISTS between the platforms and starting to EVAL in OM

     

    MAX send could be a just MESSAGE, receiving too.  one MAX-bang should send  a "message", like shown in the MAX-patch

  12. to receive data from Max MSP to...

     

    1) start/eval functions  by MAX  in OM

    2) to produce "new lists" (and sending it back to Max) based on data received from MAX (could be any data, internal processes , sensor data, whatever)... 

     

    so you could produce data for future processes in MAX (for realtime) based on incoming data... 

     

    years ago there were some LISP-inplementations in MAX (don't work anymore), but perhaps the communication via OSC would work too... and could be a simple solution. just having an "INTERFACE"

     

    SITES.MUSIC.COLUMBIA.EDU
    GITHUB.COM

    Lisper is an easy to use interface between Max/MSP and Common Lisp - thealexgraham/lisper

     

  13. hi there, i tried it NOW with receiving OSC (sending works fine), but i don't know to do it for RECEIVE... here is a sketch, but don^t work, any help?? i think it could be very very useful!!! janusz? 😄 

     

    SENDING - works fine!! you can send ANY messages (data format) via OSC (more open then the original OM-version)

     

    
    (defun osc-send (&rest args)
      (let*
          ((host #(127 0 0 1)) ;; host
           (port 7500) ;; port
           (s (usocket:socket-connect host port
                               :protocol :datagram
                               :element-type '(unsigned-byte 8)))
            (b (apply' osc:encode-message args)))
        (format t "sending to ~a on port ~A~%~%" host port)
        (unwind-protect
             (usocket:socket-send s b (length b))
          (when s (usocket:socket-close s)))))
    
    
    (osc-send  "/player" "120" 1 1 1)
    (osc-send "/beat" "defer" 0 "duration" 1 "pattern" 12)

     

     

    RECEIVING - error/crash/don't stop receiving?  (i'm a bad programmer for such things :-)) i tried to adapt a function from the NET

     

    (defun osc-receive-test (port)
      (let* ((host #(127 0 0 1)) ;; host
           (port 7500) ;; port
           (s (usocket:socket-connect host port
                               :protocol :datagram
                               :element-type '(unsigned-byte 8)))
    	(buffer (make-sequence '(vector (unsigned-byte 8)) 1024)))
        (format t "listening on localhost port ~A~%~%" host port)
        (unwind-protect
    	 (loop do
    	      (usocket:socket-receive s buffer (length buffer))
    	      (format t "received -=> ~S~%" (osc:decode-bundle buffer)))
          (when s (usocket:socket-close s)))))
    
     (osc-receive-test 7500) ;; never closing/stoping

     

     

    here is the MAX-HELP to check this side

     

    max-osc-help.maxpat

  14. Yes, but I will control/trigger the MIDI files and their change in real time, via audio and filter thresholds (live-electronics). So this can only be done in Max MSP. 

     

    My greatest wish: OM would be "integrated" in Max MSP. In the past there were some LISP-implementations in Max MSP, unfortunately no longer. I would be happy to expect certain processes in lists within Max (within a real time processes) and LISP/OM is optimal for this - this is much more cumbersome directly in MaxMSP

    Another way would be to let OM and Max MSP run in parallel and to be able to evaluate a function in OM at a Cue from Max and then be able to use the result again in Max. Can you already do about OSC but is that very complex? Or does someone practice that?

  15. I am currently learning Max MSP for a project, but I would like to use a part of computing structures that I can generate much easier in Opusmodus. So I write code in OM (sorting algorithms for some clicks), test it (and modify my code), then export it to a library in Max MSP. I can now call up/coordinate the MIDI files in realtime etc ... in Max MSP.

     

    (Workflow as a beginner in Max MSP...)

     

     

     

     

     

     

  16. [another old function]

    -----------------------------

     

    modify-proportions   n prop-list &key (style 'sharpen) (last 'nil)

     

    [Function]

     

    Arguments and Values:

     

    n generations

    prop-list  a list with integers (pos/neg)

    &key

    style 'sharpen / 'flatten

    last if t => only last gens

     

    "Modifies the integer list by changing the smallest/largest value in every generation by 1-/1+.

    The sum of the list always remains constant, as is the number of values. Sharpen leads to great differences

    Flatten paves everything at the same values."

     

     

    ;;; SUB
    (defun memberp (n liste)
      (not (equal 'nil (member n liste))))
    
    
    ;;; MAIN
    (defun modify-proportions (n prop-list &key (style 'sharpen) (last 'nil))
      (let ((rest-pos (loop for i in prop-list
                        for cnt = 0 then (incf cnt)
                        when (< i 0) collect cnt))
            (prop-list (abs! prop-list))
            (liste))
        (progn 
          (setf liste (append (list prop-list)
                              (loop repeat n
                                when (or (= (length (find-above 1 prop-list)) 1)
                                         (= (length (find-unique prop-list)) 1))
                                collect prop-list
                                else collect (setf prop-list (loop 
                                                               for i in prop-list
                                                               for cnt = 0 then (incf cnt)
                                                               collect (cond ((= cnt (position (find-closest 2 (find-above 1 prop-list)) prop-list))
                                                                              (if (equal style 'sharpen) 
                                                                                (1- i)
                                                                                (1+ i)))
                                                                             ((= cnt (position (find-max prop-list) prop-list))
                                                                              (if (equal style 'sharpen) 
                                                                  (1+ i)
                                                                                (1- i)))
                                                               (t i)))))))
          (setf liste (loop 
                        for i in liste
                        collect (loop for k in i
                                  for cnt = 0 then (incf cnt)
                                  when (memberp cnt rest-pos)
                                  collect (* -1 k) else collect k)))
          (if (equal last 'nil)
            liste
            (car (last liste))))))
    
    
    ;;;EXAMPLES
    
    (omn-to-time-signature
     (gen-length (modify-proportions 8 '(4 3 2 7) :style 'sharpen) 1/16)
     '(4 4))
    
    (omn-to-time-signature
     (gen-length (modify-proportions 8 '(4 3 2 7) :style 'flatten) 1/16)
     '(4 4))
    
    (list-plot 
     (modify-proportions 10 '(5 3 2 -7 1 8 2))
    :point-radius 0 :style :fill)
    
    (list-plot 
     (modify-proportions 10 (rnd-order '(5 3 2 -7 1 8 2)) :style 'flatten)
    :point-radius 0 :style :fill)
    
    (pitch-list-plot 
     (flatten (integer-to-pitch
     (modify-proportions 15 (rnd-order '(13 3 2 -7 1 -13 8 2)) :style 'flatten)))
    :point-radius 0 :style :fill)
    
    (pitch-list-plot 
     (flatten (integer-to-pitch
     (modify-proportions 10 (rnd-order '(1 3 2 -4 1 -2 5 2)) :style 'sharpen)))
    :point-radius 0 :style :fill)

     

     

    Bildschirmfoto2024-10-13um10_22_46.png.ccd66d727c59c3f991ca8875c99e5196.pngBildschirmfoto2024-10-13um10_22_59.png.221f81064187467599c9532d51ee621d.png

  17.  

    here is a small pure LISP-function - even older function - that I need for a project. Kind of a "shift-hysteresis", a randomized change from X to Y to ..., also possible with several value. It is best to try it out with the graph views. have fun!

    andré

     

    ;;; SUB
    
    (defun weighted-t/nil (on-weight)
      (let ((off-weight (- 1 on-weight)))
        (weighted-random (list (list 't on-weight) (list 'nil off-weight)))))
    
    (defun weighted-random (list)
      (loop for item in list
        with rand-num = (random (loop for x in list sum (second x)))
        for add = (second item) then (+ add (second item))
        when (< rand-num add) return (first item)))
                                   
    ;;; MAIN
    
    (defun gen-hysteresis (&key number-of-values 
                                       (value-list '((0 1) (4 0) (0 1) (4 7))) 
                                       (start-weight 0.1) 
                                       (sensitivity 0.02) 
                                       (static 1.0))
      (loop repeat number-of-values
        with weight = start-weight
        with cnt1 = 0
        with cnt-v = 0
        when (equal (weighted-t/nil weight) 'nil)
        collect (first (nth cnt-v value-list)) else collect (second (nth cnt-v value-list)) and do (incf cnt1) 
        when (= cnt1 3) do (setq weight (+ weight sensitivity)
                                 cnt1 0)
    
        when (> weight static)
        do (incf cnt-v)
        and do (setq weight start-weight)
        when (= cnt-v (length value-list)) do (setq cnt-v 0)))

     

    test it:

     

    (pitch-list-plot (gen-hysteresis :number-of-values 300
                    :start-weight 0.1
                    :sensitivity 0.05
                    :value-list '((gs3 a4))
                    :static 2.0)
                     :join-points t :style :fill)
    
    
    (pitch-list-plot (gen-hysteresis :number-of-values 500
                    :start-weight 0.1
                    :sensitivity 0.05
                    :value-list '((gs3 a4) (e5 ds4) (cs4 gs3))
                    :static 1.5)
                     :join-points t :style :fill)
    
    
    
                    
    (list-plot (gen-hysteresis :number-of-values 500
                    :start-weight 0.1
                    :sensitivity 0.1
                    :value-list '((1 2) (2 6) (4 3) (3 5))
                    :static 2.0)
                     :join-points t :style :fill)

    Bildschirmfoto2024-10-10um16_25_12.png.86f323f1c9f24182246cdb27ca2ee0e3.pngBildschirmfoto2024-10-10um16_24_15.png.2a116e511243f6d95db9f8086082c345.png

  18.  

     

    Opusmodus / A musical reflection tool

     

    At the beginning it should be noted that this is not a piece of music! I often try out new material in Opusmodus, test ideas, almost improvise with it. It is a good tool for me to check my idea, to reflect it, to change rules/ideas. A musical reflection tool.

     

    Basic idea:
    I would like to build a texture (based on a Pitchfield/Chord), which is structured by scales/arpeggia, should be played by a fender rhodes and two sine players. Each gesture should have a new pace (1/20 1/12 etc.) and a new dynamic, so that this texture has homogeneity on the side (through the chord), but is very precise articualted inside. The fender rhodes should and must be playable (= done by limiting the scales), sines can be "free" ...

     

    Result:

    What I get with this few code is a sketch, now I can refine my rules and conditions (chord/tempi/rests) in OPUSMODUS. Likewise, I can now experiment (if this works now) in Ableton Live on the timbres, which surely will have i kind of a feedback on my CODING in OMN. A kind of circular working process... a

     

    At the end:

    I will write it down by hand (sibelius) to be able to articulate even more precisely (like i want it) than the code. 

     

    For the stage:

    Coordiniaton will be done by click-track or https://polytempo.zhdk.ch

     

    Have fun!

    Greetings

    André

     

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; a function that generates a chains of 1/20 or 1/12 or 1/8 .. dependening on the lengths of the sub-pitch-seqences
    ;; ORD or REVERS (so that the "starttime" changes) by probp
    ;; no immediate reps
    
    (defun gen-rhythms (apitchlist)
       (loop for i in apitchlist
             for j in (rnd-sample 100 '(1/20 1/28 1/12 1/8) :norep t)
             collect (if (probp 0.5)
                         (length-rational-quantize (gen-repeat (length i) j) :round (rnd-pick '(1/4 2/4)))
                       (reverse (length-rational-quantize (gen-repeat (length i) j) :round (rnd-pick '(1/4 2/4)))))))
    
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; THE CHORD/INTERVAL
    
    (setf intervals '(7 6 3 4 6 4 3 6 7)) ;; intervals for pitches
    
    (setf n 20) ;; span for CYCLE (interval-rotation)
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    
    ;; LINES for FENDER RHODES (should be playable by humans)
    (setf lines1 '(loop for chord in (loop for i in (gen-rotate :left intervals :type 'list)
                                             collect (rnd-sample 5 (interval-to-pitch i :start 'b0))) ;; interval-rotation (all possibiliies), interval to pitch
    
                         append (loop repeat n ;; n = how many cycles per pitch-constellation
                                      collect (progn
                                                (setf direction (setf direction (prob-pick '((0 0.7) (1 0.3))))) ;; preset by probp for SCALE or DOWN
                                                (filter-repeat 1 (if (= direction 0)
                                                                     ;; take 3 or 5 pitches from momentary pitch-constellation / if probp then UP
                                                                     (sort-asc (rnd-sample (rnd-pick '(3 5)) 
                                                                                           (rnd-sample-seq 5 ;; max in SPAN 5 pitches (for fender rhodes)
                                                                                              (ambitus-filter (ambitus-instrument 'piano) chord)) :norep t))
    
                                                                   (sort-desc (rnd-sample (rnd-pick '(3 5)) 
                                                                                          (rnd-sample-seq 5 ;; max in SPAN 5 pitches (for fender rhodes)
                                                                                             (ambitus-filter (ambitus-instrument 'piano) chord)) :norep t))))))))
    
    
    
    
    
    ;; LINES for SINE PLAYER
    (setf lines2 '(loop for chord in  (loop for i in (gen-rotate :left intervals :type 'list)
                                             collect (interval-to-pitch i :start 'b0)) ;; interval-rotation (all possibiliies), interval to pitch
    
                         append (loop repeat n ;; n = how many cycles per interval-constellation
                                      collect (progn
                                                (setf direction (setf direction (prob-pick '((0 0.7) (1 0.3))))) ;; preset by probp for SCALE or DOWN
                                                (filter-repeat 1 (if (= direction 0)
                                                                     ;; take 3 or 5 pitches from momentary pitch-constellation / if probp then DOWN
                                                                     (sort-asc (rnd-sample (rnd-pick '(3 5 7)) 
                                                                                           (ambitus-filter (ambitus-instrument 'piano) chord) :norep t))
                                                                   (sort-desc (rnd-sample (rnd-pick '(3 5 7)) 
                                                                                          (ambitus-filter (ambitus-instrument 'piano) chord)))))))))
    
    
    
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    ;; GEN FENDER PART
    
    
    (progn
      (setf fdr_1 (eval lines1))
      (setf rhy1 (gen-rhythms fdr_1)) ;; gen rhy based on the pitch-seqs
      (setf fdr_1 (make-omn :length rhy1
                            :pitch fdr_1))
      
      ;; rewrite/replace dynamics
      (setf fdr_1 (loop for i in fdr_1 ;;every gesture should have their own dynamics norep !!
                        for velo in (pick-norepeat 100 '(ppp p mf fff))
                        collect (omn-replace :velocity velo i))))
      
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    ;; GEN SINE PARTS
    
    (progn
      (setf snr_1 (eval lines2))
      (setf rhy2 (gen-rhythms snr_1)) ;; gen rhy based on the pitch-seqs
      (setf snr_1 (make-omn :length rhy2
                            :pitch snr_1))  
      
      ;; rewrite/replace dynamics
      (setf snr_1 (loop for i in snr_1 ;; every gesture should have their own dynamics norep !!
                        for velo in (rnd-sample (length rhy2) '(ppp p mf fff) :norep t)
                        collect (omn-replace :velocity velo i))))
    
    
    (progn
      (setf snl_1 (eval lines2))
      (setf rhy3 (gen-rhythms snl_1)) ;; gen rhy based on the pitch-seqs
      (setf snl_1 (make-omn :length rhy3
                            :pitch snl_1))
    
       ;; rewrite/replace dynamics
      (setf snl_1 (loop for i in snl_1 ;; every gesture should have their own dynamics norep !!
                        for velo in (rnd-sample (length rhy3) '(ppp p mf fff) :norep t)
                        collect (omn-replace :velocity velo i))))
    
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    ;; PUT IN AN 3/4
    
    (setf snl (omn-to-time-signature snl_1 '(3 4)))
    (setf snr (omn-to-time-signature snr_1 '(3 4)))
    (setf fdr (omn-to-time-signature fdr_1 '(3 4)))
    
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    
    
    (def-score sketch
        (:title "sketch"
         :key-signature 'atonal
         :time-signature '(3 4)
         :tempo '(132)
    
         :layout (list 
                  (grand-layout 'fdr)
                  (bass-layout 'snl) 
                  (bass-layout 'snr)))
    
        (snl :omn snl
             :channel 1
             :port 9 )
        
        (snr :omn snr
             :channel 1
             :port 8)
    
        (fdr :omn fdr
             :channel 1
             :port 5))
    
    ;(live-coding-midi (compile-score 'sketch))
    ;(omn-list-plot (list fdr_1 snr_1 snl_1) :style :fill :point-radius 1)
    
    
    

     

  19. in make-omn -> no "time-signature", only for "def-score"...

     

    (make-omn
     :length extended-length
     :pitch pitch-loop
     :velocity velocity)
    
    => ((e b3cs4e4g4 ff -e - e b3cs4ds4a4 p< q ds4gs4a4d5 mp< eb3f3g3 f<) (e b3cs4ds4a4 ff> -e - e ds4gs4a4d5 pp> q d3g3gs3d4 ff> d4e4f4b4 f>) (e b4d5ds5f5g5 mf> -e - e ds3g3gs3d4 pp< q b3c4g4 p< d3g3gs3d4 mp<) (e b3cs4ds4a4 mf< -e - e ds4gs4a4d5 f> q eb3f3g3 mp< ff))

     

     

     

    Bildschirmfoto2024-09-13um07_47_50.png.3d275d532d7faeb2213f491d4da33c3c.png


Copyright © 2014-2025 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

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.