That is very impressive coding!! Thanks for sharing it with us.
-- "There is only love, and then oblivion. Love is all we have to set against hatred." (paraphrased) Ian McEwan On Thu, Dec 11, 2025, 1:02 PM Kyle Baldwin <[email protected]> wrote: > Hi All - > > I don't know who needs to see this today or if it can serve as an example > for anyone. > > When Finale was discontinued, the composer Casey Cangelosi posted this on > Instagram as a quasi tribute. https://www.instagram.com/reel/C_LCpmRAFMD/ > > I recreated it in Lilypond thinking one day I could dissect it on my own > website... that never got made... maybe one day. Here it is for your > enjoyment. > > #### BEGIN CODE > %% Typeset by Kyle Baldwin ([email protected]) in Lilypond > > \version "2.24.4" > > \paper { > oddHeaderMarkup = "Score" > indent = .33\in > page-count = #1 > } > > \header { > composer = \markup { > \override #'(baseline-skip . 2.5) > \column { > \halign #RIGHT "Folk Song" > \halign #RIGHT "arr. Ivana B. Komphauser" > \halign #RIGHT "Casey Cangelosi" > } > } > title = "My Bonnie Lies Over The Ocean" > tagline = \markup { \char ##x00A9"CaseyCangelosi 2024" } > } > > > %%%%% > % Clef Definitions > %%%%% > fClefDLine = { > \set Staff.clefGlyph = "clefs.F" > \set Staff.clefPosition = 0 > \set Staff.middleCPosition = 4 > } > > cClefMezzo = { > \set Staff.clefGlyph = "clefs.C" > \set Staff.clefPosition = -2 > \set Staff.middleCPosition = -2 > } > > cClefSoprano = { > \set Staff.clefGlyph = "clefs.C" > \set Staff.clefPosition = -4 > \set Staff.middleCPosition = -4 > } > > cClefBaritone = { > \set Staff.clefGlyph = "clefs.C" > \set Staff.clefPosition = 2 > \set Staff.middleCPosition = 2 > } > > gClefELine = { > \set Staff.clefGlyph = "clefs.G" > \set Staff.clefPosition = -4 > \set Staff.middleCPosition = -8 > } > > %%%%% > % Staff Line alterations > %%%%% > nineStaffLines = { > \stopStaff > \override Staff.StaffSymbol.line-count = #9 > \startStaff > } > > fiveStaffLines = { > \stopStaff > \override Staff.StaffSymbol.line-count = #5 > \startStaff > } > > oneStaffLine = { > \stopStaff > \override Staff.StaffSymbol.line-count = #1 > \startStaff > } > > %%%%% > % Tempo Markups > %%%%% > mmDottedQHalf = \markup { > \concat { > \smaller \general-align #Y #DOWN \note { 4. } #UP > " = " > \smaller \general-align #Y #DOWN \note { 2 } #UP > } > } > > eightEighteenQTempo = { > \once \override Staff.MetronomeMark.break-visibility = > #end-of-line-visible > \once \override Staff.MetronomeMark.self-alignment-X = #RIGHT > \once \override Staff.MetronomeMark.X-offset = #-5.0 > \once \override Staff.MetronomeMark.Y-offset = #4 > \tempo \markup { > \concat { > \smaller \general-align #Y #DOWN \note { 8 } #UP > " = " > \fontsize #-2 "16x" > \smaller \general-align #Y #DOWN \note { 4 } #UP > } > } > } > > eighthHalfTempo = { > \once \override Staff.MetronomeMark.break-visibility = > #end-of-line-visible > \once \override Staff.MetronomeMark.self-alignment-X = #RIGHT > \once \override Staff.MetronomeMark.X-offset = #-5.0 > \once \override Staff.MetronomeMark.Y-offset = #4 > \tempo \markup { > \concat { > \smaller \general-align #Y #DOWN \center-column { > \smaller "3" > \vspace #0.1 > \note { 8 } #UP > } > " = " > \smaller \general-align #Y #DOWN \note { 2 } #UP > } > } > } > > halfSixteenTempo = { > \once \override Staff.MetronomeMark.break-visibility = > #end-of-line-visible > \once \override Staff.MetronomeMark.self-alignment-X = #RIGHT > \once \override Staff.MetronomeMark.X-offset = #-5.0 > \once \override Staff.MetronomeMark.Y-offset = #4 > \tempo \markup { > \concat { > \smaller \general-align #Y #DOWN \note { 2 } #UP > " = " > \smaller \general-align #Y #DOWN \note { 16 } #UP > } > } > } > > %%%%% > % Rests with lines > %%%%% > mThreeRest = { > \once \override TextScript.self-alignment-X = #CENTER > \once \override TextScript.parent-alignment-X = #CENTER > r8^\markup \with-dimensions #'(0 . 0) #'(0 . 0) { > \override #'((on . 0.4) (off . 0.5)) > \draw-dashed-line #'(0 . 6) > } > } > > mFourRest = { > \once \override TextScript.self-alignment-X = #CENTER > \once \override TextScript.parent-alignment-X = #CENTER > r16^\markup { > \override #'((on . 0.4) (off . 0.5)) > \draw-dashed-line #'(0 . 4) > } > } > > mTenQRest = { > \once \override TextScript.self-alignment-X = #CENTER > \once \override TextScript.parent-alignment-X = #CENTER > r4^\markup { > \override #'((on . 0.4) (off . 0.5)) > \draw-dashed-line #'(0 . 4) > } > } > > mTenHalfRest = { > r2 > \tweak TextScript.self-alignment-X #CENTER > \tweak TextScript.parent-alignment-X #LEFT > ^\markup { > \override #'((on . 0.4) (off . 0.5)) > \draw-dashed-line #'(0 . 5.5) > } > \tweak TextScript.self-alignment-X #CENTER > \tweak TextScript.parent-alignment-X #CENTER > \tweak TextScript.X-offset #1 > ^\markup { > \override #'((on . 0.4) (off . 0.5)) > \draw-dashed-line #'(3.75 . 5) > } > } > > %%%%% > % Custom barline stencils > %%%%% > fiveLineBarline = \markup { > \override #'(line-cap-style . butt) > \combine > \path #0.20 #'( > ; actual barline > ; height is barline height (4) + staff line (0.15) > (moveto 0 -2.05) > (lineto 0 2.05)) > \override #'(line-cap-style . round) > \path #0.1 #'( > ; staff lines > ; bottom > (moveto 0 -2) > (lineto 4 -2) > (moveto 0 -1) > (lineto 4 -1) > ; middle > (moveto 0 0) > (lineto 4 0) > (moveto 0 1) > (lineto 4 1) > (moveto 0 2) > (lineto 4 2) > ) > } > > oneLineBarline = \markup { > \override #'(line-cap-style . butt) > \combine > \path #0.20 #'( > ; actual barline > ; height is barline height (4) + staff line (0.15) > (moveto 0 -2.05) > (lineto 0 2.05)) > \override #'(line-cap-style . round) > \path #0.1 #'( > ; staff line > ; middle > (moveto 0 0) > (lineto 4 0) > > ) > } > > \score { > \new PianoStaff << > \new Staff = "up" \with { > \RemoveAllEmptyStaves > } \relative c' { > % To use 4/4 and not C > \numericTimeSignature > % Turn off the autobeaming of note groups. The auto beaming is > % not helpful in this case > \autoBeamOff > % Measure 1 > \tempo 4. = 60 > \time 1/4 > r16 ees8. \showStaffSwitch > % Measure 2 > \time 4/4 > \stopStaff > \once \override Staff.TimeSignature.break-visibility = #all-invisible > \change Staff = "down" > \once \override Stem.length = #13 > c'4. \hideStaffSwitch > % Flags always go onto stems. So... make two notes and hide what you > % don't want > << > { > \once \override Voice.Stem.transparent = ##t > \once \override Voice.Flag.transparent = ##f > ceses8 > } \\ { > \once \override Voice.Flag.transparent = ##t > \once \override Voice.Stem.length = #8 > ceses8 > } > >> > \once \override Stem.length = #20 > gis4 > \change Staff = "below" > \clef tenor > \once \override Stem.length = #25 > % With dimensions tells lilypond to not worrk about the size when > trying to > % fit everything. > bes > \tweak Y-offset #3.5 > ^\markup \with-dimensions #'(0 . 0) #'(0 . 0) { > \draw-line #'(9.5 . 5.75) > } \showStaffSwitch > % Measure 3 > \change Staff = "up" > \startStaff > \time 4/8 > \fClefDLine > \once \override Beam.positions = #'(-8 . -4) > \once \override Stem.X-offset = #1.2 > \once \override Stem.Y-offset = #0.6 > \shape #'((.75 . -.5) (3 . -.5) (-.5 . .5) (-.25 . 0)) Slur > \shape #'((0 . 0) (2 . 0) (0 . 0) (0 . -.25)) Tie > \once \override Tie.avoid-slur = #'ignore > aes8.[~( > \cClefMezzo aes16]) > \fClefDLine > f8~ f8 > \override Staff.Clef.break-visibility = #end-of-line-invisible > \set Staff.explicitClefVisibility = #end-of-line-invisible > \override Staff.TimeSignature.break-visibility = > #end-of-line-invisible > \break > %% Measure 4 > \clef treble > \time 8/16 > \hideStaffSwitch > \tuplet 3/2 {ees8 c4}~ > \cClefSoprano > \tweak bracket-visibility ##t > \tweak text \markup { > \concat { > "6" > \smaller \general-align #Y #DOWN \note { 16 } #UP > ":" > \smaller \general-align #Y #DOWN \note { 4 } #UP > } > } > \tweak positions #'(5.25 . 4) > \tweak edge-height #'(1.2 . 1.2) > \tweak TupletNumber.Y-offset #6 > \tuplet 3/2 {c8[ r dis]} > % Reset the clef and time signature printing from above. We'll also > % revert the time signature setting to for cleanliness > \revert Staff.Clef.break-visibility > \unset Staff.explicitClefVisibility > \revert Staff.TimeSignature.break-visibility > % Time signature is hidden from above, but we need to supress > % this inital one too > \once \override Staff.TimeSignature.break-visibility = #all-invisible > \override Staff.BarLine.allow-span-bar = ##f > \stopStaff > % Measure 5 > \time 4/4 > % Move the melody to the actual bottom staff so we can control the > % startStaff better here > s4*2/3 \startStaff s8*2/3 > \clef alto > << > { > \tuplet 3/2 { > \stemUp > aes'8\tweak positions #'(17.5 . 17) [ > \change Staff = "above" > aeses > \change Staff = "down" > aes!] > > } > \change Staff = "up" > \stemNeutral > bes4~ \tuplet 3/2 {bes8[ r ees,8] } > \eighthHalfTempo > } > \new Staff = "above" \with { > alignAboveContext = "up" > \remove Time_signature_engraver > } { > \clef "bass^8" > % For some reason stopping the staff after the first quarter > % here makes the staff extend all of the way to the end > s4 s32 \stopStaff s32 s16 s8 > } > >> > > \break > %% Measure 6 > \time 3/4 > \clef alto > c'2~ c4 | > << > { > %% Measure 7 > \showStaffSwitch > > bes4 \once \override Staff.Clef.extra-offset = #'(3 . 0) \clef > treble > \bar "" > \stopStaff > \change Staff = "above" > \once \override Staff.Clef.extra-offset = #'(0.5 . 0) \clef > treble > \tweak NoteColumn.X-offset #1 aes2 > %% Measure 8 > \change Staff = "up" > % Again we just use a box to hid the lines we're covering up > \once \override Staff.Clef.stencil = #ly:text-interface::print > \once \override Staff.Clef.text = \markup \with-dimensions #'(0 > . 0) #'(0 . 0) { > \combine > \raise #-0.15 > \with-color #white > \filled-box #'(0 . 2.85) #'(0 . 4.3) #0 > \musicglyph "clefs.C" > } > \cClefSoprano > \time 1/1 > \startStaff > bes2 aes | > \hideStaffSwitch > %% Measure 9 > f2 ees > %% Measure 10 > \once \override Staff.BarLine.bar-extent = #'(-2 . 2) > \oneStaffLine > \repeat unfold 4 { \mTenQRest } > \halfSixteenTempo > \once \override Staff.BarLine.text = \oneLineBarline > \once \override Staff.BarLine.stencil = #ly:text-interface::print > \once \override Staff.BarLine.X-extent = #'(0 . 0) > } > \new Staff = "above" \with { > alignAboveContext = "up" > firstClef = ##f > } \relative c' { > \override Staff.BarLine.allow-span-bar = ##f > %% Measure 7 > r4 s2 | > \clef "bass^8" > \once \override Staff.TimeSignature.break-visibility = > #all-invisible > %% Measure 8 > \stopStaff > \time 1/1 > s1 > %% Measure 9 > s1 > %% Measure 10 > \startStaff > c4~ c~ c~ > \shape #'((0 . 0) (0 . 0) (2.5 . 0) (2.5 . 0)) LaissezVibrerTie > c\laissezVibrer > %% Looking at the code trying to figure out how to do this > progrmatically. I > %% assume there is a way, but break align symbols doesn't seem > to work. Is there > % a break align symbol for the right edge? Also, width could > work, but because there > % are two staff parts on this line, it connects them. For now > the easiest thing to > % do I think is to create a barline symbol that will sit under > it. > \once \override Staff.BarLine.text = \fiveLineBarline > \once \override Staff.BarLine.stencil = #ly:text-interface::print > \once \override Staff.BarLine.X-extent = #'(0 . 0) > } > \new Staff = "below" \with { > alignBelowContext = "up" > \remove Time_signature_engraver > } { > \set Staff.explicitClefVisibility = #all-invisible > \override Staff.Clef.break-visibility = #all-invisible > \stopStaff > %% Measure 7 > s2. | > %% Measure 8 > \time 1/1 > s1 > %% Measure 9 > s1 > %% Measure 10 > \oneStaffLine > \mTenHalfRest \mTenHalfRest > \unset Staff.explicitClefVisibility > \once \override Staff.Clef.glyph-name = "clefs.G_change" > \clef treble > \once \override Staff.BarLine.text = \oneLineBarline > \once \override Staff.BarLine.stencil = #ly:text-interface::print > \once \override Staff.BarLine.X-extent = #'(0 . 0) > } > >> > \break > %% Measure 11 > \change Staff = "up" > \fiveStaffLines > \gClefELine > \time 3/16 > \newSpacingSection > \override Score.SpacingSpanner.base-shortest-duration = > #(ly:make-moment 1/32) > \override Score.SpacingSpanner.spacing-increment = #3 > << > { > %% Measure 11 > % Slur goes to above. > % Phrasing slur to to below > r16 r32 r32 > \shape #'((0 . 0) (-.25 . 5) (-4.25 . 3) (0 . 0)) Slur > \shape #'((0 . 0) (0 . 0) (0 . 0) (0 . 0)) PhrasingSlur > ees32~[(_\( ees] | > %% Measure 12 > \once \override Stem.X-offset = #0.05 > \once \override Stem.Y-offset = #-0.45 > > f16\tweak positions #'(2 . 4.5) [ > \change Staff = "above" > \shape #'((0 . 0) (8 . 6) (-4 . 13) (0 . 0)) Slur > bes16)( > \change Staff = "below" > \shape #'((0 . 0) (2 . -10) (-2 . -8) (0 . 0)) PhrasingSlur > \once \override Stem.X-offset = #0.1 > \once \override Stem.Y-offset = #-0.45 > aes16]\)\( > %% Measure 13 > \change Staff = "up" > \newSpacingSection > \override Score.SpacingSpanner.base-shortest-duration = > #(ly:make-moment 1/16) > \override Score.SpacingSpanner.spacing-increment = #3 > \nineStaffLines > g16[ f g] | > %% Measure 14 > aes8.)\) > } > \new Staff = "above" \with { > alignAboveContext = "up" > \remove Time_signature_engraver > } { > \override Staff.BarLine.allow-span-bar = ##f > % Since all clefs are missing here, we can keep these two > settings turned on > \override Staff.Clef.break-visibility = #all-invisible > \set Staff.explicitClefVisibility = #all-invisible > \stopStaff > % Measure 11 > s8. > \startStaff > % Measure 12 > \nineStaffLines > \clef "bass^8" > \once \override Rest.duration-log = #3 > \once \override Rest.color = "gray" > r16 \skip 8 > % Measure 13 > \once \override Staff.BarLine.bar-extent = #'(-4 . 4) > \oneStaffLine > R8. > \stopStaff > } > \new Staff = "below" \with { > alignBelowContext = "up" > \remove Time_signature_engraver > } { > % Since all clefs are missing here, we can keep these two > settings turned on > \override Staff.Clef.break-visibility = #all-invisible > \set Staff.explicitClefVisibility = #all-invisible > \stopStaff > % Measure 11 > s8. > % Measure 12 > s16 > \startStaff > s8 > \stopStaff > } > >> > \bar "|." > } > \new Staff = "down" \with { > \RemoveAllEmptyStaves > } \relative c' { > % To use 4/4 and not C > \numericTimeSignature > \autoBeamOff > % Measure 1 > \time 1/4 > R4 > % Measure 2 > << > { > % remove the barline extending down from here > \override Staff.BarLine.allow-span-bar = ##f > \time 4/4 > \once \override Staff.MetronomeMark.X-offset = #2 > \once \override Staff.MetronomeMark.Y-offset = #4 > \tempo \mmDottedQHalf > s2. \stopStaff s4 > > % If the space is there because of the clef above > % then we can just override the clef again with a box... > % Layer 0 makes sure it is drawn first > \once \override Staff.Clef.layer = #0 > \once \override Staff.Clef.text = \markup \with-dimensions #'(0 > . 0) #'(0 . 0) { > \with-color #white > \filled-box #'(0 . 2.85) #'(-.3 . 1.8) #0 > } > \once \override Staff.Clef.stencil = #ly:text-interface::print > \once \override Staff.Clef.break-visibility = #all-visible > > % Measure 3 > \startStaff > \time 4/8 \oneStaffLine > \newSpacingSection > \override Score.SpacingSpanner.uniform-stretching = ##t > \set Score.proportionalNotationDuration = #(ly:make-moment 1/22) > \override Score.SpacingSpanner.strict-note-spacing = ##t > > \mThreeRest \mThreeRest \mThreeRest \mThreeRest > > > } > \new Staff = "below" \with { > firstClef = ##f > \override VerticalAxisGroup.default-staff-staff-spacing = > #'((basic-distance . 0) > (minimum-distance . 0) > (padding . 0) > (stretchability . 0)) > } { > << > { > \oneVoice > % This was a fun one. Cairo doesn't have a dashed function > built in > % to it's line drawing API it looks like... unless it's a > straight line. > % There is some custom code however for ties and slurs that > allow it > % to be dashed. The solution? Use ties and slurs to make > this. For now > % at least, and set it to dashed. > % We're going to draw this lower than it should be and then > move it > % into position with extra offset. This way, the staves > don't move to > % try to accomadate the slur. Because things are set in a > top/down > % fashion, this will always set the next staff down lower to > fit the > % slur in "this" row. > \slurDashed > \shape > #'((2.5 . 0) (15 . 10.5) (-2.5 . -15) (-.75 . -12.8)) Slur > r2. > \tweak Slur.Y-extent #'(+inf.0 . -inf.0) > \tweak Slur.X-extent #'(+inf.0 . -inf.0) > \tweak Slur.extra-offset #'(0 . 5) > ( > s4) > } \\ { > s4 \stopStaff s2 \startStaff s4 \stopStaff > % We need to keep this staff alive to get the weird 8/16 at > the end > \once \override Staff.TimeSignature.break-visibility = > #all-invisible > % when this is a staff, it would make a lot of space between > this staff > % and the next. Tried working with the skylines but > eventually just > % told lilypond to set on one page and it stopped. Didn't > actually figure > % out what was causing the extended extent to be calculated. > \time 4/8 > \skip 2 > } > >> > > } > >> > \newSpacingSection > % Unset m. 3 spacing > \revert Score.SpacingSpanner.uniform-stretching > \unset Score.proportionalNotationDuration > \revert Score.SpacingSpanner.strict-note-spacing > % Set m. 4 spacing > \override Score.SpacingSpanner.uniform-stretching = ##t > \set Score.proportionalNotationDuration = #(ly:make-moment 1/6) > \override Score.SpacingSpanner.shortest-duration-space = #2.20 > > > %% Measure 4 > \eightEighteenQTempo > > \once \override Staff.Clef.Y-offset = #0 > % Use _change because it's smaller > \once \override Staff.Clef.glyph-name = "clefs.tab_change" > \time 8/16 > % Stuff about the clef happening in the NEXT bar and unable to turn > off the > % staff lines. So this just uses the spacing and changes the glyphs > \repeat unfold 7 { \mFourRest } > \once \override TextScript.self-alignment-X = #CENTER > \once \override TextScript.parent-alignment-X = #CENTER > \once \override Rest.duration-log = #4 > > r32^\markup { > \override #'((on . 0.4) (off . 0.5)) > \draw-dashed-line #'(0 . 4) > } > > \once \override Rest.extra-spacing-width = #'(0 . 0.8) > \once \override Rest.stencil = #ly:text-interface::print > \once \override Rest.text = \markup { > \raise #3 > \column { > \translate #'(0.6 . -0.1) \fontsize #-4 "8" > \musicglyph "clefs.G_change" > } > } > r32 > > %% Measure 5 > > \newSpacingSection > \revert Score.SpacingSpanner.uniform-stretching > \unset Score.proportionalNotationDuration > \revert Score.SpacingSpanner.shortest-duration-space > % Measure 5 > % But we do actually need to put the actual clef so that the > % transposition is correct. > \once \override Staff.Clef.break-visibility = #all-invisible > \once \set Staff.explicitClefVisibility = #all-invisible > \clef "treble^8" > \fiveStaffLines > \time 4/4 > \once \override TupletNumber.outside-staff-priority = #10 > \slurDashed > \shape #'((-0.5 . -2) (-0.65 . 4.6) (-11.65 . -1.4) (-4 . -1.5)) Slur > \tuplet 3/2 {c'8[~( c16 bes aes8]} > \change Staff = "up" > \hideNotes aes8*2/3) s4*2/3 \change Staff = "down" > % We need to change the clef before we display it because this clef > % ain't got no modifier. > \once \override Staff.Clef.break-visibility = #all-invisible > \once \set Staff.explicitClefVisibility = #all-invisible > \clef treble > s8 \stopStaff s8 s4 > \once \override Staff.Clef.break-visibility = #end-of-line-visible > \once \override Staff.TimeSignature.break-visibility = #all-invisible > \once \override Staff.Clef.glyph-name = "clefs.G_change" > } > >> > > > \layout { > \context { > \Score > % Remove the MM mark from the top of all staves > \remove Metronome_mark_engraver > % Make bar numbers have circles around them > \override BarNumber.stencil = #(make-stencil-circler 0.1 0.25 > ly:text-interface::print) > % And move the bar numbers over slightly > \override Score.BarNumber.X-offset = #-0.25 > } > \context { > \Staff > % Allow the MM mark to appear on any staff > \consists Metronome_mark_engraver > } > \context { > \Voice > % Make the voice follower lines dotted > \override VoiceFollower.style = #'dashed-line > } > \context { > \PianoStaff > % Any staff height lower than collapse-height will not have the > brace. > \override SystemStartBrace.collapse-height = #13 > } > } > } > > > #### END CODE >
