Autor Thema: \tacetUntil  (Gelesen 4561 mal)

fugenkomponist

  • Gast
\tacetUntil
« am: Dienstag, 14. Juli 2015, 00:17 »
Hallo allerseits,

ich hatte heute folgende Idee: es wär doch schön, wenn man (z. B. in Orchesterstücken mit vielen Taktwechseln und wenig Schlagwerkeinsätzen oder beim Komponieren) sagen könnte „Ab hier will ich jetzt ne Pause bis Takt X.“ oder auch „… bis Probenziffer Y.“

Ich hab einiges rumprobiert, werd aber nicht so richtig schlau und hab nichts Sinnvolles zum Laufen gebracht. Meine Ideen bisher:
• Mit ly:context-property kriegt man Dinge wie die aktuelle Taktzahl und -länge raus. Dafür brauch ich aber nen Kontext. Hab was gelesen über \applyContext, hab aber keine Ahnung, ob das die richtige Herangehensweise ist.
• Geht das evtl. mit nem neuen Engraver? Wenn ja, wie wird der dann angesprochen? Was ich vermute: Ich müsste ein neues TacetEvent definieren (hab aber keine Ahnung, wie) und dann würde \tacetUntil einfach ein solches setzen, der TacetEngraver darauf hören und entsprechend eine Pause einfügen.
• Man könnte als ersten Schritt (bis die beiden Fragen oben geklärt sind) erstmal das ganze ohne Taktwechsel und nur mit Taktzahlen als Ziel probieren, bis es läuft, und dann ausbauen (dann kann man nicht einfach mehr die Differenz von aktueller und angepeilter Taktzahl mit der Taktlänge multiplizieren, sondern muss sich von Takt zu Takt hangeln, dafür kann man auch gleich nach \marks Ausschau halten).
• Man könnte zu guter Letzt noch drei Varianten definieren: \restUntil baut ne MultiMeasureRest (R…), \skipUntil ne Platzhalterpause (s…), und \tacetUntil macht nen \stopStaff, Ansage „tacet bis“, \startStaff beim Zieltakt (also ein echtes Überspringen, hab ich so schon ab und zu in Schlagzeugstimmen gesehen).

Ich habe leider nirgends eine gute Beschreibung gefunden,
1. wie man nen Engraver schreibt und
2. was für Typen es gibt und ich rausfinde, welche Funktionen welche Typen haben.

Hier mal einer von vielen Versuchen. Wär ich mit Zeile 13 (auskommentiert) statt Zeile 12 schon da? Nicht ganz, weil es nicht kompiliert (es wird ein Prob – was auch immer das ist – erwartet, keine Duration). Sonst schon?
\version "2.19.22"

