Autor Thema: Noten unter Ganztaktpause zentrieren  (Gelesen 3236 mal)

ewipond

  • Member
Noten unter Ganztaktpause zentrieren
« am: Sonntag, 6. November 2011, 16:20 »
Hallo zusammen,

ich schreibe gerade an einigen Arrangements von Schubert Liedern und in einem ersten Schritt habe ich versucht das Layout einer alten Peters-Ausgabe mit Lilypond nachzubilden. Es gibt da eine Sache, für die ich keine Lösung finde:

Wenn die Gesangsstimme pausiert, werden ganztaktige Klavierakkorde unter der Pause zentriert - oft am Ende der Lieder. Wenn ich versuche die Noten zu verschieben ( z.B mit NoteColumn X-offset) wird gleichzeitig der Takt breiter.
Gibt es dafür eine besser Lösung.

Gut zu sehen ist das beispielsweise am Ende des Doppelgängers - siehe Anhang.





Besten Dank

trulli

  • Member
Re: Noten unter Ganztaktpause zentrieren
« Antwort #1 am: Sonntag, 6. November 2011, 18:37 »
Hallo ewipond und herzlich Willkommen hier,

leg nächstes Mal den Code mit deiner Versionsnummer bei, dann kann man Fragen besser beantworten.

Könnte das helfen?

\override NoteColumn #'force-hshift = #-2
Gruß

harm6

  • Member
Re: Noten unter Ganztaktpause zentrieren
« Antwort #2 am: Sonntag, 6. November 2011, 20:46 »
Hallo,

ich habe früher schon mal nach einer Methode gesucht eine Note im Takt zu zentrieren. Allerdings ohne Erfolg. Heute bin ich auch nicht viel klüger. ;)

Mir will es aber so vorkommen, als ob Peters dem Taktstrich rechtsseitig einfach mehr Raum gegeben hat. Das läßt sich mittels 'extra-spacing-width recht einfach umsetzen. (->Erste Zeile).
In der zweiten Zeile habe ich noch eine andere Methode versucht. Dort habe ich die Noten verkürzt und mit spacern gearbeitet.

\version "2.14.2"

one = \relative c' {

        \repeat unfold 18 { R2. }
}

two = \relative c' {
                \time 3/4
       
        \override Staff . BarLine #'extra-spacing-width = #'(0.0 . 1.0)
        \override Staff . Clef #'extra-spacing-width = #'(0.0 . 5)
        \repeat unfold 9 { ceses2. }\break
        \revert Staff . BarLine #'extra-spacing-width
        \revert Staff . Clef #'extra-spacing-width
        s4  c'2.*1/3 s4
        \repeat unfold 8 { s4 s16 c2.*1/3 s8.}\break
}

\new StaffGroup <<
\new Staff \one
\new Staff \two
>>

Richtig gut ist das alles nicht. Es lassen sich Veränderungen beim spacing beobachten und Du wirst in einer richtigen Partitur sehr häufig die Werte verändern müssen. Aber vielleicht kannst Du ja doch was damit anfangen.

Gruß,
  Harm

P.S. Ist das eigentliche dieselbe Frage wie hier?

ewipond

  • Member
Re: Noten unter Ganztaktpause zentrieren
« Antwort #3 am: Montag, 7. November 2011, 17:36 »
ja danke für die Antworten,

@trulli: Ich verwende 2.15.16. Es gibt in der stabilen Version 2.14 noch einen bug, der alle \cresc und \decresc an den Lyrics orientiert, das ist bei Liedern etwas ungünstig.

ich hab nochmal weiter geforscht und es gibt vielleicht eine Möglichkeit, die Takte nach dem Verschieben der Note wieder zu verkürzen:
 \newSpacingSection   
 \override Score.SpacingSpanner #'base-shortest-duration =#(ly:make-moment 1 1 )

 Hier ein Beispiel:

