Jump to content

Merging and disassembling articulation symbols


Recommended Posts

Dear Janusz,

 

Are there some functions to merge or disassemble articulation symbols, as shown below?


(merge-articulations '(leg ponte))
=> leg+ponte

 

(disassemble-articulations leg+ponte)
=> (leg ponte)

 

This would be useful when algorithmically generating or processing articulations, like chordize and friends are for algorithmically working with chords.

 

Do you perhaps have such functionality already somewhere anyway, e.g., for generating this MusicXML output?

 

Thanks!

 

Best,

Torsten

Link to comment
Share on other sites

EDIT: OK, I now this this myself:

 

(defun merge-articulations (arts &key (empty-articulations '(- default)))
  "Merges list of OMN articulations to a combined attribute.

  Args:
  arts: a list of OMN articulations
  empty-attributes: articulations to ignore in a combination. 

  Examples:
  (merge-articulations '(ten ponte ubow))
  => ten+ponte+ubow
  (merge-articulations '(- stacc))
  => stacc"
  #| ; can be uncommented when articulationp works
  (assert (every #'articulationp arts)
          (arts)
          "All values to merge must be OMN attributes: ~A.~%" arts)
  |#
  (intern 
   (reduce #'(lambda (a1 a2) (format nil "~A+~A" a1 a2))
           (mappend #'(lambda (art) (unless (some #'(lambda (a) (eq art a))
                                                  empty-articulations)
                                      (list (symbol-name art))))
                    arts))))




(defun disassemble-articulations (art)
  "Splits a combined OMN articulations into a list of its individual attributes.

  Example:
  (disassemble-articulations 'leg+ponte)
  => (leg ponte)"  
  #|
  (assert (articulationp art)
          (art)
          "Value not OMN articulations: ~A.~%" art)
  |#
  ;; split-string seems to be part of OMN
  (mapcar #'intern (split-string (symbol-name art) :separator "+")))

 

Link to comment
Share on other sites

Here is some application example for the above functions.

 

(setf my-rhythm '(1/8 1/8 1/16 1/16 -1/16 1/8 1/8 1/8 1/8))

(setf arts-1 (pattern-map '(((1/8 1/8) (leg stacc)))
                          my-rhythm
                          :otherwise '(default)))
(setf arts-2 (pattern-map '(((1/8) (tasto)))
                          my-rhythm
                          :otherwise '(ord)))

(mapcar #'merge-articulations (matrix-transpose (list (flatten arts-1) (flatten arts-2))))
=> (leg+tasto stacc+tasto ord ord ord leg+tasto stacc+tasto leg+tasto stacc+tasto)

 

Link to comment
Share on other sites

I thought we better have a function zipping articulations for us, in particular if there are articulation lists of different length. The function definition is below. Here is a usage example. Apologies to all string players that this does not necessarily make sense musically :)

 

(make-omn
 :length '(1/8 1/8 1/16 1/16 -1/16 1/8 1/8 1/8 1/8)
 :articulation (zip-articulations '(default stacc stacc default)
                                  '(ubow dbow)
                                  '(ponte))
 :swallow NIL
 :flat T)

=> (e ubow+ponte nil stacc+dbow+ponte s stacc+ubow+ponte nil dbow+ponte - e ubow+ponte nil stacc+dbow+ponte nil stacc+ubow+ponte nil dbow+ponte)

 

Janusz: as with the dynamics function, this function does also not yet handle nested lists.

 

Best,

Torsten

;;; TODO: support nested lists -- somehow store nesting structure, then process flattened list and apply nesting back
(defun zip-articulations (&rest arts)
  "Expects lists of articulations and combines them to a single list of merged articulations. Shorter lists are circled to the length of the longest.

  Example:
  (zip-articulations '(default leg leg default) '(breathy))"
  (let ((max-length (apply #'max (mapcar #'length arts))))
    (mapcar #'merge-articulations             
            (matrix-transpose (mapcar #'(lambda (xs) (circle-repeat xs max-length)) arts)))))

(defun circle-repeat (pattern n)
  "Circle through elements in pattern (a list) until n elements are collected.
  NOTE: only supports flat list so far."  
  (let ((l (length pattern)))
    (loop 
      for i from 0 to (- n 1)
      collect (nth (mod i l) 
                   pattern))))

; (circle-repeat '(bb4 g4 f4) 20)


 

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