Das archivierte Lilypond-Forum von 2017 ist hier als Lese-Archiv wieder verfügbar!

Hauptmenü

Länge eines Musikstücks?

Begonnen von ingmar, Samstag, 9. Mai 2026, 11:19

Vorheriges Thema - Nächstes Thema

ingmar

Bei der Vorbereitung eines Konzerts entsteht oft die Frage: Wie lang dauert eigentlich dieses oder jenes Stück? Da gibt es immer zwei Möglichkeiten: Einmal durchspielen (aber dann auf keinen Fall abbrechen...) oder ausrechnen – wenn man das Tempo weiß und die Länge kennt. Die Musik, mit der ich zu tun habe, hat keine echten Tempoänderungen, aber doch immer mal wieder Taktwechsel.

Ich stelle mir daher immer oft eine scheme-Funktion vor, der ich eine Voice oder einen Staff übergebe und die mir dessen Länge, am einfachsten wohl in Viertelnoten, zurückliefert. Dazu müsste sie einfach alle Noten und Pausen (und Spaces s1, s2, s4,...) zusammenzählen.

Tempoänderungen würd ich erstmal ignorieren – man könnte sie später durchaus noch berücksichtigen, so weit sie durch das Verhältnis zum Grundtempo definiert sind (ich muss erstmal schauen, wie ich das in meinen Partituren bisher gehandhabt habe). Aber ich denke, das kann später dazukommen, wenn es jemandem fehlt.

Und dann, natürlich, Wiederholungen (\repeat volta 2). Da sie nun dastehen, sollten sie per default wohl auch berücksichtigt werden (soll heißen, zweimal gezählt werden). Das ist natürlich nicht ganz trivial, bedenkt man die vielen Möglichkeiten mit \alternative, Dal Segno, Repeat unfold usw. Also entweder doch erstmal Wiederholungen ganz ignorieren (das ist OK, denn viele der Stücke mit Wiederholungen sind Tanzsätze, die sich schnell von Hand auszählen lassen). Oder, da \midi das Thema ja konsequent und richtig behandelt, sich irgendwie darauf stützen.

Auch Tempoänderungen würd ich erstmal ganz ignorieren – man könnte sie durchaus berücksichtigen, so lange sie durch das Verhältnis zum Grundtempo definiert sind (ich muss mal schauen, wie ich die in meinen Partituren bisher behandelt habe). Aber ich denke, das kann dann in der nächsten Stunde kommen..

Da Michaela vor kurzem schon ein Beispiel gegeben hat für das Durchgehen Note für Note, fehlt mir für eine erste Fassung eigentlich nur das Stück Code, das die Länge der Note/Pause liefert und eventuell für das Aufaddieren.

Kann jemand weiterhelfen? : - )

Danke! – und Gruß,
--ingmar

Codebeispiel:
\version "2.24.3"

musicA = \relative { % Length = 48
c'4 d e f g2 g
a4 a a a g1
f4 f f f e2 e
d4 d d d c e g2
f4 f f f e2 e
d4 d d d c1 }

musicB = \relative { % Length = 49
\time 3/4
R2. *2
c'4 c d
b4. c8 d4
e4 e f
e4. d8 c4
d4 c b
c4 c8 d e f

g4 g g
g4. f8 e4
f4 f f
f4. e8 d4
e4 f8 e d c
\time 4/4 
e4. f8 g4 r\fermata
\time 3/4 
a8 f e4 d
c2 r4
\bar "|." }

musicC = \relative { % Length = 35
\time 4/2
R\breve
r2 d'' d d
es2 r d4 es d  c
b8 c b a g4 r8 a b4 r8 d e4 fis
g4 g8 fis g4
}

