<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.lilypond.community/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mkouhia</id>
	<title>LilyPond wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.lilypond.community/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mkouhia"/>
	<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/wiki/Special:Contributions/Mkouhia"/>
	<updated>2026-08-07T00:50:02Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Merging_simultaneous_voices_into_shared_note_heads&amp;diff=6620</id>
		<title>Merging simultaneous voices into shared note heads</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Merging_simultaneous_voices_into_shared_note_heads&amp;diff=6620"/>
		<updated>2026-08-03T12:36:59Z</updated>

		<summary type="html">&lt;p&gt;Mkouhia: Created page with &amp;quot;This snippet defines &amp;lt;code&amp;gt;\combineVoices&amp;lt;/code&amp;gt;, a music function that takes any number of rhythmically identical voices written inside &amp;lt;code&amp;gt;&amp;lt;&amp;lt; ... &amp;gt;&amp;gt;&amp;lt;/code&amp;gt; and merges them into a single voice under one stem. Wherever two or more of the voices share the same pitch at a given moment, only one note head is printed; wherever the pitches differ, a chord containing all of the distinct pitches is printed instead.  This differs from the default functionality, where double no...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This snippet defines &amp;lt;code&amp;gt;\combineVoices&amp;lt;/code&amp;gt;, a music function that takes&lt;br /&gt;
any number of rhythmically identical voices written inside&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;&amp;lt; ... &amp;gt;&amp;gt;&amp;lt;/code&amp;gt; and merges them into a single voice under one stem.&lt;br /&gt;
Wherever two or more of the voices share the same pitch at a given&lt;br /&gt;
moment, only one note head is printed; wherever the pitches differ, a&lt;br /&gt;
chord containing all of the distinct pitches is printed instead.&lt;br /&gt;
&lt;br /&gt;
This differs from the default functionality, where double note heads are printed in case of shared pitches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lilypond version=&amp;quot;2.24&amp;quot;&amp;gt;&lt;br /&gt;
% Return a list 0, 1, ..., n - 1.&lt;br /&gt;
#(define (int-range n)&lt;br /&gt;
   (let loop ((i 0) (acc &#039;()))&lt;br /&gt;
     (if (= i n)&lt;br /&gt;
         (reverse acc)&lt;br /&gt;
         (loop (+ i 1) (cons i acc)))))&lt;br /&gt;
&lt;br /&gt;
% Drill through any single-child wrapper node (as introduced by, e.g.,&lt;br /&gt;
% \relative) until a music object with a real, non-empty &#039;elements&lt;br /&gt;
% list is reached, and return that list.&lt;br /&gt;
#(define (music-elements m)&lt;br /&gt;
   (let ((elts (ly:music-property m &#039;elements)))&lt;br /&gt;
     (if (and (list? elts) (pair? elts))&lt;br /&gt;
         elts&lt;br /&gt;
         (let ((child (ly:music-property m &#039;element)))&lt;br /&gt;
           (if (ly:music? child)&lt;br /&gt;
               (music-elements child)&lt;br /&gt;
               &#039;())))))&lt;br /&gt;
&lt;br /&gt;
% Return the NoteEvents contained in a single moment of music.  A&lt;br /&gt;
% plain note is a bare NoteEvent; an explicit chord &amp;lt;...&amp;gt; is an&lt;br /&gt;
% EventChord wrapping one NoteEvent per pitch.  Rests and skips&lt;br /&gt;
% contain no pitch and contribute nothing.&lt;br /&gt;
#(define (note-events moment)&lt;br /&gt;
   (cond&lt;br /&gt;
    ((eq? (ly:music-property moment &#039;name) &#039;NoteEvent)&lt;br /&gt;
     (list moment))&lt;br /&gt;
    ((eq? (ly:music-property moment &#039;name) &#039;EventChord)&lt;br /&gt;
     (filter (lambda (e) (eq? (ly:music-property e &#039;name) &#039;NoteEvent))&lt;br /&gt;
             (ly:music-property moment &#039;elements)))&lt;br /&gt;
    (else &#039;())))&lt;br /&gt;
&lt;br /&gt;
% A comparable key for a pitch, since pitch objects do not compare&lt;br /&gt;
% correctly with equal?.&lt;br /&gt;
#(define (pitch-key p)&lt;br /&gt;
   (list (ly:pitch-notename p) (ly:pitch-alteration p) (ly:pitch-octave p)))&lt;br /&gt;
&lt;br /&gt;
% Merge one moment&#039;s worth of notes, taken from several voices, into&lt;br /&gt;
% a single EventChord with duplicate pitches removed.&lt;br /&gt;
#(define (merge-chords moments)&lt;br /&gt;
   (let ((seen &#039;())&lt;br /&gt;
         (notes &#039;()))&lt;br /&gt;
     (for-each&lt;br /&gt;
      (lambda (moment)&lt;br /&gt;
        (for-each&lt;br /&gt;
         (lambda (note)&lt;br /&gt;
           (let ((key (pitch-key (ly:music-property note &#039;pitch))))&lt;br /&gt;
             (if (not (member key seen))&lt;br /&gt;
                 (begin&lt;br /&gt;
                   (set! seen (cons key seen))&lt;br /&gt;
                   (set! notes (cons note notes))))))&lt;br /&gt;
         (note-events moment)))&lt;br /&gt;
      moments)&lt;br /&gt;
     (if (null? notes)&lt;br /&gt;
         (car moments)  ; every voice rests here: keep a rest&lt;br /&gt;
         (make-music &#039;EventChord &#039;elements (reverse notes)))))&lt;br /&gt;
&lt;br /&gt;
combineVoices =&lt;br /&gt;
#(define-music-function (music) (ly:music?)&lt;br /&gt;
   (let* ((voices (ly:music-property music &#039;elements))&lt;br /&gt;
          (seqs (map music-elements voices))&lt;br /&gt;
          (lens (map length seqs)))&lt;br /&gt;
     (make-music &#039;SequentialMusic &#039;elements&lt;br /&gt;
       (map (lambda (i) (merge-chords (map (lambda (s) (list-ref s i)) seqs)))&lt;br /&gt;
            (int-range (apply min lens))))))&lt;br /&gt;
&lt;br /&gt;
\new Voice \combineVoices &amp;lt;&amp;lt;&lt;br /&gt;
  \relative { c&#039;&#039;4 f8 d e16 f g8 d4 }&lt;br /&gt;
  \relative { c&#039;&#039;4 d8 b c16 d e8 b4 }&lt;br /&gt;
&amp;gt;&amp;gt;&lt;br /&gt;
&amp;lt;/lilypond&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Simultaneous notes]]&lt;br /&gt;
[[Category:Chords]]&lt;br /&gt;
[[Category:Snippet]]&lt;/div&gt;</summary>
		<author><name>Mkouhia</name></author>
	</entry>
</feed>