Ternärer Rhythmus im Midi file

Begonnen von uunail, Donnerstag, 31. Oktober 2024, 17:45

« vorheriges - nächstes »

uunail

Liebe Freunde des Notensatzes mit lilypond,

ich benutze das Programm seit vielen Jahren und bin immer wieder begeistert, welch hervorragende Sheets man damit erstellen kann.

Bei meinem aktuellen Projekt steht in der Spielanweisung:

Du darfst diesen Dateianhang nicht ansehen.

Gibt es nun eine Möglichkeit, diese Spielanweisung im Midi umzusetzen, d.h. dass im Notensatz weiterhin die punktierte Achtel und das Sechszehntel gezeigt wird und dass aber im Midi die Längen entsprechend der Spielanweisung geändert sind.

Vielen Dank für Eure Ideen.

Gruß

Uwe

harm6


uunail

Vielen Dank für die Antwort. Ich habe das auch schon gesehen, jedoch würde das, glaube ich, das Problem nicht lösen.

In der Anmerkung zu diesem Absatz steht nämlich, dass die Anwendung von z.B. \swing dann auch in der graphischen Ausgabe zu sehen ist. Der zweite Teil der Anmerkung führt aber möglicherweise zur Lösung, dass man einen separaten Score Block für die Midi Ausgabe erzeugen muss, in dem die Spielanweisung entsprechend umgesetzt ist.

Ich würde es jedoch schön finden, wenn man dazu nicht alles duplizieren müsste. Toll wäre es, wenn man in der Notation ein bedingtes Statement benutzen könnte, das zwischen Grafikrendering und Midiausgabe unterscheidet.

Das \if Statement ist aber wohl nicht im Music Context benutzbar.

Gruß

Uwe

harm6

Wieso sollte man alles duplizieren müssen?

Wenn Du Deine komplette Musik in eine Variable packst, z.B.
meineKompletteMusik = ...
Dann schreib einfach zwei \score:
\score {
  \meineKompletteMusik
  \layout { }
}
\score {
  \meineKompletteMusik
  \midi { }
}

Das sind nur wenige Zeilen...

Nicht sicher bin ich jedoch bei erwas anderem:
Wenn ein Stück in ternärem Rhythmus gespielt werden soll, kenne ich zwei Varianten wie es gedruckt erscheint:
a) glatte Achtel, hier kann man swing.ly problemlos einbauen
b) punktierte Achtel plus sechszehntel, hier weiß ich nicht, ob swing.ly wirken kann. Probiers halt aus.

Gruß,
  Harm

uunail

Ich möchte halt im Notenblatt die Notierung mit punktierter Viertel und Sechszehntel zeigen (weil es schöner aussieht), im Midi File aber die Längen mit den Triolen haben.

Dazu muss ich die entsprechenden Teile in der Musik Definition austauschen.

Dann mache ich die Konstruktion wie von Dir vorgeschlagen:

meineMusik = \relative c {
  a8. c16
}

meineMusikTriolen = \relative c {
  \tuplet 3/2 {a4 c8}
}

\score {
  \meineMusik
  \layout{}
}
\score {
  \meineMusikTriolen
  \midi {}
}

Ich überlege mir halt, ob es eine Möglichkeit gibt, zu erkennen, ob die Musik für layout{} oder für midi{} benutzt wird.
Könnte man so etwas in eine Funktion einpacken?

uunail

Zur Illustration meiner Idee habe ich die folgende Funktion geschrieben, die abhängig vom Ergebnis der Prüfung entweder die eine oder die andere Variante ausgibt.
fir = #
(define-music-function
 (parser location aa bb) (ly:pitch? ly:pitch?)
 (
   if (eq? 1 1)
   #{
     \relative c' { \tuplet 3/4 {$aa 4 $bb 8} }
   #}
   #{
     \relative c' { $aa 4. $bb 8 }
   #}
 )
)

Wenn ich nun wüsste, wie die Bedingung zu formulieren ist, ob die Ausgabe Richtung Grafik oder Midi geht, wäre mein Problem gelöst.

Kann man diesbezüglich jemand weiterhelfen?

Vielen Dank

harm6

Ich kenne keine Methode in einer music-function herauszufinden, ob man im \layout oder \midi ist.

Auch halte ich es hier nicht für sinnvoll eine music-function zu verwenden, um verschiedene Rhythmen auszugeben.
Besser wäre doch eine music-function, die die einmal geschriebene Musik (komplett) umwandelt.
Wie ich schon schrieb hat swing.ly ja diese Funktionalität, ist aber beschränkt auf die Abfolge gleicher Notenwerte. Punktierte Achtel plus Sechszehntel wird also nicht umgewandelt.

