Jump to content

Stephane Boussuge

Moderators
  • Posts

    1,057
  • Joined

  • Last visited

Posts posted by Stephane Boussuge

  1. Several possibilities depend what kind of variations you want.

    The simplest one is random order applied only to lengths.

     

    (setf mat '((e d4 e4 fs4 gs4 q a4)(s b4 c5 b4 gs4 q a4 e fs4 e4)))
    (rnd-order mat :type :length)

    Another way I appreciate particularly is length divide:

    (length-divide '((3 4)(1 2)) mat :set 'max)

    but this last one add some intervals so it may be not what you're searching for...

    S.

  2. 9 hours ago, JulioHerrlein said:

    Really cool, Stephane ! Any chance to get the opmo files ? All the best !

    The opmo file is a variant of one of the templates given with my video lesson pack:

    WWW.COMPOSERWORKSHOP.COM

    Welcome to the course on "Designing Generative Orchestral Templates with Opusmodus"! In this course, we will explore the fascinating world of computer-assisted composition, specifically focusing on the powerful music composition environment known as Opusmodus. Opusmodus is a cutting-edge software tool that empowers composers, music theorists, and researchers to create...

    but I will share another one soon 🙂

    S.

  3. Hi,

     

    the output of your loop get too many nested parenthesis. Use assemble-seq function to arrange this material as correct OMN expression usable by dictum.

     

    ;=====BIRDCALLS=====
    (setf bird1 '(3q d5 leg gs4 d5 leg gs4 d5 leg gs4))
    (setf bird2 '(q a3 e. b3 x c5 leg e.. bb4))
    (setf bird3 '(e fs4 leg c5 q bb4 3q fs4 stacc c5 bb4))
    (setf rest1 '(-e))
    (setf rest2 '(-q.))
    (setf rest3 '(-e.))
    
    ;=====OMN MAKER=====
    
    (setf loop1 (assemble-seq
                 (gen-loop 
                  7
                  (list
                   (rnd-pick (list bird1 bird2 bird3))
                   (rnd-pick (list rest1 rest2 rest3))
                   (rnd-pick (list rest1 rest2 rest3))))))
    
    (dictum '(:if e :do q) loop1)

     

  4. Hi,

     

    I've made a function long long time ago around this idea not following strictly Hindemith if I remember it correctly but it was based on the same idea/concept.

     

    Here's my function, you can probably tweak it to your needs.

     

    Please, if you improve it in anyway, share your improvement so it could be useful for me and community as well.

     

    Stephane

     

    ;;;===============================================================
    ;;; sort chords by tension
    ;;;===============================================================
    ;;Idée: classer des accords generés de maniere X par tension avec une courbe de tensions.
    
    ;;Analyser un accord 
    
    ;;1. extraire un vecteur d'intervalles
    ;;2. Analyser le vecteur
    ;;3. retourner le resultat
    
    
    (defun ana-tens (ivect)
    "renvoie le taux de tension harmonique d'un vecteur d'intervalles.
    utilitaire pour h-tens"
      (let* 
          ((v1 (*(nth 0 ivect) 6))
           (v2 (*(nth 1 ivect) 4))
           (v3 (*(nth 2 ivect) 3))
           (v4 (*(nth 3 ivect) 2))
           (v5 (*(nth 4 ivect) 1))
           (v6 (*(nth 5 ivect) 5))
           (r (+ v1 v2 v3 v4 v5 v6)))
        r))
    
    (defun h-tens (chord)
      (do-verbose
       ("h-tens")
    "renvoie le taux de tension harmonique relatif d'un accord."
      (let* 
          (
           (r0 (if (equal chord '(nil)) '(c4) chord)) ; Si nil, remplace par une valeur simple (c4)
           (r1 (melodize r0))  ;extraction du vecteur d'intervalles
           (r2 (pitch-to-integer r1))
           (r3 (find-unique (modus r2)))
          
    		
           (r4 (if (> (length r3) 1)
    	       (pcs-prime-form r3 :vector)
    	       '(0 0 0 0 0 0)))
           (r5 (ana-tens r4))            ;analyse du vecteur d'intervalles
    					;il faut ensuite diviser le resultat obtenu par le nombre de pcs (cardinal-number) du set et on obtient le niveau relatif de tension harmonique.
    					; on s'assure d'abord de ne pas avoir un accord à 1 seul accord
           (r6 (float (/ r5 (length r1)) 1.0)))
        r6 ;retourne le resultat
    )))
    ;;;creation d'une fonction qui prend en entrée une suite d'accords et qui renvoie cette suite triée 
    ;;;par ordre de tension harmonique croissant ou decroissant.
    (defun extraitcar (lst)
      (loop for i in lst
            collect (car i)))
    
    (defun extraitcdr (lst)
      (loop for i in lst
            collect (cdr i)))
    
    (defun sort-chords-tens-up (chords)
    "ordonne une suite d'accords par ordre croissant de tension harmonique"
      (do-verbose
       ("sort-chords-tens-up")
      (let* ((tens (mapcar 'h-tens  chords))
             (a-list (pairlis chords tens))
             (sorted (stable-sort a-list #'< :key #'cdr))
             (chordprog (extraitcar sorted)))
        chordprog)))
    
    (defun sort-chords-tens-down (chords)
    "ordonne une suite d'accords par ordre decroissant de tension harmonique"
      (do-verbose
       ("sort-chords-tens-down")
      (let* ((tens (mapcar 'h-tens chords))
             (a-list (pairlis chords tens))
             (sorted (stable-sort a-list #'> :key #'cdr))
             (chordprog (extraitcar sorted)))
        chordprog)))
    
    #|
    ;;;Usage 
    
    ;;we generate some chords
    (setf chords (chordize (gen-loop 12 (rnd-unique 4 (integer-to-pitch (gen-integer 12))))))
    
    ;;we sort chords by up tension
    (setf chords-up (flatten (sort-chords-tens-up chords)))
    ;;we sort chords by down tension
    (setf chords-down (flatten (sort-chords-tens-down chords)))
    |#
    
    
    
    ;;;====================================================================================

     

  5. In Common Lisp, `SETF` is a general-purpose assignment macro used to assign values to a designated place, such as a variable. It can be used for all forms of assignment, whether storing into an ordinary variable or a generalized variable. The syntax of `SETF` does not evaluate its first argument, which is the name of the variable. The second argument, which is the value to which the variable is set, is evaluated. The value returned by `SETF` is the value to which it set the variable.

     

    Comparatively, `DEFVAR` and `DEFPARAMETER` are used for defining variables, but with different implications and scopes. `DEFVAR` is used to establish a variable, but if the variable is already bound, redefining it with `DEFVAR` does nothing. `DEFPARAMETER`, on the other hand, always assigns a value to the variable, even if it is already bound. Both `DEFVAR` and `DEFPARAMETER` are typically used to define global variables, whereas `SETF` is used for assigning values to variables regardless of their scope.

     

    The scope of variables defined by `DEFVAR` and `DEFPARAMETER` is global, meaning the variables are accessible throughout the program. In contrast, `SETF` can be used within any scope, including local scopes within functions or global scopes, depending on where it is used. The key difference lies in their purposes: `DEFVAR` and `DEFPARAMETER` are for variable declaration (with `DEFPARAMETER` forcefully initializing the variable), while `SETF` is used for assigning or changing the value of a variable, irrespective of its scope.

  6. The number of chord tones played is controlled with the :group parameter.

     

    About chord inversion or randomisation of position, it is probably possible to do a kind of post processing with rnd-order or something similar.

  7. Sorry, my mistake, I reply too quickly without thinking.... It is not chords inversion.

    It is the use of function length-divide internally who produce this result because length-divide apply some intervals.

    Look at the doc for length-divide function.

    If you provide intervals to the function you can modify this behavior, for example , if you want only the chords notes, you can do:

     

    (setf mat1 '((h a2b2e3f3gs3 mf)
                 (h a2b2e3f3gs3 p)
                 (q bb4c5gs5a5b5 mp q bb4c5gs5a5b5 p)))
     
    (chord-dictum '((:len h :chd 5 :div 5 :int '(0)) (:len q :chd 5 :div 4)) mat1 )
    
    => ((5h a2b2e3f3gs3 mf a2b2e3f3gs3 a2b2e3f3gs3 a2b2e3f3gs3 a2b2e3f3gs3)

     

  8. I've shared a video here on CHORD-DICTUM function and you will find here the code from the video.

    Enjoy !

     

     

    The Score:

     

    ;;;--------------------------------------------------------
    ;;; SCORE 186
    ;;; VARIATIONS POUR PIANO
    ;;; Etude de la fonction "chord-dictum"
    ;;; S.BOUSSUGE
    ;;; WIEN - 27.01.2024
    ;;;--------------------------------------------------------
    ;;; LEARN OPUSMODUS: WWW.COMPOSERWORKSHOP.COM
    ;;;--------------------------------------------------------
    ;;; To view the score press the Cmd-Option-1 keys.
    ;;;--------------------------------------------------------
    ;;; UTILITY
    ;;; REA-MARK
    
    (defun rea-mark (omn-exp)
      "Add rehearsal marks even on empty bars."
      (if (event-restp (nth-event 0 omn-exp))
          (position-insert 1 'reh omn-exp :section '(0))
        (edit-events '((1 1 'reh :articulation)) omn-exp)))
    
    ;;;--------------------------------------------------------
    ;;; PARAMETERS
    
    (setf seed  (rnd-round 1 1000000))
    (init-seed seed)
    
    (setf chords.p
          '(h. cs3fs3b3d4fs4bb4 q bb2eb3g3b3eb4gs4 h. cs3fs3b3d4fs4bb4 
            q fs3bb3d4f4bb4eb5 h b2c3eb3a3c4eb4gs4 q gs2cs3f3g3bb3eb4 
            h fs2bb2d3e3gs3cs4 q eb2gs2c3d3fs3bb3 h. c3eb3fs3b3d4fs4bb4c5
            q d3fs3bb3d4f4bb4f5 b2eb3fs3b3d4fs4bb4c5 g2bb2eb3g3b3cs4fs4a4
            e2gs2cs3e3g3bb3eb4f4 a2cs3fs3a3c4eb4gs4b4 f2bb2eb3g3bb3eb4f4
            h. c3eb3gs3c4e4fs4bb4d5 q a2fs3a3cs4fs4a4 d3fs3bb3d4f4bb4eb5f5
            h f3gs3cs4f4g4bb4eb5g5 f3gs3cs4f4g4bb4eb5g5 
            w f3gs3cs4f4g4bb4eb5g5))
    
    (setf rvel (rnd-sample
                (length (omn :pitch chords.p))
                '((pp)(p)(mp)(mf)(f)(ff))))
    
    (setf chords.d (omn-replace :velocity rvel chords.p))
    
    (setf
     dictum1
     '(
       (:len w :chd 7 :div 7 :vel nil :att nil 
        :grp nil :int nil :var ? :mtd m :rhy t)
       #|2|# (:len w :chd 6 :div 2 :vel nil :att nil 
              :grp 2 :int nil :var ? :mtd nil :rhy t)
       #|3|# (:len w :chd 5 :div 5 :vel nil :att nil 
              :grp nil :int nil :var ? :mtd m :rhy t)
       #|4|# (:len w :chd 4 :div 4 :vel nil :att nil 
              :grp 3 :int nil :var ? :mtd nil :rhy t)
       #|5|# (:len h. :chd 7 :div 7 :vel nil :att nil 
              :grp nil :int nil :var ? :mtd m :rhy t)
       #|6|# (:len h. :chd 6 :div 3 :vel nil :att nil 
              :grp 3 :int nil :var ? :mtd nil :rhy t)
       #|7|# (:len h. :chd 5 :div 5 :vel nil :att nil 
              :grp nil :int nil :var ? :mtd m :rhy t)
       #|8|# (:len h. :chd 4 :div 4 :vel nil :att nil 
              :grp nil :int nil :var ? :mtd m :rhy t)
       #|9|# (:len h :chd 7 :div 2 :vel nil :att nil 
              :grp 2 :int nil :var ? :mtd nil :rhy t)
       #|10|# (:len h :chd 6 :div 6 :vel nil :att nil 
               :grp 3 :int nil :var ? :mtd nil :rhy t)
       #|11|# (:len h :chd 5 :div 3 :vel nil :att nil 
               :grp 2 :int nil :var ? :mtd nil :rhy t)
       #|12|# (:len h :chd 4 :div 4 :vel nil :att nil 
               :grp nil :int nil :var ? :mtd m :rhy t)
       #|13|# (:len q :chd 7 :div 4 :vel nil :att nil 
               :grp 2 :int nil :var ? :mtd nil :rhy t)
       #|14|# (:len q :chd 6 :div 6 :vel nil :att nil 
               :grp nil :int nil :var ? :mtd m :rhy t)
       #|15|# (:len q :chd 5 :div 2 :vel nil :att nil 
               :grp 2 :int nil :var ? :mtd nil :rhy t)
       #|16|# (:len q :chd 4 :div 4 :vel nil :att nil 
               :grp nil :int nil :var ? :mtd m :rhy t)
       )
     )
    
    (setf dictum-temp
          `(list
           (rnd-sample 8 '(w h. h q))                        ; Length map
           (rnd-number 8 4 8)                                ; Chord-size map
           (rnd-number 8 3 7)                                ; Length division
           nil                                               ; Velocity map
           nil                                               ; Attribute map
           (rnd-sample 8 '((3 4) (3 4) nil))                 ; Chord group
           (rnd-sample 8 '((0 13 1 11) nil (0 6 -6 11) nil)) ; Intervals
           '?                                                ; Variant
           (rnd-sample 8 '(m r nil))                         ; Methods
           (rnd-sample 8 '(nil t t nil))                     ; Rhythm series
           ))
    
    (setf dictum2 (gen-chord-dictum (eval dictum-temp)))
    (setf dictum3 (gen-chord-dictum (eval dictum-temp)))
    
    (setf out1 (chord-dictum dictum1 chords.d))
    (setf out2 (chord-dictum dictum2 chords.d))
    (setf out3 (chord-dictum dictum3 chords.d))
    (setf out4 (chord-dictum dictum1 chords.d))
    
    (setf piano (assemble-seq chords.d out1 out2 out3 out4))
    (setf split1 (ambitus-filter '(c4 c8) piano))
    (setf split2 (ambitus-filter '(a0 b3) piano))
    
    (setf piano-rh split1)
    (setf piano-rh.rea (assemble-seq (loop for i in piano-rh 
                                           :collect (rea-mark (list i)))))
    (setf piano-lh split2)
    
    (setf titre (concatenate 
                 'string
                 "Score186-Variation-Piano-" (stringify seed) 
                 ))
    
    ;;;--------------------------------------------------------
    ;;; SCORE AND LAYOUT
    
    (def-score Score186
        (:title titre
         :subtitle "pour Piano"
         :composer "Stephane Boussuge"
         :copyright "Copyright © 2024"
         :key-signature 'chromatic
         :time-signature '((1 1 1 1) 4)
         :tempo 108
         :layout (piano-solo-layout 'piano-rh 'piano-lh))
      
      (piano-rh
       :omn piano-rh.rea
       ;:port "bus 6"
       :channel 1
       :sound 'gm
       :program 'acoustic-grand-piano
       )
      
      (piano-lh
       :omn piano-lh
       ;:port "bus 6"
       :channel 1
       )
      )
    (init-seed nil)
    
    

     

     

×
×
  • Create New...

Important Information

Terms of Use Privacy Policy