<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.lilypond.community/index.php?action=history&amp;feed=atom&amp;title=Aligning_lyrics_based_on_vowels</id>
	<title>Aligning lyrics based on vowels - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.lilypond.community/index.php?action=history&amp;feed=atom&amp;title=Aligning_lyrics_based_on_vowels"/>
	<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Aligning_lyrics_based_on_vowels&amp;action=history"/>
	<updated>2026-05-01T06:11:51Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Aligning_lyrics_based_on_vowels&amp;diff=6548&amp;oldid=prev</id>
		<title>Gabriel Ellsworth: Created page with &quot;This snippet shows how, in music with lyrics, you can align lyrics based on where vowels fall within &lt;code&gt;LyricText&lt;/code&gt; items.  In each measure of this snippet, &#039;&#039;&#039;the first note demonstrates the use of these functions&#039;&#039;&#039;, and the second note shows LilyPond’s default alignment.  &#039;&#039;&#039;Source:&#039;&#039;&#039; Solution by Kieren MacMillan posted to the mailing list [https://lists.gnu.org/archive/html/lilypond-user/2026-01/msg00334.html in this thread]. The code for this solution was...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Aligning_lyrics_based_on_vowels&amp;diff=6548&amp;oldid=prev"/>
		<updated>2026-04-30T16:27:34Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;This snippet shows how, in music with lyrics, you can align lyrics based on where vowels fall within &amp;lt;code&amp;gt;LyricText&amp;lt;/code&amp;gt; items.  In each measure of this snippet, &amp;#039;&amp;#039;&amp;#039;the first note demonstrates the use of these functions&amp;#039;&amp;#039;&amp;#039;, and the second note shows LilyPond’s default alignment.  &amp;#039;&amp;#039;&amp;#039;Source:&amp;#039;&amp;#039;&amp;#039; Solution by Kieren MacMillan posted to the mailing list [https://lists.gnu.org/archive/html/lilypond-user/2026-01/msg00334.html in this thread]. The code for this solution was...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This snippet shows how, in music with lyrics, you can align lyrics based on where vowels fall within &amp;lt;code&amp;gt;LyricText&amp;lt;/code&amp;gt; items.&lt;br /&gt;
&lt;br /&gt;
In each measure of this snippet, &amp;#039;&amp;#039;&amp;#039;the first note demonstrates the use of these functions&amp;#039;&amp;#039;&amp;#039;, and the second note shows LilyPond’s default alignment.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Source:&amp;#039;&amp;#039;&amp;#039; Solution by Kieren MacMillan posted to the mailing list [https://lists.gnu.org/archive/html/lilypond-user/2026-01/msg00334.html in this thread]. The code for this solution was inspired by [[Center lyric syllables (ignoring punctuation)]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lilypond version=&amp;quot;2.26&amp;quot;&amp;gt;&lt;br /&gt;
% View this snippet online:&lt;br /&gt;
% https://wiki.lilypond.community/wiki/Aligning_lyrics_based_on_vowels&lt;br /&gt;
&lt;br /&gt;
% Define the set of characters that will be&lt;br /&gt;
% classified as vowels for these commands:&lt;br /&gt;
#(define vowel-set&lt;br /&gt;
   (list-&amp;gt;char-set&lt;br /&gt;
    (string-&amp;gt;list &amp;quot;AÁÀÃÂÆǼEÉÈÊIÍÌÎOÓÒÕÔŒU&lt;br /&gt;
        ÚÙÛYaáàãâæǽeéèêiíìîoóòõôœuúùûy&amp;quot;)))&lt;br /&gt;
% Tweak this set based on your needs.&lt;br /&gt;
% For example, if your lyrics are in a language&lt;br /&gt;
% in which ⟨y⟩ is *always* pronounced as a vowel,&lt;br /&gt;
% you will want to make sure that Y and y are in your list.&lt;br /&gt;
&lt;br /&gt;
% This function returns the width of the&lt;br /&gt;
% grob (stencil) for a given piece of text.&lt;br /&gt;
#(define (width grob text)&lt;br /&gt;
   (let* ((X-extent&lt;br /&gt;
           (ly:stencil-extent (grob-interpret-markup grob text) X)))&lt;br /&gt;
     (if (interval-empty? X-extent)&lt;br /&gt;
         0&lt;br /&gt;
         (cdr X-extent))))&lt;br /&gt;
