Autor Thema: Aus zwei mach eins (GEHT AUCH SO.)  (Gelesen 1324 mal)

ingmar

  • Gast
Aus zwei mach eins (GEHT AUCH SO.)
« am: Freitag, 12. August 2016, 06:57 »
Hallo,


aufbauend auf dem Problem der Homophonen Akkorde, hier ein Versuch, aus zwei Stimmen wirklich eine einzige zu machen - es soll nur der gemeinsame Rhythmus übrigbleiben:
\version "2.19.37"

aa = \relative c' { c8 d e f g4. f8 e4 d16 c c8 b2 c1 }
bb = \relative c' { c2 ~c8 b a  g a4  g8 f16 e d4 e8 d  c1 }

cc =  { \oneVoice << \aa \bb >> }
ziel = { c8 8 8 8 8 8 8 8 4 16 16 16 16 4 8 8 1 }

\new GrandStaff <<
\new Staff { \aa }
\new Staff { \bb }
\new DrumStaff { \cc }
\new DrumStaff { \ziel }
>>
Eigentlich sollte die dritte Zeile (cc) das gleiche Ergebnis bringen wie die letzte (ziel).

Im Falle des rhythmischen Zusammentreffens zweier Stimmen sollte nur eine (beispielsweise die erste) übrigbleiben. Wahrscheinlich muss man erst die Tonhöhen irgendwie eliminieren - aber ich finde nicht, wie.

Kann jemand helfen? Danke!
--ingmar
« Letzte Änderung: Sonntag, 21. August 2016, 17:19 von ingmar »

Arnold

  • Gast
Re: Aus zwei mach eins
« Antwort #1 am: Freitag, 12. August 2016, 07:44 »
Hallo,

ich verstehe dein Anliegen folgendermaßen: Aus zwei Melodielinien (Voice-Snippets) soll der Überlagerungsrythmus (jeweils von Tonanfang bis zum nächsten Tonanfang einer anderen Note) erstellt werden, aber als einzelnes Voice-Snippet.

