Hi Han-Wen,
Got it, thanks! I will attach the example file here as your reply didn't
include it.
________________________________
发件人: Han-Wen Nienhuys <[email protected]>
发送时间: 2020年5月4日 17:21
收件人: Chen Leo <[email protected]>; lilypond-devel <[email protected]>
主题: Re: Request for Big Time Signature
Hi Leo,
thanks for your kind words. I'm focusing my limited time on LilyPond
infrastructure, so I can't help you here, but I hope someone else from
the development community can. I took the liberty of including them on
this reply.
On Mon, May 4, 2020 at 6:37 AM Chen Leo <[email protected]> wrote:
>
> Hi Han-Wen,
>
> I am a new lilypond user and I have been using lilypond for a few months now.
> I want to say that I love the experience (especially the way lilypond
> automatically handles all the collisions and alignment problems with great
> accuracy). I want to thank the development team for creating such amazing
> software.
>
> One personal suggestion would be that I think lilypond can benefit from
> implementing more contemporary notations e.g. more symbols and noteheads (I
> was happy to hear that lilypond is considering adopting the SMuFL font
> format). For most of the notation problems I have encountered, I was able to
> solve by copying and modifying different snippets, thanks to the great
> lilypond community. However, there’s one specific problem that I can’t seem
> to find a solution to, even with the help of several lilypond users.
>
> The problem is to put large time signatures on top of (or in between) staves,
> it is commonly used in a lot of contemporary scores which often feature
> constant changes in time structures. In these situations, using this layout
> will make the score look a lot clearer and save much horizontal space.
>
> I found
> http://lsr.di.unimi.it/LSR/Snippet?id=272
> which seems like a perfect solution initially. However, soon I was able to
> find several problems with this snippet. (I will give examples for all of the
> problems in the attached file)
> 1a. Time signatures get aligned to cue clefs instead of the bar line whenever
> a clef change is made at the end of the bar.
> 1b. Time signatures appear twice when one staff has a grace note as the first
> note in a bar while other staves do not.
> 1c. Space is not allotted for the cautionary time signatures before line
> breaks so they always cross the left margin.
> 1d. shift-right-at-line-begin has a fixed X-offset value of 3.5 units, this
> means that if the user decides to change the clef font size or to use an
> alternative font the X-offset value won’t automatically change according to
> the width of the clef symbol.
>
> I tried another approach afterward, which is to use
> \override TimeSignature.break-align-symbol = #'staff-bar
> This successfully solves problems 1 3 and 4 yet it also starts to cause more
> problems since other staves are now aware of the time signature’s horizontal
> space. The problems are:
> 2a. Parts of hairpins and spanners are missing below the time signatures
> after a line break.
> 2b. Lilypond pushes everything to the left when \textLengthOn commands are
> used on text script objects below the time signature.
> 2c. Same as problem 1b from the original snippet.
> 2d. Bar numbers are raised to the same height as the time signatures' dummy
> staff while it should display on the top music staff. This problem can be
> solved by removing "Bar_number_engraver" from the Score context and consists
> of it only in the actual top staff’s context. Though this can cause some
> problems if the user chooses to hide staves that don’t have a part in a
> section of music and the top staff also happens to be one of the hidden
> staves.
>
> After a long discussion, a kind lilypond user named Kevin Barry was able to
> provide me with a solution that he thinks is somewhat “hacky” while it solves
> problem 2a and 2c quite well. He wrote a custom engraver that replaces all
> TimeSignature objects with TextScript objects except at the end of lines so
> that space can be allotted for the cautionary time signatures (I’ve also
> included his approach in the attached file). Problem 2b and 2d remain
> unsolvable. Because the only solution to problem 2b is to set TextScript’s
> extra-spacing-width property to #'(+inf.0 . -inf.0) while that means bars are
> no longer sensitive to the TextScript objects’ width, it causes collisions
> when time signatures exceed the barline. I wasn’t able to solve problem 2d as
> well.
>
> Eventually, I decided to contact someone from the development team and I
> found you.
> I hope that this can be improved and made into a snippet (or even better if
> this gets implemented into lilypond in future versions) as using large time
> signatures is really quite common in contemporary ensemble pieces.
>
> Here are some examples of how this layout can look like in different scores.
>
> Most scores have the time signatures vertically centered. e.g.
> Pierre Boulez - Répons
> https://www.youtube.com/watch?v=9aa8ogiwEV4
> Tristan Murail - La Barque Mystique
> https://www.youtube.com/watch?v=Te-R0eETD0c
>
> While some scores do not. e.g.
> Tōru Takemitsu - Rain Coming
> https://www.youtube.com/watch?v=YnaztoAdgWk
> Toshio Hosokawa �C Vertical Song I
> https://www.youtube.com/watch?v=Ji0gxsRp71M
>
> I hope that both options can be considered.
>
> Any help will be greatly appreciated!
>
> Best wishes,
> Leo
\version "2.20.0"
% custom engraver by Kevin Barry
#(define (Time_signature_markup_engraver context)
(let ((time-sig '())
(time-sig-copy #f)
(previous-was-grace #f)) ; to avoid printing twice at grace notes
(make-engraver
(acknowledgers
((time-signature-interface engraver grob source-engraver)
(let* ((current-moment (ly:context-current-moment context))
(grace-nom (ly:moment-grace-numerator current-moment)))
(if (not (eqv? 0 grace-nom))
(begin
(set! previous-was-grace #t)
(set! time-sig grob))
(if (and (eqv? 0 grace-nom) previous-was-grace)
(begin
(set! previous-was-grace #f)
(set! time-sig '()))
(set! time-sig grob))))))
((process-acknowledged engraver)
(and (not (null? time-sig))
(let* ((time-sig-copy (ly:engraver-make-grob
engraver
'TextScript
time-sig))
(copy-prop (lambda (prop)
(ly:grob-set-property!
time-sig-copy
prop
(ly:grob-property time-sig prop))))
(timing-context (ly:context-find context 'Timing))
(timing-time-sig
(ly:context-grob-definition timing-context 'TimeSignature))
(timing-time-sig-stencil
(ly:assoc-get 'stencil timing-time-sig '()))
(prop-list '(fraction
style
font-size
extra-spacing-width
cause)))
(map copy-prop prop-list)
(ly:grob-set-property! time-sig-copy 'stencil
timing-time-sig-stencil)
(ly:grob-set-parent! time-sig-copy Y time-sig)
(ly:grob-set-parent! time-sig-copy X time-sig)
(set! time-sig '())
)))
((stop-translation-timestep engraver)
(set! time-sig-copy #f)))))
#(define (remove-except-at-line-end grob)
(if (not (equal? (ly:item-break-dir grob) LEFT))
(ly:grob-set-property! grob 'stencil #f)))
#(define (remove-at-end grob)
(if (equal? (ly:item-break-dir grob) LEFT)
(ly:grob-set-property! grob 'stencil #f)))
#(define (center-over-barline grob)
(if (equal? (ly:item-break-dir grob) 0)
(let* ((x-extent (ly:grob-property grob 'X-extent))
(width (interval-length x-extent)))
(ly:grob-set-property! grob 'X-offset (* -1 (/ width 2))))))
#(define (center-over-barline-and-remove-at-end grob)
(begin
(remove-at-end grob)
(center-over-barline grob)))
#(define (left-align-at-end grob)
(and (and (ly:item? grob)
(equal? (ly:item-break-dir grob) LEFT))
(ly:grob-set-property! grob 'self-alignment-X 1)))
% definition of shift-right-at-line-begin
#(define (shift-right-at-line-begin g)
"Shift an item to the right, but only at the start of the line."
(if (and (ly:item? g)
(equal? (ly:item-break-dir g) RIGHT))
(ly:grob-translate-axis! g 3.5 X)))
timeSignatures = {
\tempo 4 = 80
\time 4/4 s1
\time 3/8 s4.
\time 3/4 s2.
\time 4/4 s1
\time 2/4 \acciaccatura s8 s2
\compoundMeter #'((3 8) (1 16) (1 16) (1 16))
s4. s16 s16 s16
\time 4/4 s1
}
\paper {
top-margin = #15
bottom-margin = #15
left-margin = #15
right-margin = #15
system-system-spacing =
#`((basic-distance . 10)
(minimum-distance . 6)
(padding . 2)
)
}
\markup \column \fontsize #4 {
"Approach #1"
"(http://lsr.di.unimi.it/LSR/Snippet?id=272)"
}
\score {
\layout {
\context {
\Score
\override MetronomeMark.break-align-symbols = #'(staff-bar time-signature)
}
\context {
\Staff
\override MultiMeasureRest.spacing-pair = #'(break-alignment . staff-bar)
\override Clef.font-size = #5
\remove "Time_signature_engraver"
}
\context {
\Score
}
}
<<
\new Dynamics \with {
\consists "Time_signature_engraver"
\consists "Axis_group_engraver"
\override TimeSignature.font-size = #8
\override TimeSignature.break-align-symbol = ##f
\override TimeSignature.X-offset =
#ly:self-alignment-interface::x-aligned-on-self
\override TimeSignature.self-alignment-X = #LEFT
\override TimeSignature.after-line-breaking =
#shift-right-at-line-begin
\numericTimeSignature
}
{
\timeSignatures
}
\new StaffGroup <<
\relative c' {
\time 4/4
c4 ( ^"â Problem 1d"
d4 e4 f4 ) |
\time 3/8
a'4 ( g8 ) |
\time 3/4
R2.
^\markup {
\column {
"â Problem 1a"
"Problem 1c â"
" "
" "
}
} |
\time 4/4
c1 |
\time 2/4
a8 ^"â Problem 1b"
g8 f8 e8 |
\compoundMeter #'((3 8) (1 16) (1 16) (1 16))
a2 g16 |
\time 4/4
c4 c c c |
}
\relative c' {
\time 4/4
R1 |
\time 3/8
R4. |
\clef bass
\time 3/4
a,2. \> \startTextSpan |
\break
\time 4/4
c2 e2 \! \stopTextSpan |
\time 2/4
\acciaccatura f8 a8
g8 f8 e8 |
\compoundMeter #'((3 8) (1 16) (1 16) (1 16))
a2 g16 |
\time 4/4
c4 c c c |
}
>>
>>
} \pageBreak
\markup \column \fontsize #4 {
"Approach #2"
"(\override TimeSignature.break-align-symbol = #'staff-bar)"
}
\score {
\layout {
\context {
\Score
\override MetronomeMark.break-align-symbols = #'(staff-bar time-signature)
}
\context {
\Staff
\override MultiMeasureRest.spacing-pair = #'(break-alignment . staff-bar)
\override Clef.font-size = #5
\remove "Time_signature_engraver"
}
\context {
\Score
}
}
<<
\new Dynamics \with {
\consists "Time_signature_engraver"
\consists "Axis_group_engraver"
\override TimeSignature.font-size = #8
\override TimeSignature.break-align-symbol = #'staff-bar
\override TimeSignature.X-offset =
#ly:self-alignment-interface::x-aligned-on-self
\override TimeSignature.self-alignment-X = #LEFT
\numericTimeSignature
}
{
\timeSignatures
}
\new StaffGroup <<
\relative c' {
\time 4/4
\textLengthOn
c4 ( ^"â Problem 2b"
\textLengthOff
d4 e4 f4 ) |
\time 3/8
a'4 ( g8 ) |
\time 3/4
R2. |
\time 4/4
\override Score.RehearsalMark.X-offset = #-1.5
\mark "â Problem 2d"
c1 |
\time 2/4
a8 ^"â Problem 2c"
g8 f8 e8 |
\compoundMeter #'((3 8) (1 16) (1 16) (1 16))
a2 g16 |
\time 4/4
c4 c c c |
}
\relative c' {
\time 4/4
R1 |
\time 3/8
R4. |
\clef bass
\time 3/4
a,2. \> \startTextSpan |
\break
\time 4/4
c2 ^"â Problem 2a" _"â" e2 \! \stopTextSpan |
\time 2/4
\acciaccatura f8 a8
g8 f8 e8 |
\compoundMeter #'((3 8) (1 16) (1 16) (1 16))
a2 g16 |
\time 4/4
c4 c c c |
}
>>
>>
} \pageBreak
\markup \column \fontsize #4 {
"Approach #3"
"(custom engraver by Kevin Barry)"
}
\score {
\layout {
\context {
\Score
\override MetronomeMark.break-align-symbols = #'(staff-bar time-signature)
}
\context {
\Staff
\override MultiMeasureRest.spacing-pair = #'(break-alignment . staff-bar)
\override Clef.font-size = #5
\remove "Time_signature_engraver"
}
\context {
\Score
}
}
<<
\new Dynamics \with {
\consists "Time_signature_engraver"
\consists \Time_signature_markup_engraver
\override TimeSignature.font-size = #8
\override TimeSignature.before-line-breaking = #remove-except-at-line-end
\override TimeSignature.break-align-symbol = #'staff-bar
\override TextScript.before-line-breaking = #remove-at-end
%â The only solution to problem 2b but it causes collisions
%\override TextScript.extra-spacing-width = #'(+inf.0 . -inf.0)
\override TextScript.extra-spacing-width = #'(0 . 0.8)
\override TextScript.direction = #UP
\override TextScript.Y-offset = #0
\numericTimeSignature
}
{
\timeSignatures
}
\new StaffGroup <<
\relative c' {
\time 4/4
\textLengthOn
c4 ( ^"â Problem 2b"
\textLengthOff
d4 e4 f4 ) |
\time 3/8
a'4 ( g8 ) |
\time 3/4
R2. |
\time 4/4
\override Score.RehearsalMark.X-offset = #-1.5
\mark "â Problem 2d"
c1 |
\time 2/4
a8 g8 f8 e8 |
\compoundMeter #'((3 8) (1 16) (1 16) (1 16))
a2 g16 |
\time 4/4
c4 c c c |
}
\relative c' {
\time 4/4
R1 |
\time 3/8
R4. |
\clef bass
\time 3/4
a,2. \> \startTextSpan |
\break
\time 4/4
c2 e2 \! \stopTextSpan |
\time 2/4
\acciaccatura f8 a8
g8 f8 e8 |
\compoundMeter #'((3 8) (1 16) (1 16) (1 16))
a2 g16 |
\time 4/4
c4 c c c |
}
>>
>>
} \pageBreak