bug-lilypond
[Top][All Lists]
Advanced

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

Re: Lilypond 2.19.82 with multiple voices seems to fail


From: Thomas Morley
Subject: Re: Lilypond 2.19.82 with multiple voices seems to fail
Date: Sun, 3 Mar 2019 11:43:41 +0100

Am So., 3. März 2019 um 08:18 Uhr schrieb Andrew Bernard
<address@hidden>:
>
> HI James,
>
> This elusive defect comes up a lot. See the User archives. I have seen in
> on Linux also,

Yep, me too. Though I'm surprised to see the problem on this fairly short score.

###############

Anyway, what _is_ the problem?

As far as I can tell, creating lots and lots of new contexts
overcharges lilypond. With some OS earlier, with Linux obviously
later.
Lots and lots of contexts may be created by excessive use of << \\ >>
or (rarely) by some user-defined procedure.

Look at this short example, where I coded an engraver to display
contexts-info, duplicated contexts are discarded!

#(define (my-engraver ctx)
  (let ((new-contexts '()))
     `(
       (listeners
        (AnnounceNewContext
          .
          ,(lambda (engraver event)
            (set! new-contexts (cons event new-contexts)))))
       (finalize
        .
        ,(lambda (trans)
          (let ((ctx-type-id
                  (map
                    (lambda (c)
                      (let ((creator (ly:event-property c 'creator)))
                        (list
                          (ly:event-property creator 'type)
                          (ly:event-property creator 'id))))
                    (delete-duplicates (reverse new-contexts)))))
          (format #t
"\nInside this score ~a new contexts are created. Type and id are:\n~y"
            (length ctx-type-id)
            ctx-type-id)))))))

\score {
  {
    << c''1 \\ c' >>
    R1
    << d''1 \\ d' >>
  }
  \layout {
    \context {
      \Score
      \consists \my-engraver
    }
  }
}

It returns:

Inside this score 6 new contexts are created. Type and id are:
((Staff "")
 (Voice "1")
 (Voice "2")
 (Voice "")
 (Voice "1")
 (Voice "2"))

And this music is close to minimal !!!

Applying the same engraver to the OP's original code returns:

Inside this score 56 new contexts are created. Type and id are:
((PianoStaff "")
 (Staff "upper")
 (Dynamics "dyn")
 (Staff "lower")
 (Voice "")
 (Voice "")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2")
 (Voice "1")
 (Voice "2"))

###############

What does the docs say?

From
http://lilypond.org/doc/v2.19/Documentation/notation/multiple-voices#single_002dstaff-polyphony
"
The double backslash construct

The << {…} \\ {…} >> construct, where the two (or more) expressions
are separated by double backslashes, behaves differently to the
similar construct without the double backslashes: all the expressions
within this construct are assigned to new Voice contexts. These new
Voice contexts are created implicitly and are given the fixed names
"1", "2", etc.
[...]
This syntax can be used where it does not matter that temporary voices
are created and then discarded.
[...]
In all but the simplest works it is advisable to create explicit Voice
contexts as explained in Contexts and engravers and Explicitly
instantiating voices.
"

Imho, it's all there:
<< \\ >> creates _new_ Voices.
Use it where it _does not matter_
Recommended are explicit Voices.

Can it be improved?
Not sure. Opinions?

####################

Suggestions/sollutions

(1) Use explicit Voices, meaning enter the entire music of a Voice in
a (named) Voice, kept alive, and finally join it in a Staff in \score
I'm aware some people want to keep measures (with all Voices)
together, << \\ >> is a bad way to do so, though.
Instead one could use:

(2) \parallelMusic
See:
http://lilypond.org/doc/v2.19/Documentation/notation/multiple-voices#writing-music-in-parallel

(3)
If one really, really wants to keep the << \\ >> construct a method
could be to explicitely create Voices named "1" and "2" and keep them
alive.
In the OP's score that would make for this \score:

\score {
  \new PianoStaff \with { instrumentName = #"Piano" }
  <<
    \new Staff = "upper"
    <<
        \new Voice = "1" { s2.*29 s1*25 }
        \new Voice = "2" { s2.*29 s1*25 }
        \rhnotes
    >>
    \new Dynamics = "dyn" \dynam
    \new Staff = "lower"
    <<
        \new Voice = "1"{ s2.*29 s1*25 }
        \new Voice = "2"{ s2.*29 s1*25 }
        \lhnotes
    >>
  >>
  \layout {
    \context {
      \Score
      %\consists \my-engraver
    }
  }
  \midi { }
}

Applying my engraver returns:
Inside this score 12 new contexts are created. Type and id are:
((PianoStaff "")
 (Staff "upper")
 (Voice "1")
 (Voice "2")
 (Dynamics "dyn")
 (Staff "lower")
 (Voice "1")
 (Voice "2")
 (Voice "")
 (Voice "")
 (Voice "1")
 (Voice "2"))

A significant reduction of the created Voices!
I didn't research why (Staff "lower") still has two instants of (Voice
"1") and (Voice "2"). Too lazy ... ;)
Does it help?


Cheers,
  Harm



reply via email to

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