Und dann denke ich gleich an die kommenden Probleme:
- wenn in einer Stimme Triolen vorkommen, die andere gerade geteilt ist
    { << { g'8 g' } \\ { \times 2/3 { c'8 c' c' } } >> } ==> { \times 4/6 { c'8 c'16 c' c'8 } }
- wenn eine Notenlänge herauskommt welche nicht mehr mit einem Notenkopf allein dargestellt werden kann (z. Bsp. 5/16), sondern einen Bindebogen zu einem einzufügenden Ton benötigt, und dann noch dazu je nach Lage im Takt als 4~16, 8.~8, 8~8. oder 16~4 darzustellen ist.

Die größten Realisierungschancen sehe ich, wenn man alle Tuplets "verbietet", noch einen "gleichmäßigen zweiterpotentigen Grundrythmus" anzugeben hat (z. Bsp. Achtel, Sechzehntel, ...), dann zuerst eine Folge aus Tönen und Pausen erstellt (oder besser Haltebögen setzt), und danch noch eine "Verschmelzung zu längeren Noten" drüber laufen läßt.

Wäre aber alles entsprechender Programmieraufwand, keine Out-of-the-Box-Lösung.

Arnold

ingmar

  • Gast
re: Aus zwei mach eins
« Antwort #2 am: Freitag, 12. August 2016, 09:10 »
hallo Arnold,

für meine Zwecke würde es tatsächlich ausreichen, sich auf geradzahlige Unterteilungen bis zu Zweiunddreißigsteln zu beschränken.
Es würde auch ausreichen, einfach die Länge des Tones anzugeben, also auch c2 c4. c4. etc, ohne Überbindungen. Weiß aber nicht, ob das die Sache einfacher macht...

Scheint also ein schwierigeres Problem zu sein.

Danke, Gruß,
--ingmar

fugenkomponist

  • Gast
Re: Aus zwei mach eins
« Antwort #3 am: Freitag, 12. August 2016, 12:52 »
Tatsächlich ist es ein nicht ganz einfaches Problem; hier aber eine Lösung, die mit einigen Einschränkungen funktioniert:
\version "2.19.37"

% adds property 'malte-length to all music
add-length =
#(define-music-function (music) (ly:music?)
   (music-map
    (lambda (m)
      (ly:music-set-property! m 'malte-length (ly:music-length m))
      m)
    music))

% adds property 'malte-abs-time (time since beginning) to all music
% this simplified version works only with sequential music (and wrappers like relative)
add-abs-time =
#(define-music-function (music) (ly:music?)
   (let loop ((cur-time (ly:make-moment 0))
              (music music))
     (ly:music-set-property! music 'malte-abs-time cur-time)
     (cond
      ((music-is-of-type? music 'music-wrapper-music)
       (loop cur-time (ly:music-property music 'element))
       music)
      ((music-is-of-type? music 'sequential-music)
       (map
        (lambda (element)
          (loop cur-time element)
          (set! cur-time (ly:moment-add cur-time (ly:music-property element 'malte-length))))
        (ly:music-property music 'elements))
       music)
      (else
       music))))

% make a list containing the rhythmic events of music, throwing everything else away
extract-rhythmic-events =
#(define-scheme-function (music) (ly:music?)
   (let loop ((music music))
     (cond
      ((music-is-of-type? music 'music-wrapper-music)
       (loop (ly:music-property music 'element)))
      ((music-is-of-type? music 'sequential-music)
       (flatten-list
        (map
         (lambda (element)
           (loop element))
         (ly:music-property music 'elements))))
      ((music-is-of-type? music 'rhythmic-event)
       (list music))
      (else '()))))

% merge two lists of rhythmic events; if there are two at the same time, one is discarded
% returned list is sorted by malte-abs-time (in reverse order)
merge-lists =
#(define-scheme-function (a b) (list? list?)
   (let loop ((a a)
              (b b)
              (r '()))
     (cond
      ((null? a) (append b r))
      ((null? b) (append a r))
      (else
       (let ((atime (ly:music-property (car a) 'malte-abs-time))
             (btime (ly:music-property (car b) 'malte-abs-time))
             (alength (ly:music-property (car a) 'malte-length))
             (blength (ly:music-property (car b) 'malte-length)))
         (cond
          ((ly:moment<? atime btime)
           (loop (cdr a) b (cons (car a) r)))
          ((ly:moment<? btime atime)
           (loop a (cdr b) (cons (car b) r)))
          (else
           (loop (cdr a) (cdr b) (cons (car a) r)))))))))

% ld = log_2, might fail on numbers that are not a positive power of 2
#(define (ld num)
   (if (eq? 1 num)
       0
       (1+ (ld (/ num 2)))))

% this works only for durations (moments) shorter than \breve (2/1) and
% only for simple and dotted durations (multiple dots possible)
moment-to-duration =
#(define-scheme-function (mom) (ly:moment?)
   (let* ((frac (moment->fraction mom))
          (nom (car frac))
          (den (cdr frac))
          (dots (1- (ld (1+ nom))))
          (durlog (- (ld den) dots)))
     (ly:make-duration durlog dots)))

% take a list of merged rhythmic events and shorten the durations of overlapping
% events so that there is no overlap anymore; this reverses the list (so it’s
% sorted by increasing malte-abs-time)
shorten-durations =
#(define-scheme-function (l) (list?)
   (let loop ((l l)
              (r '()))
     (if (eq? 1 (length l))
         (cons (car l) r)
         (let* ((car-time (ly:music-property (car l) 'malte-abs-time))
                (cadr-time (ly:music-property (cadr l) 'malte-abs-time))
                (diff-time (ly:moment-sub car-time cadr-time))
                (cadr-length (ly:music-property (cadr l) 'malte-length)))
           (if (ly:moment<? diff-time cadr-length)
               (ly:music-set-property!
                (cadr l)
                'duration
                (moment-to-duration diff-time)))
           (loop (cdr l) (cons (car l) r))))))

% make a sequential music from the list of rhythmic events
music-from-merged-list =
#(define-music-function (l) (list?)
   (make-music 'SequentialMusic
     'elements l))

% put the functions above together
% to be used as \mergeDurations \somemusic \someothermusic
% this might have unexpected results when used with rests
mergeDurations =
#(define-music-function (a b) (ly:music? ly:music?)
   (let ((rh-ev-a (extract-rhythmic-events (add-abs-time (add-length a))))
         (rh-ev-b (extract-rhythmic-events (add-abs-time (add-length b)))))
     (music-from-merged-list (shorten-durations (merge-lists rh-ev-a rh-ev-b)))))

% test/example
aa = \relative { c'8 d e f g4. f8 e8. e16 r16 c c8 b2 c2. c4 c1 }
bb = \relative { c''2 c8 b a  g a4  g8 f16 e d4~ d8 d  c4 c2. c r4 }

<<
  \new StaffGroup <<
    \aa
    \bb
    \mergeDurations \aa \bb
  >>
  \new StaffGroup <<
    \new RhythmicStaff \aa
    \new RhythmicStaff \bb
    \new RhythmicStaff \mergeDurations \aa \bb
  >>
>>

\layout { ragged-last = ##f }
Die ersten beiden Funktionen hab ich aus einem anderen Projekt wiederverwendet. Schön ist der Code nicht (man könnte den sicher besser strukturieren), aber er funktioniert für dieses Beispiel zumindest ganz gut.

Folgende Einschränkungen:
• Wie man sieht, gehts tatsächlich nicht mit Überbindungen.
• Triolen etc. werden nicht funktionieren (ungetestet, aber das gibt einfach meine Funktion moment-to-duration nicht her ;) ).
• Ist die Frage, wie sich der Code bei Pausen verhalten soll. Im Moment unterscheidet er nicht zwischen Noten und Pausen, was unerwünschte Ergebnisse haben kann. Das ließe sich aber sicher noch ändern.
• Das ganze geht zuverlässig nur einstimmig (ungetestet; Polyphonie ist definitiv im Moment nicht drin, wäre aber vermutlich mit wenig Aufwand machbar).

Da ich den Code fast überhaupt nicht kommentiert habe: Bei Fragen fragt ;) Und ja, das ist instabil/unflexibel, aber Stabilität/Flexibilität ließe sich an vielen Stellen mit nicht allzuviel Aufwand machen, denk ich. Also melde dich, wenn du noch was brauchst.
« Letzte Änderung: Freitag, 12. August 2016, 12:54 von fugenkomponist »

ingmar

  • Gast
re: Aus zwei mach eins
« Antwort #4 am: Freitag, 12. August 2016, 16:27 »
oh - das ist schonmal sehr viel! Danke. : - )

Aber so wird es für meine Zwecke leider nicht genügen. Übergebundene Noten müssen schon als ein Einzelton erkannt werden (auch wenn ich das eben noch anders vermutet habe), und Pausen dürfen keinen Neuanschlag bedeuten. Mit anderen Worten, folgende müssten zu gleichem Resultat führen:
  • c4. c8
  • c4 r8 c
  • c4 ~c8 c

Schade, ich meckere ungern, denn ich finde es großartig, wie sehr du in wie kurzer Zeit versucht hast, zu helfen. : - )

Danke, Gruß,
--ingmar
« Letzte Änderung: Freitag, 12. August 2016, 19:57 von ingmar »

ingmar

  • Gast
re: Aus zwei mach eins
« Antwort #5 am: Sonntag, 21. August 2016, 17:19 »
hallo,


es ist nicht so aufwändig, einfach den gewünschten resultierenden Text von Hand zu schreiben statt eine Funktion zu bemühen, auch wenn letzteres im ersten Moment eleganter scheint und dem digitalen Zeitalter angemessener. Ich hab immer vertreten, dass man nicht für alles immer eine technische Lösung haben muss. Hier scheint der Aufwand ja in keinem Verhältnis zum Gewinn zu stehen.

Also danke für die Mühe, ich komme auch so klar.


--ingmar