\version "2.15.16"
\paper{
indent = 0\cm
ragged-right=##f}
   
\score {
 <<
    \new Staff {R1 *4  }
    \new Staff \relative c' { c16 d e f d4 e f |  g1

    \newSpacingSection
   
    \override Score.SpacingSpanner #'base-shortest-duration =#(ly:make-moment 1 1 )
    \override NoteColumn #'X-offset = #3.2

    f1  ^ " newSpacingSection "  | f   }
 >>

}


Die beiden Zahlen bei (ly:make-moment 1 1 ) werden offenbar als Quotient verrechnet,
(ly:make-moment 1 1 )  ist demnach identisch mit  (ly:make-moment 32 32 )  - mit der ersten Zahl kann man dann die Breite des Taktes genauer einstellen.

Aber das ist noch heftiges Neuland...

@harm6: Das Beispiel geht doch ganz gut. Ich wußte nicht, daß man Notendauern einfach multiplizieren kann..

Das Verschieben der Noten mit BarLine #'extra-spacing-width ist tatsächlich besser. Z.B geht NoteColumn #'force-hshift nicht mit einzelnen Noten und umgekehrt geht NoteColumn #'x-offset nicht mit polyphonen Akkorden. Um das Ausprobieren von Hand führt wohl kein Weg vorbei.


P.S. Ja, die Frage in der mailing-list ist tatsächlich von mir, aber irgendwie lausig formuliert - da gabs keine Resonanz

Beste Grüße

harm6

  • Member
Re: Noten unter Ganztaktpause zentrieren
« Antwort #4 am: Donnerstag, 10. November 2011, 01:54 »
Hallo,

ich hab' mal weiter an dem Problem gearbeitet.

Um zentrieren zu können muß man die BarLines davor und danach in die Berechnung einbeziehen.

Ich habe also ein neues property definiert, welches zur Markierung benutzt wird, sowie die Funktion \markBarLine, die das dann ausführt. Diese Idee stammt ursprünglich von Arnold.
Nach diesem Vorbild anschließend center-note-column um die NoteColumn zu zentrieren sowie die Funktion \centerNotes. Es ist ganz hilfreich das die NoteColumn nicht nur die Notenköpfe sondern auch die Notenhälse und Bögen bestimmt. Allerdings nicht die Punkte von punktierten Notenwerten und die Vorzeichen auch nicht. Insofern mußte ich DotColumn und AccidentalPlacement auch in \centerNotes und center-note-column einbeziehen.

Leider ist es mir nicht gelungen die Markierung der Taktstriche zu automatisieren. Das mag daran liegen, daß ein selbst gebautes property natürlich kein call-back, interface etc hat.
Ich habe es auch nicht geschafft \centerNotes und \markBarLine in eine einzige Funktion zu packen.

Anwendung:

Mit \markBarLine werden die Taktstriche markiert. Ich empfehle die Taktzahlen zu benutzen. Nach Takt eins kommt also \markBarLine #1 etc. Wichtig ist, daß immer vor und nach dem zu zentrierenden Objekt die Taktstriche markiert sind. Man braucht aber nur dort zu markieren, wo etwas zentriert werden soll, nicht etwa das ganze Stück.

Das erste Argument von \centerNotes ist dann die Taktzahl des Taktes der zentriert werden soll. Da manchmal doch noch nachträgliche Verbesserungen nötig sind habe ich eine Korrekturliste eingebaut:#'(0 0 0) gibt das default-Verhalten von \centerNotes aus. Der erste Wert kann die NoteColumn beeinflussen. Der zweite das AccidentalPlacement, der dritte die DotColumn.

Im Code habe ich all das in eine eigene Stimme gepackt.

\version "2.14.2"

