Re: arbitrary repeat counter
On 06/06/2022 14:10, David Kastrup wrote: Ah. So now if you do a relative repeat, the contents of the braces are converted to absolute before the unfold? That's neat. It never used to be like that, Han Wen wrote that "reset octave" thingy for me yonks ago (2.4?) because I ran in to that very problem. Unfolded repeats worked via an iterator (and thus were not having the \relative problem since the music is not being duplicated) as early as 1.5.66 whereas the first occurence of resetRelativeOctave appears to be 2.9.8. You probably were thinking about a different problem. Well, I'm pretty certain the piece of music was Pennsylvania 65-000, and I remember Han-Wen writing it specifically for me. I can't remember the first version of lilypond I used, but the fact it first appeared in lilypond proper much later makes sense - I know I posted it back to the list on at least one occasion. Aha - I've found the music, and yes, it's not quite the same problem ... also, no surprise, the music has a "version 2.8.2" statement at the top, and my function is called "resetOctave". It's a phrase that's repeated in voltas, so I need to reset relative pitch when I use the phrase. So very similar, but not quite the same :-) Cheers, Wol
Re: arbitrary repeat counter
Wols Lists writes: >> What do you mean? Something like >> \relative { >> \repeat unfold 2 { c' g' } >> } >> gives the attached output. As you can see, notes are made >> relative in order without taking the repeat into account, >> so both repeats play at the same octave. This is not >> equivalent to >> \relative { >> c' g' c' g' >> } >> > Ah. So now if you do a relative repeat, the contents of the braces are > converted to absolute before the unfold? That's neat. > > It never used to be like that, Han Wen wrote that "reset octave" > thingy for me yonks ago (2.4?) because I ran in to that very problem. Unfolded repeats worked via an iterator (and thus were not having the \relative problem since the music is not being duplicated) as early as 1.5.66 whereas the first occurence of resetRelativeOctave appears to be 2.9.8. You probably were thinking about a different problem. -- David Kastrup
Re: arbitrary repeat counter
On 06/06/2022 11:46, Jean Abou Samra wrote: Le 06/06/2022 à 12:17, Wols Lists a écrit : On 01/06/2022 18:03, Simon Bailey wrote: Here's a weird one. Using this definition in the c,-octave, I get a really weird output. Each note in the music drops down an octave. In the c-octave, it works normally. Using the untagged version of \repeatCounting doesn't show this issue in either octave. Any ideas? No ideas what's causing the difference in behaviour, but if you need to fix it, there's the "reset ocatave" command, whatever the exact syntax is. I've already provided a fix for this code. Didn't you receive that message? It's archived here: https://lists.gnu.org/archive/html/lilypond-user/2022-06/msg00039.html Specifically written for relative-mode repeats where the first and last notes are a fifth or more apart, and give you that exact effect ... What do you mean? Something like \relative { \repeat unfold 2 { c' g' } } gives the attached output. As you can see, notes are made relative in order without taking the repeat into account, so both repeats play at the same octave. This is not equivalent to \relative { c' g' c' g' } Ah. So now if you do a relative repeat, the contents of the braces are converted to absolute before the unfold? That's neat. It never used to be like that, Han Wen wrote that "reset octave" thingy for me yonks ago (2.4?) because I ran in to that very problem. Cheers, Wol
Re: arbitrary repeat counter
Le 06/06/2022 à 12:17, Wols Lists a écrit : On 01/06/2022 18:03, Simon Bailey wrote: Here's a weird one. Using this definition in the c,-octave, I get a really weird output. Each note in the music drops down an octave. In the c-octave, it works normally. Using the untagged version of \repeatCounting doesn't show this issue in either octave. Any ideas? No ideas what's causing the difference in behaviour, but if you need to fix it, there's the "reset ocatave" command, whatever the exact syntax is. I've already provided a fix for this code. Didn't you receive that message? It's archived here: https://lists.gnu.org/archive/html/lilypond-user/2022-06/msg00039.html Specifically written for relative-mode repeats where the first and last notes are a fifth or more apart, and give you that exact effect ... What do you mean? Something like \relative { \repeat unfold 2 { c' g' } } gives the attached output. As you can see, notes are made relative in order without taking the repeat into account, so both repeats play at the same octave. This is not equivalent to \relative { c' g' c' g' } Best, Jean
Re: arbitrary repeat counter
On 01/06/2022 18:03, Simon Bailey wrote: Here's a weird one. Using this definition in the c,-octave, I get a really weird output. Each note in the music drops down an octave. In the c-octave, it works normally. Using the untagged version of \repeatCounting doesn't show this issue in either octave. Any ideas? No ideas what's causing the difference in behaviour, but if you need to fix it, there's the "reset ocatave" command, whatever the exact syntax is. Specifically written for relative-mode repeats where the first and last notes are a fifth or more apart, and give you that exact effect ... Cheers, Wol
Re: arbitrary repeat counter
mind. officially. blown. :D Thanks, Jean, for the additional input. I learnt some more ;) Happy weekending, sb On Wed, 1 Jun 2022 at 19:21, Jean Abou Samra wrote: > > Le 01/06/2022 à 19:03, Simon Bailey a écrit : > > Here's a weird one. Using this definition in the c,-octave, I get a > > really weird output. Each note in the music drops down an octave. In > > the c-octave, it works normally. Using the untagged version of > > \repeatCounting doesn't show this issue in either octave. > > Any ideas? > > > Ah, yes. Here's a definition that already works better: > > repeatCountingWithTags = #(define-music-function (n music) (index? > ly:music?) >#{ > << >\tag #'score \repeat unfold #n { $music } >\tag #'part \repeatCounting #n { $music \bar "!|" } > >> >#}) > > > Namely, it uses $music instead of #music. More details > are here: > https://extending-lilypond.readthedocs.io/en/latest/lily-and-scheme.html#hash-vs-dollar > and here: > https://extending-lilypond.readthedocs.io/en/latest/music.html#copying-music > Basically, for the sake of efficiency, all music functions > are allowed to mutate their input. When you do \variable > in LilyPond code, this actually makes a deep copy of the > content of the variable (at least if it's a music object). > That way, users don't have surprises with music objects > shared between several locations, and music functions can > freely mutate music objects they receive. What's happening > here is that in order to interpret the relative octaves, > \relative walks in the music and converts the pitches > to absolute as needed. In this case, the pitches end up > on the octave of "c,". After that's done on the first > part tagged with #'score, it's done again on the second > one, which shares identity with the first and thus contains > lots of "d,", which get interpreted by \relative as lowering > the octave at every note. > > Still, this isn't ideal because it doesn't work on something > like > > \repeatCountingWithTags n { d' d } > > as that translates to > > << >\tag #'score \repeat unfold n { d' d } >\tag #'part { [...] \repeat unfold n { [...] d' d } } > >> > > and the second time the music occurs is affected by the > relative octave that the first time left. Of course, you > can fix it by playing with the pitches yourself in the > Scheme code. It's much simpler, however, to rewrite > this definition so that the argument gets just once > into the output. Giving: > > > \version "2.23.9" > > #(define (Phrase_counter_engraver context) > (let ((count 1) > (count-here #f) > (spanner #f) > (spanner-to-end #f)) > (make-engraver >(listeners > ((measure-counter-event engraver event) > (cond > ((eqv? LEFT (ly:event-property event 'span-direction)) >(set! count 1)) > ((ly:event-property event 'mark-new-repeat #f) >(set! count-here #t) >((process-music engraver) > (if count-here > (let ((col (ly:context-property context 'currentCommandColumn))) > (set! spanner (ly:engraver-make-grob engraver > 'MeasureCounter '())) > (ly:spanner-set-bound! spanner LEFT col) > (if (> count 1) > (ly:grob-set-property! spanner 'text (number->string > count))) ;;; <== here > (set! count (1+ count) >(acknowledgers > ((bar-line-interface engraver grob source-engraver) > (if spanner-to-end > (let ((col (ly:context-property context > 'currentCommandColumn))) >(ly:spanner-set-bound! spanner-to-end RIGHT col) >(ly:engraver-announce-end-grob engraver spanner-to-end '()) >(set! spanner-to-end #f) >((stop-translation-timestep engraver) > (if spanner > (set! spanner-to-end spanner)) > (set! spanner #f) > (set! count-here #f) > > \layout { >\context { > \Staff > \consists #Phrase_counter_engraver >} > } > > newRepeatMarker = #(make-music 'MeasureCounterEvent 'mark-new-repeat #t) > > \defineBarLine "!|" #'("!|" "" " |") > > repeatCounting = > #(define-music-function (n music) (index? ly:music?) > #{ > \startMeasureCount > \repeat unfold #n { \newRepeatMarker #music } > #}) > > repeatCountingWithTags = #(define-music-function (n music) (index? > ly:music?) >#{ > \tag #'part \startMeasureCount > \repeat unfold #n { >\tag #'part \newRepeatMarker >$music > } >#}) > > > ebass = \relative c, { >\clef "bass_8" >d4. d8 r4 d8 r | r8 d r4 d f8 g | %45-46 >\repeatCountingWithTags 2 { d4. d8 r4 d8 r | r8 d r4 d8 r c4 | } >%\octaveCheck c, >d4. d8 r4 d8 r | r8 d r4 d f8 g | %45-46 >\repeatCounting 2 { d4. d8 r4 d8 r | r8 d r4 d8 r c4 | } > } > > ebassUp = \relative c { >\clef "bass" >d4. d8 r4 d8 r | r8 d r4 d f8 g | %45-46 >
Re: arbitrary repeat counter
Le 01/06/2022 à 19:03, Simon Bailey a écrit : Here's a weird one. Using this definition in the c,-octave, I get a really weird output. Each note in the music drops down an octave. In the c-octave, it works normally. Using the untagged version of \repeatCounting doesn't show this issue in either octave. Any ideas? Ah, yes. Here's a definition that already works better: repeatCountingWithTags = #(define-music-function (n music) (index? ly:music?) #{ << \tag #'score \repeat unfold #n { $music } \tag #'part \repeatCounting #n { $music \bar "!|" } >> #}) Namely, it uses $music instead of #music. More details are here: https://extending-lilypond.readthedocs.io/en/latest/lily-and-scheme.html#hash-vs-dollar and here: https://extending-lilypond.readthedocs.io/en/latest/music.html#copying-music Basically, for the sake of efficiency, all music functions are allowed to mutate their input. When you do \variable in LilyPond code, this actually makes a deep copy of the content of the variable (at least if it's a music object). That way, users don't have surprises with music objects shared between several locations, and music functions can freely mutate music objects they receive. What's happening here is that in order to interpret the relative octaves, \relative walks in the music and converts the pitches to absolute as needed. In this case, the pitches end up on the octave of "c,". After that's done on the first part tagged with #'score, it's done again on the second one, which shares identity with the first and thus contains lots of "d,", which get interpreted by \relative as lowering the octave at every note. Still, this isn't ideal because it doesn't work on something like \repeatCountingWithTags n { d' d } as that translates to << \tag #'score \repeat unfold n { d' d } \tag #'part { [...] \repeat unfold n { [...] d' d } } >> and the second time the music occurs is affected by the relative octave that the first time left. Of course, you can fix it by playing with the pitches yourself in the Scheme code. It's much simpler, however, to rewrite this definition so that the argument gets just once into the output. Giving: \version "2.23.9" #(define (Phrase_counter_engraver context) (let ((count 1) (count-here #f) (spanner #f) (spanner-to-end #f)) (make-engraver (listeners ((measure-counter-event engraver event) (cond ((eqv? LEFT (ly:event-property event 'span-direction)) (set! count 1)) ((ly:event-property event 'mark-new-repeat #f) (set! count-here #t) ((process-music engraver) (if count-here (let ((col (ly:context-property context 'currentCommandColumn))) (set! spanner (ly:engraver-make-grob engraver 'MeasureCounter '())) (ly:spanner-set-bound! spanner LEFT col) (if (> count 1) (ly:grob-set-property! spanner 'text (number->string count))) ;;; <== here (set! count (1+ count) (acknowledgers ((bar-line-interface engraver grob source-engraver) (if spanner-to-end (let ((col (ly:context-property context 'currentCommandColumn))) (ly:spanner-set-bound! spanner-to-end RIGHT col) (ly:engraver-announce-end-grob engraver spanner-to-end '()) (set! spanner-to-end #f) ((stop-translation-timestep engraver) (if spanner (set! spanner-to-end spanner)) (set! spanner #f) (set! count-here #f) \layout { \context { \Staff \consists #Phrase_counter_engraver } } newRepeatMarker = #(make-music 'MeasureCounterEvent 'mark-new-repeat #t) \defineBarLine "!|" #'("!|" "" " |") repeatCounting = #(define-music-function (n music) (index? ly:music?) #{ \startMeasureCount \repeat unfold #n { \newRepeatMarker #music } #}) repeatCountingWithTags = #(define-music-function (n music) (index? ly:music?) #{ \tag #'part \startMeasureCount \repeat unfold #n { \tag #'part \newRepeatMarker $music } #}) ebass = \relative c, { \clef "bass_8" d4. d8 r4 d8 r | r8 d r4 d f8 g | %45-46 \repeatCountingWithTags 2 { d4. d8 r4 d8 r | r8 d r4 d8 r c4 | } %\octaveCheck c, d4. d8 r4 d8 r | r8 d r4 d f8 g | %45-46 \repeatCounting 2 { d4. d8 r4 d8 r | r8 d r4 d8 r c4 | } } ebassUp = \relative c { \clef "bass" d4. d8 r4 d8 r | r8 d r4 d f8 g | %45-46 \repeatCountingWithTags 2 { d4. d8 r4 d8 r | r8 d r4 d8 r c4 | } \octaveCheck c d4. d8 r4 d8 r | r8 d r4 d f8 g | %45-46 \repeatCounting 2 { d4. d8 r4 d8 r | r8 d r4 d8 r c4 | } %\repeatCounting 2 { d4. d8 r4 d8 r | r8 d r4 d8 r c4 | } } \new StaffGroup << \new Staff \with { instrumentName = "Up" } \keepWithTag #'score \ebass \new Staff \with { instrumentName = "Low" } \keepWithTag #'part \ebass >> Best, Jean
Re: arbitrary repeat counter
Le 01/06/2022 à 18:19, Simon Bailey a écrit : Hi, On Wed, 1 Jun 2022 at 17:09, Jean Abou Samra - jean at abou-samra.fr wrote: What did not work? This is perfectly valid Scheme: (set! count (1+ count)) (set! counter (+ counter 1)) was giving an error message. Probably had some misaligned parentheses or other weirdness. I didn't know about (1+ var) ;) You're welcome. To be honest, and simplifying a bit, I had a year of unsuccessful attempts to grasp Scheme before Urs' Scheme tutorial made me learn as much of Scheme in 4 hours as I had learnt in a year, then another year without that kind of help to learn LilyPond internals, so if I've managed to write something that is similarly turning a year into 4 hours for you, I'm quite happy. Your readthedocs thing really helped; I still need to have a look at Urs' tutorial. I did some functional programming sometime at the beginning of the millenium, but 20yrs of OOP is a hard habit to break ;-) For what it's worth, while LilyPond's seldom uses it, Guile actually has an object-oriented layer. https://www.gnu.org/software/guile/manual/html_node/GOOPS.html You may find yourself liking that. This shows that OOP is or can be largely orthogonal to functional vs. imperative. A further definition: repeatCountingWithTags = #(define-music-function (n music) (index? ly:music?) #{ << \tag #'score \repeat unfold #n { #music } \tag #'part \repeatCounting #n { #music \bar "!|" } >> #}) ebass = \relative c { \clef bass \time 7/4 \repeatCountingWithTags 4 { c4. 8 r4 8 r c2. | d4. 4. 4 e2. | 1 r2 r4 | } } \new StaffGroup << \new Staff \with { instrumentName = "Score" } \keepWithTag #'score \ebass \new Staff \with { instrumentName = "Part" } \keepWithTag #'part \ebass and I get the attached output, which is exactly what I want. And it makes my input files so much easier to read and manage. Thanks ever so much for your help! Again, you're welcome. Best, Jean
Re: arbitrary repeat counter
Hi, On Wed, 1 Jun 2022 at 17:09, Jean Abou Samra - jean at abou-samra.fr wrote: > What did not work? This is perfectly valid Scheme: > > (set! count (1+ count)) (set! counter (+ counter 1)) was giving an error message. Probably had some misaligned parentheses or other weirdness. I didn't know about (1+ var) ;) > You're welcome. To be honest, and simplifying a bit, I had a > year of unsuccessful attempts to grasp Scheme before Urs' > Scheme tutorial made me learn as much of Scheme in 4 hours > as I had learnt in a year, then another year without that kind > of help to learn LilyPond internals, so if I've managed to write > something that is similarly turning a year into 4 hours for > you, I'm quite happy. Your readthedocs thing really helped; I still need to have a look at Urs' tutorial. I did some functional programming sometime at the beginning of the millenium, but 20yrs of OOP is a hard habit to break ;-) A further definition: repeatCountingWithTags = #(define-music-function (n music) (index? ly:music?) #{ << \tag #'score \repeat unfold #n { #music } \tag #'part \repeatCounting #n { #music \bar "!|" } >> #}) ebass = \relative c { \clef bass \time 7/4 \repeatCountingWithTags 4 { c4. 8 r4 8 r c2. | d4. 4. 4 e2. | 1 r2 r4 | } } \new StaffGroup << \new Staff \with { instrumentName = "Score" } \keepWithTag #'score \ebass \new Staff \with { instrumentName = "Part" } \keepWithTag #'part \ebass >> and I get the attached output, which is exactly what I want. And it makes my input files so much easier to read and manage. Thanks ever so much for your help! Kind regards, sb -- Do not meddle in the affairs of trombonists, for they are subtle and quick to anger.
Re: arbitrary repeat counter
Le 01/06/2022 à 18:04, Simon Bailey a écrit : On Wed, 1 Jun 2022 at 16:14, Jean Abou Samra wrote: 1. What is the duration of a measure dependent on the current time signature? In an engraver :-) (ly:context-property context 'measureLength) You can't get it in the music function, since timing is not established at that point (just think that the time signature could come from another element of a << >> construct, for example). Remember, though, that the time signature might change in the middle of the repeat. Thus it will be a bit more reliable to actually acknowledge the PercentRepeatCount grobs and increment a counter whenever you see one. I actually tried that and ran into scheme problems (incrementing a counter didn't seem to work). What did not work? This is perfectly valid Scheme: (set! count (1+ count)) In fact, it's in the code of my engraver. 2. How long is a given musical expression (in measures or beats)? (ly:music-length your-music) I think I might use your engraver ;) But I've definitely learnt more today. Thanks! You're welcome. To be honest, and simplifying a bit, I had a year of unsuccessful attempts to grasp Scheme before Urs' Scheme tutorial made me learn as much of Scheme in 4 hours as I had learnt in a year, then another year without that kind of help to learn LilyPond internals, so if I've managed to write something that is similarly turning a year into 4 hours for you, I'm quite happy. Best, Jean
Re: arbitrary repeat counter
On Wed, 1 Jun 2022 at 16:14, Jean Abou Samra wrote: > > 1. What is the duration of a measure dependent on the current time > > signature? > > In an engraver :-) > > (ly:context-property context 'measureLength) > > You can't get it in the music function, since timing is not > established at that point (just think that the time signature > could come from another element of a << >> construct, for > example). > > Remember, though, that the time signature might change > in the middle of the repeat. Thus it will be a bit > more reliable to actually acknowledge the PercentRepeatCount > grobs and increment a counter whenever you see one. I actually tried that and ran into scheme problems (incrementing a counter didn't seem to work). > > 2. How long is a given musical expression (in measures or beats)? > > (ly:music-length your-music) > I think I might use your engraver ;) But I've definitely learnt more today. Thanks! I did make one small change to your engraver: (if (> count 1) (ly:grob-set-property! spanner 'text (number->string count))) ;;; <== here So that it only prints the numbers for repeated phrases. Kind regards, sb -- Do not meddle in the affairs of trombonists, for they are subtle and quick to anger.
Re: arbitrary repeat counter
Le 01/06/2022 à 17:04, Simon Bailey a écrit : A bit more work and I now have the following: \version "2.23.9" #(set-object-property! 'phrase-length 'backend-type? integer?) #(define (counter-stencil grob) (let* ((counter (string->number (ly:grob-property grob 'text))) (phrase-length (ly:grob-property grob 'phrase-length))) (if (and (eq? (modulo counter phrase-length) 1) (>= counter phrase-length)) (ly:stencil-aligned-to (grob-interpret-markup grob (markup (number->string (ceiling (/ counter phrase-length) Y CENTER \defineBarLine "!|" #'("!|" "" "!|") repeatCounting = #(define-music-function (n bar-length phrase-length music) (index? ly:music? integer? ly:music?) #{ << \repeat unfold #n { #music \bar "!|" } { \set countPercentRepeats = ##t \hide PercentRepeat \override PercentRepeatCounter.phrase-length = #phrase-length \override PercentRepeatCounter.stencil = #counter-stencil \repeat percent #(* phrase-length n) { #bar-length } } >> #}) \new Staff \relative c' { \repeatCounting 4 s1 2 {c4 d e f | g f e d } \break c1 \time 7/4 \repeatCounting 4 s4*7 3 {c4 d e f r r r | g f e d r r r| c1 r2 r4 } } How can I find out the following two bits of information? 1. What is the duration of a measure dependent on the current time signature? In an engraver :-) (ly:context-property context 'measureLength) You can't get it in the music function, since timing is not established at that point (just think that the time signature could come from another element of a << >> construct, for example). Remember, though, that the time signature might change in the middle of the repeat. Thus it will be a bit more reliable to actually acknowledge the PercentRepeatCount grobs and increment a counter whenever you see one. 2. How long is a given musical expression (in measures or beats)? (ly:music-length your-music) Best, Jean
Re: arbitrary repeat counter
On Wed, 1 Jun 2022 at 15:50, Jean Abou Samra wrote: > I tested it with 2.22. There were some changes (by me) in > the internals of MeasureCounter in 2.23, so it needs to > be adapted a little: > I'll test that in a moment. > > I intend to wrap that in a music function that does all the override > > magic and will take the music as a parameter (maybe work out the > > phrase length from that, or pass it manually) and number of repeats. > > > > Yes, that works too. Good job :-) A bit more work and I now have the following: \version "2.23.9" #(set-object-property! 'phrase-length 'backend-type? integer?) #(define (counter-stencil grob) (let* ((counter (string->number (ly:grob-property grob 'text))) (phrase-length (ly:grob-property grob 'phrase-length))) (if (and (eq? (modulo counter phrase-length) 1) (>= counter phrase-length)) (ly:stencil-aligned-to (grob-interpret-markup grob (markup (number->string (ceiling (/ counter phrase-length) Y CENTER \defineBarLine "!|" #'("!|" "" "!|") repeatCounting = #(define-music-function (n bar-length phrase-length music) (index? ly:music? integer? ly:music?) #{ << \repeat unfold #n { #music \bar "!|" } { \set countPercentRepeats = ##t \hide PercentRepeat \override PercentRepeatCounter.phrase-length = #phrase-length \override PercentRepeatCounter.stencil = #counter-stencil \repeat percent #(* phrase-length n) { #bar-length } } >> #}) \new Staff \relative c' { \repeatCounting 4 s1 2 {c4 d e f | g f e d } \break c1 \time 7/4 \repeatCounting 4 s4*7 3 {c4 d e f r r r | g f e d r r r| c1 r2 r4 } } How can I find out the following two bits of information? 1. What is the duration of a measure dependent on the current time signature? 2. How long is a given musical expression (in measures or beats)? If I can work out those two problems, then I could get rid of the two extra parameters bar-length and phrase-length… Thanks, kind regards, sb -- Do not meddle in the affairs of trombonists, for they are subtle and quick to anger.
Re: arbitrary repeat counter
Le 01/06/2022 à 15:50, Simon Bailey a écrit : Hi Jean, thanks for that example. Is it supposed to print any numbers? It's not doing so in 2.23.9 (windows, frescobaldi). I tested it with 2.22. There were some changes (by me) in the internals of MeasureCounter in 2.23, so it needs to be adapted a little: \version "2.23.9" newRepeatMarker = #(make-music 'MeasureCounterEvent 'mark-new-repeat #t) repeatCounting = #(define-music-function (n music) (index? ly:music?) #{ \startMeasureCount \repeat unfold #n { \newRepeatMarker #music } #}) #(define (My_counter_engraver context) (let ((count 1) (count-here #f) (spanner #f) (spanner-to-end #f)) (make-engraver (listeners ((measure-counter-event engraver event) (cond ((eqv? LEFT (ly:event-property event 'span-direction)) (set! count 1)) ((ly:event-property event 'mark-new-repeat #f) (set! count-here #t) ((process-music engraver) (if count-here (let ((col (ly:context-property context 'currentCommandColumn))) (set! spanner (ly:engraver-make-grob engraver 'MeasureCounter '())) (ly:spanner-set-bound! spanner LEFT col) (ly:grob-set-property! spanner 'text (number->string count)) ;;; <== here (set! count (1+ count) (acknowledgers ((bar-line-interface engraver grob source-engraver) (if spanner-to-end (let ((col (ly:context-property context 'currentCommandColumn))) (ly:spanner-set-bound! spanner-to-end RIGHT col) (ly:engraver-announce-end-grob engraver spanner-to-end '()) (set! spanner-to-end #f) ((stop-translation-timestep engraver) (if spanner (set! spanner-to-end spanner)) (set! spanner #f) (set! count-here #f) \layout { \context { \Staff \consists #My_counter_engraver } } \new Staff \relative c' { \repeatCounting 4 { c4. 8 r4 8 r | d4. 4. 4 | 1 } } I've come up with a slightly different approach, that's not quite finished (and not as fancy as creating a new engraver): #(set-object-property! 'phrase-length 'backend-type? integer?) #(define (counter-stencil grob) (let* ((counter (string->number (ly:grob-property grob 'text))) (phrase-length (ly:grob-property grob 'phrase-length))) (if (and (eq? (modulo counter phrase-length) 1) (>= counter phrase-length)) (ly:stencil-aligned-to (grob-interpret-markup grob (markup (number->string (ceiling (/ counter phrase-length) Y CENTER \relative c' { \set countPercentRepeats = ##t \override PercentRepeatCounter.phrase-length = 4 \override PercentRepeatCounter.stencil = #counter-stencil \repeat percent 12 { c d e f } } I intend to wrap that in a music function that does all the override magic and will take the music as a parameter (maybe work out the phrase length from that, or pass it manually) and number of repeats. Yes, that works too. Good job :-) Best, Jean
Re: arbitrary repeat counter
Hi Jean, thanks for that example. Is it supposed to print any numbers? It's not doing so in 2.23.9 (windows, frescobaldi). I've come up with a slightly different approach, that's not quite finished (and not as fancy as creating a new engraver): #(set-object-property! 'phrase-length 'backend-type? integer?) #(define (counter-stencil grob) (let* ((counter (string->number (ly:grob-property grob 'text))) (phrase-length (ly:grob-property grob 'phrase-length))) (if (and (eq? (modulo counter phrase-length) 1) (>= counter phrase-length)) (ly:stencil-aligned-to (grob-interpret-markup grob (markup (number->string (ceiling (/ counter phrase-length) Y CENTER \relative c' { \set countPercentRepeats = ##t \override PercentRepeatCounter.phrase-length = 4 \override PercentRepeatCounter.stencil = #counter-stencil \repeat percent 12 { c d e f } } I intend to wrap that in a music function that does all the override magic and will take the music as a parameter (maybe work out the phrase length from that, or pass it manually) and number of repeats. Thanks, kind regards, sb On Wed, 1 Jun 2022 at 13:51, Jean Abou Samra wrote: > > Le 01/06/2022 à 12:25, Simon Bailey a écrit : > > Hi, > > > > with a little bit of digging through your manual, i have solved some > > of my questions: > > > > #(define (counter-stencil grob) > > (let* ((counter (ly:grob-property grob 'text))) ; get the value of > > the counter > > (ly:stencil-aligned-to > > (grob-interpret-markup grob > > (markup counter "!")) ; print the counter back with ! > > Y > > CENTER))) > > > > This basically replicates the behaviour of the regular percent counter > > and adds an exclamation mark. so now i can just add some if/mod/div > > magic and it should do what I want. Getting there… ;) > > > > Well, you have two possible approaches. The one you sketch above is > the backend approach: override the measure counter's alignment so > it aligns within the first measure rather than the whole span. > The other is the translation approach: arrange to create the > counter so that it has the right bound you want from the start. > I think that is simpler in this case, so I'd do something like > > \version "2.22.2" > > newRepeatMarker = #(make-music 'MeasureCounterEvent 'mark-new-repeat #t) > > repeatCounting = > #(define-music-function (n music) (index? ly:music?) > #{ > \startMeasureCount > \repeat unfold #n { \newRepeatMarker #music } > #}) > > #(define (My_counter_engraver context) > (let ((count 1) > (count-here #f) > (spanner #f) > (spanner-to-end #f)) > (make-engraver >(listeners > ((measure-counter-event engraver event) > (cond > ((eqv? LEFT (ly:event-property event 'span-direction)) >(set! count 1)) > ((ly:event-property event 'mark-new-repeat #f) >(set! count-here #t) >((process-music engraver) > (if count-here > (let ((col (ly:context-property context 'currentCommandColumn))) > (set! spanner (ly:engraver-make-grob engraver > 'MeasureCounter '())) > (ly:spanner-set-bound! spanner LEFT col) > (ly:grob-set-property! spanner 'count-from count) > (set! count (1+ count) >(acknowledgers > ((bar-line-interface engraver grob source-engraver) > (if spanner-to-end > (let ((col (ly:context-property context > 'currentCommandColumn))) > (ly:spanner-set-bound! spanner-to-end RIGHT col) > (ly:engraver-announce-end-grob engraver spanner-to-end '()) > (set! spanner-to-end #f) >((stop-translation-timestep engraver) > (if spanner > (set! spanner-to-end spanner)) > (set! spanner #f) > (set! count-here #f) > > \layout { >\context { > \Staff > \consists #My_counter_engraver >} > } > > \new Staff \relative c' { >\repeatCounting 4 { c4. 8 r4 8 r | d4. 4. 4 | 1 } > } > > > Best, > Jean > -- Do not meddle in the affairs of trombonists, for they are subtle and quick to anger.
Re: arbitrary repeat counter
Le 01/06/2022 à 12:25, Simon Bailey a écrit : Hi, with a little bit of digging through your manual, i have solved some of my questions: #(define (counter-stencil grob) (let* ((counter (ly:grob-property grob 'text))) ; get the value of the counter (ly:stencil-aligned-to (grob-interpret-markup grob (markup counter "!")) ; print the counter back with ! Y CENTER))) This basically replicates the behaviour of the regular percent counter and adds an exclamation mark. so now i can just add some if/mod/div magic and it should do what I want. Getting there… ;) Well, you have two possible approaches. The one you sketch above is the backend approach: override the measure counter's alignment so it aligns within the first measure rather than the whole span. The other is the translation approach: arrange to create the counter so that it has the right bound you want from the start. I think that is simpler in this case, so I'd do something like \version "2.22.2" newRepeatMarker = #(make-music 'MeasureCounterEvent 'mark-new-repeat #t) repeatCounting = #(define-music-function (n music) (index? ly:music?) #{ \startMeasureCount \repeat unfold #n { \newRepeatMarker #music } #}) #(define (My_counter_engraver context) (let ((count 1) (count-here #f) (spanner #f) (spanner-to-end #f)) (make-engraver (listeners ((measure-counter-event engraver event) (cond ((eqv? LEFT (ly:event-property event 'span-direction)) (set! count 1)) ((ly:event-property event 'mark-new-repeat #f) (set! count-here #t) ((process-music engraver) (if count-here (let ((col (ly:context-property context 'currentCommandColumn))) (set! spanner (ly:engraver-make-grob engraver 'MeasureCounter '())) (ly:spanner-set-bound! spanner LEFT col) (ly:grob-set-property! spanner 'count-from count) (set! count (1+ count) (acknowledgers ((bar-line-interface engraver grob source-engraver) (if spanner-to-end (let ((col (ly:context-property context 'currentCommandColumn))) (ly:spanner-set-bound! spanner-to-end RIGHT col) (ly:engraver-announce-end-grob engraver spanner-to-end '()) (set! spanner-to-end #f) ((stop-translation-timestep engraver) (if spanner (set! spanner-to-end spanner)) (set! spanner #f) (set! count-here #f) \layout { \context { \Staff \consists #My_counter_engraver } } \new Staff \relative c' { \repeatCounting 4 { c4. 8 r4 8 r | d4. 4. 4 | 1 } } Best, Jean
Re: arbitrary repeat counter
Hi, with a little bit of digging through your manual, i have solved some of my questions: #(define (counter-stencil grob) (let* ((counter (ly:grob-property grob 'text))) ; get the value of the counter (ly:stencil-aligned-to (grob-interpret-markup grob (markup counter "!")) ; print the counter back with ! Y CENTER))) This basically replicates the behaviour of the regular percent counter and adds an exclamation mark. so now i can just add some if/mod/div magic and it should do what I want. Getting there… ;) Kind regards, sb
Re: arbitrary repeat counter
Hi Jean, On Wed, 1 Jun 2022 at 10:04, Jean Abou Samra wrote: > How about doing it like this? > < SNIP SNIP SNIP> > << >\new Staff \unfoldRepeats \part >\new Staff \otherPart > >> Yeah, I know about unfoldRepeats. But using voltas in a part where they're not in a score is a big no-no. I realise it was given practice in some editions, but it just leads to confusion and panic in rehearsals. Also, simply unfolding the repeats does not solve the numbering issue ;) (indeed, \repeat volta 8 doesn't indicate that it gets repeated 8 times without adding some markup somewhere). Gould says on repeated sections: << Repeated section[s] in instrumental parts must correspond exactly with the layout of a score. Parts must have the same number of notated bars as a score and repeats must occur in identical places in all material, […] >> > Sadly, the extending manual isn't overly helpful. That's > the reason why I wrote > > https://extending-lilypond.readthedocs.io > > You may find it more useful. At any rate, it is definitely > more thorough. I'll bookmark that one right away. Thanks! Kind regards, sb -- Do not meddle in the affairs of trombonists, for they are subtle and quick to anger.
Re: arbitrary repeat counter
Le 01/06/2022 à 10:53, Simon Bailey a écrit : Hi, There's a handy snippet for counting repeated bars in the manual. But I'm running into limitations when for instance I'd like to have 2- or 4-bar sections that I'd like to count. Usage example: a bass guitar has a 4-bar riff that's repeated 8 times, but I can't use a volta repeat in the part because the rest of the ensemble doesn't have repeatable music; How about doing it like this? \version "2.22.2" part = { \repeat volta 8 { c'1 1 1 1 } } { \part } otherPart = { c'1 1 1 1 d'1 1 1 1 e'1 1 1 1 f'1 1 1 1 g'1 1 1 1 a'1 1 1 1 b'1 1 1 1 c'1 1 1 1 } << \new Staff \unfoldRepeats \part \new Staff \otherPart I'd like to print a counting number over the centre of the first bar of each phrase. For 2-bar phrases, using the example from the manual, I get the following, but the Counter is centred over the middle bar-line. Does anyone have a suggestion for some scheme magic I can investigate to calculate the X-offset to the centre of the first bar? \new Staff \relative c' { << { \set countPercentRepeats = ##t \hide DoublePercentRepeat \repeat percent 4 { s1*2} } \repeat unfold 4 { c4. 8 r4 8 r | d4. 4. 4 } >> } For 4-bar phrases, the best thing I've managed to come up with is this: \new Staff \relative c { \clef bass << \context Voice = "foo" { \repeat unfold 4 { r4 d8 r r f r4 | a8 r r g r a f r8 | r4 d'8 r r f, r4 | a8 r r g8 ~ g4 r | } } \context Voice = "foo" { \hide MultiMeasureRest \override Voice.MultiMeasureRestText.font-encoding = #'fetaText \override Voice.MultiMeasureRestText.font-size = #-2 s1*4 | R1^"(2)" s1*3 | R1^"(3)" s1*3 | R1-"(4)" s1*3 | } >> } but that's all a bit "manual" ;) I was thinking it may be possible to override the stencil for the PercentRepeatCounter and do some math on the current percent repeat count, but I have no idea how to: a) get the current repeat number b) replace a text-interface::print stencil I've just spent 2 hours digging through LSR and the exending lilypond manual, but that was a bit fruitless. Sadly, the extending manual isn't overly helpful. That's the reason why I wrote https://extending-lilypond.readthedocs.io You may find it more useful. At any rate, it is definitely more thorough. That said, if you use the suggestion above, the problem is solved without needing it at all ;-) I'm also wondering if there's any form of convention to show these repeated phrases – as a player, if I was given a part with these repeated phrases and no counting, I'd add the numbers in pencil and probably a flare to the final barline of each phrase. I'm open to suggestions ;) I don't know whether there is an established convention, but I would say it is definitely easier to follow the score if the repeat is condensed, especially for something repeated 8 times. On the other hand, it might be trickier to make it easy to jump to a specific bar number. Regards, Jean
arbitrary repeat counter
Hi, There's a handy snippet for counting repeated bars in the manual. But I'm running into limitations when for instance I'd like to have 2- or 4-bar sections that I'd like to count. Usage example: a bass guitar has a 4-bar riff that's repeated 8 times, but I can't use a volta repeat in the part because the rest of the ensemble doesn't have repeatable music; I'd like to print a counting number over the centre of the first bar of each phrase. For 2-bar phrases, using the example from the manual, I get the following, but the Counter is centred over the middle bar-line. Does anyone have a suggestion for some scheme magic I can investigate to calculate the X-offset to the centre of the first bar? \new Staff \relative c' { << { \set countPercentRepeats = ##t \hide DoublePercentRepeat \repeat percent 4 { s1*2} } \repeat unfold 4 { c4. 8 r4 8 r | d4. 4. 4 } >> } For 4-bar phrases, the best thing I've managed to come up with is this: \new Staff \relative c { \clef bass << \context Voice = "foo" { \repeat unfold 4 { r4 d8 r r f r4 | a8 r r g r a f r8 | r4 d'8 r r f, r4 | a8 r r g8 ~ g4 r | } } \context Voice = "foo" { \hide MultiMeasureRest \override Voice.MultiMeasureRestText.font-encoding = #'fetaText \override Voice.MultiMeasureRestText.font-size = #-2 s1*4 | R1^"(2)" s1*3 | R1^"(3)" s1*3 | R1-"(4)" s1*3 | } >> } but that's all a bit "manual" ;) I was thinking it may be possible to override the stencil for the PercentRepeatCounter and do some math on the current percent repeat count, but I have no idea how to: a) get the current repeat number b) replace a text-interface::print stencil I've just spent 2 hours digging through LSR and the exending lilypond manual, but that was a bit fruitless. I'm also wondering if there's any form of convention to show these repeated phrases – as a player, if I was given a part with these repeated phrases and no counting, I'd add the numbers in pencil and probably a flare to the final barline of each phrase. I'm open to suggestions ;) Thanks, kind regards, sb -- Do not meddle in the affairs of trombonists, for they are subtle and quick to anger.