Autor Thema: Fallunterscheidung mit Scheme  (Gelesen 4171 mal)

stefanhuglfing

  • Member
Fallunterscheidung mit Scheme
« am: Sonntag, 30. März 2014, 17:11 »
ich mache gerade erste Schritte mit scheme und frage mich, warum der folgnde code nicht funktioniert:

\version "2.18.2"

Tondauer = #(define-music-function (parser location dur) (integer?)
  (let ((dur (if (= dur 0)
                 '#{ c'\breve #}
                 '(ly:make-duration (ly:intlog2 dur) 0 1 1) #{ { b' $dur } #} ))))   
 
{ \Tondauer 8 }

kann sein, dass ich euch schon auf die Nerven gehe, aber vielleicht könnt ihr mir helfen.

harm6

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #1 am: Sonntag, 30. März 2014, 18:41 »
Hallo,

bevor ich tiefer einsteige:
1. achte auf das log. Es gbt einen "end of file"-Fehler, d.h. in der Regel hast Du eine Klammer vergessen.
2. was genau möchtest Du erreichen? Noch genauer, was soll die Funktion ausgeben?

Dem Aufruf nach zu urteilen, { \Tondauer 8 }, soll sie eine (oder mehrere?) Note(n) mit der spezifierten Dauer zurückgeben.
Diese Noten wären nach dem jetzigen Stand natürlich hard-coded.

Damit ich verstehe, was Du möchtest, wäre es schön, wenn Du das mal gegenüberstellen könntest.
Z.B.
{ \Tondauer 8 }  = { b'8 }
Ist das richtig? Da schwirrt ja auch noch ein { c'\breve  } rum. Was soll damit geschehen?

Zitat
ich mache gerade erste Schritte mit scheme und frage mich, warum der folgnde code nicht funktioniert:
[...]
kann sein, dass ich euch schon auf die Nerven gehe, aber vielleicht könnt ihr mir helfen.

Du gehst keineswegs auf die Nerven.
Zumindest für mich ist das sehr viel interessanter, als auf Fragen zu reagieren deren Antworten leicht nachlesbar oder bei sorgfältigem Studium des eigenen Codes offensichtlich sind.

Gruß,
  Harm


stefanhuglfing

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #2 am: Sonntag, 30. März 2014, 20:32 »
Was ich eigentlich mache: Ich schreibe an einem Stück, bei dem bestimmte Tonfolgen immer wiederkehren, jedoch mit einer unterschiedlichen Anzahl von Tönen und Notenwerten, wie z.B.:
A A:  c4 d d e    c2 d e2 e4
B:     f2 a g
A:     c4 c d2 e8
B:     f4 f a g8
...

Dabei möchte ich ausnützen, dass sich vieles wiederholt, um Schreibarbeit zu sparen.

Aber wenn ich nicht einmal eine einfache Fallunterscheidung hinbringe, brauche ich ja gar nicht anzufangen.

Jetzt habe ich die fehlende Klammer eingefügt:

\version "2.18.2"

Tondauer = #(define-music-function (parser location dur) (integer?)
  (let ((dur (if (= dur 0)
                 '#{ c'\breve #}
                 '(ly:make-duration (ly:intlog2 dur) 0 1 1) #{ { b' $dur } #} ))))) 
 
{ \Tondauer 8 }

und bekomme schon weniger Fehlermeldungen.
Was die Funktion machen sollte:

1. Fall: die übergebene Zahl ist ungleich Null, dann soll ein b' mit dem entsprechenden Notenwert entstehen;
2. Fall: die übergebene Zahl ist Null, dann soll ein b' als Brevisnote entstehen;

Also:

{ \Tondauer 8 }  = { b'8 }
{ \Tondauer 4 }  = { b'4 }
{ \Tondauer 2 }  = { b'2 }
{ \Tondauer 1 }  = { b'1 }
{ \Tondauer 0 }  = { b' \breve }

harm6

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #3 am: Montag, 31. März 2014, 01:58 »
Hi,

erstmal vielen Dank für die weiteren Erläuterungen.
Ich sehe aber noch nicht wie es Schreibarbeit sparen wird...

Davon abgesehen, wie viel Zeit hast Du?
Ich würde gerne mit Dir Schritt für Schritt vorgehen und die Funktion entwickeln. Es muß Dir allerdings klar sein, daß ich in einer Arbeitswoche nicht so häufig kommunizieren kann. Wird also dauern.
Alternativ könnte ich eine Lösung entwickeln und posten...

Zu Deiner Funktion. Du bekommst die Meldung:
In procedure memoization in expression (let (#)):
[...]
d.h. da stimmt mit dem "let" was nicht.
Mittels "let" werden locale Variablen erstellt.
Du mußt aber auch, in der korrekten Syntax, angeben was gemacht werden soll.

Z.B.:
(define (addiere-etwas zu-etwas)
(let ((eins 1.1)
       (zwei 2.2))
  (+ zu-etwas eins zwei)))


Aufruf:
z.B.:
(addiere-etwas 2)
Ausgabe: 5.3

Diese procedure definiert "eins" als 1.1 und "zwei" als 2.2 als lokale Variablen.
Nachher werden diese Werte "zu-etwas" addiert.
Achte genau auf die zueinander passenden Klammern. Probiers aus in einem guile-interpreter oder in LilyPonds scheme-sandbox.
Aufruf der sandbox mit:
lilypond scheme-sandbox

In Deiner bisherigen Funktion fehlt was gemacht werden soll, bzw die Syntax/Klammersetzung ist falsch.

Ich empfehle bei der Entwicklung die verschiedenen display-Möglichkeiten ausgiebig zu nutzen.
Z.B.:
#(display-scheme-music #{ b'\breve #})
Ergibt:
(make-music
  'NoteEvent
  'duration
  (ly:make-duration -1 0 1)
  'pitch
  (ly:make-pitch 0 6 0))

Insoweit würde ich die brevis via -1 angeben.

Eine Möglichkeit die Tondauer, genauer den ersten Wert den ly:make-duration braucht, auszugeben wäre:

#(define (dur-log integer)
 (if (integer? integer)
     (cond ((> integer 0)
            (ly:intlog2 integer))
           ((>= integer -3) integer)
           (else (ly:error (_ "not a valid duration: ~a") integer)))
     (ly:error (_ "not a valid duration: ~a") integer)))

Teste in einem LilyPond-file mit:
#(write (dur-log 8))
#(write (dur-log 4))
#(write (dur-log 2))
#(write (dur-log 1))
#(write (dur-log 0))
#(write (dur-log -1))
#(write (dur-log -2))
#(write (dur-log -3))

Soweit für heute. ;)

Gruß,
  Harm

stefanhuglfing

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #4 am: Montag, 31. März 2014, 22:33 »
Schritt für Schritt vorgehen

das ist ganz in meinem Sinn.

Ich habe schon kleine Fortschritte gemacht. Mir ist eine Funktion gelungen, die keine kürzeren Noten als 1/16 zulässt.
(Ist zwar sinnlos, aber funktioniert)

\version "2.18.2"

Tondauer =
 #(
  define-music-function (parser location dauer) (integer?)
   (
    let ((dur (ly:make-duration (ly:intlog2 dauer) 0 1 1)))
        (if (< dauer 20)  #{ b' $dur #} #{ b'16 #}  ) 
   )
  )
 
\Tondauer 20

Warum aber funktioniert der folgnde code nicht?

\version "2.18.2"

Tondauer =
 #(
  define-music-function (parser location dauer) (integer?)
   (
    let
     ( if (< dauer 20) 
        ((dur (ly:make-duration (ly:intlog2 dauer) 0 1 1))  #{ b' $dur #} )
        #{ b'16 #} 
     ) 
   )
  )
 
\Tondauer 20

harm6

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #5 am: Montag, 31. März 2014, 23:29 »
Zitat
Warum aber funktioniert der folgnde code nicht?

\version "2.18.2"

Tondauer =
 #(
  define-music-function (parser location dauer) (integer?)
   (
    let
     ( if (< dauer 20) 
        ((dur (ly:make-duration (ly:intlog2 dauer) 0 1 1))  #{ b' $dur #} )
        #{ b'16 #} 
     ) 
   )
  )
 
\Tondauer 20

Nun, Du bekommst wieder die Meldung:
In procedure memoization in expression (let (if # # ...)):
[...]
Und in der Tat hast Du nach let direkt die Fallunterscheidung versucht. Klappt so nicht.
Nach let muß eine lokale Variable benannt und definiert werden, es gibt zwar auch named let, daß ist aber erstmal ohne Belang.

Im folgenden habe ich mal drei Möglichkeiten entworfen:

TondauerI benutzt let innerhalb der Fallunterscheidung.

In TondauerII wird im vorangestellten let immer die Tondauer berechnet aber später nur angewendet, falls die condition der Fallunterscheidung #t ergibt.

TondauerIII benutzt let* um das Argument der Funktion gemäß der condition zu revidieren. Dann wird darauf zugegriffen, um die Tondauer zu kreieren. (Deshalb let*, mit einfachem let können die lokalen Variablen nicht aufeinander zugreifen, sondern könnten erst im sog. body der Funktion wieder benutzt werden.)
Dann folgt was ausgegeben werden soll: der Ton mit der Tondauer.
Ich persönlich halte TondauerIII für die eleganteste Version :)

\version "2.18.0"

TondauerI =
#(define-music-function (parser location dauer) (integer?)
  (if (< dauer 20) 
      (let ((dur (ly:make-duration (ly:intlog2 dauer) 0 1 1)))
        #{ b' $dur #})
      #{ b'16 #}))
 
TondauerII =
#(define-music-function (parser location dauer) (integer?)
  (let ((dur (ly:make-duration (ly:intlog2 dauer) 0 1 1)))
    (if (< dauer 20) 
       #{ b' $dur #}
       #{ b'16 #})))

TondauerIII =
#(define-music-function (parser location dauer) (integer?)
  (let* ((dauer-rev (if (< dauer 20) dauer 16))
         (dur (ly:make-duration (ly:intlog2 dauer-rev) 0 1 1)))
    #{ b' $dur #})) 
 
\TondauerI 20
\TondauerII 20
\TondauerIII 20

HTH,
  Harm

stefanhuglfing

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #6 am: Dienstag, 1. April 2014, 22:55 »
Danke für deine Tipps bisher. Soweit hab ich es ausprobiert und kapiert.
Aber jetzt wird es kompliziert:

Ich möchte die Zahlen einer Liste der Reihe nach lesen.
Jede Zahl soll in eine Notenlänge umgewandelt werden und ein Ton mit dieser Länge geschrieben werden,
bis eine Null in der Liste kommt.

Es gibt ja keine vorgefertigten Schleifen in Scheme, sondern man muss es mit sich selbst aufrufenden Funktionen machen.
Das gelingt mir (noch) nicht. Deshalb habe ich mal einen Code geschrieben, in dem ich einfach Die Schlüsselwörter aus BASIC oder PASCAL verwende, damit du weißt, was ich meine.

Vielleicht kannst du es in Scheme übersetzen?

seqI =
 #(
   define-music-function (parser location Notenwerte) (list?)
    (
     let*
      (
       (n 0)
       (let*
        (
         REPEAT
          (dauer (list-ref Notenwerte n))
          (
           if (=dauer 0) () 
                         ((d (ly:make-duration (ly:intlog2 dauer) 0 1 1)) #{ f' $dauer  #} (+ n 1))
          )           
         UNTIL (= dauer 0)   
        )
       )     
      )
     )
  )

\seqI #'(2 2 2 0)

ich habe es selbst probiert, aber es hagelt Fehlermeldungen:

seqI =
 #(
   define-music-function (parser location Zaehler Notenwerte) (integer? list?)
       
       (let*
        (dauer (list-ref Notenwerte Zaehler))
        (if (= dauer 0) ()
                        ( (d (ly:make-duration (ly:intlog2 dauer) 0 1 1))
                          #{ f' $dauer  #}
                          (SeqI (+ Zaehler 1) Notenwerte) )
        )               
       ) 
   )
 
 
\seqI 0 #'(2 2 2 0)
« Letzte Änderung: Mittwoch, 2. April 2014, 08:56 von stefanhuglfing »

harm6

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #7 am: Mittwoch, 2. April 2014, 15:02 »
Zitat
Es gibt ja keine vorgefertigten Schleifen in Scheme, sondern man muss es mit sich selbst aufrufenden Funktionen machen.

Das ist beides nicht ganz richtig.

Zitat
Das gelingt mir (noch) nicht. Deshalb habe ich mal einen Code geschrieben, in dem ich einfach Die Schlüsselwörter aus BASIC oder PASCAL verwende, damit du weißt, was ich meine.

Vielen Dank, doch kenne ich mich weder mit BASIC noch PASCAL aus. Tatsächlich ist scheme die einzige Computersprache mit der ich umgehen kann. Hab' sie auch nur deshalb gelernt, damit ich LilyPond nach meinen Wünschen erweitern kann. ;)
Aber es ist ja offensichtlich was Du erreichen möchtest.

Zitat
ich habe es selbst probiert, aber es hagelt Fehlermeldungen:
[...]

Das eine Musikfunktion sich selber aufruft habe ich in dieser Form noch nicht gesehen. Ich bezweifle, daß man es kodieren könnte bzw daß es auch nur wünschenswert wäre ...

Stattdessen sollte die Musikfunktion einen musikalischen Ausdruck ausgeben. Bei der Erstellung dieses Ausdrucks kann natürlich alles mögliche verwendet werden.

Im folgenden habe ich mal fünf Möglichkeiten kodiert.

make-m-list-1 benutzt eine klassische Rekursion.
make-m-list-2 benutzt "named let" und ist damit auch selbstaufrufend.
make-m-list-3 vorverarbeitet die Liste mit den Notenlängen mittels der split-list-by-separator procedure, die in lily-library.scm zu finden ist. Diese neue Liste wird dann einfach mittels map verarbeitet, d.h. eine procedure wird auf jedes Element der neuen Liste angewendet und das Resultat als neue Liste ausgegeben.
make-m-list-4 ist ähnlich wie make-m-list-3, nur daß statt map fold-right verwendet wird
make-m-list-5 mag Dir, der Methode nach, am vertrautesten sein. Denn die do-procedure geht durch die Liste bis eine bestimmte Abbruchbedingung erfüllt ist. Eine klassische Schleife.
Allerdings wird so was von schemern eher mit Nase rümpfen betrachtet. Ist auch die längste Definition. :D

Jede dieser procedures gibt eine simple Liste aus. Um daraus Musik zu machen muß man im finalen Aufruf der Funktion noch make-sequential-music daraus machen, falls es das ist was Du möchtest.

Ich habe das ganze dann mal in separate Staffs einer StaffGroup gesetzt, damit man sehen kann, ob jede procedure wirklich dasgleiche ausgibt.

\version "2.18.0"

#(define (make-m-list-1 pitch duration-list)
  (define (helper p l1 l2)
   (if (or (null? l1) (= (car l1) 0))
       (reverse l2)
       (let ((dur (ly:make-duration (ly:intlog2 (car l1)) 0 1 1)))
         (helper pitch (cdr l1) (cons #{ $pitch $dur #} l2)))))
   (helper pitch duration-list '()))
   
#(define (make-m-list-2 pitch duration-list)
  (let loop ((l1 '())
             (l2 duration-list))
    (if (or (null? l2) (= 0 (car l2)))
        (reverse l1)
        (let ((dur (ly:make-duration (ly:intlog2 (car l2)))))
          (loop (cons #{ $pitch $dur #} l1) (cdr l2))))))
           
#(define (make-m-list-3 pitch duration-list)
  (let ((dur-list (split-list-by-separator duration-list (lambda (x) (= x 0)))))
    (map
      (lambda (d)
        (let ((dur (ly:make-duration (ly:intlog2 d) 0 1 1)))
          #{ $pitch $dur #}))
      (car dur-list))))
     
#(define (make-m-list-4 pitch duration-list)
  (let ((dur-list (split-list-by-separator duration-list (lambda (x) (= x 0)))))
    (fold-right
      (lambda (elem prev)
        (let ((dur (ly:make-duration (ly:intlog2 elem))))
          (cons #{ $pitch $dur #} prev)))
      '()
      (car dur-list))))
   
#(define (make-m-list-5 pitch duration-list)
  (do ((i 0 (1+ i))
       (l duration-list)
       (result-ls '()))
       
      ((or (= i (length l))
           (= (list-ref l i) 0))
       (reverse result-ls))
       
      (let ((dur (ly:make-duration (ly:intlog2 (list-ref l i)))))
        (set! result-ls
              (cons #{ $pitch $dur #}
                    result-ls)))))     
                   
seqI =
#(define-music-function (parser location Notenwerte) (list?)
#{
  \new StaffGroup
    <<
      \new Staff $(make-sequential-music (make-m-list-1 #{ f #} Notenwerte))
      \new Staff $(make-sequential-music (make-m-list-2 #{ g #} Notenwerte))
      \new Staff $(make-sequential-music (make-m-list-3 #{ a #} Notenwerte))
      \new Staff $(make-sequential-music (make-m-list-4 #{ b #} Notenwerte))
      \new Staff $(make-sequential-music (make-m-list-5 #{ c' #} Notenwerte))
    >>
#}
)

\seqI #'(2 2 8 0 1 2)

Weiter denkend, meine ich, daß Du die Liste mit den Notenwerten vor dem Aufruf irgeneiner der obigen procedures bearbeiten solltest, bzw Vorkehrungen treffen solltest, daß ly:intlog2 nicht aus der Kurve fliegt falls 0 in der Liste auftaucht. Aber auch damit wirklich alle Notenwerte verarbeitet werden können, einschließlich breve, maxima, longa ...
Und Du wirst wahrscheinlich nicht nur einen einzelnen pitch sondern eine Liste von pitches verarbeiten wollen ...
:D


Gruß,
  Harm
« Letzte Änderung: Mittwoch, 2. April 2014, 15:07 von harm6 »

stefanhuglfing

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #8 am: Mittwoch, 2. April 2014, 22:19 »
Da kommen jetzt viele Dinge vor, die ich noch nie gesehen habe.
Ich muss mich wohl durchfressen.

Gar nichts hilfreiches finde ich zu "make-sequential-music". Nur Beispiele, die es verwenden, aber nicht was es ist.

Ich kann deine Beispiele auch nicht einfach verwenden, weil sie so gabaut sind, dass ich sie mit meinen Mitteln nicht erweitern kann.

Ich erkläre mal, was ich eigentlich will.

Ein Stück, das ich letztes Jahr geschrieben habe (meine ersten Gehversuche mit lilypond), sieht so aus:

\version "2.18.2"

\header
 {
     title = \markup \center-align {"Deus, Deus meus"}
  subtitle = \markup \center-align {"Psalm 22 A"}
  composer = \markup \fontsize #-1 "GL 293, Samuel Wesley (1766-1837), Stefan Kratzer (März 2013)"
   tagline = ##f
 }
 
\paper 
 {
  myStaffSize = #20
  #(define fonts
    (make-pango-font-tree "Ubuntu Condensed"
                          "Ubuntu"
                          "Ubuntu"
                           (/ myStaffSize 20)))
 }



\include "gregorian.ly"
Tenor = \relative c'
 {
  \clef "G_8"
  c\breve c4 c c c b2 b  \divisioMaior
  c\breve a4 c b a gis2 gis \divisioMaior
  c\breve f4 f d d b2 b  \divisioMaior
  e\breve a,4 a a b2 a4 gis a2 a \finalis  \break
  c\breve c2 c4 b2 c  \divisioMaior
  c\breve c4 b a gis gis gis2 \divisioMaior \break
  c\breve c4 c c b2  \divisioMaior
  c\breve a4 c b a gis2 gis \divisioMaior \break
  c\breve f4 f d b2   \divisioMaior
  e\breve a,4 b b a gis a2 \finalis \break
  c\breve c4 c b2  \divisioMaior
  c\breve a2 c4 b a gis2 gis \divisioMaior
  c\breve c4 c c b b b2  \divisioMaior \break
  c\breve a2 c4 b b a gis2 \divisioMaior
  c4 f f d b2  \divisioMaior
     a4 b a gis a2 a \finalis \break
  c\breve f4 d b2  \divisioMaior
  a4 b a gis a2 a \finalis \break
  c\breve c2 c4 c b b b2  \divisioMaior
     c4 a2 a4 c b a gis2 gis \divisioMaior \break
  c\breve c4 c c b2 b  \divisioMaior
  c\breve a2 c b a gis2 \divisioMaior \break
  c\breve f4 d b2 b  \divisioMaior
  e\breve a,4 b a gis a2 \finalis \break
  c\breve c4 c c c b2  \divisioMaior
  c\breve a4 c b ( a ) gis2 \divisioMaior \break
  c\breve f4 d b b b2 \divisioMaior
     a4 a b a gis a2 a \finalis
 }

Bariton = \relative c'
 {
  \clef "G_8"
  e,\breve d4 e f f f2 f 
  e\breve f4 a f d b2 b
  e\breve a4 a f f d2 d 
  g\breve f4 f f f2 e4 d c2 c
  e\breve d4 (e) f4 f2 e 
  e\breve a4 f d b b b2
  e\breve d4 e f f2
  e\breve f4 a f d b2 b
  e\breve a4 a f d2   
  g\breve f4 f f e d c2
  e\breve d4 e f2
  e\breve f2 a4 f d b2 b
  e\breve d4 e f f f f2 
  e\breve f2 a4 f f d b2
  e4 a a f d2 
     f4 f e d c2 c
  e\breve a4 f d2 
  f4 f e d c2 c
  e\breve d4 ( e ) f f f f f2 
     e4 f2 e4 a f d b2 b
  e\breve d4 e f f2 f 
  e\breve f2 a f d b2
  e\breve a4 f d2 d 
  g\breve f4 f e d c2
  e\breve d4 e f f f2 
  e\breve f4 a f ( d ) b2
  e\breve a4 f d d d2 
     e4 f f e d c2 c
 }

Bass = \relative c'
 {
  \clef "F"
  a,\breve a4 a d d g,2 g  \divisioMaior
  c\breve f4 e d f e2 e \divisioMaior
  a,\breve d4 d a a g2 g  \divisioMaior
  c\breve f4 f f d2 e4 b a2 a ^\markup{ \sans \bold KV }  \finalis
  a\breve a2  d4 g,2 c  \divisioMaior
  c\breve e4 d f e e e2  \divisioMaior
  a,\breve a4 a d g,2  \divisioMaior
  c\breve f4 e d f e2 e \divisioMaior
  a,\breve d4 d a g2  \divisioMaior
  c\breve f4 d d e b a2 ^\markup{ \sans \bold KV } \finalis
  a\breve a4 a g2  \divisioMaior
  c\breve f2 e4 d f e2 e \divisioMaior
  a,\breve a4 a d g, g g2  \divisioMaior
  c\breve f2 e4 d d f e2 \divisioMaior
  a,4 d d a g2  \divisioMaior
     f'4 d e b a2 a ^\markup{ \sans \bold KV }  \finalis
  a\breve d4 a g2  \divisioMaior
  f'4 d e b a2 a ^\markup{ \sans \bold "      KV" } \finalis
  a\breve a2 d4 d g, g g2  \divisioMaior
     c4 f2 c4 e d f e2 e \divisioMaior
  a,\breve a4 a d g,2 g  \divisioMaior
  c\breve f2 e d f e2 \divisioMaior
  a,\breve d4 a g2 g  \divisioMaior
  c\breve f4 d e b a2 ^\markup{ \sans \bold "      KV" } \finalis
  a\breve a4 a d d g,2  \divisioMaior
  c\breve f4 e d ( f ) e2 \divisioMaior
  a,\breve d4 a g g g2  \divisioMaior
      c4 d d c b a2 a ^\markup{ \sans \bold "      KV" } \finalis
 }

Text = \lyricmode
 {
  \override LyricText #'font-size = #0.5
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "Mein Gott, mein " \underline Gott ", warum"} 
  hast du mich ver -- las -- sen,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"bist fern meinem " \underline  Schreien", den"}
  Wor -- ten mei -- ner Kla -- ge?
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"Mein " \underline  Gott ", ich rufe bei  " \underline  Tag ", doch"}
  du gibst kei -- ne Ant -- wort;
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"ich rufe bei " \underline  Nacht }
  und fin -- de doch kei -- ne Ru -- he.
  \once \override LyricText #'self-alignment-X = #-1
  "Aber" du bist hei -- lig,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"du " \underline  thronst " über"}
  dem Lob -- preis Is -- ra -- els.
  \once \override LyricText #'self-alignment-X = #-1
  "Dir haben unsere"
  Vä -- ter ver -- traut,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"sie haben ver- " \underline traut ", und"}
  du hast sie ge -- ret -- tet.
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"Zu dir riefen " \underline sie " und" }
  wur -- den be -- freit,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"sie hofften auf " \underline dich } 
  und wur -- den nicht ent -- täuscht.
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"Ich aber bin ein " \underline  Wurm}
  und kein Mensch,
  \once \override LyricText #'self-alignment-X = #-1
  "der Leute"
  Spott, vom Volk ver -- ach -- tet.
  \once \override LyricText #'self-alignment-X = #-1
  "Alle die mich"
  se -- hen, ver -- la -- chen mich,
  \once \override LyricText #'self-alignment-X = #-1
  "verziehen den"
  Mund und schüt -- teln den Kopf:
  \once \override LyricText #'self-alignment-X = #-1
  "Ver"
  -- trau doch auf Gott,
  der kann dir ja hel -- fen!
  \once \override LyricText #'self-alignment-X = #-1
  "Lässt er"
  dich im Stich?
  \once \override LyricText #'self-alignment-X = #-1
  Du bist doch sein Lieb -- ling!
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {  \underline Du " bist es, der mich aus dem"}
  Schoß mei -- ner Mut -- ter zog,
  \once \override LyricText #'self-alignment-X = #-1
  "mich" barg an der Brust der Mut -- ter.
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "Ohne "  \underline dich }
  kann ich nicht at -- men;
  \once \override LyricText #'self-alignment-X = #-1
  "seit meiner Ge" --
  burt bist du mein Gott.
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"Sei mir nicht " \underline  fern ", denn die"}
  Not ist na -- he,
   \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"und " \underline nie }
  -- mand ist da, der hilft.
  \once \override LyricText #'self-alignment-X = #-1
  "Ehre sei dem"
  Va -- ter und dem Sohn
  \once \override LyricText #'self-alignment-X = #-1
  "und dem"
  hei -- li -- gen Geist,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat {"wie im " \underline An "fang so auch"}
  jetzt und al -- le Zeit
  \once \override LyricText #'self-alignment-X = #-1
  und in E -- wig -- keit, A -- men.
 }

\score
 {
  <<
   \new ChoirStaff
    <<
     \new Staff 
      <<
       \new Voice = "melody" \Tenor \Bariton
       \new Lyrics = "one" \lyricsto melody \Text
      >>
   
     \new Staff  \Bass
    >> 
  >>
 
  \layout
   {
    ragged-last = ##f
    \override LyricHyphen #'minimum-distance = #1.0
    \context
     {
      \Staff
      \remove "Time_signature_engraver"
      \remove "Bar_engraver"
      \override Stem #'stencil = ##f
      \override NoteColumn #'ignore-collision = ##t     
     }
   }
 }
 

(Heuer kommt etwas ähnliches dran.) Ich würde den code für das Stück oben aber lieber ungefähr so schreiben:

SeqI = #(define(....)
               
   .....
     c' c' c' c' b   
     e  d  e  f  f
     a, a, a, d  g,
           \divisioMaior
   .....)

SeqII = #(define(....)
               
   .....
     c' a c' b a gis
     e  f a  f d b,
     c  f e  d f e 
           \divisioMaior
   .....)

SeqIII = #(define(....)
               
   .....
     c' f' d' b
     e  a  f  d
     a, d  a, g,     
           \divisioMaior
   .....)

SeqIV = #(define(....)
               
   .....
     e' a b a gis a
     g  f f e d   c
     c  f d e b,  a,
           ^\markup{ \sans \bold KV }  \finalis
   .....)
   
   
\SeqI #'(-1 0 4 0 4 0 4 4 0 2 2 0)
\SeqII #'(-1 0 4 0 4 0 4 0 4 0 2 2 0)
\SeqIII #'(-1 0 4 4 0 4 4 0 2 2 0)
\SeqIV #'(-1 0 4 4 4 0 2 4 0 4 0 2 2 0)

% die nächste Sequenz I muss ich ausschreiben, weil ein Sonderfall auftritt:

% Tenor
{ c\breve c2 c4 b2 c }
% Bariton
{ e\breve d4 (e) f4 f2 e }
%Bass
{ a\breve a2  d4 g,2 c }

\SeqII #'(-1 0 4 0 4 0 4 0 4 4 0 2 0)
\SeqIII #'(-1 0 4 0 4 0 4 0 2 0)
\SeqIV #'(-1 0 4 0 4 0 4 0 4 0 2 2 0)

\SeqI #'(...)
\SeqII  ...
  ...
 
\Text = ....
 
\score
 {
  <<
   \new ChoirStaff
    <<
     ....
     ....
    >> 
  >>
 
  \layout
   {
    ....
   }
   
 }

Erklärung:
 Die Funktion SeqI soll Tenor/Bariton und Bass schreiben (Den Tonvorrat schreibe ich in den body der Funktion rein, dort würde eine Schleife die   entsprechende Anzahl von Noten der ersten Tonhöhe schreiben, nach jeder Null in der Liste müsste eine ähnliche Schleife die nächsten Töne schreiben)
 
SeqII soll ebenfalls Tenor/Bariton und Bass schreiben aber hinter die Noten von SeqI, nicht darunter.
Das bringe ich nicht hin.

 

harm6

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #9 am: Samstag, 5. April 2014, 23:51 »
Hallo,

ich habe noch ein bißchen weiter dran gearbeitet.
Zur Demonstration habe ich Deine erste Seite neu getippt. (Bild im Anhang)
Ich hoffe es kommt dem was Du haben willst zumindest nahe. Man kann jetzt auch punktierte Notenwerte eingeben. (Als Beispiel habe ich den Anfang etwas verändert.)
'articulations werden aus der Eingabe übernommen.
Für mehr Erklärungen bin ich heute einfach zu müde.
Schau mal, ob Du mit dem Code klar kommst ...

\version "2.18.2"

\include "gregorian.ly"
 
#(use-modules (ice-9 regex))
%#(use-modules (ice-9 pretty-print))

%% c/p from define-markup-commands.scm
#(define (parse-simple-duration duration-string)
  "Parse the `duration-string', e.g. ''4..'' or ''breve.'',
and return a (log dots) list."
  (let ((match (regexp-exec (make-regexp "(breve|longa|maxima|[0-9]+)(\\.*)")
                            duration-string)))
    (if (and match (string=? duration-string (match:substring match 0)))
        (let ((len (match:substring match 1))
              (dots (match:substring match 2)))
          (list (cond ((string=? len "breve") -1)
                      ((string=? len "longa") -2)
                      ((string=? len "maxima") -3)
                      (else (log2 (string->number len))))
                (if dots (string-length dots) 0)))
        (ly:error (_ "not a valid duration string: ~a") duration-string))))
       
#(define (make-duration-from-number-or-string dur)
  (let* ((duration-string
           (cond ((and (integer? dur) (>= dur 0)) (number->string dur))
                 ((and (integer? dur) (= dur -1)) "breve")
                 ((and (integer? dur) (= dur -2)) "longa")
                 ((and (integer? dur) (= dur -3)) "maxima")
                 ((string? dur) dur)
                 (else (ly:error (_ "not a valid duration: ~a") dur))))
         (log-dots-list (parse-simple-duration duration-string)))
   (ly:make-duration (car log-dots-list) (cadr log-dots-list) 1 1)))

#(define (make-simple-pitch-list simple-music)
  (let ((music (if (music-is-of-type? simple-music 'relative-octave-music)
                   (ly:music-property simple-music 'element)
                   simple-music)))
    (map
      (lambda (m)
        (ly:music-property m 'pitch))
      (event-chord-notes music))))
   
#(define (make-simple-articulations-list simple-music)
  (let ((music (if (music-is-of-type? simple-music 'relative-octave-music)
                   (ly:music-property simple-music 'element)
                   simple-music)))
    (map
      (lambda (m)
        (ly:music-property m 'articulations))
      (event-chord-notes music))))
         
#(define (make-m-list music duration-list)
  (let ((duration-log-list
          (map
            (lambda (i) (make-duration-from-number-or-string i))
            duration-list))
        (pitch-list (make-simple-pitch-list music))
        (arts-list (make-simple-articulations-list music)))
    (map
      (lambda (p d a) #{ $p $d $@a #})
      pitch-list
      duration-log-list
      arts-list)))
     
seq =
#(define-music-function (parser location music Notenwerte to-append)
     (ly:music? list? ly:music?)

  (let* ((new-mus
           (map
             (lambda (m) (make-sequential-music (make-m-list m Notenwerte)))
             (ly:music-property music 'elements))))

    #{
      \context ChoirStaff
      <<
      \context Staff = "UP"
        <<
        \context Voice = "1" { $(car new-mus) $to-append }
        \context Voice = "2" { $(cadr new-mus) $to-append }
        >>
        \context Staff = "DOWN" { \clef bass $(caddr new-mus)  $to-append }
      >>
    #}))

\paper {
  myStaffSize = #20
  #(define fonts
    (make-pango-font-tree "Ubuntu Condensed"
                          "Ubuntu"
                          "Ubuntu"
                           (/ myStaffSize 20)))
}
   
\layout {
  \context {
    \Staff
    \remove "Time_signature_engraver"
    \remove "Bar_engraver"
    \override Stem #'stencil = ##f
    \override NoteColumn #'ignore-collision = ##t     
  }
}
 
\header {
  title = \markup \center-align { "Deus, Deus meus" }
  subtitle = \markup \center-align { "Psalm 22 A" }
  composer =
  \markup \fontsize #-1 "GL 293, Samuel Wesley (1766-1837), Stefan Kratzer (März 2013)"
  tagline = ##f
}
   
txt = \lyricmode {
  \override LyricText #'font-size = #0.5
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "Mein Gott, mein " \underline Gott ", warum" } 
  hast du mich ver -- las -- sen,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "bist fern meinem " \underline  Schreien", den" }
  Wor -- ten mei -- ner Kla -- ge?
  \once \override LyricText #'self-alignment-X = #-1
  \markup
    \concat {
      "Mein " \underline  Gott ", ich rufe bei  " \underline Tag ", doch"
    }
  du gibst kei -- ne Ant -- wort;
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "ich rufe bei " \underline  Nacht }
  und fin -- de doch kei -- ne Ru -- he.
  \once \override LyricText #'self-alignment-X = #-1
  "Aber" du bist hei -- lig,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "du " \underline  thronst " über" }
  dem Lob -- preis Is -- ra -- els.
  \once \override LyricText #'self-alignment-X = #-1
  "Dir haben unsere"
  Vä -- ter ver -- traut,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "sie haben ver- " \underline traut ", und" }
  du hast sie ge -- ret -- tet.
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "Zu dir riefen " \underline sie " und" }
  wur -- den be -- freit,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "sie hofften auf " \underline dich } 
  und wur -- den nicht ent -- täuscht.
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "Ich aber bin ein " \underline  Wurm }
  und kein Mensch,
  \once \override LyricText #'self-alignment-X = #-1
  "der Leute"
  Spott, vom Volk ver -- ach -- tet.
  \once \override LyricText #'self-alignment-X = #-1
  "Alle die mich"
  se -- hen, ver -- la -- chen mich,
  \once \override LyricText #'self-alignment-X = #-1
  "verziehen den"
  Mund und schüt -- teln den Kopf:
  \once \override LyricText #'self-alignment-X = #-1
  "Ver"
  -- trau doch auf Gott,
  der kann dir ja hel -- fen!
  \once \override LyricText #'self-alignment-X = #-1
  "Lässt er"
  dich im Stich?
  \once \override LyricText #'self-alignment-X = #-1
  Du bist doch sein Lieb -- ling!
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { \underline Du " bist es, der mich aus dem" }
  Schoß mei -- ner Mut -- ter zog,
  \once \override LyricText #'self-alignment-X = #-1
  "mich" barg an der Brust der Mut -- ter.
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "Ohne "  \underline dich }
  kann ich nicht at -- men;
  \once \override LyricText #'self-alignment-X = #-1
  "seit meiner Ge" --
  burt bist du mein Gott.
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "Sei mir nicht " \underline  fern ", denn die" }
  Not ist na -- he,
   \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "und " \underline nie }
  -- mand ist da, der hilft.
  \once \override LyricText #'self-alignment-X = #-1
  "Ehre sei dem"
  Va -- ter und dem Sohn
  \once \override LyricText #'self-alignment-X = #-1
  "und dem"
  hei -- li -- gen Geist,
  \once \override LyricText #'self-alignment-X = #-1
  \markup \concat { "wie im " \underline An "fang so auch" }
  jetzt und al -- le Zeit
  \once \override LyricText #'self-alignment-X = #-1
  und in E -- wig -- keit, A -- men.
 }

KV = \markup{ \sans \bold KV }   

\relative c <<
 {
 \seq
        {                               
          { c'' c c c c b b }
          { e, d e f f f f } 
          { a,, a a d d g, g } 
        }                               
        #'("breve" 4 4 4 4 "2." "2..")
        \divisioMaior
 \seq
        {           
         { c'' a c b a gis gis }
         { e f a f d b b }
         { c, f e d f e e }
        }
        #'(-1 4 4 4 4 2 2)
        \divisioMaior
 \seq
        {           
         { c'' f f d d b b }
         { e, a a f f d d }
         { a, d d a a g g }
        }
        #'(-1 4 4 4 4 2 2)
        \divisioMaior
 \seq
        {           
         { e''' a, a a b a gis a a }
         { g f f f f e d c c }
         { c, f f f d e b a a^\KV }
        }
        #'(-1 4 4 4 2 4 4 2 2)
        { \finalis \break }
 
%% Ausnahme:
%      \context ChoirStaff
       <<
       \context Staff = "UP"
         <<
         \context Voice = "1" {
          c''\breve c2 c4 b2 c
          \divisioMaior
         }
         \context Voice = "2" {
          e,\breve d4( e) f f2 e
         }
         >>
         \context Staff = "DOWN" {
          \clef bass
          a,,\breve a2 d4 g,2 c
          \divisioMaior
         }
       >>
       
 \seq
        {           
         { c'' c b a gis gis gis }
         { e a f d b b b }
         { c, e d f e e e }
        }
        #'(-1 4 4 4 4 2 2)
        { \divisioMaior \break }
 
 \seq
        {           
         { c'' c c c b }
         { e, d e f f }
         { a,, a a d g, }
        }
        #'(-1 4 4 4 2)
        \divisioMaior
       
 \seq
        {           
         { c'' a c b a gis gis }
         { e f a f d b b }
         { c, f e d f e e }
        }
        #'(-1 4 4 4 4 2 2)
        \divisioMaior
       
 \seq
        {           
         { c'' f f d b }
         { e, a a f d }
         { a, d d a g }
        }
        #'(-1 4 4 4 2)
        \divisioMaior
       
 \seq
        {           
         { e''' a, b b a gis a }
         { g f f f e d c }
         { c, f d d e b a^\KV }
        }
        #'(-1 4 4 4 4 4 2)
        \finalis
       
 \seq
        {           
         { c'' c c b  }
         { e, d e f }
         { a,, a a g }
        }
        #'(-1 4 4 2)
        \finalis
 }
 
 \new Lyrics \with { alignBelowContext = #"UP" } \lyricsto "1" \txt
>>

HTH,
  Harm

stefanhuglfing

  • Member
make-sequential-music
« Antwort #10 am: Freitag, 11. April 2014, 21:43 »
Du bist ja unglaublich fleißig!
Der Schlüssel für mein Verständnis wäre eine Erklärung für die Funktion

make-sequential-music 

Kann ich darüber irgendwo etwas lesen?

harm6

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #11 am: Freitag, 11. April 2014, 23:19 »
Zitat
Der Schlüssel für mein Verständnis wäre eine Erklärung für die Funktion
make-sequential-music
Kann ich darüber irgendwo etwas lesen?

Eigentlich nicht.
Am ehesten:
http://lilypond.org/doc/v2.19/Documentation/extending-big-page#importing-scheme-in-lilypond

Dir muß klar sein, daß wir hier die primäre Eingabe völlig neu gestalten und dann alles ganz neu zusammensetzen.
Das geht schon, aber man braucht ein paar tools, die nicht so geläufig sind.

Betrachte z.B.

Zitat
   m = { c''2 e'' }
   #(display-scheme-music m)

Retourniert:
Zitat
(make-music
  'SequentialMusic
  'elements
  (list (make-music
          'NoteEvent
          'duration
          (ly:make-duration 1 0 1)
          'pitch
          (ly:make-pitch 1 0 0))
        (make-music
          'NoteEvent
          'pitch
          (ly:make-pitch 1 2 0)
          'duration
          (ly:make-duration 1 0 1))))

Also: make-music, dann der Typ (SequentialMusic), dann kommt das 'elements-music-property, eine Liste dessen was in der Musik enthalten ist.

Mit
Zitat
  (event-chord-notes m)
  #(display-scheme-music (event-chord-notes m))
kann man diese Liste auch direkt erhalten, zumindest in diesem einfachen Beispiel.
(event-chord-notes ist zwar eigentlich für EventChords gedacht funktioniert aber hier auch. :) )

make-sequential-music ist definiert in music-functions.scm als:
Zitat
  (define-public (make-sequential-music elts)
    (make-music 'SequentialMusic
                'elements elts))
D.h. als quasi Kurzfassung von (make-music 'SequentialMusic 'elements ... )
(Um das Studium der .ly und .scm Dateien wirst Du nicht immer herum kommen. :) )

Hier nochmal das obige zusammengestellt, sowie weiteres Anschauungsmaterial:

\version "2.19.3"

m = { c''2 e'' }

#(display-scheme-music m)
#(display-scheme-music (event-chord-notes m))

$(make-sequential-music (event-chord-notes m))

$(make-simultaneous-music (event-chord-notes m))

$(make-event-chord (event-chord-notes m))

Gruß,
  Harm


stefanhuglfing

  • Member
Re: Fallunterscheidung mit Scheme
« Antwort #12 am: Dienstag, 15. April 2014, 12:55 »
ich habe es jetzt im Prinzip so, wie ich es haben will: Ich muss nur noch die Dauer der Noten eingeben. Die Tonhöhe ist in Funktionen ausgelagert.

Allerdings gibt es noch einige Probleme:
 - Ich kann keine Taktstriche machen das habe ich inzwischen geschafft (und den code unten erneuert);
 - Ich weiß nicht, wie ich Sonderfälle unterbringe ist mir jetzt auch gelungen (siehe code unten);

 - aber Brevis-Noten bringe ich noch nicht rein. das geht jetzt auch (siehe code).

\version "2.18.2"

\paper 
 {
  myStaffSize = #20
  #(define fonts
    (make-pango-font-tree "Ubuntu Condensed"
                          "Ubuntu"
                          "Ubuntu"
                           (/ myStaffSize 20)))
 }

\include "gregorian.ly"
   
#(define (make-m-list-5 pitch duration-list)
  (do ((i 0 (1+ i))
       (l duration-list)
       (result-ls '()))
       
      ((or (= i (length l))
           (= (list-ref l i) 0))
       (reverse result-ls))
       
      (let ((dur (ly:make-duration (ly:intlog2 (list-ref l i)))))
        (set! result-ls
              (cons #{ $pitch $dur #}
                    result-ls)))))     
                   
TenA =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4)
  (list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ c' #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ c' #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ c' #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ b  #} Notenwerte4))
 #}
 )

BarA =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4)
  (list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ d  #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ e  #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ f  #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ f  #} Notenwerte4))
 #}
 )

BasA =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4)
  (list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ a, #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ a,   #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ d   #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ g,  #} Notenwerte4))
 #}
 )

TenB =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4 Notenwerte5)
  (list? list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ a  #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ c' #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ b  #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ a  #} Notenwerte4))
   $(make-sequential-music (make-m-list-5 #{ gis#} Notenwerte5))
 #}
)

BarB =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4 Notenwerte5)
  (list? list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ f  #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ a  #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ f  #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ d  #} Notenwerte4))
   $(make-sequential-music (make-m-list-5 #{ b,   #} Notenwerte5))
 #}
 )

BasB =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4 Notenwerte5)
  (list? list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ f   #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ e   #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ d   #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ f   #} Notenwerte4))
   $(make-sequential-music (make-m-list-5 #{ e   #} Notenwerte5))   
 #}
 )

TenC =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3)
  (list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ f' #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ d' #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ b  #} Notenwerte3))
 #}
)

BarC =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3)
  (list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ a  #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ f  #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ d  #} Notenwerte3))
 #}
 )

BasC =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3)
  (list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ d   #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ a,  #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ g,  #} Notenwerte3))
 #}
 )

TenD =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4 Notenwerte5)
  (list? list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ a  #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ b  #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ a  #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ gis#} Notenwerte4))
   $(make-sequential-music (make-m-list-5 #{ a  #} Notenwerte5))
 #}
)

BarD =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4 Notenwerte5)
  (list? list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ f  #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ f  #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ e  #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ d  #} Notenwerte4))
   $(make-sequential-music (make-m-list-5 #{ c  #} Notenwerte5))
 #}
 )

BasD =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4 Notenwerte5)
  (list? list? list? list? list?)
 #{
   $(make-sequential-music (make-m-list-5 #{ f   #} Notenwerte1))
   $(make-sequential-music (make-m-list-5 #{ d   #} Notenwerte2))
   $(make-sequential-music (make-m-list-5 #{ e   #} Notenwerte3))
   $(make-sequential-music (make-m-list-5 #{ b,  #} Notenwerte4))
   $(make-sequential-music (make-m-list-5 #{ a,  #} Notenwerte5))   
 #}
 )

seqA =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4)
  (list? list? list? list?)
    #{
      \context ChoirStaff
      <<
      \context Staff = "UP"
        <<
        \context Voice = "1"
         {
          \clef"G_8"
          \voiceOne { c'\breve }
          \TenA #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4 
          \divisioMaior
         }
        \context Voice = "2"
         {
           \voiceTwo { e\breve }
           \BarA #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4
         }
        >>
        \context Staff = "DOWN"
         {
          \clef bass
          { a,\breve }
          \BasA #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4 
          \divisioMaior
         }
      >>
    #}
 )

seqB =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4 Notenwerte5)
  (list? list? list? list? list?)
    #{
      \context ChoirStaff
      <<
      \context Staff = "UP"
        <<
        \context Voice = "1"
         {
          {c'\breve }
          \TenB #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4 #Notenwerte5 
          \divisioMaior
         }
        \context Voice = "2"
         {
          { e\breve }
          \BarB #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4 #Notenwerte5
         }
        >>
        \context Staff = "DOWN"
         {
          \clef bass
          { c\breve }
          \BasB #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4 #Notenwerte5 
          \divisioMaior
         }
      >>
    #}
 )

seqC =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3)
  (list? list? list?)
    #{
      \context ChoirStaff
      <<
      \context Staff = "UP"
        <<
        \context Voice = "1"
         {
          { c'\breve }
          \TenC #Notenwerte1 #Notenwerte2 #Notenwerte3
          \divisioMaior
         }
        \context Voice = "2"
         {
          { e\breve } 
          \BarC #Notenwerte1 #Notenwerte2 #Notenwerte3
         }
        >>
        \context Staff = "DOWN"
         {
          \clef bass
          { a,\breve }
          \BasC #Notenwerte1 #Notenwerte2 #Notenwerte3 
          \divisioMaior
         }
      >>
    #}
 )

seqD =
#(define-music-function
  (parser location Notenwerte1 Notenwerte2 Notenwerte3 Notenwerte4 Notenwerte5)
  (list? list? list? list? list?)
    #{
      \context ChoirStaff
      <<
      \context Staff = "UP"
        <<
        \context Voice = "1"
         {
          { e'\breve }
          \TenD #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4 #Notenwerte5
          \finalis
         }
        \context Voice = "2"
         {
          { g\breve }
          \BarD #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4 #Notenwerte5
         }
        >>
        \context Staff = "DOWN"
         {
          \clef bass
          { c\breve }
          \BasD #Notenwerte1 #Notenwerte2 #Notenwerte3 #Notenwerte4 #Notenwerte5
          \finalis \break
         }
      >>
    #}
 )

Ausnahme =
#(define-music-function (parser location Tenor Bariton Bass) (ly:music? ly:music? ly:music?)
  #{
    \context ChoirStaff
     <<
      \context Staff = "UP"
        <<
        \context Voice = "1"
         {
          $Tenor
          \divisioMaior
         }
        \context Voice = "2"
          $Bariton
        >>
        \context Staff = "DOWN"
         {
          $Bass
          \divisioMaior
         }
      >>
  #} 
 )

links = { \once \override LyricText #'self-alignment-X = #-1 }

Text = \lyricmode
 {
  \override LyricText #'font-size = #0.5
  \links \markup \concat { "Mein Gott, mein " \underline Gott ", warum"} 
  hast du mich ver -- las -- sen,
  \links \markup \concat {"bist fern meinem " \underline  Schreien", den"}
  Wor -- ten mei -- ner Kla -- ge?
  \links \markup \concat {"Mein " \underline  Gott ", ich rufe bei  " \underline  Tag ", doch"}
  du gibst kei -- ne Ant -- wort;
  \links \markup \concat {"ich rufe bei " \underline  Nacht }
  und fin -- de doch kei -- ne Ru -- he.
  \links "Aber" du bist hei -- lig,
  \links \markup \concat {"du " \underline  thronst}
  ü -- ber dem Lob -- preis Is -- ra -- els.
  \links "Dir haben unsere" Vä -- ter ver -- traut,
  \links \markup \concat {"sie haben ver- " \underline traut ", und"}
  du hast sie ge -- ret -- tet.
  \links \markup \concat {"Zu dir riefen " \underline sie " und" }
  wur -- den be -- freit,
  \links \markup \concat {"sie hofften auf " \underline dich } 
  und wur -- den nicht ent -- täuscht.
 }

  <<
   {
    \seqA  #'(4 0)     #'(4 0)   #'(4 4 0) #'(2 2 0)
    \seqB  #'(4 0)     #'(4 0)   #'(4 0)   #'(4 0)  #'(2 2 0) 
    \seqC  #'(4 4 0)   #'(4 4 0) #'(2 2 0)
    \seqD  #'(4 4 4 0) #'(2 0)   #'(4 0)   #'(4 0)  #'(2 2 0)
   
    \Ausnahme
     { c'\breve c'2     c'4 b2  c' }         
     { e \breve d4 (e4) f4  f2  e  }
     { a,\breve a,2     d4  g,2 c  }
     
    \Ausnahme
     { c'\breve c'4 c' c' b a gis gis gis2 }         
     { e \breve a4  a  a  f d b,  b,  b,2 }
     { c\breve  f4  f  e  d f e   e   e2 } 
     
    \seqA  #'(4 0)   #'(4 0)   #'(4 0) #'(2 0) 
    \seqB  #'(4 0)   #'(4 0)   #'(4 0) #'(4 0)  #'(2 2 0) 
    \seqC  #'(4 4 0) #'(4 0)   #'(2 0)
    \seqD  #'(4 0)   #'(4 4 0) #'(4 0) #'(4 0)  #'(2 0)
   
   % usw.
   
   }
 
   \new Lyrics \with { alignBelowContext = #"UP" } \lyricsto "1" \Text
  >>

  \layout
   {
    \context
     {
      \Staff
      \remove "Time_signature_engraver"
      \remove "Bar_engraver"
      \override Stem #'stencil = ##f
     }
   } 

Der Code ist jetzt lang geworden: für die Sequenzen ABCD mal drei Stimmen brauche ich schon mal 12 Funktionen, die alle fast das gleiche machen. Wenn ich gut Programmieren könnte, würde mich der Ehrgeiz packen und ich würde versuchen, alle Fälle mit einer Funktion zu erledigen.

Vielleicht hast du Zeit und Lust, Harm.

« Letzte Änderung: Dienstag, 22. April 2014, 15:57 von stefanhuglfing »