#(define (define-grob-custom-property symbol type? description)
  (if (not (equal? (object-property symbol 'backend-doc) #f))
      (ly:error (_ "symbol ~S redefined") symbol))

  (set-object-property! symbol 'backend-type? type?)
  (set-object-property! symbol 'backend-doc description)
  symbol)

#(define all-user-grob-custom-properties
  (map
   (lambda (x)
     (apply define-grob-custom-property x))

   `(
     (markers ,list? "Tag marker(s) in grob for function center-between")
     )))
     
#(define ((center-note-column symbol tags extra-X-offset) grob)
   (let* ((refp (ly:grob-system grob))
          (all-grobs (ly:grob-array->list (ly:grob-object refp 'all-elements)))
          (grob-ext (ly:grob-extent grob refp X))
          (note-head (ly:grob-parent grob X))
          (note-head-ext (ly:grob-extent note-head refp X))
          (X-extent (lambda (q) (ly:grob-extent q refp X)))
          (targets (filter (lambda (q) (member tags (ly:grob-property q 'markers))) all-grobs)))

     (cond ((not (pair? targets)) (ly:programming-error (_ "no grobs marked ~S") tags))
           ((= (length targets) 1) (ly:programming-error (_ "only one grob marked ~S") tags))
           ((> (length targets) 2) (ly:programming-error (_ "more than two grobs marked ~S") tags))

           (else
             (begin
               (if (> (car (X-extent (car targets))) (car (X-extent (cadr targets))))
                   (set! targets (reverse targets)))
               (let ((left (if (> (cdr (X-extent (car targets)))
                                  (car (X-extent (cadr targets))))
                               (car (X-extent (car targets)))
                               (cdr (X-extent (car targets)))))
                     (right (car (X-extent (cadr targets)))))
                     
           (cond ((equal? symbol "NoteColumn")       
                  (ly:grob-translate-axis! grob
                     (+ (- (- (interval-center (X-extent grob))
                           (/ (+ left right) 2)))
                           extra-X-offset)
                     X))
                 ((equal? symbol "AccidentalPlacement")
                  (ly:grob-translate-axis! grob
                     (+ (- (- (interval-center (X-extent grob))
                           (/ (+ (- left (interval-length (interval-widen note-head-ext (/ (interval-length grob-ext) 1.5)))) right) 2)))
                           extra-X-offset)
                     X))
                 ((equal? symbol "DotColumn")
                  (ly:grob-translate-axis! grob
                    (+ (- (- (- (interval-center (X-extent grob)) (/ (interval-length note-head-ext) 2))
                          (/ (+ left right) 2)))
                          extra-X-offset)
                    X))
                 )
                 
                 ))))))

markBarLine =
#(define-music-function (parser location barnumber)(number?)
#{
        \once\override Staff.BarLine #'markers = #(list  $barnumber (+ $barnumber 1))
#})
                 
centerNotes =
#(define-music-function (parser location between? corr)(number? list?)
#{
         \once\override PianoStaff.NoteColumn #'after-line-breaking =
          #(center-note-column "NoteColumn" $between? $(car corr))
         
         \once\override PianoStaff.AccidentalPlacement #'after-line-breaking =
          #(center-note-column "AccidentalPlacement" $between? $(cadr corr))
         
         \once\override PianoStaff.DotColumn #'after-line-breaking =
          #(center-note-column "DotColumn" $between? $(caddr corr))
#})

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\paper {
        indent = 40
        ragged-right = ##f
}

voice = \relative c' {
        \key b\minor
        \time 3/4
b'2_"Zeit?" r4
R2.*6
R2.*1\fermataMarkup
\bar "|."
}

centerVoice = {
        \key b\minor
        \clef "bass"
%1
        s2.
        \markBarLine #1
%2     
        \centerNotes #2 #'(0 0 0)
        s 
        \markBarLine #2
%3
        \centerNotes #3 #'(0 0 0)
        s
        \markBarLine #3
%4
        \centerNotes #4 #'(0 0 0)
        s
        \markBarLine #4
%5
        \centerNotes #5 #'(-0.7 0 -1.8)
        s
        \markBarLine #5
%6
        \centerNotes #6 #'(0 0 0)
        s
        \markBarLine #6
%7
        \centerNotes #7 #'(0 0 0)
        s
        \markBarLine #7
%8
        \centerNotes #8 #'(0 0 -0.3)
        s
        \markBarLine #8
}

pUp = \relative c' {
        \key b\minor
        \clef "bass"
     
        <d, fis b>2.\pp (
        <fis ais> 
        <fis d'>
        <e g c!> )
        <dis fis a! b>\ppp^\markup \with-color #red "hier" (
        <e g b> )
        <dis fis b> ~
        <dis fis b>\fermata
}

pDown = \relative c' {
        \key b\minor
        \clef "bass"
        <b,, fis' b>2. ( |
        <ais fis' ais> |
        <d fis d'> |
        <c g' c> ) |
        <b b'> ~ |
        <b b'> |
        <b b'> ~ |
        <b b'>\fermata |
}

 <<
   \new Staff \voice
   \new PianoStaff <<
    \new Staff <<
       \new Voice \pUp
       \new Voice \centerVoice
    >>
    \new Staff \pDown
    >>
 >>

Wenn man sich den output genau ansieht, so kann man an der mit "hier" markierten Stelle ein nicht so besonders schönes Ergebnis beobachten. Das liegt an den links und rechts vom Notenhals platzierten Notenköpfen in der rechten Hand. Die NoteColumn wird absolut korrekt zentriert (wenn man die Liste an dieser Stelle auf '(0 0 0) zurücksetzt), aber sie hat jetzt in x-Richtung eine größere Ausdehnung, so daß die NoteColumn in der linken Hand nicht mehr so ganz dazu passt. Ich würde hier auf das schon oben erwähnte Verfahren mittels 'extra-spacing-width zurückgehen und die NoteColumn nicht verschieben.

Vielleicht kann jemand anderes das noch verbessern.

Gruß,
  Harm

ewipond

  • Member
Re: Noten unter Ganztaktpause zentrieren
« Antwort #5 am: Freitag, 11. November 2011, 21:32 »
Hallo harm6,

erstmal heftigen Dank - das ist wirklich sehr genial!

Verständnismäßig muss ich allerdings erstmal passen - ich kann nur ahnen, was da vor sich geht. Aber es ist ein Grund mehr, mich mit der Scheme-Sprache zu beschäftigen.
Eine Frage wäre da noch:
Das ungleiche Verschieben bei *hier  entsteht ja nur, weil die Funktion sich gleichzeitig auf beide Systeme bezieht. Wenn jeweils nur ein System betroffen wäre, könnte man doch genau solche Fälle mit deinen 3 zusätzlichen Parametern ausgleichen? Und man könnte auch eine Einzelstimme zentrieren.

Beste Grüße

harm6

  • Member
Re: Noten unter Ganztaktpause zentrieren
« Antwort #6 am: Samstag, 12. November 2011, 00:45 »
Hallo,

das Ganze ist nur ein erster Versuch. So wie es jetzt ist, funktioniert es z.B. nicht mit dem ersten Takt einer Zeile (d.h. mit Takt 1 bzw nach \break).

Zitat
Das ungleiche Verschieben bei *hier  entsteht ja nur, weil die Funktion sich gleichzeitig auf beide Systeme bezieht. Wenn jeweils nur ein System betroffen wäre, könnte man doch genau solche Fälle mit deinen 3 zusätzlichen Parametern ausgleichen? Und man könnte auch eine Einzelstimme zentrieren.

Das ist natürlich richtig. Wenn Du in \centerNotes \once\override PianoStaff zu \once\override Staff veränderst wird die Funktion nur noch pro einzelnem Staff ausgeführt. Man muß sie dann in jedem Staff erneut anwenden. Ich hatte mich erstmal an Deinem Beispiel orientiert: der erste Takt (bei "Zeit?" wird nicht zentriert. Aber der nachfolgende PianoStaff schon)

Es gibt hier noch seeehr viel Raum für Verbesserungen z.B.:

-automatisiert Markierung
-verbesserte Zentrierung
etc

Ich denke mal weiter drüber nach.


Gruß,
  Harm

harm6

  • Member
Re: Noten unter Ganztaktpause zentrieren
« Antwort #7 am: Dienstag, 29. November 2011, 23:37 »