Jump to content

velocity-to-dynamic limitation


Recommended Posts

I would like to algorithmically generate dynamic markings with dynamic indications like mp plus hairpins. The code snippet below shows vector values created with custom envelopes that I would like to translate, and the function velocity-to-dynamic almost does that for me already (vector-to-velocity is primarily there to translate a vector into a list).

 

(velocity-to-dynamic
 (vector-to-velocity
  0.1 0.7
  #(0.0 0.07936508 0.15873016 0.23809525 0.31746033 0.39682543 0.4761905 0.5555556 0.63492066 0.71428573 0.79365087 0.8730159 0.952381 0.9259259 0.74074066 0.5555556 0.37037033 0.18518525 0.0)))

 

My problem is that velocity-to-dynamic creates lots of intermediate dynamic indications, where instead I would prefer a long hairpin connecting only the extreme dynamic indications. Instead of

 

   (pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp)

 

I would like to get something like the following result, which is much clearer for the performer.

 

   (pppp< < < < < < < < < < < < ff> > > > > > pppp)

 

Would it be possible to revise velocity-to-dynamic accordingly, or should I better roll my own? Thanks!

 

EDIT: On second thought, a separate function would likely be better, because that can then be used for all functions that generate hairpins, e.g., also gen-dynamic.

 

Best,

Torsten

 

PS: A remaining problem would be how to handle rests, where hairpins will be interrupted. A possible solution could be to keep the output of velocity-to-dynamic as is, and instead be able to specify that the final score generation leaves out intermediate dynamic markings as those shown above, but keeps them for rests. However, that might be tricky to implement. Leaving the proper handling of rests to users and instead to simplify the output of velocity-to-dynamic with a new function is much simpler.

 

Link to comment
Share on other sites

Below is a first attempt. What I am now missing to further improve it are functions that basically parse the OMN dynamics symbols to be able to tell whether some symbol expresses a crescendo or diminuendo. 

 

For example, something like the following.

 

(cresc-p 'pp<)

=> T

 

or

 

(parse-dynamics 'pp<)

=> (pp <)

 

Do you already have any such functions?

 

(Without such functions, we could also have a lot of further cond clauses, but that would be unnecessary long and error prone.)

 

Best,

Torsten

 

(defun simplify-dynamics (dynamics)
  "Removes intermediate textual dynamic indicators from longer hairpins.
  
  Example:
  (simplify-dynamics (pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp))"
  (append (list (first dynamics))
          (loop
            for (d1 d2 d3) on dynamics 
            when (and d2 d3)
            collect (cond ((and (eq d1 '<) (eq d3 '<)) '<)
                          ((and (eq d1 '>) (eq d3 '>)) '>)
                          (t d2)))
          (last dynamics)))


#|
(simplify-dynamics 
  '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp))
=> (pppp< < ppp< pp< < < < mp< mf< < < < ff> > mf> mp> p> ppp> pppp)
|#

 

Link to comment
Share on other sites

OK, I now defined the necessary auxiliary functions and almost finished the function. What is still missing is support for nested lists that retains the nesting structure. Janusz, you did this in several OMN functions already, it might be more easy if you add that yourself :)

 

Best,

Torsten

 

(defun cresc-p (dyn)
  "Example: 
  (cresc-p 'p<)
  => T"
  (and (velocityp dyn)
       (let ((str (symbol-name dyn)))
         (equal (subseq str (1- (length str)))
                "<"))))

(defun dim-p (dyn)
  "Example: 
  (dim-p 'f>)
  => T"
  (and (velocityp dyn)
       (let ((str (symbol-name dyn)))
         (equal (subseq str (1- (length str)))
                ">"))))


;;; TODO: support nested lists -- somehow store nesting structure, then process flattened list and apply nesting back
(defun simplify-dynamics (dynamics)
  "Removes intermediate textual dynamic indicators from longer hairpins (e.g., generated by velocity-to-dynamic or gen-dynamic).
  
  Example:
  (simplify-dynamics '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp))
  => (pppp< < < < < < < < < < < < ff> > > > > > pppp)"
  (append (list (first dynamics))
          (loop
            for (d1 d2 d3) on dynamics 
            when (and d2 d3)
            collect (cond ((or (and (cresc-p d1) (cresc-p d3))
                               (and (not (eq d2 '<))
                                    (not (eq d3 '<))
                                    (< (get-velocity d2) (get-velocity d3))))
                           '<)
                          ((or (and (dim-p d1) (dim-p d3))
                               (and (not (eq d2 '>))
                                    (not (eq d3 '>))
                                    (> (get-velocity d2) (get-velocity d3))))
                           '>)
                          (t d2)))
          (last dynamics)))


 

Link to comment
Share on other sites

Found a little bug, here is a revision.

 

(defun simplify-dynamics (dynamics)
  "Removes intermediate textual dynamic indicators from longer hairpins (e.g., generated by velocity-to-dynamic or gen-dynamic).
  
  Example:
  (simplify-dynamics '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp))
  => (pppp< < < < < < < < < < < < ff> > > > > > pppp)"
  (append (list (first dynamics))
          (loop
            for (d1 d2 d3) on dynamics 
            when (and d2 d3)
            collect (cond ((or (and (cresc-p d1) (cresc-p d3))
                               (and (not (member d2 '(< >)))
                                    (not (member d3 '(< >)))
                                    (< (get-velocity d2) (get-velocity d3))))
                           '<)
                          ((or (and (dim-p d1) (dim-p d3))
                               (and (not (member d2 '(< >)))
                                    (not (member d3 '(< >)))
                                    (> (get-velocity d2) (get-velocity d3))))
                           '>)
                          (t d2)))
          (last dynamics)))

 

Link to comment
Share on other sites

Other thing you need to do is to fix the one-note dynamic symbols.

Here the 0<mp>0 symbol is gone:

(simplify-dynamics '(p< mp< < < f> p> > 0<mp>0 mf< f> >))
=> (p< < < < > > > < < f> >)

 

This will help:

*one-note-dynamic-symbol*

 

Example:

(memq x *one-note-dynamic-symbol*)

 

Link to comment
Share on other sites

Thanks! Should be fixed now.

(defun simplify-dynamics (dynamics)
  "Removes intermediate textual dynamic indicators from longer hairpins (e.g., generated by velocity-to-dynamic or gen-dynamic).
  
  Example:
  (simplify-dynamics '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp))
  => (pppp< < < < < < < < < < < < ff> > > > > > pppp)
  "
  (append (list (first dynamics))
          (loop
            for (d1 d2 d3) on dynamics 
            when (and d2 d3)
            collect (cond ((or (and (cresc-p d1) (dim-p d3))
                               (and (dim-p d1) (cresc-p d3)))
                           d2)
                          ((or (and (cresc-p d1) (cresc-p d3))
                               (and (not (member d2 '(< >)))
                                    (not (member d3 '(< >)))
                                    (not (member d2 *one-note-dynamic-symbol*))
                                    (not (member d3 *one-note-dynamic-symbol*))
                                    (< (get-velocity d2) (get-velocity d3))))
                           '<)
                          ((or (and (dim-p d1) (dim-p d3))
                               (and (not (member d2 '(< >)))
                                    (not (member d3 '(< >)))
                                    (not (member d2 *one-note-dynamic-symbol*))
                                    (not (member d3 *one-note-dynamic-symbol*))
                                    (> (get-velocity d2) (get-velocity d3))))
                           '>)
                          (t d2)))
          (last dynamics)))

 

Link to comment
Share on other sites

As we all like the idea of the intermediate velocities I therefore have written a function which will work with both, velocity and dynamic symbols.

 

Example:

(velocity-intermediate '(p pppp f p pp ppp mp ff))
=> (p> pppp< f> > > ppp< < ff)

(velocity-intermediate '((p pp ppp pppp f ff fff p pp ppp pppp ff)
                         (p pppp f p pp ppp mp ff)))
=> ((p> > > pppp< < < fff> > > > pppp< ff) (p> pppp< f> > > ppp< < ff))

(velocity-intermediate '(ppppp< pppp< ppp< < < < mf> > > p f< ff< fff< ffff< fffff))
=> (ppppp< < < < < < mf> > > p< < < < < fffff)

 

Link to comment
Share on other sites

Here is the final function. The VELOCITY-INTERMEDIATE will be part (keyword :join t) of the VELOCITY-TO-DYNAMIC function.

 

 Source code:

(defvar *cresc-dynamic-symbol*
  '(< cresc cresc-molto cresc-poco cresc-poco-poco
      ppppp< pppp< ppp< pp< p< mp< mf< f< ff< fff< ffff< fffff<))

(defvar *dim-dynamic-symbol*
  '(> dim dim-molto dim-poco dim-poco-poco
      fffff> ffff> fff> ff> f> mf> mp> p> pp> ppp> pppp> ppppp>))

(defun cresc-p (x)
  (memq x *cresc-dynamic-symbol*))

(defun dim-p (x)
  (memq x *dim-dynamic-symbol*))

(defun velocity-intermediate (velocity &key end (flatten t) section exclude)
  (do-verbose ("velocity-intermediate")
    (labels ((velocity-intermediate-l (velocity &key end (flatten t))
               (let ((dyn (velocity-to-dynamic velocity :end end :flatten flatten)))
                 (append
                  (list (first dyn))
                  (loop
                    for (v1 v2) on dyn 
                    when (and v1 v2)
                    collect (cond ((and (cresc-p v1) (cresc-p v2)) '<)
                                  ((and (dim-p v1) (dim-p v2)) '>)
                                  (t v2))))))
             
             (%velocity-intermediate (velocity &key end (flatten t))
               (if (listsp velocity)
                 (loop for v in velocity
                   collect (velocity-intermediate-l v :end end :flatten flatten))
                 (velocity-intermediate-l velocity :end end :flatten flatten)))
             
             (velocity-intermediate* (velocity &key end (flatten t))
               (if (and (listsp velocity) flatten)
                 (gen-divide
                  (get-count velocity)
                  (%velocity-intermediate (flatten velocity) :end end :flatten flatten))
                 (%velocity-intermediate velocity :end end :flatten flatten))))
      
      (disassembling-omn ((velocity plist) velocity :velocity)
        (let ((velocity (remove-nils velocity)))
          (maybe-section
           (lambda (x) (velocity-intermediate* x :end end :flatten flatten))
           velocity section exclude))))))

#|
(velocity-intermediate '(p pppp f p pp ppp mp ff))
=> (p> pppp< f> > > ppp< < ff)

(velocity-intermediate '((e c4 f cs5 f d4 f ds5 p f4 p fs5 p c5 p pp)
                         (e cs4 p f d4 f eb5 p f4 p eb4 f d3 p ppppp)))
=> ((e c4 f> cs5 > d4 > ds5 > f4 > fs5 > c5 > pp<)
    (e cs4 < f> d4 > eb5 p< f4 < eb4 f> d3 > ppppp))

(velocity-intermediate '(p pp ppp pppp f ff fff p pp ppp f ff
                         fff ffff f p pp ppp mp ff))
=> (p> > > pppp< < < fff> > > ppp< < < < ffff> > > > ppp< < ff)

(velocity-intermediate '((p pp ppp pppp f ff fff p pp ppp f ff)
                         (fff ffff f p pp ppp mp ff)))
=> ((p> > > pppp< < < fff> > > > pppp< ff) (p> pppp< f> > > ppp< < ff))

(velocity-intermediate '(ppppp< pppp< ppp< < < < mf> > > p f< ff< fff< ffff< fffff))
=> (ppppp< < < < < < mf> > > p< < < < < fffff)
|#

 

Link to comment
Share on other sites

  • 3 weeks later...

For the record, the functions cresc-p and dim-p are meanwhile predefined by Opusmodus (with a subset of the dynamic symbols listed above), but velocity-intermediate is not (as of 13 April 2017), nor is an argument :join for the function velocity-to-dynamic.

 

So, if you are interested in this you better add the functions to your user libraries :)

 

Best,

Torsten

added 7 minutes later

UPDATE: seemingly these functions are not quite finished yet and therefore not included.

 

(velocity-intermediate '(ppppp< pppp< ppp< < < < mf> > > p f< ff< fff< ffff< fffff))

=> (ppppp pppp ppp < < < mf > > p f ff fff ffff fffff)

 

So, if you want the simplified dynamics discussed in the thread above, you better use the function simplify-dynamics, of which you also find the code above.

 

(simplify-dynamics '(ppppp< pppp< ppp< < < < mf> > > p f< ff< fff< ffff< fffff))
=> (ppppp< < < < < < mf> > > p < < < < fffff)

 

Best,

Torsten

Link to comment
Share on other sites

Here is a slightly revised version of simplify-dynamics that can also handle nested lists (bars). See documentation string for details and examples.

 

Best,

Torsten

 

(defun simplify-dynamics (dynamics &key (flat T))
  "Removes intermediate textual dynamic indicators from longer hairpins (e.g., generated by velocity-to-dynamic or gen-dynamic).
  
  Args
  flat (default T): whether or not to simplify dynamics across sublists.

  Examples:
  (simplify-dynamics '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp))
  => (pppp< < < < < < < < < < < < ff> > > > > > pppp)

  (simplify-dynamics '((pppp< < ppp< pp< < p< <) (mp< mf< < f< < ff> > mf> mp> p> ppp> pppp)))
  => ((pppp< < < < < < <) (< < < < < ff> > > > > > pppp))

  (simplify-dynamics '((pppp< < ppp< pp< < p< <) (mp< mf< < f< < ff> > mf> mp> p> ppp> pppp))
                      :flat nil)
  => ((pppp< < < < < < <) (mp< < < < < ff> > > > > > pppp))
  "
  (if (or flat 
          (not (some #'listp dynamics)))
    (let ((flat-dynamics (flatten dynamics))) 
      (span dynamics
            (append (list (first flat-dynamics))
                    (loop
                      for (d1 d2 d3) on flat-dynamics 
                      when (and d2 d3)
                      collect (cond ((or (and (cresc-p d1) (dim-p d3))
                                         (and (dim-p d1) (cresc-p d3)))
                                     d2)
                                    ((or (and (cresc-p d1) (cresc-p d3))
                                         (and (not (member d2 '(< >)))
                                              (not (member d3 '(< >)))
                                              (not (member d2 *one-note-dynamic-symbol*))
                                              (not (member d3 *one-note-dynamic-symbol*))
                                              (< (get-velocity d2) (get-velocity d3))))
                                     '<)
                                    ((or (and (dim-p d1) (dim-p d3))
                                         (and (not (member d2 '(< >)))
                                              (not (member d3 '(< >)))
                                              (not (member d2 *one-note-dynamic-symbol*))
                                              (not (member d3 *one-note-dynamic-symbol*))
                                              (> (get-velocity d2) (get-velocity d3))))
                                     '>)
                                    (t d2)))
                    (last flat-dynamics))))
    (mapcar #'simplify-dynamics dynamics)))

 

Link to comment
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.

Guest
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.

×
×
  • Create New...

Important Information

Terms of Use Privacy Policy