Hello Leo,

You could use for-some-music, but this would require us to handle lots of 
different cases to properly count the time. So we rather want to keep using 
ly:music-length to determine the actual length of a bit of music. Rather I 
suggest doing it like before, but calling the method recursively with some 
offset for nested elements, somewhat like this. The appended file should work 
for any nested music (although there can always be some cases I did not think 
about). The make-time-table function still requires flat music.

Cheers,
Valentin

Am Mittwoch, 22. Dezember 2021, 16:12:01 CET schrieb Leo Correia de Verdier:
> Hi Valentin!
> 
> Thanks very much for your help!
> 
> How would I go about to make the function climb the music tree? (There are
> nested sequential music expressions, needed for another function to work)
> 
> Could I use for-some-music in some way?
> 
> > 21 dec. 2021 kl. 00:15 skrev Valentin Petzel <valen...@petzel.at>:
> > 
> > Hello Leo,
> > 
> > Maybe something like this? Here we create a time table of articulations,
> > and then apply these articulations on music. This method does only handle
> > flat music for now. If there are nested constructs of consecutive music
> > we’d need to modify the function to basically walk the full music tree.
> > 
> > Cheers,
> > Valentin
#(define (moment->number mom)
   (let ((frac (moment->fraction mom)))
     (/ (car frac) (cdr frac))))

#(define (make-time-table music)
   (define (make-pairs list-of-music current-time)
     (if (null? list-of-music)
         '()
         (let* ((next (car list-of-music))
                (mom (ly:music-length next))
                (duration (moment->number mom))
                (articulations (ly:music-property next 'articulations)))
           (cons (cons current-time articulations)
                 (make-pairs (cdr list-of-music) (+ current-time duration))))))
   (make-pairs
    (ly:music-property music 'elements)
    0))

applyTable =
#(define-music-function (timetable music) (list? ly:music?)
   (define (apply-table list-of-music current-time current-timetable)
     (if (and (not (null? list-of-music)) (not (null? current-timetable)))
         (let* ((next-table-pair (car current-timetable))
                (table-time (car next-table-pair))
                (table-articulations (cdr next-table-pair))
                (current-music (car list-of-music))
                (current-articulations (ly:music-property current-music 'articulations))
                (current-elements (ly:music-property current-music 'elements))
                (current-mom (ly:music-length current-music))
                (current-mom-num (moment->number current-mom))
                (next-time (+ current-time current-mom-num))
                (next-table current-timetable))
           (while (and (not (null? next-table)) (< (caar next-table) next-time))
                  (set! next-table (cdr next-table)))
           (if (or (music-is-of-type? current-music 'note-event)
                   (music-is-of-type? current-music 'event-chord))
               (if (and (= current-time table-time)
                        (music-is-of-type? current-music 'event-chord))
                   (ly:music-set-property! current-music
                                           'elements
                                           (append current-elements table-articulations))
                   (ly:music-set-property! current-music
                                           'articulations
                                           (append current-articulations table-articulations)))
               (outer-handler current-music current-time current-timetable)) 
           (apply-table (cdr list-of-music) next-time next-table))))
   ;; If only one note or chord is specified then we apply to the list having this one chord
   ;; if music is simultaneous we apply the articulations to all entries
   ;; if music has an element we delegate to this element
   ;; else we assume that music is sequential (or not of importance) and
   ;; we apply the table to the elements
   (define (outer-handler music current-time current-timetable)
     (if (or (music-is-of-type? music 'note-event) (music-is-of-type? music 'event-chord))
         (apply-table (list music) current-time current-timetable)
         (if (music-is-of-type? music 'simultaneous-music)
             (map (lambda (x) (outer-handler x current-time current-timetable))
                  (ly:music-property music 'elements))
             (let ((elt (ly:music-property music 'element))
                   (elts (ly:music-property music 'elements)))
               (if (null? elt)
                   (apply-table elts current-time current-timetable)
                   (outer-handler elt current-time current-timetable))))))
   (outer-handler music 0 timetable)
   music)

articulations = { s16_> s16_> s16 s16_. s16_- s8_> s16_! s8__ s8__ s16_.  s8_- s16_. }
#(define myTable (make-time-table articulations))
%#(display myTable)

<<
 \new RhythmicStaff \with { \override Script.Y-offset = #-1.7 } 
<< { s16_> s16_> s16 s16_. s16_- s8_> s16_! s8__ s8__ s16_.  s8_- s16_. }
  { f'16 16 16 16 16 8 16 8 8 16 8 16 } >>

% but also apply the first sequential expressions, with the articulations, to for instance

\new RhythmicStaff { c'8. 16 8. 16 8 r8 8. 16 }

% so that the result would be 

\new RhythmicStaff \with { instrumentName = "this method" }
\applyTable #myTable { c'8. 16 8. 16 8 r8 8. 16 }

\new RhythmicStaff { c'8._> 16-. 8._- 16_! 8__  r8 8.-. 16-. }

% or to 

\new RhythmicStaff {c'16 16 16 16 r8. 16 r8 16 16 r16 8. }

\new RhythmicStaff \with { instrumentName = "this method" }
\applyTable #myTable {c'16 16 16 16 r8. 16 r8 16 16 r16 8. }

% getting

\new RhythmicStaff {c'16_> 16_> 16 16_. r8. 16_! r8 16__ 16 r16 8._- }

\new RhythmicStaff \with { instrumentName = "nested music" }
\applyTable #myTable { { c'16 16 16 16} \repeat volta 2 {16 16 16 16} {{16 16 16 16} << {{16 16} {16 16}} \\ {16 16 16 16}>> } }
>>

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to