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