&lt;br /&gt;
% This callback sets the alignment point of a LyricText grob&lt;br /&gt;
% to the centre of the first vowel that it contains.&lt;br /&gt;
#(define (center-on-first-vowel grob)&lt;br /&gt;
   (let* ((text (ly:grob-property-data grob &amp;#039;text))&lt;br /&gt;
          (syllable (markup-&amp;gt;string text))&lt;br /&gt;
          (vowel-position&lt;br /&gt;
           (if (string-index syllable vowel-set)&lt;br /&gt;
               (string-index syllable vowel-set)&lt;br /&gt;
               0))&lt;br /&gt;
          (vowel-end&lt;br /&gt;
           (if (string-index syllable vowel-set)&lt;br /&gt;
               (+ (string-index syllable vowel-set) 1)&lt;br /&gt;
               (string-length syllable)))&lt;br /&gt;
          (preword (substring syllable 0 vowel-position))&lt;br /&gt;
          (word (substring syllable vowel-position vowel-end))&lt;br /&gt;
          (preword-width (width grob preword))&lt;br /&gt;
          (word-width (width grob&lt;br /&gt;
                             (if (string-null? syllable) text word)))&lt;br /&gt;
          (note-column (ly:grob-parent grob X))&lt;br /&gt;
          (note-column-extent (ly:grob-extent&lt;br /&gt;
                               note-column note-column X))&lt;br /&gt;
          (note-column-width (interval-length note-column-extent))&lt;br /&gt;
          (self-X (ly:grob-property-data grob &amp;#039;self-alignment-X)))&lt;br /&gt;
     (-&lt;br /&gt;
      (*&lt;br /&gt;
       (/ (- note-column-width word-width) 2)&lt;br /&gt;
       (1+ (if (procedure? self-X) (self-X grob) self-X)))&lt;br /&gt;
      preword-width)))&lt;br /&gt;
&lt;br /&gt;
% This callback sets the alignment point of a LyricText grob&lt;br /&gt;
% to the point midway between its first and last vowels.&lt;br /&gt;
#(define (center-between-vowels grob)&lt;br /&gt;
   (let* ((text (ly:grob-property-data grob &amp;#039;text))&lt;br /&gt;
          (syllable (markup-&amp;gt;string text))&lt;br /&gt;
          (word-position&lt;br /&gt;
           (if (string-index syllable vowel-set)&lt;br /&gt;
               (string-index syllable vowel-set)&lt;br /&gt;
               0))&lt;br /&gt;
          (word-end&lt;br /&gt;
           (if (string-index-right syllable vowel-set)&lt;br /&gt;
               (+ (string-index-right syllable vowel-set) 1)&lt;br /&gt;
               (string-length syllable)))&lt;br /&gt;
          (preword (substring syllable 0 word-position))&lt;br /&gt;
          (word (substring syllable word-position word-end))&lt;br /&gt;
          (preword-width (width grob preword))&lt;br /&gt;
          (word-width (width grob&lt;br /&gt;
                             (if (string-null? syllable) text word)))&lt;br /&gt;
          (note-column (ly:grob-parent grob X))&lt;br /&gt;
          (note-column-extent (ly:grob-extent&lt;br /&gt;
                               note-column note-column X))&lt;br /&gt;
          (note-column-width (interval-length note-column-extent))&lt;br /&gt;
          (self-X (ly:grob-property-data grob &amp;#039;self-alignment-X)))&lt;br /&gt;
&lt;br /&gt;
     (-&lt;br /&gt;
      (*&lt;br /&gt;
       (/ (- note-column-width word-width) 2)&lt;br /&gt;
       (1+ (if (procedure? self-X) (self-X grob) self-X)))&lt;br /&gt;
      preword-width)))&lt;br /&gt;
&lt;br /&gt;
% Helper functions that use the above code:&lt;br /&gt;
cvs = \once \override LyricText.X-offset = #center-between-vowels&lt;br /&gt;
cfv = \once \override LyricText.X-offset = #center-on-first-vowel&lt;br /&gt;
&lt;br /&gt;
\fixed c&amp;#039; {&lt;br /&gt;
  \*8 { f2 f }&lt;br /&gt;
  % The command \* requires&lt;br /&gt;
  % version 2.25 or later.&lt;br /&gt;
  % For version 2.24, use&lt;br /&gt;
  % \repeat unfold 8&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
\addlyrics {&lt;br /&gt;
  \cfv piste piste&lt;br /&gt;
  \cfv “O—!!!” “O—!!!”&lt;br /&gt;
  \cvs “O—!!!” “O—!!!”&lt;br /&gt;
  \cfv blessed blessed&lt;br /&gt;
  \cfv heaven heaven&lt;br /&gt;
  \cvs heav’n heav’n&lt;br /&gt;
  \cvs youths youths&lt;br /&gt;
  \cvs each each&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lilypond&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to apply one of these functions globally, you can place either of the following in your &amp;lt;code&amp;gt;\layout&amp;lt;/code&amp;gt; block:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;\override Score.LyricText.X-offset = #center-between-vowels&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;\override Score.LyricText.X-offset = #center-on-first-vowel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you then need to switch off the function locally, use &amp;lt;code&amp;gt;\once \revert LyricText.X-offset&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Category:Vocal music]]&lt;br /&gt;
[[Category:Text]]&lt;br /&gt;
[[Category:Tweaks and overrides]]&lt;br /&gt;
[[Category:Scheme]]&lt;br /&gt;
[[Category:Spacing]]&lt;br /&gt;
[[Category:Snippet]]&lt;/div&gt;</summary>
		<author><name>Gabriel Ellsworth</name></author>
	</entry>
</feed>