Jump to content

edit-omn update: 'dynamic' arguments supported

Recommended Posts

Stephane Boussuge wrote on 23 October

> your edit-omn function is definitively super-mega useful !!


I updated my function edit-omn. Remember that this function is for turning relatively simple functions processing some OMN parameter sequence (e.g., pitch or length lists) quasi automatically into much more expressive functions processing arbitrary OMN expressions, including nested expressions, and automatically supporting typical Opusmodus arguments like section and flat.


I now added support for creating functions with 'dynamic' arguments, i.e. arguments where different values are used for processing different sublists of OMN expressions. For example, again consider a generalisation of the builtin Opusmodus function gen-rotate,which represents a very useful compositional concept, but its current implementation is rather restricted. I already showed how the new and generalised function rotate-omn expands the existing gen-rotate by introducing arguments like flat and section as shown below.   


(setf melody '((-h e c4 e4) (q. f4 e g4 q a4) (q g4 f4 e e4 d4)))

;; Rotate default parameter pitch of 2nd bar (section 1) to the right.

;; The link above shows how to alternatively rotate length values etc.

(rotate-omn 1 melody :section '(1) :flat nil)

; => ((-h e c4 e4) (q. a4 e f4 q g4) (q g4 f4 e e4 d4)) 


Using a new version of rotate-omn defined with the revised edit-omn we can now also specify different rotation amounts for different bars. The first argument of the function is given a list of rotation amounts (0 1 2), so the pitches of the first bar are not rotated at all, the pitches of the first bar are rotated 1 step to the right, and the pitches of the second bar 2 steps.


(rotate-omn '(0 1 2) melody :flat nil)

=> ((-h e c4 e4) (q. a4 e f4 q g4) (q e4 d4 e g4 f4))


Such 'dynamic' function arguments can be combined with the section argument to limit the processing of the input music to only certain bars. The following call rotates the bars 2 and 3 only (section is (1 2)), the first bar of this selection by 2 steps to the right, and the next by 1 step.


(rotate-omn '(2 1) melody :section '(1 2) :flat nil)

; => ((-h e c4 e4) (q. g4 e a4 q f4) (q d4 g4 e f4 e4))


Now, remember that this post is actually about simplifying the definition of functions like rotate-omn. The definition of this function is pretty short, as the actual rotation is already implemented by gen-rotate, and all support of arguments like section, flat and now also 'dynamic' arguments is automatically implemented by edit-omn. For getting dynamic arguments, all we need to do is the following. First, we test whether the argument we want to turn into a 'dynamic' argument is a list. If not, we want to use it as a static value. The result of that test (using listp) is bound to the local variable n-list-arg?, because we need to use this value at two places. The argument additional-args on the last line gets our argument n if it is a list.


We tell edit-omn how to actually transform the input music (e.g., sublists) by handing it a function -- that is another program that does the actual transformation. In the case below this function is an anonymous function (it has no name). Such functions are defined with lambda, which is pretty much like defun but without expecting a function name. Our anonymous function basically just calls gen-rotate, but if n is a list, then we first need to extract the OMN data to rotate and the amount by which to rotate it from the single argument xs of our anonymous function.


(defun rotate-omn (n sequence &key (parameter :pitch) (flat T) (section nil))
  (let ((n-list-arg? (listp n)))
    (edit-omn parameter sequence
              #'(lambda (xs)
                 (if n-list-arg?
                     (gen-rotate (second xs) (first xs))
                     (gen-rotate n xs)))
              :section section
              :flat flat
              :additional-args (when n-list-arg? n))))


With this approach you can write relatively simply functions for processing individual parameters, and then turn that relatively simple function into a much more fancy function processing arbitrary OMN expressions, including nested expressions, and automatically supporting typical Opusmodus arguments like section and flat, and now also with dynamic arguments. 


As mentioned in other posts, the function edit-omn can be found as part of my tot library at GitHub (and yes, that library has a buch of dependencies, and is therefore a bit tricky to install the first time; updates are a bit more easy).  I also cleaned up the definition of edit-omn and fixed some bug that way.  




Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Similar Topics

    • By o_e
      I'am exploring gen-dynamic-controller,  which jumps immeadiately to the value of zero, which is cutting off the sample ( Spitfire string quartet), see attachments. Is there a way to avoid this?

    • By opmo
      – Fixes:
      COUNTERPOINT – span added an additional 1/4 length.
      PS – error if controller option in an instrument.
      CREATE-CHORD – error if incorrect chord arguments.
      ttrem – error in display when ttrem inside a tuplet.
      Italian documentation – misspels and typos.

      – Changes:
      Changes to method names in default Unfold Set OM.lisp file.
      Update to Quick Start folder.

      How to install the new Quick Start workspace:
      1. Delete the Quick Start folder from your Opusmodus directory.
      2. Select the Install Quick Start Workspace command from the Opusmodus Help menu.
      3. New Quick Start workspace will open. 
    • By terekita
      I'm a little confused about how to include the :map step tonality form in this example. I start with my tonality-series:
      (setf g-tonality (tonality-series '( (0 3 5 7 10)) :root '(8 11 4 7 0 4 11 4 7 0 3 8 0 7 0 4 11 4 8 3 8 0 7 0 8 3)))  
      Next, I grab an omn list:
      (setf bomn1 '(#|1|# (q^e.. b4 q^e.. -e e^s. b4) #|2|# (q^e.. a4 q^e.. -e e^s. d5) #|3|# (q^e.. d5 q^e.. cs5 -e e^s. g4) #|4|# (e.^et g4 s^t e4 q^e.. fs4 -e e^s. a4) #|5|# (e.^et d4 s^t e4 q^e.. f4 -e e^s. g4) #|6|# (e.^et g4 s e4 d4 e. c4 -e e4) #|7|# (e. a3 s b3 q c4 -e d4) #|8|# (e. d4 s b3 q g3 -) #|9|# (e. g5 3e^t fs5 t e5 q d5 -e s b5 tie 3e tie 3t tie) #|10|# (3t b5 q a5 a5 -e s a5 tie 3e tie 3t tie) #|11|# (3t a5 q q g5 -e s g5 tie 3e tie 3t tie) #|12|# (3t g5 e. s e5 b4 e. a4 -e s g5 tie 3e tie 3t tie) #|13|# (3t g5 e. s e5 e5 e. fs5 -e s a5 tie 3e tie 3t tie) #|14|# (3t a5 e. b5 s fs5 fs5 e. g5 -e s g5 tie 3e tie 3t tie) #|15|# (3t g5 q q cs5 -e s a4 tie 3e tie 3t tie) #|16|# (3t a4 e. s e4 e4 e. fs4 -e -s -3e -3t) #|17|# (-3t e fs4 tie t - e4 - q fs4 -e s. d4 -3s) #|18|# (-3t e g4 tie t - a4 - a4 - e. b4 -e s. g5 -3s) #|19|# (-3t e. e5 s b5 q a5 -e s a5 tie 3e tie 3t tie) #|20|# (3t a5 e tie t - fs5 - q ds5 -e s. fs5 -3s) #|21|# (-3t e g5 tie t - fs5 - q e5 tie s. -t s g5 tie 3e tie 3t tie) #|22|# (3t g5 q q f5 -e s a5 tie 3e tie 3t tie) #|23|# (3t a5 e. s fs5 q ds5 -e s fs5 tie 3e tie 3t tie) #|24|# (3t fs5 e. s ds5 t e5 ds5 e. e5 -3e e3 fs3 g3 a3 t b3 tie) #|25|# (3t b3 e e4 -s gs4 e. a4 s b4 e c5 tie s tie 3e tie 3t tie) #|26|# (e c5 tie 3t -s fs4 e. g4 s a4 e b4 tie s tie 3e tie 3t tie) #|27|# (e b4 tie 3t -s e4 e. fs4 s g4 e. a4 3e g4 tie 3t tie) #|28|# (3t g4 3s fs4 tie fs4 3t g4 tie t 3e fs4 cs4 d4 e4 fs4 e4 fs4 g4 fs4 g4 3e^t a4 g4 a4 b4 g4 t a4 tie) #|29|# (3t a4 3s b4 tie b4 3t c5 tie t 3e b4 fs4 g4 a4 3e^t b4 a4 b4 c5 b4 c5 d5 c5 d5 e5 c5 t d5 tie) #|30|# (3t d5 3s e5 tie e5 3t f5 tie t 3e e5 b4 c5 d5 3e^t e5 d5 e5 fs5 e5 fs5 g5 fs5 g5 a5 fs5 t g5 tie) #|31|# (3t g5 3s a5 tie a5 3t b5 tie t 3e a5 fs5 g5 a5 b5 a5 b5 d6 c6 b5 a5 g5 fs5 e5 d5 t c5 tie) #|32|# (3t c5 3s b4 tie b4 3t a4 tie t 3e g4 fs4 g4 d4 s. b3))) And finally, do the tonality map:
      (setf mapped-g (omn-to-time-signature (tonality-map g-tonality bomn1 :time '(4/8 2/8 4/8 2/8 3/4 4/8 2/8 4/8 2/8 4/8 2/8 3/4 4/8 2/8 3/4 4/8 2/8 3/4 4/8 2/8 3/4 4/8 2/8 3/4 4/8 2/8) :loop t ) '(3 4))) Ok, all of that works, but I'd like to use :map step when I create the tonality-map, and I can't figure out where to put that. It seems like it wants to be part of a list with, in my example, g-tonality, but I'm not seeing quite how to do it. Any tips would be greatly appreciated. Thanks!, Michael
  • Create New...