Deutsches Lilypond Forum (Archiv)

Allgemein => Fragen zu Funktionen => Thema gestartet von: fugenkomponist am Freitag, 10. Juli 2015, 16:32

Titel: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Freitag, 10. Juli 2015, 16:32
Hallo allerseits,

weiß jemand, warum sich \articulate nicht auf zitierte Musik auswirkt?
\version "2.19.20"
\include "articulate.ly"

% kürzt Noten auf 1/2 statt 7/8 für bessere Hörbarkeit
#(define ac:normalFactor '(1 . 2))

vlI = { d'2 d' }
\addQuote "vlI" \vlI

vlII = { d'2 \quoteDuring "vlI" s2}

\score {
  \articulate <<
    \new Staff \with {
      midiInstrument = "violin"
    } \vlI
    \new Staff \with {
      midiInstrument = "violin"
    } \vlII
  >>
  \layout { }
  \midi { }
}
Zum Nachhören ist mindestens LilyPond 2.19.19 erforderlich, weil vorher zitierte Musik nicht ins MIDI kam.
Titel: Re: \quoteDuring und \articulate
Beitrag von: harm6 am Freitag, 10. Juli 2015, 17:11
Wenn Du
#(display-scheme-music vlII)betrachtest, siehst Du dasselbe was auch articulate als Eingabe bekommt.

Ein SkipEvent wird von articulate nicht bearbeitet.
Somit entsteht folgerichtig:
#(display-scheme-music (articulate vlII))
articulate ist eine Musikfunktion die als solche zu früh in das Geschehen einzugreifen versucht.
Zumindest ist das meine Vermutung, denn meine kleine test-Funktion 'foo' hat das gleiche Problem:

\version "2.19.22"
\include "articulate.ly"       

foo =
#(define-music-function (music)(ly:music?)
(music-map
  (lambda (m)
    (if (music-is-of-type? m 'note-event)
        (begin
          (ly:music-set-property! m 'tweaks
            (acons 'color red
              (ly:music-property m 'tweaks)))
          m)
        m))
  music))

% kürzt Noten auf 1/2 statt 7/8 für bessere Hörbarkeit
#(define ac:normalFactor '(1 . 2))

vlI = { d'2 dis' }
\addQuote "vlI" \vlI

vlII = { d'2 \quoteDuring "vlI" s2 }

\score {
  \foo
  \articulate <<
    \new Staff \with {
      midiInstrument = "violin"
    } \vlI
    \new Staff \with {
      midiInstrument = "violin"
    } \vlII
  >>
  \layout { }
  \midi { }
}

Gruß,
  Harm
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Samstag, 11. Juli 2015, 13:11
Danke für deine Antwort. Das klingt ja so, als ließe sich da wenig machen. Ich probier aber trotzdem nachher oder morgen mal, mich da reinzuwühlen und vielleicht nen geeigneten Angriffspunkt zu finden.
Titel: Re: \quoteDuring und \articulate
Beitrag von: harm6 am Samstag, 11. Juli 2015, 13:26
Das einzige was ich gefunden habe, ist \articulate schon auf das Argument von \addQuote anzuwenden.

\addQuote "vlI" \articulate \vlI
Das wird dann aber natürlich dauerhaft verändert.
Kann man vielleicht mit \tag beheben, hab ich aber nicht versucht...

Gruß,
  Harm
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Samstag, 11. Juli 2015, 14:02
Hmja, da müsste man dann halt
\addQuote "vlImidi" \articulate \vlI
\addQuote "vlIscore" \vlI
und \tag beim Zitieren arbeiten, denn ich will ja auch eine les- und druckbare Partitur haben ;)

Ist jetzt auch nicht so wichtig, midi ist sowieso nicht das Gelbe vom Ei für das Überprüfen, wie ein Stück wohl klingt, aber ich dachte, besser mit \articulate als ohne (v. a. auch wegen so Dingen wie c2:8 c: c: c: etc., die \unfoldRepeats ja nicht zu Achteln macht).

slightly off-topic: \articulate tut nicht mehr mit 2.19.22, aufgrund ähnlicher Fehlermeldungen vermute ich, dass articulate.ly noch nicht vollständig auf diese „parser-und-location-brauchen-wir-nicht-mehr-in-Musikfunktionen“-Änderung eingegangen ist.
Titel: Re: \quoteDuring und \articulate
Beitrag von: harm6 am Samstag, 11. Juli 2015, 14:09
slightly off-topic: \articulate tut nicht mehr mit 2.19.22, aufgrund ähnlicher Fehlermeldungen vermute ich, dass articulate.ly noch nicht vollständig auf diese „parser-und-location-brauchen-wir-nicht-mehr-in-Musikfunktionen“-Änderung eingegangen ist.

Das war issue 4471 (https://code.google.com/p/lilypond/issues/detail?id=4471) ist in 2.19.23 (kommt bald) gefixt.

Kannst Du aber auch für 2.19.22 selbst machen. Siehe den patch-diff:
https://codereview.appspot.com/250830043/diff/1/scm/music-functions.scm (https://codereview.appspot.com/250830043/diff/1/scm/music-functions.scm)
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Sonntag, 12. Juli 2015, 09:52
Vielen Dank für den Hinweis! Hab im issue-tracker geschaut, aber nicht genug verstanden von der Fehlermeldung, um den richtigen Suchbegriff zu verwenden (denn articulate wird ja nicht erwähnt). Dieser einfache Patch ist durchaus von Hand anwendbar ;) Das ist übrigens das erste Mal, dass ich merke, dass eine sog. unstabile Version wirklich irgendwo kaputt ist (was ja ihr gutes Recht ist, auch wenn man es natürlich gern vermeidet), die Entwickler leisten gute Arbeit :)
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Freitag, 7. August 2015, 12:27
In diesem Thread (https://liarchiv.joonet.de/index.php?topic=2053) geht es um Zitate, die Zitate zitieren, was in LilyPond leider nicht einfach so funktioniert. Eine Möglichkeit, die genannt wurde, war, mit ly:score-music und scorify-music zu arbeiten. Ich dachte mir, vielleicht könnte ein ähnlicher Ansatz auch hier helfen. Tut er aber nicht.
\version "2.19.22"
\include "articulate.ly"

foo = \relative {
  c'1 |
  g' |
}
\addQuote "foo" \foo

baz = \relative {
  c''1 |
  \quoteDuring "foo" s1 |
}

\markup "ganz normaler score << \foo \baz >>:"

<<
  \foo
  \baz
>>

\markup "\articulate auf den score geschmissen artikuliert keine Zitate:"

\articulate <<
  \foo
  \baz
>>

\markup "\articulate \foo:"

\displayMusic \articulate \foo

\markup "\articulate #(ly:score-music (scorify-music foo)) geht schon kaputt ohne Zitate:"

\displayMusic \articulate #(ly:score-music (scorify-music foo))

\markup "Merkwürdigerweise sind beide Ausgaben von \display*Lily*Music der letzten beiden Beispiele gleich."
Es gehen Pausen verloren und die barchecks gehen schief. Wenn man jetzt noch kleinere Notenwerte verwendet und an ac:normalFactor, dem Faktor, auf den normale Noten verkürzt werden, dreht (per #(define ac:normalFactor '(1 . 2)) o. ä.), dann sieht man, dass sich da auch einiges im Notenbild tut, es gehen sogar Noten verloren.

Hier mal ein diff (mit Option -y) der beiden \displayMusic-Ausgaben:(make-music (make-music
  'RelativeOctaveMusic   'RelativeOctaveMusic
      >   'length
      >   (ly:make-moment 2)
  'element   'element
  (make-music   (make-music
    'SequentialMusic     'SequentialMusic
      >     'length
      >     (ly:make-moment 2)
    'elements     'elements
    (list (make-music     (list (make-music
            'SequentialMusic             'SequentialMusic
            'elements             'elements
            (list (make-music             (list (make-music
                    'EventChord                     'EventChord
                    'elements                     'elements
                    (list (make-music                     (list (make-music
                            'NoteEvent                             'NoteEvent
      >                             'length
      >                             (ly:make-moment 1)
                            'duration                             'duration
                            (ly:make-duration 0 0 7/8)                             (ly:make-duration 0 0 7/8)
                            'pitch                             'pitch
                            (ly:make-pitch 0 0))))                             (ly:make-pitch 0 0))))
                  (make-music                   (make-music
                    'EventChord                     'EventChord
                    'elements                     'elements
                    (list (make-music                     (list (make-music
                            'RestEvent                             'RestEvent
                            'duration                             'duration
                            (ly:make-duration 0 0 1/8))))))                             (ly:make-duration 0 0 1/8))))))
          (make-music           (make-music
            'SequentialMusic             'SequentialMusic
            'elements             'elements
            (list (make-music (quote BarCheck))))       |             (list (make-music
      >                     'BarCheck
      >                     'length
      >                     (ly:make-moment 0))))
          (make-music           (make-music
            'SequentialMusic             'SequentialMusic
            'elements             'elements
            (list (make-music             (list (make-music
                    'EventChord                     'EventChord
                    'elements                     'elements
                    (list (make-music                     (list (make-music
                            'NoteEvent                             'NoteEvent
      >                             'length
      >                             (ly:make-moment 1)
                            'pitch                             'pitch
                            (ly:make-pitch 0 4)                             (ly:make-pitch 0 4)
                            'duration                             'duration
                            (ly:make-duration 0 0 7/8))))                             (ly:make-duration 0 0 7/8))))
                  (make-music                   (make-music
                    'EventChord                     'EventChord
                    'elements                     'elements
                    (list (make-music                     (list (make-music
                            'RestEvent                             'RestEvent
                            'duration                             'duration
                            (ly:make-duration 0 0 1/8))))))                             (ly:make-duration 0 0 1/8))))))
          (make-music           (make-music
            'SequentialMusic             'SequentialMusic
            'elements             'elements
            (list (make-music (quote BarCheck)))))))       |             (list (make-music
      >                     'BarCheck
      >                     'length
      >                     (ly:make-moment 0)))))))
Es scheint so, als würden da irgendwie noch length-Eigenschaften festgesetzt während des ly:scorify-music. Mir ist jetzt nicht ganz klar, was length und duration tun; kann es sein, dass length die Länge bis zum nächsten Event und duration die Länge des aktuellen Events ist? Falls ja, wäre dieser Ansatz ja von vorneherein zum Scheitern verurteilt, oder?
Titel: Re: \quoteDuring und \articulate
Beitrag von: harm6 am Freitag, 7. August 2015, 18:48
Offensichtlich setzt die \score-function das 'length-property, \articulate aber nicht. Das kollidiert.

Schau mal, ob die brutalst-mögliche Herangehensweise zuviel kaputtmacht:

\version "2.19.24"

\include "articulate.ly"

test =
#(define-music-function (music)(ly:music?)
  (music-map
     (lambda (m)
       (if (music-is-of-type? m 'rhythmic-event)
           (begin
             (ly:music-set-property! m 'length '())
             m)
           m))
     (articulate
       (ly:score-music
         (scorify-music (ly:music-deep-copy music))))))
   
foo = \relative {
  c'1 |
  g' |
}

baz = \relative {
  cis''1 |
  \quoteDuring "foo" s1 |
}

\addQuote "foo" \test \foo

\score {
  \articulate
  <<
    \foo
    \baz
  >>
}

Gruß,
  Ham
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Freitag, 7. August 2015, 21:35
Hmja, leider löst das mein Problem nicht. Ich hab mal dein \test aufgeteilt, sodass \test das gleiche tut (oder tun sollte) wie \addLengths \articulate \scoreScorify:\version "2.19.22"
\include "articulate.ly"

scoreScorify =
#(define-music-function (music) (ly:music?)
   (ly:score-music
    (scorify-music
     (ly:music-deep-copy music))))

addLengths =
#(define-music-function (music) (ly:music?)
   (music-map
    (lambda (m)
      (if (music-is-of-type? m 'rhythmic-event)
          (begin
           (ly:music-set-property! m 'length '())
           m)
          m))
    music))

foo = \relative {
  c'1 |
  g' |
}
\addQuote "foo" \addLengths \articulate \scoreScorify \foo

baz = \relative {
  c''1 |
  \quoteDuring "foo" s1 |
}

\foo

\baz

\articulate \foo

\articulate \baz
Das Problem ist, dass damit \articulate wieder im \addQuote steht (und damit artikuliert \baz schon das Zitat ohne \articulate \baz). Nehm ich es da raus, hab ich den gleichen Effekt wie ohne \scoreScorify und \addLengths (\baz artikuliert das Zitat nicht, wenn man \articulate dranschreibt). Das einzige, was \addLengths ändert, ist, dass \articulate \scoreScorify \foo nicht mehr kaputt geht, wenn man \addLengths vornedran schreibt (also \test \foo). Aber dieses Problem kam ja erst mit meinem erfolglosen Versuch auf, \scoreScorify irgendwie auf mein Problem zu werfen … Ich hab jetzt auch verschiedene Varianten versucht, \scoreScorify an alle möglichen Stellen zu schreiben, jedoch ohne den erhofften Effekt.

Edit: Gut möglich, dass es in diese Richtung nicht groß weiter geht, ich hatte bloß diese spontane Idee aus dem Nachbarthread …
Titel: Re: \quoteDuring und \articulate
Beitrag von: harm6 am Sonntag, 9. August 2015, 11:58
Ich habe dann doch noch einiges dran gearbeitet.

Zunächst mal eine Definition die es erlaubt sich anzeigen zu lassen welche QuoteMusic dem parser in welcher Form bekannt ist.

\version "2.19.24"

I = { dis'2 dis' }
II = { ces'2 \quoteDuring "I" s2}


\addQuote "I" \I
\addQuote "II" \II
\addQuote "III"  #(ly:score-music (scorify-music (ly:music-deep-copy II)))

#(define* (music-quotes-info #:optional (name "")(print #f))
 (let* ((music-quotes-list
          (hash-map->list cons (ly:parser-lookup 'musicQuotes)))
        (quote-vector (assoc-get name music-quotes-list #()))
        (quote-list (vector->list quote-vector)))
  (cond ((string-null? name)
         (display-scheme-music music-quotes-list))
        ((and (not (null? quote-list)) print)
         (make-sequential-music
           (map
             (lambda (m) (ly:prob-property (caadr m) 'music-cause))
             quote-list)))
        (else (display-scheme-music
                (make-sequential-music
                  (map
                    (lambda (m) (ly:prob-property (caadr m) 'music-cause))
                    quote-list)))))))

%% raw data of all quotes
#(music-quotes-info)

%% `display-scheme-music' the quotes named "I"/"II"/"III" as sequential music
#(music-quotes-info "I")
#(music-quotes-info "II")
#(music-quotes-info "III")

%% set `print' #t and use $ to get it printed
$(music-quotes-info "I" #t)
$(music-quotes-info "II" #t)
$(music-quotes-info "III" #t)

EDIT: Kommentar im Code korrigiert

Wenn man die Rohdaten genau analysiert stellt man fest, daß für Quote III die zitierte Musik gespeichert wird im Gegensatz zu Quote II.

Mein Gedanke war jetzt, wenn etwas da ist, dann wird man wohl auch irgendwie Zugriff erlangen können, um diese Daten dann zu manipulieren und weiter zu verwenden:

\version "2.19.24"

\include "articulate.ly"
   
#(define (return-increasing-moms l1 rl)
"
Expects a paired list, with a moment as car and a music-event as cdr.
This list is transformed into a paired list where the car shows when the event
happens.
(list (cons (ly:make-moment 1/2)
            (make-music
              'NoteEvent
              'length
              (ly:make-moment 1/2)
              'pitch
              (ly:make-pitch 1 0 1/2)
              'duration
              (ly:make-duration 1)))
      (cons (ly:make-moment 1/2)
            (make-music
              'NoteEvent
              'length
              (ly:make-moment 1/2)
              'pitch
              (ly:make-pitch 1 0 1/2)
              'duration
              (ly:make-duration 1))))
==>
(list (cons (ly:make-moment 0)
            (make-music
              'NoteEvent
              'length
              (ly:make-moment 1/2)
              'duration
              (ly:make-duration 1)
              'pitch
              (ly:make-pitch 1 0 1/2)))
      (cons (ly:make-moment 1/2)
            (make-music
              'NoteEvent
              'length
              (ly:make-moment 1/2)
              'pitch
              (ly:make-pitch 1 0 1/2)
              'duration
              (ly:make-duration 1))))
"
  (if (null? l1)
      (reverse rl)
      (return-increasing-moms
        (cdr l1)
        (cons
          (cons
            (ly:moment-add
              (caar l1)
              (if (null? rl) (ly:make-moment 0) (caar rl)))
            (cdar l1))
            rl))))
           
#(define (replace-music-of-type type l1 l2 rl)
"Expects two list of the type `return-increasing-moms' returns. Music of type
@var{type} in l1 is replaced by the relevant entries of l2."
  (if (null? l1)
      (reverse rl)
      (cond ((music-is-of-type? (cdar l1) 'rhythmic-event)
              (replace-music-of-type type (cdr l1) l2 (cons (car l1) rl)))
            ((equal? (ly:music-property (cdar l1) 'name) type)
             (let* ((at (caar l1))
                    (nxt-at (caadr l1))
                    (real-mus
                      (filter
                        (lambda (x)
                          (and (not (ly:moment<? (car x) at))
                               (ly:moment<? (car x) nxt-at)))
                        l2)))
             (replace-music-of-type type (cdr l1) l2 (append (reverse real-mus) rl))))
            (else (ly:error "Something is wrong.")))))
           
#(define (replace-quotes-with-real-music music)
"Returns sequential music.
'length-property is set '()
'quoted-events are not cited but inserted into the music-flow.
"
  (let* (;; get access to 'quoted-events, better to use a copy
         (music-copy
           (ly:score-music (scorify-music (ly:music-deep-copy music))))
         (evts (extract-named-music music-copy 'QuoteMusic)))
         
    (if (null? evts)
        ;; If no 'QuoteMusic, clear 'length and return.
        (music-map
          (lambda (m)
            (if (music-is-of-type? m 'rhythmic-event)
                (begin
                  (ly:music-set-property! m 'length '())
                  m)
                m))
          music-copy)
        (let* ((quoted-events-lst
                 (vector->list (ly:music-property (car evts) 'quoted-events)))
               ;; creates an alist with the moment when it happens and the
               ;; music there from the `quoted-events-lst'
               ;; TODO this whole approach feels clumsy ...
               (mom-evt-alist
                 (map
                   (lambda (x)
                     (cons (caar x) (ly:prob-property (caadr x) 'music-cause)))
                   quoted-events-lst))
               ;; a list to accumulate moment and music as pairs from the
               ;; music-copy
               (mls '())
               ;; somewhat tricky, a list to accumulate moments
               ;; used to get the moments correct later
               (moms (list (ly:make-moment 0))))

          ;; needed to set `mls'
          (for-some-music
            (lambda (m)
              (and (or (music-is-of-type? m 'rhythmic-event)
                       (equal? (ly:music-property m 'name) 'QuoteMusic))
                   (set! mls (cons (cons (car moms) m) mls))
                   (set! moms (cons (ly:music-property m 'length) moms))
                   m))
            music-copy)

          ;; replace the 'QuoteMusic with the relevant events
          ;; returning sequential music
          (let ((replaced-elts
                  (map
                   (lambda (x)
                     (ly:music-set-property! (cdr x) 'length '())
                     (cdr x))
                   (replace-music-of-type
                     'QuoteMusic
                     (return-increasing-moms (reverse mls) '())
                     mom-evt-alist
                     '()))))
            (make-sequential-music replaced-elts))))))   
replaceQuotes =
#(define-music-function (music)(ly:music?)
  (replace-quotes-with-real-music music))

%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%

foo = \relative c {
  c'2 c |
  ges' ges |
  aisis16 aisis aisis aisis aisis2. |
  b1 |
}

baz = \relative {
  cis''2 cis |
  d2 d
  \quoteDuring "foo" s1 |
  des4 des des des
}

bla = {
  c'8 d' e' f' g' a' b' c''
  c'8 d' e' f'   
  \quoteDuring "baz" s1*2
  g'8 a' b' c''
}

blaII = {
  bes4
  \quoteDuring "bla" { s1*3 s2 }
  bes4
}
\addQuote "foo" \replaceQuotes \foo
\addQuote "baz" \replaceQuotes \baz
\addQuote "bla" \replaceQuotes \bla
\addQuote "bla" \replaceQuotes \blaII

%\displayMusic
\foo
%\displayMusic
\baz
%\displayMusic
\bla
%\displayMusic
\blaII

%% needs to be stored in a variable before, otherwise \articulate would map
%% through one music-expression after the other disturbing \replaceQuotes
mus =
  <<
    \foo
    \replaceQuotes \baz
    \replaceQuotes \bla
    \replaceQuotes \blaII
  >>
 
\score {
  \articulate
  \mus
}

Zumindest für die Minimalbeispiele ist das Zitieren von Zitaten möglich.
Um \articulate zu verwenden muß man das Ergebnis vorher in eine Variable packen und erst danach aufrufen.

Das Ganze ist mit Sicherheit noch in größtem Ausmaß verbesserungsfähig und eigentlich erwarte ich noch zahlreiche bugs, sobald man größere real-life Beispiele versucht. ;)


HTH,
  Harm
Titel: Re: \quoteDuring und \articulate
Beitrag von: harm6 am Freitag, 14. August 2015, 02:02
Hallo fugenkomponist,

hat Dir der Code aus meinem letzten post hier eigentlich geholfen oder war es völlig daneben? ;)

Gruß,
  Harm
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Freitag, 14. August 2015, 09:48
Tut mir leid, dass ich noch nicht geantwortet habe, wo du dir doch so viel Mühe gegeben hast, vielen Dank dafür schonmal :) Mir sind in letzter Zeit so viele Dinge aufgefallen, die ich am PDF-Output und an der Benutzung verbessern würde, dass ich articulate/MIDI erstmal hintenan gestellt habe. Dabei kommen vielleicht ja auch ein paar Dinge für openlilylib raus ;) Ich habe aber diesen Thread als ungelesen markiert (und werds gleich wieder tun), damit ich ihn nicht vergesse. Jedenfalls sehen deine kleinen Beispiele schon sehr vielversprechend aus und ich werd mich innerhalb der nächsten Tage mal dransetzen, das in meine Partitur zu integrieren, dann berichte ich von meinen Erfahrungen.
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Montag, 17. August 2015, 19:05
Ein erster Test hat ergeben, dass es Probleme gibt, wenn ein Zitat ganz am Ende eines Stücks auftaucht.
\include "replaceQuotes.ily"

foo = \relative {
  c'4 d e f g a b c
}
\addQuote "foo" \replaceQuotes \foo

baz = \relative {
  c'4 c c c \quoteDuring "foo" s1
}
\addQuote "baz" \replaceQuotes \baz

\baz
Das kann man aber beheben, indem man nach das \quoteDuring noch ein s1*0 schreibt. Ich verwende im Moment auch die hier (https://liarchiv.joonet.de/index.php?topic=2033.msg11218#msg11218) erwähnte Funktion alignTo, die aus anderen Gründen ebenfalls ein s1*0 am Ende braucht, also ist das erstmal nicht weiter schlimm ;)

[off-topic]Ich wollte mich eigentlich mal drum kümmern, dass ich alignTo beibringe, dass es ohne s1*0 auskommt …[/off-topic]
Titel: Re: \quoteDuring und \articulate
Beitrag von: harm6 am Montag, 17. August 2015, 23:19
Ich hatte doch das vage Gefühl etwas vergessen zu haben ...

Ersetze das alte `replace-music-of-type' durch

#(define (replace-music-of-type type l1 l2 rl)
"Expects two list of the type `return-increasing-moms' returns. Music of type
@var{type} in l1 is replaced by the relevant entries of l2."
  (if (null? l1)
      (reverse rl)
      (cond ((music-is-of-type? (cdar l1) 'rhythmic-event)
             (replace-music-of-type type (cdr l1) l2 (cons (car l1) rl)))
            ((null? (cdr l1))
             ;(display-scheme-music l2)
             l2)
            ((equal? (ly:music-property (cdar l1) 'name) type)
             (let* ((at (caar l1))
                    (nxt-at (caadr l1))
                    (real-mus
                      (filter
                        (lambda (x)
                          (and (not (ly:moment<? (car x) at))
                               (ly:moment<? (car x) nxt-at)))
                        l2)))
               (replace-music-of-type type
                 (cdr l1) l2 (append (reverse real-mus) rl))))
            (else (ly:error "Something is wrong.")))))

Und schau mal wie weit Du damit kommst. ;)


Gruß,
  Harm
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Donnerstag, 20. August 2015, 15:18
So, ich hab noch ein bisschen damit rumprobiert und es scheint jetzt ganz gut zu klappen. Ich hab das ganze jetzt so zusammengebaut, dass man \replaceQuote (und auch \articulate) nirgendwo mehr von Hand einsetzen muss, sondern nur eine einzige Datei per \include einbinden muss. Für artikulierte Zitate dann noch zwei weitere Includes (ich dachte mir erst, dass die Dateien sich vielleicht gegenseitig einbinden sollten, habe das aber wieder verworfen, damit man nicht nachher Dateien mehrmals einbindet).

Den Code habe ich in ein .zip gepackt, weil ich an diesen Beitrag nur vier Anhänge hängen darf. Es enthält folgende Dateien:


Angehängt habe ich außerdem noch als Bilder die Ergebnisse der drei Varianten.

Vielen Dank nochmal an harm!
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Donnerstag, 20. August 2015, 20:59
Mir ist soeben eine ganz wesentliche Einschränkung von harms Lösung (https://liarchiv.joonet.de/index.php?topic=2031.msg11309#msg11309) und damit auch meiner Abwandlung davon aufgefallen: Nicht jeder kann jeden zitieren, erstaunlich, dass uns das beiden noch nicht aufgefallen ist … Wenn die \addQuote-Befehle eine bestimmte Reihenfolge haben, in der A über B steht, dann kann B A zitieren, aber A B nicht (z. B. kann foo im verlinkten Beitrag nicht bla zitieren).

Allgemein gesprochen: Wir stellen uns einen gerichteten Graphen vor, in dem eine Kante A→B bedeutet, dass A B zitiert. An diesen gabs bisher so gut wie keine Anforderungen (Zyklen sind nur verboten, wenn die Zitate alle zum gleichen Zeitpunkt passieren; lustigerweise gerät LilyPond weder in eine Endlosschleife noch hauts ne Warnung raus falsch gedacht, LilyPonds quoteDuring ist ja nicht transitiv). Jetzt muss er aber ein DAG (gerichteter azyklischer Graph) sein; die nötige Anordnung der \addQuote-Befehle ergibt sich dann aus einer topologischen Sortierung dieses Graphen. Das ist schon eine ziemlich einschneidende Anforderung.

Meine Erklärung mithilfe von LilyPonds Fehlermeldung: Angenommen, \addQuote "A" \A steht über \addQuote "B" \B und A zitiert B per \quoteDuring "B" s1.
\addQuote "A" \A wertet A nun per replaceQuote aus, stößt auf den \quoteDuring-Befehl, schaut also nach einem zitierbaren "B" und findet es nicht.

Ich habe gerade nur eine Idee, was man da machen könnte: lazy evaluation. Ich hab mal gelesen, dass Scheme das kann, bin mir aber noch nicht klar darüber, in welchem Ausmaß das geht und ob das hier weiterhelfen könnte oder LilyPond mir nen Strich durch die Rechnung macht. Ich probier das mal.

Edit: Mal abgesehen davon, dass promise?, force und delay da sind, aber GUILE lazy nicht kennt (warum auch immer delay und force sind grundsätzlich Teil der Sprache, lazy kommt mit SRFI-45 dazu, wenn ich das hier (https://www.gnu.org/software/guile/manual/html_node/Delayed-Evaluation.html#Delayed-Evaluation) und das hier (https://www.gnu.org/software/guile/manual/html_node/SRFI_002d45.html) richtig verstehe), hab ich irgendwie gerade gar keinen Plan …
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Freitag, 21. August 2015, 17:58
Ich weiß immer noch nicht, ob das mit der lazy evaluation irgendwie klappen könnte, meine Intuition sagt aber „nein, eine Zitier-Iteration reicht nicht aus“. (harm, kannst du da vielleicht etwas zu sagen? Ich hab das nichtmal anständig zum Kompilieren gebracht, ganz zu schweigen von irgendwelchen Ergebnissen in die richtige Richtung ;) )

Was aber irgendwie gehen sollte wäre folgendes: Erstmal haben wir die Musikvariablen m_1 bis m_n, die alle irgendwelche Zitate per \quoteDuring q_1 bis \quoteDuring q_n enthalten können (die q_i sind Strings, die ja irgendetwas sein können, nicht unbedingt die Namen der m_i). Dann kommen die n Zeilen \addQuote q_i m_i. Und dann füttern wir eine Funktion mit m_1 bis m_n und q_1 bis q_n; diese Funktion ersetzt nun erstmal in allen m_i die Vorkommen von \quoteDuring q_1 durch die entsprechenden Teile von m_1. Dann das gleiche mit q_2, …, q_n.

Das vergrößert natürlich den Rechenaufwand. Aber ich hab das Gefühl, dass ich da nicht drumherum komme. (Alles unter der Annahme, dass ich nicht einfach sage „ok, ich zitiere immer die erste Geige in der zweiten, nie andersrum“. Vielleicht mach ich das irgendwann – es ist nicht so wichtig, dass sich da jetzt noch jemand extra stundenlang reinhängen sollte.)

Edit: Hier mal eine Datei, die im Endeffekt dann in allen Stimmen 10 as, 10 hs, 10 c's, 10 d's haben soll. Ich bin alle möglichen Kombinationen, wer wen direkt, indirekt über eine Zwischenstation oder indirekt über zwei Zwischenstationen zitiert, durchgegangen.\version "2.19.25"

A = \relative {
  \time 10/4
  a a a a a a a a a a |
  \quoteDuring "B" { s s }
  \quoteDuring "C" { s }
  \quoteDuring "D" { s }
  \quoteDuring "B" { s s }
  \quoteDuring "C" { s }
  \quoteDuring "D" { s s }
  \quoteDuring "C" { s } |
  \quoteDuring "C" { s s }
  \quoteDuring "B" { s }
  \quoteDuring "D" { s }
  \quoteDuring "C" { s s }
  \quoteDuring "B" { s }
  \quoteDuring "D" { s s }
  \quoteDuring "B" { s } |
  \quoteDuring "D" { s s }
  \quoteDuring "B" { s }
  \quoteDuring "C" { s }
  \quoteDuring "D" { s s }
  \quoteDuring "B" { s }
  \quoteDuring "C" { s s }
  \quoteDuring "B" { s } |
}

B = \relative {
  \time 10/4
  \quoteDuring "A" { s s }
  \quoteDuring "C" { s }
  \quoteDuring "D" { s }
  \quoteDuring "A" { s s }
  \quoteDuring "C" { s }
  \quoteDuring "D" { s s }
  \quoteDuring "C" { s } |
  b b b b b b b b b b |
  \quoteDuring "C" { s }
  \quoteDuring "A" { s }
  \quoteDuring "C" { s }
  \quoteDuring "D" { s }
  \quoteDuring "A" { s }
  \quoteDuring "D" { s }
  \quoteDuring "C" { s s }
  \quoteDuring "A" { s }
  \quoteDuring "D" { s } |
  \quoteDuring "D" { s }
  \quoteDuring "A" { s }
  \quoteDuring "D" { s }
  \quoteDuring "C" { s }
  \quoteDuring "A" { s }
  \quoteDuring "C" { s }
  \quoteDuring "D" { s s }
  \quoteDuring "A" { s }
  \quoteDuring "C" { s } |
}

C = \relative {
  \time 10/4
  \quoteDuring "A" { s }
  \quoteDuring "B" { s }
  \quoteDuring "A" { s }
  \quoteDuring "D" { s }
  \quoteDuring "B" { s }
  \quoteDuring "D" { s }
  \quoteDuring "A" { s s }
  \quoteDuring "B" { s }
  \quoteDuring "D" { s } |
  \quoteDuring "B" { s }
  \quoteDuring "A" { s }
  \quoteDuring "B" { s }
  \quoteDuring "D" { s }
  \quoteDuring "A" { s }
  \quoteDuring "D" { s }
  \quoteDuring "B" { s s }
  \quoteDuring "A" { s }
  \quoteDuring "D" { s } |
  c' c c c c c c c c c |
  \quoteDuring "D" { s }
  \quoteDuring "A" { s }
  \quoteDuring "B" { s }
  \quoteDuring "D" { s }
  \quoteDuring "B" { s }
  \quoteDuring "A" { s s }
  \quoteDuring "B" { s }
  \quoteDuring "D" { s s } |
}

D = \relative {
  \time 10/4
  \quoteDuring "A" { s }
  \quoteDuring "B" { s }
  \quoteDuring "C" { s }
  \quoteDuring "A" { s }
  \quoteDuring "C" { s }
  \quoteDuring "B" { s s }
  \quoteDuring "C" { s }
  \quoteDuring "A" { s s } |
  \quoteDuring "B" { s }
  \quoteDuring "A" { s }
  \quoteDuring "C" { s }
  \quoteDuring "B" { s }
  \quoteDuring "C" { s }
  \quoteDuring "A" { s s }
  \quoteDuring "C" { s }
  \quoteDuring "B" { s s } |
  \quoteDuring "C" { s }
  \quoteDuring "A" { s }
  \quoteDuring "B" { s }
  \quoteDuring "C" { s }
  \quoteDuring "B" { s }
  \quoteDuring "A" { s s }
  \quoteDuring "B" { s }
  \quoteDuring "C" { s s } |
  d' d d d d d d d d d |
}

\addQuote "A" \A
\addQuote "B" \B
\addQuote "C" \C
\addQuote "D" \D

<<
  \A
  \B
  \C
  \D
>>

2. Edit: Irgendwie läuft auch das noch nicht so, ich bleib aber dran. Mir ist aber inzwischen eine weitere Idee gekommen: Nicht nacheinander die Stimmen anschauen (und dann jede (n−1)-mal), sondern alle gleichzeitig durchlaufen. Dafür muss man natürlich erst einmal eine sortierte Liste der Zeitpunkte aller Events in allen Stimmen anlegen (die enthält dann z. B. Tripel (Zeitpunkt Stimme Event)). Einfach wird das sicher auch nicht, aber es dürfte den Rechenaufwand wieder runterbringen, zumindest bei wenigen Zitaten. (Jaja, ich hab Informatik studiert und müsste auch eine anständige Laufzeitanalyse machen können, aber so wichtig ist das im Moment nicht, es geht nur um ein ungefähres Gefühl und da bin ich mir ja relativ sicher; deshalb spar ich mir die erstmal, nachliefern kann ich sie dann noch mit ner fertigen Lösung …)
Titel: Re: \quoteDuring und \articulate
Beitrag von: harm6 am Sonntag, 23. August 2015, 01:31
Ich habe noch nie mit `delay', etc gearbeitet. Kann Dir da also nicht groß helfen.

Aber hier was ich weiß:
`delay' wird ein paar mal in .scm-files verwendet, meist in Verbindung mit 'delay-stencil-evaluation'.
Außerdem gibt es:
https://github.com/openlilylib/openlilylib/blob/master/input-shorthands/late-evaluation-of-variables.ly (https://github.com/openlilylib/openlilylib/blob/master/input-shorthands/late-evaluation-of-variables.ly)

Mehr weiß ich dazu nicht.

Leider habe ich momentan auch sehr wenig Zeit. Wird wohl etwas dauern bis ich mich nochmal tiefer in das Problem versenken kann.


Gruß,
  Harm
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Sonntag, 23. August 2015, 02:03
Ich habe noch nie mit `delay', etc gearbeitet. Kann Dir da also nicht groß helfen.
Kein Problem. Du kannst ja auch nicht alles wissen ;) Vielen dank schonmal für die beiden folgenden Hinweise:
Zitat
Aber hier was ich weiß:
`delay' wird ein paar mal in .scm-files verwendet, meist in Verbindung mit 'delay-stencil-evaluation'.
Außerdem gibt es:
https://github.com/openlilylib/openlilylib/blob/master/input-shorthands/late-evaluation-of-variables.ly (https://github.com/openlilylib/openlilylib/blob/master/input-shorthands/late-evaluation-of-variables.ly)
(Genaueres zum ersten Hinweis sagt mir git grep.)
Zitat
Wird wohl etwas dauern bis ich mich nochmal tiefer in das Problem versenken kann.
Kein Problem, du hast mir in diesem Thread schon so sehr geholfen :) Außerdem hab ich ja jetzt erstmal drei verschiedene Ansätze, an denen ich selber ganz gut arbeiten kann (der letzte basiert glaub ich auf etwas ähnlichem wie deine ursprüngliche Lösung). Wenn ich dann mit denen irgendwann nicht mehr weiterkomm, kann ich mich ja immer noch mal hier oder auf der Mailingliste melden, und vielleicht hat ja auch jemand anders ne Idee ;)
Titel: Re: \quoteDuring und \articulate
Beitrag von: fugenkomponist am Samstag, 5. September 2015, 16:56
So, ich habe jetzt viel dran getan und im Endeffekt alles neu geschrieben. Dabei hab ich einiges über Scheme und LilyPond gelernt und ohne harms vorherige Komplettlösung als Vorlage zum Anschauen und Lernen wär das nicht möglich gewesen :)

Es kann jetzt in beliebige Richtungen zitiert werden und mit \articulate klappts auch. Es sind noch ein paar Kleinigkeiten optimierbar und ich weiß nicht, obs vielleicht doch an irgendeiner Stelle kaputtgehen kann (insbesondere hab ich noch keine Akkorde/Mehrstimmigkeit und merkwürdige Konstellationen von music-wrapper-music wie \tuplet, \grace und \relative getestet). Aber im Großen und Ganzen stimmts.

Hier (und im Anhang als transitiveReplaceDemo.ly) eine kleine Kostprobe:
\version "2.19.25"
\include "transitiveReplace.ily"
\include "articulate.ly"

violin = \relative {
  c'1~ c
  \quoteDuring "clarinet" s1 \quoteDuring "flute" s
  \quoteDuring "clarinet" s1 \quoteDuring "flute" s
}

flute = \relative {
  \quoteDuring "violin" s1 \quoteDuring "clarinet" s
  d'1~ d
  \quoteDuring "violin" s1 \quoteDuring "clarinet" s
}

klarinette = \relative {
  \quoteDuring "flute" s1 \quoteDuring "violin" s
  \quoteDuring "flute" s1 \quoteDuring "violin" s
  e'1~ e
}

\addQuote "violin"   \violin
\addQuote "flute"    \flute
% Bisher einziger bekannter Stolperstein:
% Unten muss jetzt \clarinet statt \klarinette verwendet werden.
\addQuote "clarinet" \klarinette

\replaceQuotes

\articulate
<<
  \new Staff \violin
  \new Staff \flute
  \new Staff \clarinet
>>