Jump to content

Recommended Posts

Below is a function for creating durational accents on the beginning of bars. Many musical styles pay careful attention to how their rhythmic language expresses accents. Certain rhythmic events are perceived as stronger emphasised than others. Such accents do not need to be forced by a performer, e.g., by a dynamic accent. Instead, music theorists identified various musical factors that express accents. Durational accents (expressed by inter-onset intervals) are particularly effective. They are caused by relatively long durations following one or more shorter durations.

 

The function definition is below. Here are two demo calls, showing multiple solutions.

 

(durational-accent '((1/4 1/4 1/4) (1/4 1/4 -1/4) (1/4 1/4 1/4) (1/2 -1/4)))

=> ((1/4 1/4 1/4) (1/4 1/4 -q) (1/4 1/4 1/8 1/8) (1/2 -1/4))

=> ((1/4 1/4 1/8 1/8) (1/4 1/4 -q) (1/4 1/4 1/8 1/8) (1/2 -1/4))

 

(durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3))

=> ((1/2 1/4) (1/4 1/4 1/12 1/12 1/12) (1/2 -q) (1/2 1/4) (1/4 1/4 1/12 1/12 1/12) (1/2 -1/4))

=> ((1/2 1/12 1/12 1/12) (1/4 1/4 1/8 1/8) (1/2 -q) (1/2 1/8 1/8) (1/4 1/4 1/4) (1/2 -1/4))

=> ((1/2 1/8 1/8) (1/4 1/4 1/4) (1/2 -q) (1/2 1/12 1/12 1/12) (1/4 1/4 1/12 1/12 1/12) (1/2 -1/4))

 

NB: Unfortunately, I did not get the seed argument working. I tested rnd-seed and friends with a simpler function, and everything seemed to work fine there, but I could not find what stops it working for the durational accents.

 

Janusz: can you perhaps see what I am missing here?

 

Best,

Torsten

 

(defun durational-accent (lengths &key (seed nil) (divide 2) (set nil) (ignore nil))
  "Adds durational accents on first notes of bars by subdividing the last note of the preceding bar. `lengths' must be a list of length lists (multiple bars). 

  If a bar starts with a rest, then it cannot carry a durational accent, and hence its preceding note is never subdivided. 

  Note: currently only plain length values, and no OMN supported.

  Args:
  divide (integer or list of integers, default 2): specifies into how many equal note values notes preceeding a durational accent are subdivided. If list of integer, subdivision is randomly chosen.
  set (length or list of lengths): only specified lengths are subdivided. 
  ignore (length or list of lengths): specified lengths are *not* subdivided. 

  lengths must be list of lists.
  For now simpler version: accents only supported leading to strong beat at beginning of bar, but metric structure does not need to be regular.

  Example:
  (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3))

  BUG: arg seed not working."
  (rnd-seed seed)
  (assert (and (listp lengths) (every #'listp lengths)) 
          (lengths)
          "Given `lengths' ~A is not a sequence of bars (a list of lists).~%" lengths)
  (append 
   (map-neighbours 
    #'(lambda (bar1 bar2) 
          (if (length-notep (first bar2))
            ;; subdivide last note of bar
            (append (butlast bar1) (length-divide
                                    ; random control whether subdivision happens
                                    (rnd-pick '(0 1) :seed (seed))
                                    (if (listp divide)
                                      (rnd-pick divide :seed (seed))
                                      divide) 
                                    (last bar1)
                                    :set set
                                    :ignore ignore))
            bar1))
    lengths)
   (last lengths)))
   
   
;; aux def
(defun map-neighbours (func list &optional n)
  "Applying `func' to consecutive sublists of `list'. The number of arguments expected by func implicitly specifies the number of consecutive elements to which the function is applied. This can be overwritten by the optional `n'."
  (let ((n2 (if n n (length (ccl:arglist func)))))
    (loop for l on list 
      when (>= (length l) n2)
      collect (apply func (subseq l 0 n2)))))

#|
(map-neighbours #'(lambda (x y) (list x y)) 
                '(1 2 3 4 5 6))
=> ((1 2) (2 3) (3 4) (4 5) (5 6))

(map-neighbours #'+ '(1 2 3 4 5 6)
                3)
=> (6 9 12 15)
|#

 

Link to post
Share on other sites

You forgot to add the seed into the LENGTH-DIVIDE function.

 

To stop the endless print in the Listener you could add DO-VERBOSE marco:

(defun durational-accent (lengths &key seed (divide 2) (set nil) (ignore nil))
    (do-verbose ("durational-accent")
      (rnd-seed seed)
      (assert (and (listp lengths) (every #'listp lengths)) 
              (lengths)
              "Given `lengths' ~A is not a sequence of bars (a list of lists).~%" lengths)
      (append 
       (map-neighbours 
        #'(lambda (bar1 bar2) 
            (if (length-notep (first bar2))
              (append (butlast bar1) (length-divide
                                      (rnd-pick '(0 1) :seed (seed))
                                      (if (listp divide)
                                        (rnd-pick divide :seed (seed))
                                        divide) 
                                      (last bar1)
                                      :set set
                                      :ignore ignore :seed (seed)))
              bar1))
        lengths)
       (last lengths))))

 

Link to post
Share on other sites

Ah, brilliant -- thank you! Below this message is the corrected function for those interested. The following works now as expected.

 

  (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3) :seed 4321)

 

The definition of map-neighbours is still in the other post above.

 

> To stop the endless print in the Listener you could add DO-VERBOSE marco

 

Thanks. I would prefer disabling such tracing globally -- I would only need it for debugging. Is that perhaps possible?

 

Best,

Torsten

 

(defun durational-accent (lengths &key (seed nil) (divide 2) (set nil) (ignore nil))
  "Adds durational accents on first notes of bars by subdividing the last note of the preceding bar. `lengths' must be a list of length lists (multiple bars). 

  If a bar starts with a rest, then it cannot carry a durational accent, and hence its preceding note is never subdivided. 

  Note: currently only plain length values, and no OMN supported.

  Args:
  divide (integer or list of integers, default 2): specifies into how many equal note values notes preceeding a durational accent are subdivided. If list of integer, subdivision is randomly chosen.
  set (length or list of lengths): only specified lengths are subdivided. 
  ignore (length or list of lengths): specified lengths are *not* subdivided. 

  lengths must be list of lists.
  For now simpler version: accents only supported leading to strong beat at beginning of bar, but metric structure does not need to be regular.

  Example:
  (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3))"
  (assert (and (listp lengths) (every #'listp lengths)) 
          (lengths)
          "Given `lengths' ~A is not a sequence of bars (a list of lists).~%" lengths)
  (rnd-seed seed)
  (append 
   (map-neighbours 
    #'(lambda (bar1 bar2) 
          (if (length-notep (first bar2))
            ;; subdivide last note of bar
            (append (butlast bar1) (length-divide
                                    ; random control whether subdivision happens
                                    (rnd-pick '(0 1) :seed (seed))
                                    (if (listp divide)
                                      (rnd-pick divide :seed (seed))
                                      divide) 
                                    (last bar1)
                                    :set set
                                    :ignore ignore
				    :seed (seed)))
            bar1))
    lengths)
   (last lengths)))

 

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.

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