musicD = \relative { % Length including repetition = 328, without repetition (using alternative 2) = 236
\language "english"
\time 4/2
g'2 b4. c8 d4 e d b
a2 cs d4. d8 d4 d
cs4( d2) cs4 d2 r
b2 c4 d c c b b
a4 a d4. c8 b4 g d'2

r4 a e'4. d8 c4 c b b
c4. b8 a4 g fs2 r
g4 g8 g g2 r g4 c8 c
c4 a b b a2 r
r1 r2 a

g4 a b2 a4 b c2
b1 a2 r
r1 r2 d4 d8 c
b4. a8 g4 g fs2 r
d'4 d8 c b4 b a a g2

r1 e'2 d4 d
d2 cs d2. r4
\repeat volta 2 {
r4 d2 c b a
g2 fs4 fs8( g4) fs8 g2
b4 g a2 g f4 f
e2 g b4 c2( b4)
c2 r4 b a c b cs
d2 r4 d e2 d
d2 r4 d g2. g,4
g2 c e2. e4
d2. d4 c b c c
b4 g a2 r b
a2 g a2. a4
}
\alternative {
{ g2. r4 }
{ g2. g4 a a g f g1\fermata }
}
\bar "||"
}


lengthA = "99" % \length \of \musicA \...

\markup "A – Länge in Vierteln:"
\markup \lengthA

harm6

Hallo ingmar :)

für den Anfang:
#(define all-music
  ;; Collect and list relevant music
  (list musicA musicB musicC musicD))
 
#(define (all-unfolded-music music-list)
  ;; Unfold all music in MUSIC-LIST
  (map unfoldRepeats music-list))
 
#(define (all-music-lengths-list music-list)
  ;; Return a list of all lengths of the elements of MUSIC-LIST
  ;; as a list of moments.
  (map musicLength (all-unfolded-music music-list)))
 
#(define (certain-durations-amount music-list duration)
  ;; Return a list with the amount of multiples of DURATION for each element
  ;; of MUSIC-LIST
  (map
    (lambda (l)
      (ly:moment-main (/ l (ly:duration->number duration))))
  (all-music-lengths-list music-list)))
 

 
output =
#(define-scheme-function (music-list dur)(list? ly:duration?)
  ;; Return a formated markup expressing how many multiples of DURATION each
  ;; element of MUSIC-LIST contains. These element are counted: 1, 2, 3, ...
  (let* ((amounts (certain-durations-amount music-list dur)))
    #{
      \markup
        \column
          #(map
            (lambda (i p)
              (format #f "Musik #~a dauert wie ~a Noten der Länge ~a"
                i
                p
                (/ 1 (ly:duration->number dur))))
            (iota (length amounts) 1) amounts)
    #}))
   
\markup \output #all-music ##{ 4 #}

Falls Du allerdings Tempoveränderungen wirklich berücksichtigen willst oder auch die Passagen bei denen \unfoldRepeats nicht hinreichend wirkt, so wird es mit Sicherheit erheblich komplexer. Eventuell muss man auch komplett anders vorgehen.

Gruß,
  Harm

ingmar

Vielen Dank für deine Arbeit, harm!

Zitat von: harm6 am Samstag,  9. Mai 2026, 14:18Falls Du allerdings Tempoveränderungen wirklich berücksichtigen willst oder auch die Passagen bei denen \unfoldRepeats nicht hinreichend wirkt, so wird es mit Sicherheit erheblich komplexer.

Ich glaube im Moment nicht, dass das die Mühe wert ist. Erst mal will ich deinen Code zum Laufen kriegen, stolpre aber doch über einen Fehler:

Starting lilypond 2.24.3 [book_forum(adapted).ly]...

Analysieren...ERROR: In procedure %resolve-variable:
Unbound variable: musicLength
Exited with return code 1.

harm6

Ich arbeite für gewöhnlich mit der aktuellen stable oder devel-Version oder gleich mit dem neuesten master des repositories.
Insoweit ist mir entgangen, das so einiges im geposteten Code zu neu ist.

Folgendes läuft aber mit 2.24.
#(define all-music
  ;; Collect and list relevant music
  (list musicA musicB musicC musicD))
 
#(define (all-unfolded-music music-list)
  ;; Unfold all music in MUSIC-LIST
  (map unfoldRepeats music-list))
 
#(define (all-music-lengths-list music-list)
  ;; Return a list of all lengths of the elements of MUSIC-LIST
  ;; as a list of moments.
  (map ly:music-length (all-unfolded-music music-list)))
 
