lilypond-user
[Top][All Lists]
Advanced

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

Re: Controlling hairpin length


From: Thomas Morley
Subject: Re: Controlling hairpin length
Date: Tue, 19 Jan 2016 23:00:48 +0100

2016-01-19 13:53 GMT+01:00 David Sumbler <address@hidden>:
> On Tue, 2016-01-19 at 01:27 +0100, Thomas Morley wrote:
>> 2016-01-19 1:04 GMT+01:00 Thomas Morley <address@hidden>:
>> > Hi David,
>> >
>> > 2016-01-18 22:56 GMT+01:00 David Sumbler <address@hidden>:
>> >
>> >> After spending some hours trying to get to the bottom of this problem,
>> > [...]
>> >
>> > Well, I spend some hours creating the function(s) ;)
>> >
>> >> I narrowed it down to 3 different elements in my files
>> > [...]
>> >> I feel
>> >> that ideally an improvement in an area where Lilypond is somewhat
>> >> unsatisfactory (so far as the user is concerned) should not at the same
>> >> time break some other aspect(s) of the program's output,
>> >
>> > Indeed.
>> > Though I can't fix a problem which I didn't foresee or which wasn't 
>> > reported.
>> > Thus, thanks for your examples.
>> >
>> > Please replace
>> > #(define ((hairpin-minimum-length my-minimum) grob)
>> > ...
>> >
>> > with the code below:
>> >
>> > #(define ((hairpin-minimum-length my-minimum) grob)
>> >   (let* ((bound-left (ly:spanner-bound grob LEFT))
>> >          (bound-right (ly:spanner-bound grob RIGHT))
>> >          (sys (look-up-for-parent 'System Y grob))
>> >          (left-x-ext (ly:grob-extent bound-left sys X))
>> >          (right-x-ext (ly:grob-extent bound-right sys X)))
>> >     (ly:grob-set-property! grob 'minimum-length
>> >       ;; keep 'minimum-length user-settable
>> >       (max (ly:grob-property-data grob 'minimum-length)
>> >            ;; nb, this calculation is only an approximation
>> >            ;; should work in most cases, though
>> >            (+ my-minimum
>> >               (max (cdr left-x-ext) 0)
>> >               (max (cdr right-x-ext) 0))))))
>>
>> Probably even better:
>>
>> #(define ((hairpin-minimum-length my-minimum) grob)
>>   (let* ((bound-left (ly:spanner-bound grob LEFT))
>>          (bound-right (ly:spanner-bound grob RIGHT))
>>          (sys (look-up-for-parent 'System Y grob))
>>          (left-x-ext (ly:grob-extent bound-left sys X))
>>          (right-x-ext (ly:grob-extent bound-right sys X)))
>>     (ly:grob-set-property! grob 'minimum-length
>>       ;; keep 'minimum-length user-settable
>>       (max (ly:grob-property-data grob 'minimum-length)
>>            ;; nb, this calculation is only an approximation
>>            ;; should work in most cases, though
>>            (+ my-minimum
>>               (if (interval-sane? left-x-ext) (cdr left-x-ext) 0)
>>               (if (interval-sane? right-x-ext) (cdr right-x-ext) 0))))))
>>
>> >
>> > Please report back, whether it works now.
>> >
>> > Cheers,
>> >   Harm
>
> Thank you for accepting my comments about the usability of
> \myHairpinMinimumLength in the spirit that was intended.
>
> I can report that both of the new versions produce no errors.
>
> However, I am still having a problem with the following bar:
>
> g8\< g a g fs4\mf\> r\invP |
>
> where invP = \tweak stencil ##f \p
>
> This gives a "decrescendo too small" warning, with the all too familiar
> vertical line in place of a hairpin, if myHairpinMinimumLength is set to
> a value of less than 3.
>
> Yet in the very next bar:
>
> b,8\mp as\< b cs as--\> b\! r4 |
>
> the diminuendo is unnecessarily long (approximately 5.5 staff spaces
> with the variable set to #2), forcing the final two quavers apart.
>
> I note that in the comments you say "nb, this calculation is only an
> approximation; should work in most cases, though".  But from the above 2
> bars it appears that the printed length of a hairpin can be at least 2.5
> staff spaces shorter or longer than the requested length.  This means
> that the length of individual hairpins may need to be tweaked - which is
> the same problem that we have with the built in Hairpin.minimum-length .
>
> David
>

Well, `minimum-length' is a beasty thing ...

Please try the code below. I paste the complete one plus examples,
because it's changed more than only improve some calculations.
`myHairpinMinimumLength' is now an override reading `minimum-length'
from a separate override or taking the default.

\version "2.19.35"

\language "english"

%% a helper:
#(define (look-up-for-parent name-symbol axis grob)
"Return the parent of @var{grob}, specified by it's @var{name-symbol} in
axis @var{axis} of @var{grob}.  If @var{grob} is already equal to the grob
named @var{name-symbol} return @var{grob}.  If not found, look up for the next
parent."
 (let* ((parent (ly:grob-parent grob axis)))
 (cond
   ((not (ly:grob? parent))
    (ly:error
       (_"Perhaps typing error for \"~a\" or \"~a\" is not in the parent-tree.")
       name-symbol name-symbol))
   ((equal? name-symbol (grob::name grob)) grob)
   ((not (equal? name-symbol (grob::name parent)))
    (look-up-for-parent name-symbol axis parent))
   (else parent))))

#(define (my-hairpin-minimum-length grob)
"Sets @code{minimum-length} for @code{Hairpin}, if their left bound is not the
@code{NoteColumn}.
The visible length is actually the one, specified by an additional override for
@code{minimum-length} or the default.
If left bound is @code{NoteColumn}, default or specified @code{minimum-length}
will take over."
  (let* ((bound-left (ly:spanner-bound grob LEFT))
         (sys (look-up-for-parent 'System Y grob))
         (left-x-ext (ly:grob-extent bound-left sys X))
         (not-note-column?
           (lambda (g)
             (not (and (ly:grob? g)
                       (grob::has-interface g 'note-column-interface))))))
     (if (not-note-column? bound-left)
         (ly:grob-set-property! grob 'minimum-length
           (+
              (* (if (interval-sane? left-x-ext) (cdr left-x-ext) 1)
                 (ly:grob-property-data grob 'bound-padding))
              (ly:grob-property-data grob 'minimum-length)
              (if (interval-sane? left-x-ext) (cdr left-x-ext) 0))))))

%% `myHairpinMinimumLength' tries to warrant the visible length of a Hairpin
%% to be not less than the value of `minimum-length'
myHairpinMinimumLength =
  \override Hairpin.before-line-breaking = #my-hairpin-minimum-length

\layout {
  \context {
    \Voice
    \myHairpinMinimumLength
    %% default for 'minimum-length is #2
    %% try different values
    \override Hairpin.minimum-length = #2
  }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

{
  \repeat unfold 3 { c4\ffff\> d\pppp c d \noBreak }
  \break
  \override Hairpin.minimum-length = 20
  \repeat unfold 3 { c4\ffff\> d\pppp c d \noBreak }
}

{ g8 g a g fs4\mf\> r-\tweak stencil ##f \p | }

{ g8 g a g fs4\mf\> r\p | }

{ b,8\mp as\< b cs as--\> b\! r4 | }

\parallelMusic #'(A B C D) {
        g8\< a b cs( ~ cs\mf\> b) d,\mp cs |
        g8\< g a g fs4\mf\> r\! |
        d8\< e fs e as,(\mf\> b) r4\! |
        e2\< d4\mf\> fs8(--\mp fs)-- |
}

\new StaffGroup <<
  \new Staff \A
  \new Staff \B
  \new Staff \C
  \new Staff \D
>>

\new Staff \A
\new Staff \B
\new Staff \C
\new Staff \D

\parallelMusic #'(P Q S T) {
    << b1\fermata {s2..\> s8\!} >> |
    << c1\fermata {s2..\> s8\!} >> |
    << e1\fermata {s2..\> s8\!} >> |
    << b1\fermata {s2..\> s8\!} >> |
}

\new StaffGroup <<
  \new Staff \P
  \new Staff \Q
  \new Staff \S
  \new Staff \T
>>

\new Staff \P
\new Staff \Q
\new Staff \S
\new Staff \T



HTH,
  Harm



reply via email to

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