lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Bar numbers “repeat aware” for music for dancing


From: Niols
Subject: Bar numbers “repeat aware” for music for dancing
Date: Wed, 15 Apr 2020 01:13:11 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0

Hello everyone,

This is my first message on this mailing list and I hope I do it correctly. My apologies in advance if I don't. I have been using LilyPond for a while to engrave various things. Among them, traditional Scottish tunes used for dancing.

For such tunes, we are not so interested in the “usual” printed bar numbers, but rather in the bar numbers (“repeat aware”) from the dance. In particular, a repeat in the music does not mean a repeat in the dance: if the first eight bars are repeated in the music, I would like the bar numbers to go from 1 to 8 and then directly to 17.

I am unsure how to deal with that in an automated and clean way. I have tried searching for that on Internet, without great success. I have then tried implementing something myself with some success. I copied the code at the end of this e-mail, if you are interested. The logic is that every time a repeat starts, I push the current bar number to a stack. That way, when the repeat ends, I can see for how many bars it lasted and adjust the current bar number accordingly. However, my solution has many big issues:

- It is quite ugly Scheme code, but that bit I could improve myself quite easily.

- I am pretty sure I did not do it “the right way” by defining an engraver.

- I did not find an easy way (which is most likely related to the previous point) to detect the right events I wanted to be listening to, so there is quite a lot of machinery to not repeat the same things several times per bar.

- The handling of alternatives seems very ad hoc, and the code always assumes that we repeat twice.

Would you have pointers to help me write a cleaner more efficient version?

Also, I would want to not print one bar number but all the bar numbers within the repeat. If the first eight bars are repeated, I would like to print 1 9, 2 10, 3 11, etc. This is less a priority for me but I guess it is linked to the same problem. Would you have pointers for that too?

Thank you in advance for your time!

Best regards,
— Nicolas “Niols” Jeannerod

#(define-public (Repeat_bar_number_skip_engraver context)
  (make-engraver
   (listeners
    (
      (StreamEvent engraver event)
      (let* ((cbn  (ly:context-property context 'currentBarNumber))
             (mp   (ly:context-property context 'measurePosition))
             (mp   (if (eq? mp '()) '() (ly:moment-main-numerator mp)))
             (rc   (ly:context-property context 'repeatCommands))
             (h-rc (not (null? rc)))
             (srbn (ly:context-property context 'startRepeatBarNumbers))
             (lrec (ly:context-property context 'lastRbnskEngraverCall))
             (trec (list cbn mp rc)))
       (if (equal? trec lrec)
        (display "")
        (begin
         ;; Iter on all repeat commands. Remember if we see a volta;
         ;; because if we see a end-repeat followed by a volta, it means
         ;; we are in an alternative where, for some reason, the measure
         ;; number is that of the beginning of the measure.
         ;;
         (let ((s #f)(v #f))
          (map
           (lambda (r)
            (if (eq? r 'start-repeat)
             (begin
              ;; For each start of a repeat, we push the current bar
              ;; number on the stack startRepeatBarNumbers
              ;;
              (set! s #t)
              (set! srbn (cons cbn srbn)))

             (if (eq? r 'end-repeat)
              (begin
               ;; For each end of a repeat, we pop the opening of it,
               ;; and we make the current bar number jump by the
               ;; difference. In case of volta previously seen, we have
               ;; to add one.
               ;;
               ;; FIXME: figure out why exactly.
               ;; FIXME: handle partials nicely
               ;; FIXME: handle repeats more than twice
               ;;
               (if s
                (display "")
                (begin
                 ;; Update current bar number by adding the number of
                 ;; bars in the repeat.
                 ;; Add 1 more if we are in an alternative.
                 ;; Add 1 more if we are in a partial measure.
                 (set! cbn (+ cbn (- cbn (car srbn))))
                 (set! cbn (+ cbn (if v 1 0)))
                 (set! cbn (+ cbn (if (= mp 0) 0 1)))
                 ;; Pop from the list
                 (set! srbn (cdr srbn)))))
              (begin
               (set! v #t)))))
           rc))
         (let ((trec (list cbn mp rc)))
          (ly:context-set-property! context 'currentBarNumber cbn)
          (ly:context-set-property! context 'startRepeatBarNumbers srbn)
          (ly:context-set-property! context 'lastRbnskEngraverCall trec))
       )))))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]