#(define (certain-durations-amount music-list duration)
  ;; Return a list with the amount of multiples of DURATION for each element
  ;; of MUSIC-LIST
  (map
    (lambda (l)
      (ly:moment-main (ly:moment-div l (ly:duration-length duration))))
  (all-music-lengths-list music-list)))
 

 
output =
#(define-scheme-function (music-list dur)(list? ly:duration?)
  ;; Return a formated markup expressing how many multiples of DURATION each
  ;; element of MUSIC-LIST contains. These element are counted: 1, 2, 3, ...
  (let* ((amounts (certain-durations-amount music-list dur)))
    #{
      \markup
        \column
          #(map
            (lambda (i p)
              (format #f "Musik #~a dauert wie ~a Noten der Länge ~a"
                i
                p
                (/ 1 (duration-visual-length dur))))
            (iota (length amounts) 1) amounts)
    #}))
   
\markup \output #all-music ##{ 4 #}

Gruß,
  Harm

Manuela

Harm, eine sehr interessante Funktion, danke.

Das ist jetzt Erbsenklauberei von mir. Wenn ich folgendes eingebe

\markup \output #all-music ##{ 1*2 #}
dann kommt als Ergebnis Musik #1 dauert wie 6 Noten der Länge 1/2 etc statt Länge 2 Ganze oder 8 Viertel
Danke für eure Hilfe
viele Grüße
-- Manuela

Manuela

Zitat von: ingmar am Samstag,  9. Mai 2026, 11:19Da Michaela vor kurzem schon

Jetzt habe ich kurz gedacht, wer soll diese Michaela im Forum sein. Bis mir eingefallen ist, dass ich schon oft versehentlich mit diesem Namen angesprochen worden bin.
Danke für eure Hilfe
viele Grüße
-- Manuela

ingmar

Zitat von: Manuela am Sonntag, 10. Mai 2026, 08:07Jetzt habe ich kurz gedacht, wer soll diese Michaela im Forum sein. Bis mir eingefallen ist, dass ich schon oft versehentlich mit diesem Namen angesprochen worden bin.
Oh, entschuldige!! *rotwerd*. Ich bekomme auch immer seltsame Namen, teilweise auch aus meinem Nachname generiert. Und Susanne und Sabine verwechsel ich schon mein ganzes Leben lang (ich zweifle sehr, dass dich das tröstet..).


harm6

Zitat von: Manuela am Sonntag, 10. Mai 2026, 07:48Das ist jetzt Erbsenklauberei von mir. Wenn ich folgendes eingebe
\markup \output #all-music ##{ 1*2 #}dann kommt als Ergebnis Musik #1 dauert wie 6 Noten der Länge 1/2 etc statt Länge 2 Ganze oder 8 Viertel

Hallo Manuela,

schwächen im Code aufzuzeigen ist doch keine Erbsenklauberei, sondern notwendig um Verbesserungen überhaupt zu erreichen! Oder anders gesagt: ohne bug-report kein fix.
Also vielen Dank für den Hinweis. :)

Hier eine überarbeitete Fassung.
  • läuft mit 2.24. und neuer
  • falls Brüche auftauchen, so werden sie auf 2 Stellen nach dem Komma gerundet.
  • Punktierungen/Skalierungen werden berücksichtigt.
  • ausgegeben werden wieviele Noten der eingegebenen Dauer vorkämen, keine Umrechnung in Viertel (wenn man Viertel haben will, dann sollte man das auch so eingeben).

#(define all-music
  ;; Collect and list relevant music
  (list musicA musicB musicC musicD))
 
#(define (all-unfolded-music music-list)
  ;; Unfold all music in MUSIC-LIST
  (map unfoldRepeats music-list))
 
#(define (all-music-lengths-list music-list)
  ;; Return a list of all lengths of the elements of MUSIC-LIST
  ;; as a list of moments.
  (map ly:music-length (all-unfolded-music music-list)))
 
#(define (certain-durations-amount music-list duration)
  ;; Return a list with the amount of multiples of DURATION for each element
  ;; of MUSIC-LIST
  (map
    (lambda (l)
      (if (string<? "2.24.4" (lilypond-version))
          (ly:moment-main (/ l (ly:duration->number duration)))
          (ly:moment-main (ly:moment-div l (ly:duration-length duration)))))
  (all-music-lengths-list music-list)))