Nun wäre es natürlich am allerbesten swing.ly zu erweitern, damit das klappt. Da habe ich aber nicht die Zeit und Energie für.
Aber ich habe mal eine music-function geschrieben, die zumindest teilweise funktioniert.
Ich habe sie "8. 16 -> 4*2/3 8*2/3" genannt, ist halt sehr deskriptiv, kannst du ja ändern ;)
Sie geht dann fehl, wenn das punktierte Achtel nicht auf einer der Hauptzählzeiten erscheint.
Dann musst du an den relevanten Stellen \notHere einfügen.

\version "2.24.3"

"8. 16 -> 4*2/3 8*2/3" =
#(define-music-function (music)(ly:music?)
  (let ((rh-1 (ly:make-duration 3 1)) ;; 8.
        (rh-2 (ly:make-duration 4))  ;; 16
        (rh-1-rev (ly:make-duration 2 0 2/3)) ;; 4*2/3
        (rh-2-rev (ly:make-duration 3 0 2/3)) ;; 8*2/3
        (notes-1 '()))
  (map-some-music
    (lambda (mus)
      (and
        (or (music-is-of-type? mus 'event-chord)
            (music-is-of-type? mus 'rhythmic-event))

        (cond ((music-is-of-type? mus 'event-chord)
                (let* ((chrd-notes (event-chord-notes mus))
                       (chrd-note (and (pair? chrd-notes) (car chrd-notes)))
                       (match-rh-1?
                         (and chrd-note
                              (equal?
                                (ly:music-property chrd-note 'duration)
                                rh-1)))
                       (on-beat?
                         (and chrd-note
                              (ly:music-property chrd-note 'on-beat #t)))
                       (match-rh-2?
                         (and chrd-note
                              (equal?
                                (ly:music-property chrd-note 'duration)
                                rh-2))))
                  ;; 8.
                  (cond ((and on-beat? match-rh-1?)
                          (for-each
                            (lambda (n1)
                              (ly:music-set-property! n1 'duration rh-1-rev))
                            chrd-notes)
                          (set! notes-1 chrd-notes))
                        (match-rh-1? (set! notes-1 '())))
                  ;; 16
                  (when (and (pair? notes-1) match-rh-2?)
                    (for-each
                      (lambda (n2)
                        (ly:music-set-property! n2 'duration rh-2-rev))
                      chrd-notes)
                    (set! notes-1 '()))
                  ;; return mus
                  mus))
              ;; single notes, rests, skips
              ((music-is-of-type? mus 'rhythmic-event)
                (let* ((match-rh-1?
                         (equal? (ly:music-property mus 'duration) rh-1))
                       (on-beat? (ly:music-property mus 'on-beat #t))
                       (match-rh-2?
                         (equal? (ly:music-property mus 'duration) rh-2)))
                  ;; 8.
                  (cond ((and on-beat? match-rh-1?)
                          (ly:music-set-property! mus 'duration rh-1-rev)
                          (set! notes-1 (cons mus notes-1)))
                        (match-rh-1? (set! notes-1 '())))
                  ;; 16
                  (when (and (pair? notes-1) match-rh-2?)
                    (ly:music-set-property! mus 'duration rh-2-rev)))
                  ;; return mus
                  mus))))
    music)))

notHere =
#(define-music-function (music)(ly:music?)
  (cond ((music-is-of-type? music 'event-chord)
          (for-each
            (lambda (m) (withMusicProperty 'on-beat #f m))
            (event-chord-notes music))
          music)
         ((music-is-of-type? music 'rhythmic-event)
           (withMusicProperty 'on-beat #f music)
           music)
         (else music)))

mus =
  <<
    \new StaffGroup <<
      \new Staff
        \with { instrumentName = "Original" }
        \repeat unfold 8 { <b f'>8. <b f'>16 }
      \new Staff
        \with { instrumentName = "Ternär" }
        \"8. 16 -> 4*2/3 8*2/3"
          \repeat unfold 8 {  <b f'>8. <b f'>16 } %% chords
          %\repeat unfold 8 {  b8. f'16 }  %% single notes
          %\repeat unfold 8 {  b8. <b f'>16 }  %% single note & chord
          %\repeat unfold 8 {  <b f'>8. f'16 }  %% chord & single note
          %\repeat unfold 8 {  r8. f'16 }  %% rest & single note
      \new Staff
        \with { instrumentName = "Control" }
        \repeat unfold 24 { b8*2/3 }
    >>
    \new StaffGroup <<
      \new Staff
        \with { instrumentName = "Original" }
        {
         b8. <b f'>8. <b f'>16 b2 b16
         b16 b8. b8. b16 b2
       }
      \new Staff
        \with { instrumentName = "Issues with 8." }
        \"8. 16 -> 4*2/3 8*2/3" {
         b8. <b f'>8. <b f'>16 b2 b16
         b16 b8. b8. b16 b2
       }
      \new Staff
        \with { instrumentName = "\\notHere" }
        \"8. 16 -> 4*2/3 8*2/3" {
          <>^"Use barChecks and \\notHere"
          \notHere b8. \notHere <b f'>8. <b f'>16 b2 b16 |
          b16 \notHere b8. b8. <b f'>16 b2 |
        }
    >>
>>

%% For now ... better to use two \score
\score {
  \mus
  \layout {
    indent = 30
  }
  \midi {}
}

HTH,
  Harm

uunail

Vielen Dank für die Antwort.

Ich denke, das hilft mir wirklich weiter. Ich benötige auch noch die andere rhythmische Variante (erst 16-tel, dann punktierte Achtel) und versuche deshalb, Deine Funktion entsprechend angepasst zu duplizieren.

Dabei lerne ich wohl auch noch mehr über die Funktionen, die mir bis jetzt noch nicht so geläufig sind. Ich würde mich gerne noch einmal melden, falls ich das doch nicht hinbekomme.

Vielen Dank einstweilen.

Gruß

Uwe

uunail

Leider bin ich mit der vorgestellten Funktion doch nicht zurechtgekommen, weil die programmierte Einschränkung (nur auf der vollen Taktzeit) zu häufig verletzt war.

Deshalb habe ich meinen eigenen Ansatz noch einmal aufgegriffen und bin, so glaube ich, auch zu einer brauchbaren Lösung gekommen. Diese erlaubt es mir, die Musik nur einmal zu schreiben, in verschiedenen Kontexten aber rhythmisch unterschiedlich auszugeben.

Ich habe dazu ein illustratives Beispiel erzeugt, in dem ich meine Lösung vorstelle. Im vierten Takt wird die unterschiedliche Notation gezeigt.

\version "2.24.4"

%%%%%%%%%%%%%%%%%%%%         %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%   fir   %%%%%%%%%%%%%%%%%%%%
%%%
%%% music is interpreted in tuplet notation when called with 1 as third parameter
%%%
fir = #
(define-music-function
 (parser location aa bb switch) (ly:pitch? ly:pitch? number?)
 (
   if (eq? switch 1 )
   #{
     \relative c' { \tuplet 3/4 {$aa 4 $bb 8} }
   #}
   #{
     \relative c' { $aa 4. $bb 8 }
   #}
 )
)

global = {
  \key c \major
  \numericTimeSignature
  \time 3/4
}

%%%%%%%%%%%%%%%%%%%%         %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%  music  %%%%%%%%%%%%%%%%%%%%
%%%
%%% this is the music, wherever a change is
%%% necessary the function fir is called
%%% with the argument switch forwarded
%%%
%%% The argument switch is passed to this function
%%%
music = #
(define-music-function
 (switch) (number?)
   #{
    \global
    \relative c'' {
      c4 c4. a8            % Music hardcoded in 'normal' mode
      c4 \fir c' a #0      % Music always in 'normal' mode
      c4 \fir c' a #1      % Music always in tuplet notation
      c4 \fir c' a $switch % Music notation depending on mode passed by switch
    }
   #}
)

musicLayout = \music #0    % call music with switch to normal notation
musicMidi   = \music #1    % call music with switch to tuplet notation

\score  {
  \new StaffGroup <<

    \new Staff \with {
      instrumentName = \markup { "Layout" }
    } \new Voice { \musicLayout }
   
    \new Staff \with {
      instrumentName = \markup { "Midi" }
    } \new Voice { \musicMidi }
  >>
  \layout { }
}

\score  {
    \new Staff = "Midi" \with {
      midiInstrument = "choir aahs"
      instrumentName = \markup { "Midi" }
    } \new Voice {\musicMidi}
  \midi {
    \tempo 4=60
  }
}

Die Musik selbst wird in eine Funktion 'music' gepackt, an die ein zusätzlicher Parameter übergeben wird. Überall in der Musik, wo es unterschiedliche rhythmische Interpretationen geben soll, wird die Funktion 'fir' aufgerufen, die den Switch als drittes Argument übergeben bekommt.

Nun kann man mit jeweils einer Zeile die Musik entweder in der einen oder der anderen Notation ausgeben.

Ich habe dazu in einem Score eine StaffGroup erstellt, in der beide Varianten gezeigt werden.

Im zweiten Score, der nur Midi erzeugt, wird die Tuplet Notation fix definiert.

Über diese Konstruktion kann ich die unterschiedlichen rhythmischen Varianten relativ einfach, ohne aufwendige Wiederholungen, erzeugen.