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.