tacetUntil =
#(define-music-function (targetBar) (integer?)
   #{
     \applyContext
     #(lambda (context)
        (let* ((currentBar (ly:context-property context 'currentBarNumber))
               (currentMeasureLength (ly:moment-main (ly:context-property context 'measureLength)))
               (difference (- targetBar currentBar))
               (product (* currentMeasureLength difference)))
          (write product)))
          %(mmrest-of-length (ly:make-duration 0 0 product))))
   #})

%\displayMusic
\relative {
  \override Score.BarNumber #'break-visibility = #'#(#t #t #t)
  \time 3/4
  c'2.
  \tacetUntil #5 % wir sind am Anfang von Takt 2, brauchen also eine Pause von 2.*3=9/4
  c2.
}

Kann mir da jemand auf die Sprünge helfen? Ich brauche/möchte keine fertige Lösung, aber ohne Plan von den Typen und ob ein Engraver nötig ist bzw. wo ich rauskriege, wie ich einen schreibe, komm ich grad nicht weiter ;)
« Letzte Änderung: Dienstag, 14. Juli 2015, 00:20 von fugenkomponist »

fugenkomponist

  • Gast
Re: \tacetUntil
« Antwort #1 am: Dienstag, 14. Juli 2015, 09:29 »
Ich hab inzwischen rausgefunden, was statt mmrest-of-length geht, nämlich make-multi-measure-rest oder auch gleich make-music:
\version "2.19.22"

tacetUntil =
#(define-music-function (targetBar) (integer?)
   #{
     \applyContext
     #(lambda (context)
        (let* ((currentBar (ly:context-property context 'currentBarNumber))
               (currentMeasureLength (ly:moment-main (ly:context-property context 'measureLength)))
               (difference (- targetBar currentBar))
               (product (* currentMeasureLength difference)))
          (make-music
           'MultiMeasureRestMusic
           'duration
           (ly:make-duration 0 0 product))))
   #})



\displayMusic
\relative {
  \override Score.BarNumber #'break-visibility = #'#(#t #t #t)
  \time 3/4
  % Takt 1
  c'2.
  % Takt 2
  \tacetUntil #5
  % Takt 5
  #(make-multi-measure-rest
    (ly:make-duration 0 0 15/4)
           (ly:make-moment 0 0))
  % Takt 10
  c2.
}
Aber die Funktion liefert nicht das zurück, was ich gerne hätte, sondern
          (make-music
            'ApplyContext
            'procedure
            #<procedure #f (context)>)
\applyContext scheint also der falsche Weg zu sein. (Edit: ist irgendwie auch klar, schließlich ist das nur der Rückgabewert dieser Funktion #(lambda …))




Der zweite Versuch funktioniert auch nicht so ganz: wenn ich theRest zurückgebe, wird (write product) und auch das (set! …) nicht erreicht. Lasse ich es weg, dann passiert ein (write …), dafür hab ich halt als Rückgabewert wieder das gleiche wie oben.
\version "2.19.22"

tacetUntil =
#(define-music-function (targetBar) (integer?)
   (define theRest
     (make-music
      'MultiMeasureRestMusic
      'duration (ly:make-duration 0 0 3/4)))
   #{
     \applyContext
     #(lambda (context)
        (let* ((currentBar (ly:context-property context 'currentBarNumber))
               (currentMeasureLength (ly:moment-main (ly:context-property context 'measureLength)))
               (difference (- targetBar currentBar))
               (product (* currentMeasureLength difference)))
          (write product)
          (set! (ly:music-property theRest 'duration) product)))
   #}
   theRest)



%\displayMusic
\relative {
  \override Score.BarNumber #'break-visibility = #'#(#t #t #t)
  \time 3/4
  % Takt 1
  c'2.
  % Takt 2
  \tacetUntil #5
  % Takt 5
  c2.
  %#(make-multi-measure-rest
  %  (ly:make-duration 0 0 15/4)
  %  (ly:make-moment 0 0))
}

Pierre

  • Gast
Re: \tacetUntil
« Antwort #2 am: Dienstag, 14. Juli 2015, 12:45 »
Hallo fugenkomponist,

siehe auch: http://lsr.di.unimi.it/LSR/Item?id=923

Gruß,
~Pierre

fugenkomponist

  • Gast
Re: \tacetUntil
« Antwort #3 am: Dienstag, 14. Juli 2015, 16:05 »
Danke für deine Antwort, sie hilft mir aber leider überhaupt nichts. Es geht darum, in einer Orchesterschlagwerkstimme nicht sowas wie R1 R2.*34 R4*5*31 R4.*5 R1 und dann wieder Noten schreiben zu müssen, nicht um das Bild eines Tacet unbestimmter Länge.

Anwendung soll dann im Endeffekt so aussehen:

\relative {
  % Takt 1, in ner globalen Stimme Taktart 2/4, Tonart, ...
  r8 a' a a
  f2
  r8 g g g
  e2
  % Takt 5
  \tacetUntilBar #17
  % Takt 17
  r8 cis e a
 
  [...]

  \tacetUntilMark #"zweites Thema"
  % Takt unbekannt, im Score hier (z. B. in der globalen Stimme) \mark "zweites Thema"
}
« Letzte Änderung: Dienstag, 14. Juli 2015, 16:48 von fugenkomponist »

fugenkomponist

  • Gast
Re: \tacetUntil
« Antwort #4 am: Sonntag, 19. Juli 2015, 17:20 »
Ich habe auch auf der englischen Mailingliste nachgefragt und inzwischen eine Lösung, die zwar nicht genau das tut, was ich oben beschrieben habe, die aber für meine Zwecke (ich komponiere und sag Sachen wie „Oboe setzt schon mal in der Reprise wieder ein, ich weiß aber noch nicht, wie lang die Durchführung wird und ob sie da noch spielt“) ausreichend ist. http://lists.gnu.org/archive/html/lilypond-user/2015-07/msg00235.html

Die Handhabung dieser Lösung war erstmal nicht ganz einfach; falls noch mal jemand ein ähnliches Problem haben sollte, kann ich meine Hilfsfunktionen und Tips zur Benutzung noch loswerden (z. B. „Wie verträgt sich das mit partcombine und addQuote/quoteDuring?“, „Warum zur Hölle gibts da Probleme mit der Länge der allerletzten Note einer Stimme und was kann ich dagegen tun?“).

Edit: ganz kurze Hinweise:\partcombine \useAndAlignTo \global \instrI \alignTo \global \instrII
\addQuote "instr" \alignTo \global \instr
%{ letzte Note, dann %} s1*0 % keine Ahnung, warum das nötig ist und dann funktioniert, aber es tuts

2. Edit (drei Wochen später): das s1*0 nach der letzten Note ist nötig, weil alignTo die Note bis zum nächsten \tag skalieren würde (welches aber nicht mehr kommt, deshalb wird anscheinend bis zum Schluss skaliert). Für das Skalieren wird aber schonmal die Länge der Note auf eine Ganze gesetzt; der Skalierfaktor ist dann richtig, aber der Notenkopf nicht. Aus c'4 wird dann c'1*1/4. s1*0 bringt da Abhilfe, weil daraus wieder s1*0 wird.

Damit ich den Überblick behalte, wo in der Partitur sich welche Tags befinden, lasse ich jedes Tag auch als \mark ausgeben in der Stimme, nach der sich die anderen richten (oben \global genannt):markTag =
#(define-music-function (markText) (string?)
   #{
     \tag #(string->symbol markText) \mark #markText
   #})
Zu verwenden als \markTag "meinTag", tut das gleiche wie \tag #'meinTag \mark "meinTag". Wer lieber \markTag #'meinTag hat: Es gibt auch die umgekehrte Funktion symbol->string ;)

Und \useAndAlignTo macht nicht viel, aber die Arbeit leichter:useAndAlignTo =
#(define-music-function
  (global music) (ly:music? ly:music?)
  #{
    <<
      #global
      #(alignTo global music)
    >>
  #})
« Letzte Änderung: Sonntag, 9. August 2015, 23:25 von fugenkomponist »

fugenkomponist

  • Gast
Re: \tacetUntil
« Antwort #5 am: Mittwoch, 19. August 2015, 13:11 »
Soooo, ich habe jetzt noch einiges dran verändert, was mir hoffentlich in Zukunft die Benutzung vereinfacht:

Mit \alignTo bzw. \useAndAlignTo kann eine Stimme sich an einer anderen (i. d. R. wohl globalen) Stimme orientieren. Die Orientierung wird erleichtert dadurch, dass die gesetzten tags (heißen jetzt anchors) als marks in der Partitur angezeigt werden, sofern mit point-and-click kompiliert wird. Außerdem hab ich noch meine eigenen \quoteDuring- und \ottavaQuoteDuring-Befehle ergänzt um \quoteUntil und \ottavaQuoteUntil, weil erstere nicht mit der ursprünglichen Lösung funktionieren. Ich kann also jetzt sagen „spiel bis zum nächsten Doppelstrich die erste Geige mit, aber bitte zwei Oktaven drunter“ :) anchors und Zitate werden farbig markiert, die Farben sind einstellbar (und nur wirksam, wenn point-and-click an ist).

Im Anhang die Dateien, die die entsprechenden Funktionen enthalten, sowie das Ergebnis des folgenden (zumindest ein bisschen) kommentierten Demo-Codes, einmal mit und einmal ohne point-and-click kompiliert:% mit point-and-click werden Zitate gefärbt und \marks an Ankern gesetzt
% ohne point-and-click eben nicht

\version "2.19.25"
\language "deutsch"

\include "alignTo.ily"
\include "advancedQuote.ily"

%#(define quote-color magenta) % default ist grey
%#(define anchor-color red) % default ist blue

global = {
  \time 3/4
  \key d \major
  s2.*4
  \anchor "unis.-Einsatz"
  s
  \anchor "unis.-Ende"
  s
  \anchor "Ende Flötensolo"
  s
  \bar "|."
}

klarinette = \relative {
  d'4 e fis
  g a h
  a h cis
  d2.
  d4 a a
  h fis fis
  g e a
  d,2.
  % verlängert die Pause bis zum Anker; geht auch mit s statt R
  R \until "Ende Flötensolo"
  d'4 a fis'
  d a fis'
  d d, d
  d2.
}
% nicht vergessen: auch hier brauchts schon ein \alignTo für korrekte Zitate
\addQuote "klarinette" \alignTo \global \klarinette

floete = \relative {
  d''4 cis d
  h cis d
  cis d e
  d2.
  % zitiert bis zum Anker; \quoteDuring … s \until geht nicht
  % und würde deshalb eine Warnung ausgeben
  \quoteUntil "klarinette" "unis.-Ende"
  d4 fis a
  g e a
  a d fis
  e2.
  % \quoteDuring und \quoteUntil haben oktavierende Versionen
  % die Zahl gibt die Oktaven nach oben (positiv) oder unten (negativ) an
  \ottavaQuoteDuring 1 "klarinette" { s2.*2 s4 }
  fis,,4 fis
  fis2.
}

\new StaffGroup <<
  \new Staff \with {
    instrumentName = "Flöte"
  } \useAndAlignTo \global \floete
  \new Staff \with {
    instrumentName = "Klar. in A"
  } \transpose a c' \useAndAlignTo \global \klarinette
>>

Der Code ist für Version 2.19.25 geschrieben, lässt sich aber mit verhältnismäßig kleinem Aufwand auch auf 2.18.2 umschneidern.

Ach ja, und beide Dateien (alignTo/advancedQuote) lassen sich auch jeweils einzeln benutzen ohne Einschränkungen (für den Fall, dass man keine bunten oder oktavierenden Zitate braucht oder dass man kein alignTo & friends braucht).

Edit: Eine winzige Sache hab ich gefunden, die vielleicht noch irgendwie schöner ginge, mir den Aufwand aber nicht wert ist. In dem Fall – und nur in dem Fall (soweit ich das sehe) –, dass eine Stimme als allerletzte Musik ein \quoteUntil oder \ottavaQuoteUntil hat, brauchts danach noch ein s1*0 (dieses wird sonst von \until immer schon gesetzt, quoteUntil funktioniert aber grundsätzlich anders).
« Letzte Änderung: Mittwoch, 19. August 2015, 13:30 von fugenkomponist »