output =
#(define-scheme-function (music-list dur)(list? ly:duration?)
  ;; Return a formated markup expressing how many multiples of DURATION each
  ;; element of MUSIC-LIST contains. These element are counted: 1, 2, 3, ...
  (let* ((amounts (certain-durations-amount music-list dur))
         (dur-log (ly:duration-log dur))
         (dot-count (ly:duration-dot-count dur))
         (dots (list->string  (make-list dot-count #\.)))
         (dur-string
           (if (negative? dur-log)
               (case dur-log
                 ((-1) (format #f "breve ~a" dots))
                 ((-2) (format #f "longa ~a" dots))
                 ((-3) (format #f "maxima ~a" dots))
                 (else (begin
                         ;; Bad durations should error earlier, better be
                         ;; paranoid, though.
                         (ly:warning "Unknown duration ~a" dur)
                         "?")))
               (ly:duration->string dur))))
    #{
      \markup
        \override #'(baseline-skip . 3)
        \column
          #(map
            (lambda (i p)
              (format #f "Musik #~a dauert wie ~a Noten der Länge \"~a\""
                i
                (if (integer? p)
                    p
                    (format #f "~a (gerundet)"
                      (exact->inexact (/ (round (* p 100)) 100))))
                dur-string))
            (iota (length amounts) 1) amounts)
    #}))
   

\markup
  \override #'(baseline-skip . 15)
  \column  {
    \output #all-music ##{ 4 #}
    \output #all-music ##{ 4. #}
    \output #all-music ##{ 4*3/2 #}
    \output #all-music ##{ 4.. #}
    \output #all-music ##{ 4.*3/2 #}
    \output #all-music ##{ 1 #}
    \output #all-music ##{ \breve . #}
    \output #all-music ##{ \longa #}
  }

Gruß,
  Harm

Manuela

#8
Harm, genial wie immer, danke.  :)

Um die Erbsenzählerei jetzt auf die Spitze zu treiben ;) : Manchmal gibt es Fälle, wo das gerundete Ergebnis (zufällig) exakt ist, wie z.B. Musik #2 bei Länge 1

Update: ich habe es mit meinen bescheidenen Kenntnissen geschafft, den Zusatz "gerundet" für diesen Fall zu entfernen

output =
#(define-scheme-function (music-list dur)(list? ly:duration?)
   ;; Return a formated markup expressing how many multiples of DURATION each
   ;; element of MUSIC-LIST contains. These element are counted: 1, 2, 3, ...
   (let* ((amounts (certain-durations-amount music-list dur))
          (dur-log (ly:duration-log dur))
          (dot-count (ly:duration-dot-count dur))
          (dots (list->string  (make-list dot-count #\.)))
          (dur-string
           (if (negative? dur-log)
               (case dur-log
                 ((-1) (format #f "breve ~a" dots))
                 ((-2) (format #f "longa ~a" dots))
                 ((-3) (format #f "maxima ~a" dots))
                 (else (begin
                        ;; Bad durations should error earlier, better be
                        ;; paranoid, though.
                        (ly:warning "Unknown duration ~a" dur)
                        "?")))
               (ly:duration->string dur))))
     #{
       \markup
       \override #'(baseline-skip . 3)
       \column
       #(map
         (lambda (i p)
           (format #f "Musik #~a dauert wie ~a Noten der Länge \"~a\""
                   i
                   (if
                    (integer? p)
                    p
                    (if (= (/ (round (* p 100)) 100) p)
                        (format #f "~a"
                                (exact->inexact (/ (round (* p 100)) 100)))
                        (format #f "~a (gerundet)"
                                (exact->inexact (/ (round (* p 100)) 100)))
                        ))
                   dur-string))
         (iota (length amounts) 1) amounts)
     #}))
Danke für eure Hilfe
viele Grüße
-- Manuela

harm6

Zitat von: ManuelaManchmal gibt es Fälle, wo das gerundete Ergebnis (zufällig) exakt ist, [...]
Ja, das kann natürlich vorkommen. Ich würde das "(gerundet)" trotzdem drin lassen, schon um den user zu informieren, dass da eigentlich noch was ist.

Gruß,
  Harm