[{"data":1,"prerenderedAt":4361},["ShallowReactive",2],{"\u002Fblog\u002F2026-05-04-engraving-music":3,"surround:\u002Fblog\u002F2026-05-04-engraving-music":4264,"navigation":4270},{"id":4,"title":5,"body":6,"date":4256,"description":12,"extension":4257,"meta":4258,"navigation":622,"path":4260,"published":622,"seo":4261,"stem":4262,"__hash__":4263},"blog\u002Fblog\u002F2026-05-04-engraving-music.md","Engraving Beautiful Musical Scores With “Musical LaTeX”",{"type":7,"value":8,"toc":4241},"minimark",[9,13,16,19,35,68,71,76,83,349,366,369,373,386,389,428,434,463,495,543,548,551,554,590,594,597,600,1136,1141,1145,1148,1151,1154,1157,1162,1182,1185,1225,1261,1264,1285,1449,1462,1465,1470,1481,1557,1570,1589,1594,1598,1605,1608,1738,1743,1758,1768,1774,1873,1878,1903,1906,1949,1953,1963,1966,2041,2044,2065,2068,2071,2074,2196,2199,2202,2325,2335,2340,2343,2397,2403,2408,2412,2415,2420,2426,2462,2484,2502,2519,2529,2534,2537,2548,2573,2576,2595,2609,2614,2643,2646,2767,2772,2775,2796,2801,2804,2857,2860,2879,2891,2895,2898,2903,2913,2916,2921,2924,2961,2966,2971,2974,2979,2986,3081,3086,3098,3103,3127,3146,3177,3197,3215,3220,3238,3255,3260,3263,3282,3292,3432,3444,3486,3491,3516,3521,3524,3553,3561,3606,3611,3623,3627,3630,3637,3741,3746,3753,3770,4019,4024,4028,4035,4040,4045,4065,4070,4081,4090,4168,4171,4176,4179,4204,4207,4211,4214,4221,4224,4229,4237],[10,11,12],"p",{},"If you know me in person, you likely know how much I admire the music of John Williams.\nAs a musician, this sort of admiration is rarely fully satisfied by listening to the pieces\nor watching the movies they accompany. Rather, we musicians feel this urge to study the music,\nlearn the part written for our instrument, and practice (often demanding) excerpts, either\nwith the intention of playing the piece with an orchestra, or purely for our own enjoyment.",[10,14,15],{},"One problem with this is that unless you're very lucky and your library or orchestra has the precise piece and part\nyou want to play, in order to obtain the original parts written by the composer (or orchestrator),\nyou would usually have to pay around 600 to 900 USD for the complete score with all parts, which is quite unreasonable.",[10,17,18],{},"As such, I was thinking about transcribing the parts I was interested in from conductor scores (which are cheaper and easier to come by),\nbut I wasn't sure if there was any reasonably priced software that could satisfy my perfectionism and high expectations regarding the produced scores. Occasionally, I do use MuseScore for some toy projects, which is free and works well for basic scores, but it was clear to me that this software would not be well suited for this need.",[10,20,21,22,26,27,34],{},"So, I did some ",[23,24,25],"em",{},"research"," (asked Claude), and found out about ",[28,29,33],"a",{"href":30,"rel":31},"https:\u002F\u002Flilypond.org\u002F",[32],"nofollow","LilyPond",":",[36,37,38,44,47,52],"blockquote",{},[10,39,40,43],{},[41,42,33],"strong",{}," is the gold standard for engraving quality. It uses a text-based input language (similar to coding), giving you precise control over every element. The output rivals professionally engraved scores. The tradeoff is a steeper learning curve — you describe music in markup rather than clicking notes in.",[10,45,46],{},"(...)",[10,48,49,51],{},[41,50,33],{}," wins hands-down for raw customization:",[53,54,55,59,62,65],"ul",{},[56,57,58],"li",{},"You can override virtually any property of any engraving object — stem lengths, beam angles, slur curves, staff spacing, collision avoidance behavior, everything",[56,60,61],{},"Full control over fonts (text and music glyphs), including support for alternative music fonts like Bravura, Gonville, or custom ones",[56,63,64],{},"Since it's text-based, you can programmatically generate or transform scores with scripting",[56,66,67],{},"The downside is that deep customization requires learning its Scheme-based override system, which can get arcane",[10,69,70],{},"I looked up LilyPond as well as all the other alternatives that the monsieur suggested, and LilyPond seemed most promising. What surprised me was Claude's description of LilyPond as a \"gold standard\" despite being free and open-source software (FOSS). With time, I understood just how much of a hidden gem this piece of software is and how incredibly well it suits my situation specifically.",[72,73,75],"h2",{"id":74},"the-latex-of-music-notation","The LaTeX of Music Notation",[10,77,78,79,82],{},"Unlike MuseScore or Sibelius, LilyPond is practically a ",[23,80,81],{},"compiler"," in the traditional computer science sense. It takes some source text as input, and produces a binary output (e.g. a PDF). I think any technical person reading this will immediately think of TeX (or more specifically LaTeX) as an analogue, and this analogy only keeps solidifying as you dig deeper into LilyPond.",[10,84,85,86,90,91,348],{},"For those unfamiliar, TeX is an old, but still very widely used typesetting system. It can be used to typeset entire books or scientific articles, and likely most university theses, at least in technical and mathematical fields, have been produced using it. However, technically speaking anything is possible with it — TeX is infamous for its gargantuan complexity and meta-programmability. For typesetting mathematical texts in particular, LaTeX can be used, which is in simple terms an extension of TeX with a lot of predefined \"commands\" (macros) for mathematical writing. In fact, this blog supports rendering LaTeX expressions, which is why I can write something like ",[87,88,89],"code",{},"\\text H (X) = - \\sum_{x \\in \\mathcal X} p(x) \\log p(x)"," and you can see something like ",[92,93,96,175],"span",{"className":94},[95],"katex",[92,97,100],{"className":98},[99],"katex-mathml",[101,102,104],"math",{"xmlns":103},"http:\u002F\u002Fwww.w3.org\u002F1998\u002FMath\u002FMathML",[105,106,107,171],"semantics",{},[108,109,110,114,119,123,126,129,132,149,151,153,155,157,160,163,165,167,169],"mrow",{},[111,112,113],"mtext",{},"H",[115,116,118],"mo",{"stretchy":117},"false","(",[120,121,122],"mi",{},"X",[115,124,125],{"stretchy":117},")",[115,127,128],{},"=",[115,130,131],{},"−",[133,134,135,138],"msub",{},[115,136,137],{},"∑",[108,139,140,143,146],{},[120,141,142],{},"x",[115,144,145],{},"∈",[120,147,122],{"mathvariant":148},"script",[120,150,10],{},[115,152,118],{"stretchy":117},[120,154,142],{},[115,156,125],{"stretchy":117},[120,158,159],{},"log",[115,161,162],{},"⁡",[120,164,10],{},[115,166,118],{"stretchy":117},[120,168,142],{},[115,170,125],{"stretchy":117},[172,173,89],"annotation",{"encoding":174},"application\u002Fx-tex",[92,176,180,222],{"className":177,"ariaHidden":179},[178],"katex-html","true",[92,181,184,189,197,201,206,210,215,219],{"className":182},[183],"base",[92,185],{"className":186,"style":188},[187],"strut","height:1em;vertical-align:-0.25em;",[92,190,194],{"className":191},[192,193],"mord","text",[92,195,113],{"className":196},[192],[92,198,118],{"className":199},[200],"mopen",[92,202,122],{"className":203,"style":205},[192,204],"mathnormal","margin-right:0.07847em;",[92,207,125],{"className":208},[209],"mclose",[92,211],{"className":212,"style":214},[213],"mspace","margin-right:0.2778em;",[92,216,128],{"className":217},[218],"mrel",[92,220],{"className":221,"style":214},[213],[92,223,225,229,232,236,307,310,313,316,319,322,325,333,336,339,342,345],{"className":224},[183],[92,226],{"className":227,"style":228},[187],"height:1.0771em;vertical-align:-0.3271em;",[92,230,131],{"className":231},[192],[92,233],{"className":234,"style":235},[213],"margin-right:0.1667em;",[92,237,240,246],{"className":238},[239],"mop",[92,241,137],{"className":242,"style":245},[239,243,244],"op-symbol","small-op","position:relative;top:0em;",[92,247,250],{"className":248},[249],"msupsub",[92,251,255,298],{"className":252},[253,254],"vlist-t","vlist-t2",[92,256,259,293],{"className":257},[258],"vlist-r",[92,260,264],{"className":261,"style":263},[262],"vlist","height:0.1786em;",[92,265,267,272],{"style":266},"top:-2.4003em;margin-left:0em;margin-right:0.05em;",[92,268],{"className":269,"style":271},[270],"pstrut","height:2.7em;",[92,273,279],{"className":274},[275,276,277,278],"sizing","reset-size6","size3","mtight",[92,280,282,285,288],{"className":281},[192,278],[92,283,142],{"className":284},[192,204,278],[92,286,145],{"className":287},[218,278],[92,289,122],{"className":290,"style":292},[192,291,278],"mathcal","margin-right:0.14643em;",[92,294,297],{"className":295},[296],"vlist-s","​",[92,299,301],{"className":300},[258],[92,302,305],{"className":303,"style":304},[262],"height:0.3271em;",[92,306],{},[92,308],{"className":309,"style":235},[213],[92,311,10],{"className":312},[192,204],[92,314,118],{"className":315},[200],[92,317,142],{"className":318},[192,204],[92,320,125],{"className":321},[209],[92,323],{"className":324,"style":235},[213],[92,326,328,329],{"className":327},[239],"lo",[92,330,332],{"style":331},"margin-right:0.01389em;","g",[92,334],{"className":335,"style":235},[213],[92,337,10],{"className":338},[192,204],[92,340,118],{"className":341},[200],[92,343,142],{"className":344},[192,204],[92,346,125],{"className":347},[209]," as output.",[10,350,351,352,355,356,359,360,365],{},"Essentially, we can draw a pretty nice parallel: Engraving music in MuseScore is like writing a book in Microsoft Word — there's an intuitive (well, somewhat...) user interface, everything can be clicked in, rearranged, styles are configured through menus and dialogues. On the other hand, LilyPond and TeX are text-based; everything you desire must be explicitly stated in the source code, however, a major advantage of this approach is the ",[23,353,354],{},"determinism"," and ",[23,357,358],{},"predictability"," it creates. This is not to say that text-based typesetting or engraving is better than ",[28,361,364],{"href":362,"rel":363},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FWYSIWYG",[32],"WYSIWIG","; either approach has its benefits and its target audience. However, personally I am completely on the side of predictability and explainability.",[10,367,368],{},"With this in mind, I was curious to see how difficult it would be to learn LilyPond's syntax and how painful it would be to troubleshoot errors or unexpected behaviour (because believe me, the universality of TeX comes at a cost). Then I remembered something that made this whole \"getting started\" process a lot easier, compared to what it would have been a couple years ago: As big tech CEOs are competing who can pour more money into making the best new glorified word predictor, the time cost of debugging errors is cut significantly, if a large language model (LLM) can read through hundreds of pages of documentation, forums, wikis and mailing lists (yep, I told you it was FOSS), and produce a couple of best guesses at what the solution might be to a given problem.",[72,370,372],{"id":371},"tutorial-the-basics","Tutorial: The Basics",[10,374,375,376,381,382,385],{},"While you can install and invoke LilyPond directly using a command line, I opted to try another software called Frescobaldi, which bundles LilyPond and provides a text editor and output views (think Overleaf or Kile for LaTeX). I found it to work reasonably well, unless you turn on \"Automatic Engrave\"; unfortunately, Frescobaldi v4.0.5 ",[28,377,380],{"href":378,"rel":379},"https:\u002F\u002Fgithub.com\u002Ffrescobaldi\u002Ffrescobaldi\u002Fissues\u002F2159",[32],"leaks a little bit of memory"," every time a document is rendered and thus gets less and less responsive the more you work, so rerendering the document on every keystroke is not helpful. Instead, you can use the keyboard shortcut ",[87,383,384],{},"Ctrl+M"," to engrave the document on demand.",[10,387,388],{},"The \"hello world\" of LilyPond is quite simple. In the simplest case, you can just start writing note names and see a score instantly.",[390,391,396],"pre",{"className":392,"code":393,"language":394,"meta":395,"style":395},"language-tex shiki shiki-themes github-dark","\\version \"2.24\"\n{\n  a b c d\n}\n","tex","",[87,397,398,410,416,422],{"__ignoreMap":395},[92,399,402,406],{"class":400,"line":401},"line",1,[92,403,405],{"class":404},"sDLfK","\\version",[92,407,409],{"class":408},"s95oV"," \"2.24\"\n",[92,411,413],{"class":400,"line":412},2,[92,414,415],{"class":408},"{\n",[92,417,419],{"class":400,"line":418},3,[92,420,421],{"class":408},"  a b c d\n",[92,423,425],{"class":400,"line":424},4,[92,426,427],{"class":408},"}\n",[10,429,430],{},[431,432],"img",{"alt":395,"src":433},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F01-helloworld.png",[10,435,436,437,355,440,443,444,447,448,450,451,454,455,458,459,462],{},"Getting around the basics was surprisingly smooth. The LilyPond documentation explains how ",[87,438,439],{},"'",[87,441,442],{},","," move a pitch up or down an octave, so that ",[87,445,446],{},"a'"," is one octave higher than ",[87,449,28],{},", it explains how numbers are appended to signify duration, so that ",[87,452,453],{},"a'1"," is a semibreve, ",[87,456,457],{},"a'2"," a minim, ",[87,460,461],{},"a'4"," a crotchet, etc., and a dot can be appended to make the duration dotted (which in music notation means increased by 50 %). Also, \"relative\" input mode is introduced early, where the octave of a note is specified relative to the previous, so that the absolute octave does not have to be specified for each note repeatedly.",[10,464,465,466,469,470,355,472,474,475,478,479,482,483,486,487,490,491,494],{},"I explored more basic features: the ",[87,467,468],{},"\\time"," declaration, slurs using ",[87,471,118],{},[87,473,125],{}," after a note for beginning and end respectively, ",[87,476,477],{},"-"," followed by another symbol for articulations (",[87,480,481],{},"-."," staccato, ",[87,484,485],{},"--"," tenuto, ",[87,488,489],{},"->"," marcato), ",[87,492,493],{},"r"," instead of a note name for rests, etc.:",[390,496,498],{"className":392,"code":497,"language":394,"meta":395,"style":395},"\\version \"2.24\"\n{\n  \\relative {\n    \\time 3\u002F4\n    a'4.( b8 c d) | e2-> r4\n  }\n}\n",[87,499,500,506,510,518,526,532,538],{"__ignoreMap":395},[92,501,502,504],{"class":400,"line":401},[92,503,405],{"class":404},[92,505,409],{"class":408},[92,507,508],{"class":400,"line":412},[92,509,415],{"class":408},[92,511,512,515],{"class":400,"line":418},[92,513,514],{"class":404},"  \\relative",[92,516,517],{"class":408}," {\n",[92,519,520,523],{"class":400,"line":424},[92,521,522],{"class":404},"    \\time",[92,524,525],{"class":408}," 3\u002F4\n",[92,527,529],{"class":400,"line":528},5,[92,530,531],{"class":408},"    a'4.( b8 c d) | e2-> r4\n",[92,533,535],{"class":400,"line":534},6,[92,536,537],{"class":408},"  }\n",[92,539,541],{"class":400,"line":540},7,[92,542,427],{"class":408},[10,544,545],{},[431,546],{"alt":395,"src":547},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F02-basics.png",[10,549,550],{},"Depending on the region of the world that you come from, the above may or may not feel correct. Note (pitch) names differ in various languages: For example, the notes we call \"b-flat\" and \"b\" in English are called \"bes\" and \"b\" in Dutch or \"b\" and \"h\" in German, respectively.",[10,552,553],{},"As I'm used to the German convention, I will set the language mode appropriately.",[390,555,557],{"className":392,"code":556,"language":394,"meta":395,"style":395},"\\version \"2.24\"\n\\language \"deutsch\" % 'Deutsch' is German for 'German'.\n{\n  % ... (Just like in LaTeX, comments start with a percent sign.)\n}\n",[87,558,559,565,577,581,586],{"__ignoreMap":395},[92,560,561,563],{"class":400,"line":401},[92,562,405],{"class":404},[92,564,409],{"class":408},[92,566,567,570,573],{"class":400,"line":412},[92,568,569],{"class":404},"\\language",[92,571,572],{"class":408}," \"deutsch\" ",[92,574,576],{"class":575},"sAwPA","% 'Deutsch' is German for 'German'.\n",[92,578,579],{"class":400,"line":418},[92,580,415],{"class":408},[92,582,583],{"class":400,"line":424},[92,584,585],{"class":575},"  % ... (Just like in LaTeX, comments start with a percent sign.)\n",[92,587,588],{"class":400,"line":528},[92,589,427],{"class":408},[72,591,593],{"id":592},"tutorial-an-actual-score","Tutorial: An Actual Score",[10,595,596],{},"While the simple examples above (and similar ones showcased in the official documentation) are sufficient to learn about inputting different kinds of music notation, when engraving a real score, we want a proper layout, with a header, possibly a footer, an instrument name, a composer name, etc.",[10,598,599],{},"All of this is accounted for in LilyPond with sensible defaults. The following is an example of how a score can be created with multiple movements and multiple levels of headers:",[390,601,603],{"className":392,"code":602,"language":394,"meta":395,"style":395},"\\version \"2.24\"\n\\language \"deutsch\"\n\n\\paper {\n  % Print headers also for individual movements\u002Fpieces.\n  print-all-headers = ##t\n}\n\n\\book {\n  \\header {\n    title = \"Harry Potter And The Prisoner Of Azkaban\"\n    composer = \"John Williams\"\n    instrument = \"Piccolo (Flute)\"\n    tagline = #f\n  }\n\n  % Insert a bit of vertical space.\n  \\markup \\vspace #1\n\n  \\score {\n    \\header {\n      title = \"I. Witches, Wands and Wizards\"\n      composer = ##f\n      instrument = ##f\n    }\n\n    \\new Staff {\n      \\time 3\u002F4\n      \\tempo \"Allegro\"\n      \\textMark \"Picc.\"\n      | \\relative { \\grace { a''16\\\u003C(^\"“Quidditch 2004”\" h c d } e8-^\\!\\sfz) r r4 r }\n      | R1*3\u002F4\n      | \\relative { \\grace { a''16\\\u003C( h c d } e8-^\\!\\sfz) r r4 r }\n      | R1*3\u002F4\n      | \\relative { \\grace { a''16\\\u003C( h c d } e8-^\\!\\sfz) r r4 r }\n      | s4\n      \\stopStaff\n      % For now, treat this as magic\n      \\once \\override Score.TextScript.Y-offset = #0\n      s2^\\markup \\large \"…\"\n    }\n  }\n\n  \\score {\n    \\header {\n      title = \"II. Aunt Marge’s Waltz\"\n      composer = ##f\n      instrument = ##f\n    }\n\n    \\new Staff {\n      \\numericTimeSignature\n      \\time 3\u002F4\n      \\set Timing.beamExceptions = #'()\n      \\set Timing.beatBase = #1\u002F8\n      \\set Timing.beatStructure = 2,2,2\n\n      \\tempo \"Playfully Light Waltz\"\n      \\compressMMRests { R1*3\u002F4*16 } \\textEndMark \"Flute\"\n      | \\relative { fis''8-.->\\mf fis-.-> fis-.-> fis-.-> fis-.-> fis-.-> }\n      | \\relative { \\acciaccatura ais''8 g-.-> g, g g g g }\n      | s4\n      \\stopStaff\n      \\once \\override Score.TextScript.Y-offset = #0\n      s2^\\markup \\large \"…\"\n    }\n  }\n}\n",[87,604,605,611,618,624,631,636,641,645,650,658,666,672,678,684,690,695,700,706,718,723,731,739,745,751,757,763,768,777,785,794,803,833,839,861,866,887,893,899,905,917,932,937,942,947,954,961,967,972,977,982,987,994,1000,1007,1016,1024,1032,1037,1045,1060,1076,1091,1096,1101,1110,1121,1126,1131],{"__ignoreMap":395},[92,606,607,609],{"class":400,"line":401},[92,608,405],{"class":404},[92,610,409],{"class":408},[92,612,613,615],{"class":400,"line":412},[92,614,569],{"class":404},[92,616,617],{"class":408}," \"deutsch\"\n",[92,619,620],{"class":400,"line":418},[92,621,623],{"emptyLinePlaceholder":622},true,"\n",[92,625,626,629],{"class":400,"line":424},[92,627,628],{"class":404},"\\paper",[92,630,517],{"class":408},[92,632,633],{"class":400,"line":528},[92,634,635],{"class":575},"  % Print headers also for individual movements\u002Fpieces.\n",[92,637,638],{"class":400,"line":534},[92,639,640],{"class":408},"  print-all-headers = ##t\n",[92,642,643],{"class":400,"line":540},[92,644,427],{"class":408},[92,646,648],{"class":400,"line":647},8,[92,649,623],{"emptyLinePlaceholder":622},[92,651,653,656],{"class":400,"line":652},9,[92,654,655],{"class":404},"\\book",[92,657,517],{"class":408},[92,659,661,664],{"class":400,"line":660},10,[92,662,663],{"class":404},"  \\header",[92,665,517],{"class":408},[92,667,669],{"class":400,"line":668},11,[92,670,671],{"class":408},"    title = \"Harry Potter And The Prisoner Of Azkaban\"\n",[92,673,675],{"class":400,"line":674},12,[92,676,677],{"class":408},"    composer = \"John Williams\"\n",[92,679,681],{"class":400,"line":680},13,[92,682,683],{"class":408},"    instrument = \"Piccolo (Flute)\"\n",[92,685,687],{"class":400,"line":686},14,[92,688,689],{"class":408},"    tagline = #f\n",[92,691,693],{"class":400,"line":692},15,[92,694,537],{"class":408},[92,696,698],{"class":400,"line":697},16,[92,699,623],{"emptyLinePlaceholder":622},[92,701,703],{"class":400,"line":702},17,[92,704,705],{"class":575},"  % Insert a bit of vertical space.\n",[92,707,709,712,715],{"class":400,"line":708},18,[92,710,711],{"class":404},"  \\markup",[92,713,714],{"class":404}," \\vspace",[92,716,717],{"class":408}," #1\n",[92,719,721],{"class":400,"line":720},19,[92,722,623],{"emptyLinePlaceholder":622},[92,724,726,729],{"class":400,"line":725},20,[92,727,728],{"class":404},"  \\score",[92,730,517],{"class":408},[92,732,734,737],{"class":400,"line":733},21,[92,735,736],{"class":404},"    \\header",[92,738,517],{"class":408},[92,740,742],{"class":400,"line":741},22,[92,743,744],{"class":408},"      title = \"I. Witches, Wands and Wizards\"\n",[92,746,748],{"class":400,"line":747},23,[92,749,750],{"class":408},"      composer = ##f\n",[92,752,754],{"class":400,"line":753},24,[92,755,756],{"class":408},"      instrument = ##f\n",[92,758,760],{"class":400,"line":759},25,[92,761,762],{"class":408},"    }\n",[92,764,766],{"class":400,"line":765},26,[92,767,623],{"emptyLinePlaceholder":622},[92,769,771,774],{"class":400,"line":770},27,[92,772,773],{"class":404},"    \\new",[92,775,776],{"class":408}," Staff {\n",[92,778,780,783],{"class":400,"line":779},28,[92,781,782],{"class":404},"      \\time",[92,784,525],{"class":408},[92,786,788,791],{"class":400,"line":787},29,[92,789,790],{"class":404},"      \\tempo",[92,792,793],{"class":408}," \"Allegro\"\n",[92,795,797,800],{"class":400,"line":796},30,[92,798,799],{"class":404},"      \\textMark",[92,801,802],{"class":408}," \"Picc.\"\n",[92,804,806,809,812,815,818,821,824,827,830],{"class":400,"line":805},31,[92,807,808],{"class":408},"      | ",[92,810,811],{"class":404},"\\relative",[92,813,814],{"class":408}," { ",[92,816,817],{"class":404},"\\grace",[92,819,820],{"class":408}," { a''16",[92,822,823],{"class":404},"\\\u003C",[92,825,826],{"class":408},"(^\"“Quidditch 2004”\" h c d } e8-^",[92,828,829],{"class":404},"\\!\\sfz",[92,831,832],{"class":408},") r r4 r }\n",[92,834,836],{"class":400,"line":835},32,[92,837,838],{"class":408},"      | R1*3\u002F4\n",[92,840,842,844,846,848,850,852,854,857,859],{"class":400,"line":841},33,[92,843,808],{"class":408},[92,845,811],{"class":404},[92,847,814],{"class":408},[92,849,817],{"class":404},[92,851,820],{"class":408},[92,853,823],{"class":404},[92,855,856],{"class":408},"( h c d } e8-^",[92,858,829],{"class":404},[92,860,832],{"class":408},[92,862,864],{"class":400,"line":863},34,[92,865,838],{"class":408},[92,867,869,871,873,875,877,879,881,883,885],{"class":400,"line":868},35,[92,870,808],{"class":408},[92,872,811],{"class":404},[92,874,814],{"class":408},[92,876,817],{"class":404},[92,878,820],{"class":408},[92,880,823],{"class":404},[92,882,856],{"class":408},[92,884,829],{"class":404},[92,886,832],{"class":408},[92,888,890],{"class":400,"line":889},36,[92,891,892],{"class":408},"      | s4\n",[92,894,896],{"class":400,"line":895},37,[92,897,898],{"class":404},"      \\stopStaff\n",[92,900,902],{"class":400,"line":901},38,[92,903,904],{"class":575},"      % For now, treat this as magic\n",[92,906,908,911,914],{"class":400,"line":907},39,[92,909,910],{"class":404},"      \\once",[92,912,913],{"class":404}," \\override",[92,915,916],{"class":408}," Score.TextScript.Y-offset = #0\n",[92,918,920,923,926,929],{"class":400,"line":919},40,[92,921,922],{"class":408},"      s2^",[92,924,925],{"class":404},"\\markup",[92,927,928],{"class":404}," \\large",[92,930,931],{"class":408}," \"…\"\n",[92,933,935],{"class":400,"line":934},41,[92,936,762],{"class":408},[92,938,940],{"class":400,"line":939},42,[92,941,537],{"class":408},[92,943,945],{"class":400,"line":944},43,[92,946,623],{"emptyLinePlaceholder":622},[92,948,950,952],{"class":400,"line":949},44,[92,951,728],{"class":404},[92,953,517],{"class":408},[92,955,957,959],{"class":400,"line":956},45,[92,958,736],{"class":404},[92,960,517],{"class":408},[92,962,964],{"class":400,"line":963},46,[92,965,966],{"class":408},"      title = \"II. Aunt Marge’s Waltz\"\n",[92,968,970],{"class":400,"line":969},47,[92,971,750],{"class":408},[92,973,975],{"class":400,"line":974},48,[92,976,756],{"class":408},[92,978,980],{"class":400,"line":979},49,[92,981,762],{"class":408},[92,983,985],{"class":400,"line":984},50,[92,986,623],{"emptyLinePlaceholder":622},[92,988,990,992],{"class":400,"line":989},51,[92,991,773],{"class":404},[92,993,776],{"class":408},[92,995,997],{"class":400,"line":996},52,[92,998,999],{"class":404},"      \\numericTimeSignature\n",[92,1001,1003,1005],{"class":400,"line":1002},53,[92,1004,782],{"class":404},[92,1006,525],{"class":408},[92,1008,1010,1013],{"class":400,"line":1009},54,[92,1011,1012],{"class":404},"      \\set",[92,1014,1015],{"class":408}," Timing.beamExceptions = #'()\n",[92,1017,1019,1021],{"class":400,"line":1018},55,[92,1020,1012],{"class":404},[92,1022,1023],{"class":408}," Timing.beatBase = #1\u002F8\n",[92,1025,1027,1029],{"class":400,"line":1026},56,[92,1028,1012],{"class":404},[92,1030,1031],{"class":408}," Timing.beatStructure = 2,2,2\n",[92,1033,1035],{"class":400,"line":1034},57,[92,1036,623],{"emptyLinePlaceholder":622},[92,1038,1040,1042],{"class":400,"line":1039},58,[92,1041,790],{"class":404},[92,1043,1044],{"class":408}," \"Playfully Light Waltz\"\n",[92,1046,1048,1051,1054,1057],{"class":400,"line":1047},59,[92,1049,1050],{"class":404},"      \\compressMMRests",[92,1052,1053],{"class":408}," { R1*3\u002F4*16 } ",[92,1055,1056],{"class":404},"\\textEndMark",[92,1058,1059],{"class":408}," \"Flute\"\n",[92,1061,1063,1065,1067,1070,1073],{"class":400,"line":1062},60,[92,1064,808],{"class":408},[92,1066,811],{"class":404},[92,1068,1069],{"class":408}," { fis''8-.->",[92,1071,1072],{"class":404},"\\mf",[92,1074,1075],{"class":408}," fis-.-> fis-.-> fis-.-> fis-.-> fis-.-> }\n",[92,1077,1079,1081,1083,1085,1088],{"class":400,"line":1078},61,[92,1080,808],{"class":408},[92,1082,811],{"class":404},[92,1084,814],{"class":408},[92,1086,1087],{"class":404},"\\acciaccatura",[92,1089,1090],{"class":408}," ais''8 g-.-> g, g g g g }\n",[92,1092,1094],{"class":400,"line":1093},62,[92,1095,892],{"class":408},[92,1097,1099],{"class":400,"line":1098},63,[92,1100,898],{"class":404},[92,1102,1104,1106,1108],{"class":400,"line":1103},64,[92,1105,910],{"class":404},[92,1107,913],{"class":404},[92,1109,916],{"class":408},[92,1111,1113,1115,1117,1119],{"class":400,"line":1112},65,[92,1114,922],{"class":408},[92,1116,925],{"class":404},[92,1118,928],{"class":404},[92,1120,931],{"class":408},[92,1122,1124],{"class":400,"line":1123},66,[92,1125,762],{"class":408},[92,1127,1129],{"class":400,"line":1128},67,[92,1130,537],{"class":408},[92,1132,1134],{"class":400,"line":1133},68,[92,1135,427],{"class":408},[10,1137,1138],{},[431,1139],{"alt":395,"src":1140},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F03-headers.png",[72,1142,1144],{"id":1143},"making-the-score-beautiful","Making the Score Beautiful",[10,1146,1147],{},"While the above snippet is technically correct, it isn't particularly visually pleasing (at least compared to the original score). One issue you can see even in these shorts excerpts is that a lot of the notes and text are crammed together, which only gets worse in more complicated passages that come later in the score. Since one of my goals was to preserve as much of the original score's quality in my extracted part, and match its style and formatting as well as I could, I needed to solve a range of problems.",[10,1149,1150],{},"At almost every point, tackling the next problem seemed very daunting. Having an LLM \"assistant\" was helpful in a lot of cases, but in what feels like equally many cases, it hallucinated a feasible-sounding answer that was completely false. This was expected; the key was to remain persistent and cross-check LLM responses with documentation, forum posts and other search results and try to gain more understanding of how LilyPond works internally in the process.",[10,1152,1153],{},"In the end, I managed to solve a surprisingly vast majority of the issues I had with the scores, and more importantly, learn how to think about these problems in the mental “framework” that LilyPond provides. The elegance of the solutions varied from setting a single flag to engraving invisible grace notes with visible slurs and overriding internal properties of various symbol types (in LilyPond terminology, \"grobs\"), but overall, the amount of customization achievable with LilyPond is impressive to me, especially since I'm confident there are still many mechanics and options I have not discovered.",[10,1155,1156],{},"In the remainder of this blog, I'll explain some of the challenges I wanted to solve and how I managed them.",[1158,1159,1161],"h3",{"id":1160},"fonts-and-header-layout","Fonts and Header Layout",[10,1163,1164,1165,1170,1171,1174,1175,355,1178,1181],{},"One thing that is particularly beautiful about the original John Williams scores is the choice of both text fonts and the music font used to engrave them. I wasn't sure what text fonts were used exactly until I found a ",[28,1166,1169],{"href":1167,"rel":1168},"https:\u002F\u002Ftypography.guru\u002Fforums\u002Ftopic\u002F1042-what-font-does-the-hal-leonard-corporation-use-for-john-williams-musical-scores\u002F",[32],"typography forum post"," which suggested the respective fonts to be ",[41,1172,1173],{},"Palatino",", ",[41,1176,1177],{},"Times New Roman",[41,1179,1180],{},"Futura",". This humbled my inner typography nerd, as these are all timeless, ubiquitous fonts found absolutely everywhere, that I should have recognized straight away, but I was happy to have the right answer regardless.",[10,1183,1184],{},"To customize the text fonts used in LilyPond v2.24+, we can simply override some global properties:",[390,1186,1188],{"className":392,"code":1187,"language":394,"meta":395,"style":395},"\\version \"2.24\"\n\n\\paper {\n  property-defaults.fonts.serif     = \"Times New Roman\"\n  property-defaults.fonts.title     = \"Palatino\"\n  property-defaults.fonts.titlesans = \"Futura\"\n}\n",[87,1189,1190,1196,1200,1206,1211,1216,1221],{"__ignoreMap":395},[92,1191,1192,1194],{"class":400,"line":401},[92,1193,405],{"class":404},[92,1195,409],{"class":408},[92,1197,1198],{"class":400,"line":412},[92,1199,623],{"emptyLinePlaceholder":622},[92,1201,1202,1204],{"class":400,"line":418},[92,1203,628],{"class":404},[92,1205,517],{"class":408},[92,1207,1208],{"class":400,"line":424},[92,1209,1210],{"class":408},"  property-defaults.fonts.serif     = \"Times New Roman\"\n",[92,1212,1213],{"class":400,"line":528},[92,1214,1215],{"class":408},"  property-defaults.fonts.title     = \"Palatino\"\n",[92,1217,1218],{"class":400,"line":534},[92,1219,1220],{"class":408},"  property-defaults.fonts.titlesans = \"Futura\"\n",[92,1222,1223],{"class":400,"line":540},[92,1224,427],{"class":408},[10,1226,1227,1228,1231,1232,1235,1236,1239,1240,1235,1243,1239,1246,1235,1249,1252,1253,1256,1257,1260],{},"By default, the ",[87,1229,1230],{},"fonts"," property contains font families named ",[87,1233,1234],{},"serif"," (",[87,1237,1238],{},"roman","), ",[87,1241,1242],{},"sans",[87,1244,1245],{},"sans-serif",[87,1247,1248],{},"typewriter",[87,1250,1251],{},"monospace","), and ",[87,1254,1255],{},"music"," (which, understandably, is a music font rather than a text font). However, as I found out through experimentation, nothing stops you from adding another family name to this ",[87,1258,1259],{},"property-defaults.fonts"," list and assigning a font name, like shown in the snippet above.",[10,1262,1263],{},"Understandably however, defining a font family is not enough to have it used in the score, as the rest of LilyPond simply isn't aware of its existence. This ties in to the next issue I wanted to solve, which was customizing the layout of the score header.",[10,1265,1266,1267,1270,1271,1274,1275,1277,1278,1280,1281,1284],{},"This turned out to be one of the simpler and more pleasant customization mechanisms in LilyPond. All you need is to add a ",[87,1268,1269],{},"bookTitleMarkup"," property, and potentially a ",[87,1272,1273],{},"scoreTitleMarkup"," property, to the ",[87,1276,628],{}," block either at the top level, or inside the ",[87,1279,655],{}," or ",[87,1282,1283],{},"\\bookpart"," you wish to customize.",[390,1286,1288],{"className":392,"code":1287,"language":394,"meta":395,"style":395},"\\paper {\n  print-all-headers = ##t\n  bookTitleMarkup = \\markup {\n    \\column {\n      \\fill-line { \\fontsize #7 \\override #'(baseline-skip . 5) \\override #'(font-family . title) \\fromproperty #'header:title }\n      \\vspace #1.5\n      \\fill-line {\n        \\override #'(font-family . title) \\fromproperty #'header:instrument\n        \\override #'(font-family . title) \\fontsize #1 \\fromproperty #'header:composer\n      }\n    }\n  }\n  scoreTitleMarkup = \\markup {\n    \\column {\n      \\fill-line { \\fontsize #4 \\override #'(font-family . title) \\fromproperty #'header:title }\n    }\n  }\n}\n",[87,1289,1290,1296,1300,1309,1316,1347,1355,1362,1374,1390,1395,1399,1403,1412,1418,1437,1441,1445],{"__ignoreMap":395},[92,1291,1292,1294],{"class":400,"line":401},[92,1293,628],{"class":404},[92,1295,517],{"class":408},[92,1297,1298],{"class":400,"line":412},[92,1299,640],{"class":408},[92,1301,1302,1305,1307],{"class":400,"line":418},[92,1303,1304],{"class":408},"  bookTitleMarkup = ",[92,1306,925],{"class":404},[92,1308,517],{"class":408},[92,1310,1311,1314],{"class":400,"line":424},[92,1312,1313],{"class":404},"    \\column",[92,1315,517],{"class":408},[92,1317,1318,1321,1324,1327,1330,1333,1336,1338,1341,1344],{"class":400,"line":528},[92,1319,1320],{"class":404},"      \\fill",[92,1322,1323],{"class":408},"-line { ",[92,1325,1326],{"class":404},"\\fontsize",[92,1328,1329],{"class":408}," #7 ",[92,1331,1332],{"class":404},"\\override",[92,1334,1335],{"class":408}," #'(baseline-skip . 5) ",[92,1337,1332],{"class":404},[92,1339,1340],{"class":408}," #'(font-family . title) ",[92,1342,1343],{"class":404},"\\fromproperty",[92,1345,1346],{"class":408}," #'header:title }\n",[92,1348,1349,1352],{"class":400,"line":534},[92,1350,1351],{"class":404},"      \\vspace",[92,1353,1354],{"class":408}," #1.5\n",[92,1356,1357,1359],{"class":400,"line":540},[92,1358,1320],{"class":404},[92,1360,1361],{"class":408},"-line {\n",[92,1363,1364,1367,1369,1371],{"class":400,"line":647},[92,1365,1366],{"class":404},"        \\override",[92,1368,1340],{"class":408},[92,1370,1343],{"class":404},[92,1372,1373],{"class":408}," #'header:instrument\n",[92,1375,1376,1378,1380,1382,1385,1387],{"class":400,"line":652},[92,1377,1366],{"class":404},[92,1379,1340],{"class":408},[92,1381,1326],{"class":404},[92,1383,1384],{"class":408}," #1 ",[92,1386,1343],{"class":404},[92,1388,1389],{"class":408}," #'header:composer\n",[92,1391,1392],{"class":400,"line":660},[92,1393,1394],{"class":408},"      }\n",[92,1396,1397],{"class":400,"line":668},[92,1398,762],{"class":408},[92,1400,1401],{"class":400,"line":674},[92,1402,537],{"class":408},[92,1404,1405,1408,1410],{"class":400,"line":680},[92,1406,1407],{"class":408},"  scoreTitleMarkup = ",[92,1409,925],{"class":404},[92,1411,517],{"class":408},[92,1413,1414,1416],{"class":400,"line":686},[92,1415,1313],{"class":404},[92,1417,517],{"class":408},[92,1419,1420,1422,1424,1426,1429,1431,1433,1435],{"class":400,"line":692},[92,1421,1320],{"class":404},[92,1423,1323],{"class":408},[92,1425,1326],{"class":404},[92,1427,1428],{"class":408}," #4 ",[92,1430,1332],{"class":404},[92,1432,1340],{"class":408},[92,1434,1343],{"class":404},[92,1436,1346],{"class":408},[92,1438,1439],{"class":400,"line":697},[92,1440,762],{"class":408},[92,1442,1443],{"class":400,"line":702},[92,1444,537],{"class":408},[92,1446,1447],{"class":400,"line":708},[92,1448,427],{"class":408},[10,1450,1451,1452,1454,1455,1458,1459,1461],{},"This showcases an important concept in LilyPond, which is ",[87,1453,925],{},". In simple terms, anywhere that you can input text (",[87,1456,1457],{},"\"text\"",") in a score, you can equivalently input ",[87,1460,925],{},", which allows you to customize text size, alignment, font family, insert glyphs from the musical font, and much more.",[10,1463,1464],{},"With this customization, the John Williams score snippet from earlier can now look something like this:",[10,1466,1467],{},[431,1468],{"alt":395,"src":1469},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F04-fonts.png",[10,1471,1472,1473,1476,1477,1480],{},"One thing that still keeps the original font is the numbers displayed above multi-measure rests. Because this ",[23,1474,1475],{},"grob",", called ",[87,1478,1479],{},"MultiMeasureRestNumber",", actually uses the music font family by default, which is not text, the customization is a little less straightforward, but still easy:",[390,1482,1484],{"className":392,"code":1483,"language":394,"meta":395,"style":395},"\\version \"2.24\"\n% ...\n\n\\layout {\n  \\context {\n    \\Score\n    \\override MultiMeasureRestNumber.font-family = #'serif\n    \\override MultiMeasureRestNumber.font-encoding = #'latin1\n    \\override MultiMeasureRestNumber.font-size = #2\n    \\override MultiMeasureRestNumber.font-series = #'bold\n  }\n}\n",[87,1485,1486,1492,1497,1501,1508,1515,1520,1528,1535,1542,1549,1553],{"__ignoreMap":395},[92,1487,1488,1490],{"class":400,"line":401},[92,1489,405],{"class":404},[92,1491,409],{"class":408},[92,1493,1494],{"class":400,"line":412},[92,1495,1496],{"class":575},"% ...\n",[92,1498,1499],{"class":400,"line":418},[92,1500,623],{"emptyLinePlaceholder":622},[92,1502,1503,1506],{"class":400,"line":424},[92,1504,1505],{"class":404},"\\layout",[92,1507,517],{"class":408},[92,1509,1510,1513],{"class":400,"line":528},[92,1511,1512],{"class":404},"  \\context",[92,1514,517],{"class":408},[92,1516,1517],{"class":400,"line":534},[92,1518,1519],{"class":404},"    \\Score\n",[92,1521,1522,1525],{"class":400,"line":540},[92,1523,1524],{"class":404},"    \\override",[92,1526,1527],{"class":408}," MultiMeasureRestNumber.font-family = #'serif\n",[92,1529,1530,1532],{"class":400,"line":647},[92,1531,1524],{"class":404},[92,1533,1534],{"class":408}," MultiMeasureRestNumber.font-encoding = #'latin1\n",[92,1536,1537,1539],{"class":400,"line":652},[92,1538,1524],{"class":404},[92,1540,1541],{"class":408}," MultiMeasureRestNumber.font-size = #2\n",[92,1543,1544,1546],{"class":400,"line":660},[92,1545,1524],{"class":404},[92,1547,1548],{"class":408}," MultiMeasureRestNumber.font-series = #'bold\n",[92,1550,1551],{"class":400,"line":668},[92,1552,537],{"class":408},[92,1554,1555],{"class":400,"line":674},[92,1556,427],{"class":408},[10,1558,1559,1560,1562,1563,1565,1566,1569],{},"The ",[87,1561,1505],{}," block allows to globally override grob properties, in this case, we are modifying properties of the aforementioned ",[87,1564,1479],{}," in a ",[87,1567,1568],{},"Score"," context. With this tweak, multi-measure rests now use the Times New Roman font family we have configured earlier.",[390,1571,1573],{"className":392,"code":1572,"language":394,"meta":395,"style":395},"\\time 3\u002F4\n\\compressMMRests { R1*3\u002F4*16 }\n",[87,1574,1575,1581],{"__ignoreMap":395},[92,1576,1577,1579],{"class":400,"line":401},[92,1578,468],{"class":404},[92,1580,525],{"class":408},[92,1582,1583,1586],{"class":400,"line":412},[92,1584,1585],{"class":404},"\\compressMMRests",[92,1587,1588],{"class":408}," { R1*3\u002F4*16 }\n",[10,1590,1591],{},[431,1592],{"alt":395,"src":1593},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F05-multi-measure-rest.png",[1158,1595,1597],{"id":1596},"rehearsal-marks-and-bar-numbers","Rehearsal Marks and Bar Numbers",[10,1599,1600,1601,1604],{},"It is common practice in orchestral scores and parts to engrave rehearsal marks — markings that allow an ensemble to start rehearsing at a particular section of the score without needing to count measures. Because the rehearsal marks in the score I'm copying take the form of boxed bar numbers, and because I'm a fool and didn't bother to read the documentation properly before trying to implement this, I defined a macro (in LilyPond called a “music function”) to change the appearance of a single bar number on request, instead of using the builtin ",[87,1602,1603],{},"RehearsalMark"," grob.",[10,1606,1607],{},"A music function allows you to define a “callable” symbol with a defined set of parameters, which you can then invoke in your score. Anything you've defined in the music function will then act as if it was “copy-pasted” into the score with the parameters replaced with their supplied values.",[390,1609,1611],{"className":392,"code":1610,"language":394,"meta":395,"style":395},"% On the top level:\nshowBarNumber = #(define-music-function (number) (number?) #{\n    % For simplicity we use #all-visible, this means bar numbers will be\n    % duplicated at the end of a line and the beginning of the following one.\n    \\once \\override Score.BarNumber.break-visibility = #all-visible\n    \\once \\override Score.BarNumber.self-alignment-X = #CENTER\n    \\once \\override Score.BarNumber.font-size = #2\n    \\once \\override Score.BarNumber.font-series = #'bold\n    % Draw a box around the printed glyphs.\n    \\once \\override Score.BarNumber.stencil = #(make-stencil-boxer 0.1 0.3 ly:text-interface::print)\n    \\barNumberCheck $number\n  #})\n\n% In a score:\n{\n  \\time 3\u002F4\n  \\compressMMRests { R1*3\u002F4*6 }\n  \\showBarNumber 7\n  \\compressMMRests { R1*3\u002F4*8 }\n}\n",[87,1612,1613,1618,1623,1628,1633,1643,1652,1661,1670,1675,1684,1696,1701,1705,1710,1714,1719,1724,1729,1734],{"__ignoreMap":395},[92,1614,1615],{"class":400,"line":401},[92,1616,1617],{"class":575},"% On the top level:\n",[92,1619,1620],{"class":400,"line":412},[92,1621,1622],{"class":408},"showBarNumber = #(define-music-function (number) (number?) #{\n",[92,1624,1625],{"class":400,"line":418},[92,1626,1627],{"class":575},"    % For simplicity we use #all-visible, this means bar numbers will be\n",[92,1629,1630],{"class":400,"line":424},[92,1631,1632],{"class":575},"    % duplicated at the end of a line and the beginning of the following one.\n",[92,1634,1635,1638,1640],{"class":400,"line":528},[92,1636,1637],{"class":404},"    \\once",[92,1639,913],{"class":404},[92,1641,1642],{"class":408}," Score.BarNumber.break-visibility = #all-visible\n",[92,1644,1645,1647,1649],{"class":400,"line":534},[92,1646,1637],{"class":404},[92,1648,913],{"class":404},[92,1650,1651],{"class":408}," Score.BarNumber.self-alignment-X = #CENTER\n",[92,1653,1654,1656,1658],{"class":400,"line":540},[92,1655,1637],{"class":404},[92,1657,913],{"class":404},[92,1659,1660],{"class":408}," Score.BarNumber.font-size = #2\n",[92,1662,1663,1665,1667],{"class":400,"line":647},[92,1664,1637],{"class":404},[92,1666,913],{"class":404},[92,1668,1669],{"class":408}," Score.BarNumber.font-series = #'bold\n",[92,1671,1672],{"class":400,"line":652},[92,1673,1674],{"class":575},"    % Draw a box around the printed glyphs.\n",[92,1676,1677,1679,1681],{"class":400,"line":660},[92,1678,1637],{"class":404},[92,1680,913],{"class":404},[92,1682,1683],{"class":408}," Score.BarNumber.stencil = #(make-stencil-boxer 0.1 0.3 ly:text-interface::print)\n",[92,1685,1686,1689,1693],{"class":400,"line":668},[92,1687,1688],{"class":404},"    \\barNumberCheck",[92,1690,1692],{"class":1691},"sU2Wk"," $",[92,1694,1695],{"class":404},"number\n",[92,1697,1698],{"class":400,"line":674},[92,1699,1700],{"class":404},"  #})\n",[92,1702,1703],{"class":400,"line":680},[92,1704,623],{"emptyLinePlaceholder":622},[92,1706,1707],{"class":400,"line":686},[92,1708,1709],{"class":575},"% In a score:\n",[92,1711,1712],{"class":400,"line":692},[92,1713,415],{"class":404},[92,1715,1716],{"class":400,"line":697},[92,1717,1718],{"class":404},"  \\time 3\u002F4\n",[92,1720,1721],{"class":400,"line":702},[92,1722,1723],{"class":404},"  \\compressMMRests { R1*3\u002F4*6 }\n",[92,1725,1726],{"class":400,"line":708},[92,1727,1728],{"class":404},"  \\showBarNumber 7\n",[92,1730,1731],{"class":400,"line":720},[92,1732,1733],{"class":404},"  \\compressMMRests { R1*3\u002F4*8 }\n",[92,1735,1736],{"class":400,"line":725},[92,1737,427],{"class":404},[10,1739,1740],{},[431,1741],{"alt":395,"src":1742},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F06-bar-number-macro.png",[10,1744,1745,1746,1749,1750,1753,1754,1757],{},"In this case, we're overriding properties of ",[87,1747,1748],{},"BarNumber"," for one time only, and then using the convenient ",[87,1751,1752],{},"\\barNumberCheck"," function to print a warning when the expected bar number does not match the actual counter. This guardrail, similar to how the ",[87,1755,1756],{},"|"," symbol checks that the current position in the score is at a measure break, is invaluable for engraving ensemble parts where a mismatch would be highly unwanted.",[10,1759,1760,1761,1764,1765,1767],{},"Although I did not end up using this approach after discovering the builtin ",[87,1762,1763],{},"\\mark"," function with the customizable ",[87,1766,1603],{}," grob, this still shows the extent of control over the score LilyPond offers.",[10,1769,1770,1771,1773],{},"Let's demonstrate the same behaviour using ",[87,1772,1603],{},"s, and in the process, let's customize the appearance of multi-measure rests. By default, different kinds of rests are displayed depending on the number of measures the rest is spanning. However, in modern scores, this is rarely used, and all multi-measure rests use the same H-bar style rest.",[390,1775,1777],{"className":392,"code":1776,"language":394,"meta":395,"style":395},"\\layout {\n  \\context {\n    \\Score\n    % Start using the H-bar style rest already at 2-measure rests.\n    \\override MultiMeasureRest.expand-limit = #2\n  }\n}\n\n{\n  \\set Score.rehearsalMarkFormatter = #format-mark-box-barnumbers\n  \\time 3\u002F4\n  \\compressMMRests { R1*3\u002F4*6 }\n  \\mark \\default\n  \\barNumberCheck 7\n  \\compressMMRests { R1*3\u002F4*8 } \n}\n",[87,1778,1779,1785,1791,1795,1800,1807,1811,1815,1819,1823,1831,1838,1846,1854,1862,1869],{"__ignoreMap":395},[92,1780,1781,1783],{"class":400,"line":401},[92,1782,1505],{"class":404},[92,1784,517],{"class":408},[92,1786,1787,1789],{"class":400,"line":412},[92,1788,1512],{"class":404},[92,1790,517],{"class":408},[92,1792,1793],{"class":400,"line":418},[92,1794,1519],{"class":404},[92,1796,1797],{"class":400,"line":424},[92,1798,1799],{"class":575},"    % Start using the H-bar style rest already at 2-measure rests.\n",[92,1801,1802,1804],{"class":400,"line":528},[92,1803,1524],{"class":404},[92,1805,1806],{"class":408}," MultiMeasureRest.expand-limit = #2\n",[92,1808,1809],{"class":400,"line":534},[92,1810,537],{"class":408},[92,1812,1813],{"class":400,"line":540},[92,1814,427],{"class":408},[92,1816,1817],{"class":400,"line":647},[92,1818,623],{"emptyLinePlaceholder":622},[92,1820,1821],{"class":400,"line":652},[92,1822,415],{"class":408},[92,1824,1825,1828],{"class":400,"line":660},[92,1826,1827],{"class":404},"  \\set",[92,1829,1830],{"class":408}," Score.rehearsalMarkFormatter = #format-mark-box-barnumbers\n",[92,1832,1833,1836],{"class":400,"line":668},[92,1834,1835],{"class":404},"  \\time",[92,1837,525],{"class":408},[92,1839,1840,1843],{"class":400,"line":674},[92,1841,1842],{"class":404},"  \\compressMMRests",[92,1844,1845],{"class":408}," { R1*3\u002F4*6 }\n",[92,1847,1848,1851],{"class":400,"line":680},[92,1849,1850],{"class":404},"  \\mark",[92,1852,1853],{"class":404}," \\default\n",[92,1855,1856,1859],{"class":400,"line":686},[92,1857,1858],{"class":404},"  \\barNumberCheck",[92,1860,1861],{"class":408}," 7\n",[92,1863,1864,1866],{"class":400,"line":692},[92,1865,1842],{"class":404},[92,1867,1868],{"class":408}," { R1*3\u002F4*8 } \n",[92,1870,1871],{"class":400,"line":697},[92,1872,427],{"class":408},[10,1874,1875],{},[431,1876],{"alt":395,"src":1877},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F07-h-bars.png",[10,1879,1880,1881,1884,1885,1888,1889,1892,1893,1896,1897,1902],{},"To my defense, finding the ",[87,1882,1883],{},"Score.rehearsalMarkFormatter"," property and the ",[87,1886,1887],{},"#format-mark-box-barnumbers"," variable without knowing it exists is not exactly trivial. This is unfortunately the case with many concepts in LilyPond — I will not be quick to accuse the documentation of being bad, since whatever ",[23,1890,1891],{},"is"," contained in there is described well, and there are simply too many nuances in music notation to be contained in a well-structured document, especially if that document and the whole software it describes is ",[23,1894,1895],{},"written almost exclusively by volunteers","™. Besides the official documentation, there is also a ",[28,1898,1901],{"href":1899,"rel":1900},"https:\u002F\u002Fwiki.lilypond.community\u002Fwiki\u002FMain_Page",[32],"community wiki"," with many useful snippets, although both are difficult to search efficiently.",[10,1904,1905],{},"The final adjustment I made in regards to bar numbers is to place them on the bottom of the stave rather than top, to match other scores I've seen from the same publisher:",[390,1907,1909],{"className":392,"code":1908,"language":394,"meta":395,"style":395},"\\layout {\n  \\context {\n    \\Score\n    \\override BarNumber.self-alignment-X = #LEFT\n    \\override BarNumber.direction = #DOWN\n  }\n}\n",[87,1910,1911,1917,1923,1927,1934,1941,1945],{"__ignoreMap":395},[92,1912,1913,1915],{"class":400,"line":401},[92,1914,1505],{"class":404},[92,1916,517],{"class":408},[92,1918,1919,1921],{"class":400,"line":412},[92,1920,1512],{"class":404},[92,1922,517],{"class":408},[92,1924,1925],{"class":400,"line":418},[92,1926,1519],{"class":404},[92,1928,1929,1931],{"class":400,"line":424},[92,1930,1524],{"class":404},[92,1932,1933],{"class":408}," BarNumber.self-alignment-X = #LEFT\n",[92,1935,1936,1938],{"class":400,"line":528},[92,1937,1524],{"class":404},[92,1939,1940],{"class":408}," BarNumber.direction = #DOWN\n",[92,1942,1943],{"class":400,"line":534},[92,1944,537],{"class":408},[92,1946,1947],{"class":400,"line":540},[92,1948,427],{"class":408},[1158,1950,1952],{"id":1951},"tempo-marks-and-section-titles","Tempo Marks and Section Titles",[10,1954,1955,1956,1280,1959,1962],{},"Another aspect of the original score I wanted to match was the appearance, placement and alignment of tempo markings (e.g. ",[41,1957,1958],{},"Quickly",[41,1960,1961],{},"In “4”",") and section titles (like “Quidditch 2004” or “End Credits”). Specifically, there are situations where both of these are specified at the same place, potentially also including a rehearsal mark. I have found that letting each marking be laid out independently is too unpredictable, so in these cases, I had to find workarounds to arrive at the appearance I wanted.",[10,1964,1965],{},"In terms of text markings, LilyPond provides these primitives:",[53,1967,1968,1982,1994,2011],{},[56,1969,1970,1973,1974,1977,1978,1981],{},[87,1971,1972],{},"TextScript"," is probably the most intuitive. It can be obtained by suffixing a note, rest or spacer with ",[87,1975,1976],{},"^\"some text or markup\""," to attach text above that thing, or ",[87,1979,1980],{},"_\"...\""," to attach text below it.",[56,1983,1984,1986,1987,1989,1990,1993],{},[87,1985,1603],{}," was already mentioned; its primary usage is to mark certain spots in the score for easy reference. It is created with the ",[87,1988,1763],{}," command followed by arbitrary markup, or ",[87,1991,1992],{},"\\mark \\default",", which uses the preset default rehearsal mark (e.g. automatically incremented letters, numbers, or exact bar numbers).",[56,1995,1996,1999,2000,2003,2004,2006,2007,2010],{},[87,1997,1998],{},"MetronomeMark"," is a grob intended to indicate the tempo of a piece or section, and is created using ",[87,2001,2002],{},"\\tempo",". Like a ",[87,2005,1603],{},", it can accept simple markup as argument, but besides that, you can specify a note duration and its BPM value. I ended up not using this feature and inserted my own rhythm markings using the ",[87,2008,2009],{},"\\rhythm"," command. This provides greater flexibility, although it does not emit any MIDI information, but that's fine for my use case.",[56,2012,2013,2014,2017,2018,2020,2021,1280,2024,2026,2027,2029,2030,2033,2034,2036,2037,2040],{},"Finally, a ",[87,2015,2016],{},"TextMark"," is similar to a ",[87,2019,1972],{},", except it is bound to the entire score instead of a single staff. It can be created using ",[87,2022,2023],{},"\\textMark",[87,2025,1056],{},", the difference being that ",[87,2028,2023],{}," comes ",[23,2031,2032],{},"in front"," of an element (note, rest, ...) and is left-aligned to its beginning, whereas ",[87,2035,1056],{}," is specified ",[23,2038,2039],{},"after"," an element and is right-aligned to its end.",[10,2042,2043],{},"Conversely, the types of annotations I needed to engrave in my scores, were:",[53,2045,2046,2049,2052,2055],{},[56,2047,2048],{},"tempo\u002Fcharacter markings, like “Quickly” or “Misterioso”,",[56,2050,2051],{},"rehearsal marks, as mentioned before,",[56,2053,2054],{},"information about which instrument to play, when to switch instruments, or cues referencing what other instrument is playing, like “Flute”, “to Piccolo”, or “(Ob.)”",[56,2056,2057,2058,1280,2061,2064],{},"expression marks, like ",[23,2059,2060],{},"“cantabile”",[23,2062,2063],{},"“marcatissimo”",".",[10,2066,2067],{},"Mostly, these requirements mapped neatly to the primitives LilyPond provides. One initial choice I made that didn't turn out to be great was using TextMarks for instrument switches. At first, I appreciated the automatic alignment that this grob provided. However, later I found out that I could achieve the same (or even better) results with simple TextScripts, which allowed the text annotations to be less convoluted and more consistent.",[10,2069,2070],{},"A more complicated hack I had to put together was to vertically align rehearsal and tempo marks placed in the same measure.",[10,2072,2073],{},"For comparison, this is the simpler music function I used for customized rehearsal marks.",[390,2075,2077],{"className":392,"code":2076,"language":394,"meta":395,"style":395},"makeRehearsalMark = #(define-music-function (expected) (number?)\n    #{\n        \\once \\override Score.RehearsalMark.self-alignment-X = #CENTER\n        \\mark \\markup {\n          \\center-align\n          \\column {\n            \" \" % Non-breaking space\n            \\vspace #0.5 % Add some vertical padding to avoid collision with above staff\n            \\override #'(box-padding . 0.4) \\box \\rehearsalMarkText #(number->string expected)\n          }\n        }\n        \\barNumberCheck $expected % Check that the mark matches the actual bar number.\n        \\once \\override Score.BarNumber.break-visibility = #'#(#f #f #f) % Hide the normal BarNumber grob for this bar.\n    #})\n",[87,2078,2079,2084,2089,2099,2109,2117,2124,2132,2143,2160,2165,2170,2183,2191],{"__ignoreMap":395},[92,2080,2081],{"class":400,"line":401},[92,2082,2083],{"class":408},"makeRehearsalMark = #(define-music-function (expected) (number?)\n",[92,2085,2086],{"class":400,"line":412},[92,2087,2088],{"class":408},"    #{\n",[92,2090,2091,2094,2096],{"class":400,"line":418},[92,2092,2093],{"class":404},"        \\once",[92,2095,913],{"class":404},[92,2097,2098],{"class":408}," Score.RehearsalMark.self-alignment-X = #CENTER\n",[92,2100,2101,2104,2107],{"class":400,"line":424},[92,2102,2103],{"class":404},"        \\mark",[92,2105,2106],{"class":404}," \\markup",[92,2108,517],{"class":408},[92,2110,2111,2114],{"class":400,"line":528},[92,2112,2113],{"class":404},"          \\center",[92,2115,2116],{"class":408},"-align\n",[92,2118,2119,2122],{"class":400,"line":534},[92,2120,2121],{"class":404},"          \\column",[92,2123,517],{"class":408},[92,2125,2126,2129],{"class":400,"line":540},[92,2127,2128],{"class":408},"            \" \" ",[92,2130,2131],{"class":575},"% Non-breaking space\n",[92,2133,2134,2137,2140],{"class":400,"line":647},[92,2135,2136],{"class":404},"            \\vspace",[92,2138,2139],{"class":408}," #0.5 ",[92,2141,2142],{"class":575},"% Add some vertical padding to avoid collision with above staff\n",[92,2144,2145,2148,2151,2154,2157],{"class":400,"line":652},[92,2146,2147],{"class":404},"            \\override",[92,2149,2150],{"class":408}," #'(box-padding . 0.4) ",[92,2152,2153],{"class":404},"\\box",[92,2155,2156],{"class":404}," \\rehearsalMarkText",[92,2158,2159],{"class":408}," #(number->string expected)\n",[92,2161,2162],{"class":400,"line":660},[92,2163,2164],{"class":408},"          }\n",[92,2166,2167],{"class":400,"line":668},[92,2168,2169],{"class":408},"        }\n",[92,2171,2172,2175,2177,2180],{"class":400,"line":674},[92,2173,2174],{"class":404},"        \\barNumberCheck",[92,2176,1692],{"class":1691},[92,2178,2179],{"class":404},"expected ",[92,2181,2182],{"class":575},"% Check that the mark matches the actual bar number.\n",[92,2184,2185,2188],{"class":400,"line":680},[92,2186,2187],{"class":404},"        \\once \\override Score.BarNumber.break-visibility = #'#(#f #f #f) ",[92,2189,2190],{"class":575},"% Hide the normal BarNumber grob for this bar.\n",[92,2192,2193],{"class":400,"line":686},[92,2194,2195],{"class":404},"    #})\n",[10,2197,2198],{},"To align the MetronomeMark next to the RehearsalMark, I got rid of the MetronomeMark altogether and instead added the tempo marking to the rehearsal mark. However, since I wanted to keep the RehearsalMark centered on the barline, I needed to prevent the text from taking up horizontal space. This worked, but since the text had a zero width, it was “invisible” to the layout engine and would collide with other elements. So, I simply added another parameter that creates padding between the staff and the rehearsal mark.",[10,2200,2201],{},"It may seem that this is way too volatile and will easily break whenever the score layout changes. There may be truth to this, but this is actually kind of irrelevant in my use case — I'm not composing scores that change often, I'm engraving existing parts and then tweaking the layout until I'm satisfied. Hence, this workaround worked fine. Perhaps now, after I've learned more about LilyPond and ways of aligning different elements, I would approach this differently, but for the present time, I don't have a reason to rework it. The final code snippet follows.",[390,2203,2205],{"className":392,"code":2204,"language":394,"meta":395,"style":395},"makeRehearsalMarkWithTempo = #(define-music-function (expected tempo padding) (number? markup? number?)\n    #{\n        \\once \\override Score.RehearsalMark.self-alignment-X = #CENTER\n        \\once \\override Score.RehearsalMark.outside-staff-padding = $padding\n        \\mark \\markup {\n          \\center-align\n          \\column {\n            \" \"\n            \\vspace #0.5\n            \\concat {\n              \\override #'(box-padding . 0.4) \\box \\rehearsalMarkText #(number->string expected)\n              \\override #'(baseline-skip . 0)\n              \\with-dimension #X #'(0 . 0)\n              { \\translate #'(1 . 0.1) \\normalsize \\fontsize #1 \\bold $tempo }\n            }\n          }\n        }\n        \\barNumberCheck $expected\n        \\once \\override Score.BarNumber.break-visibility = #'#(#f #f #f)\n    #})\n",[87,2206,2207,2212,2216,2224,2239,2244,2249,2254,2259,2264,2269,2274,2279,2284,2294,2299,2303,2307,2316,2321],{"__ignoreMap":395},[92,2208,2209],{"class":400,"line":401},[92,2210,2211],{"class":408},"makeRehearsalMarkWithTempo = #(define-music-function (expected tempo padding) (number? markup? number?)\n",[92,2213,2214],{"class":400,"line":412},[92,2215,2088],{"class":408},[92,2217,2218,2220,2222],{"class":400,"line":418},[92,2219,2093],{"class":404},[92,2221,913],{"class":404},[92,2223,2098],{"class":408},[92,2225,2226,2228,2230,2233,2236],{"class":400,"line":424},[92,2227,2093],{"class":404},[92,2229,913],{"class":404},[92,2231,2232],{"class":408}," Score.RehearsalMark.outside-staff-padding = ",[92,2234,2235],{"class":1691},"$",[92,2237,2238],{"class":404},"padding\n",[92,2240,2241],{"class":400,"line":528},[92,2242,2243],{"class":404},"        \\mark \\markup {\n",[92,2245,2246],{"class":400,"line":534},[92,2247,2248],{"class":404},"          \\center-align\n",[92,2250,2251],{"class":400,"line":540},[92,2252,2253],{"class":404},"          \\column {\n",[92,2255,2256],{"class":400,"line":647},[92,2257,2258],{"class":404},"            \" \"\n",[92,2260,2261],{"class":400,"line":652},[92,2262,2263],{"class":404},"            \\vspace #0.5\n",[92,2265,2266],{"class":400,"line":660},[92,2267,2268],{"class":404},"            \\concat {\n",[92,2270,2271],{"class":400,"line":668},[92,2272,2273],{"class":404},"              \\override #'(box-padding . 0.4) \\box \\rehearsalMarkText #(number->string expected)\n",[92,2275,2276],{"class":400,"line":674},[92,2277,2278],{"class":404},"              \\override #'(baseline-skip . 0)\n",[92,2280,2281],{"class":400,"line":680},[92,2282,2283],{"class":404},"              \\with-dimension #X #'(0 . 0)\n",[92,2285,2286,2289,2291],{"class":400,"line":686},[92,2287,2288],{"class":404},"              { \\translate #'(1 . 0.1) \\normalsize \\fontsize #1 \\bold ",[92,2290,2235],{"class":1691},[92,2292,2293],{"class":408},"tempo }\n",[92,2295,2296],{"class":400,"line":692},[92,2297,2298],{"class":408},"            }\n",[92,2300,2301],{"class":400,"line":697},[92,2302,2164],{"class":408},[92,2304,2305],{"class":400,"line":702},[92,2306,2169],{"class":408},[92,2308,2309,2311,2313],{"class":400,"line":708},[92,2310,2174],{"class":404},[92,2312,1692],{"class":1691},[92,2314,2315],{"class":404},"expected\n",[92,2317,2318],{"class":400,"line":720},[92,2319,2320],{"class":404},"        \\once \\override Score.BarNumber.break-visibility = #'#(#f #f #f)\n",[92,2322,2323],{"class":400,"line":725},[92,2324,2195],{"class":404},[10,2326,2327,2328,2331,2332,2064],{},"(Note: ",[87,2329,2330],{},"rehearsalMarkText"," is a custom function that determines and applies the style of the number based on a global flag set elsewhere.) The next image illustrates how I used this function in the piece ",[41,2333,2334],{},"“Double Trouble”",[10,2336,2337],{},[431,2338],{"alt":395,"src":2339},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F08-rehearsal-mark-aligned.png",[10,2341,2342],{},"In a similar manner, instead of aligning tempo marks with section names, I defined a function that puts both in a column.",[390,2344,2346],{"className":392,"code":2345,"language":394,"meta":395,"style":395},"makeThemeAndTempoMark = #(define-music-function (name tempo) (markup? markup?)\n    #{\n        \\tempo \\markup \\column { \\normal-text #name \\vspace #0 \\normalsize \\bold \\fontsize #1.5 #tempo }\n    #})\n",[87,2347,2348,2353,2357,2393],{"__ignoreMap":395},[92,2349,2350],{"class":400,"line":401},[92,2351,2352],{"class":408},"makeThemeAndTempoMark = #(define-music-function (name tempo) (markup? markup?)\n",[92,2354,2355],{"class":400,"line":412},[92,2356,2088],{"class":408},[92,2358,2359,2362,2364,2367,2369,2372,2375,2378,2381,2384,2387,2390],{"class":400,"line":418},[92,2360,2361],{"class":404},"        \\tempo",[92,2363,2106],{"class":404},[92,2365,2366],{"class":404}," \\column",[92,2368,814],{"class":408},[92,2370,2371],{"class":404},"\\normal",[92,2373,2374],{"class":408},"-text #name ",[92,2376,2377],{"class":404},"\\vspace",[92,2379,2380],{"class":408}," #0 ",[92,2382,2383],{"class":404},"\\normalsize",[92,2385,2386],{"class":404}," \\bold",[92,2388,2389],{"class":404}," \\fontsize",[92,2391,2392],{"class":408}," #1.5 #tempo }\n",[92,2394,2395],{"class":400,"line":424},[92,2396,2195],{"class":408},[10,2398,2399,2400,2064],{},"This was useful in the piece ",[41,2401,2402],{},"“Witches, Wands and Wizards”",[10,2404,2405],{},[431,2406],{"alt":395,"src":2407},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F09-section-name-aligned.png",[1158,2409,2411],{"id":2410},"score-spacing-and-text-positioning","Score Spacing and Text Positioning",[10,2413,2414],{},"To mirror the score as closely as I wanted, I needed to have fine-grained control over the positioning and spacing of the whole score.",[10,2416,2417],{},[41,2418,2419],{},"1. Global spacing",[10,2421,2422,2423,2425],{},"The global spacing properties are defined in the ",[87,2424,628],{}," block. Specifically, the ones I often found useful were these:",[53,2427,2428,2434,2444,2450,2456],{},[56,2429,2430,2433],{},[87,2431,2432],{},"system-system-spacing"," controls the spacing between systems (staves),",[56,2435,2436,2439,2440,2443],{},[87,2437,2438],{},"markup-system-spacing"," the spacing between top-level markup (including ",[87,2441,2442],{},"\\header","s but not including page headers and footers) and the following system,",[56,2445,2446,2449],{},[87,2447,2448],{},"markup-markup-spacing"," the spacing between consecutive top-level markups (as above),",[56,2451,2452,2455],{},[87,2453,2454],{},"score-markup-spacing"," the spacing between the last system of a score and the top-level markup following it,",[56,2457,2458,2461],{},[87,2459,2460],{},"top-markup-spacing"," the spacing between the top of the page (including\u002Fafter a page header) and the first markup.",[10,2463,2464,2465,1174,2468,1174,2471,355,2474,2477,2478,2481,2482,2064],{},"Each of these is a list of 4 values, ",[87,2466,2467],{},"basic-distance",[87,2469,2470],{},"minimum-distance",[87,2472,2473],{},"padding",[87,2475,2476],{},"stretchability",". Whenever I wanted to introduce more space, I would set the padding, e.g. ",[87,2479,2480],{},"top-markup-spacing.padding = #2","; where I wanted less space, I would lower the ",[87,2483,2467],{},[10,2485,2486,2487,355,2490,2493,2494,2497,2498,2501],{},"Another pair of variables worth mentioning are the booleans ",[87,2488,2489],{},"ragged-bottom",[87,2491,2492],{},"ragged-last-bottom",", which control whether to insert space between systems to fill the entire page (",[87,2495,2496],{},"##f",") or not (",[87,2499,2500],{},"##t",").",[10,2503,2504,2505,2507,2508,2513,2514,2064],{},"All ",[87,2506,628],{}," variables can be ",[28,2509,2512],{"href":2510,"rel":2511},"https:\u002F\u002Flilypond.org\u002Fdoc\u002Fv2.25\u002FDocumentation\u002Fnotation\u002Fpaper-variables",[32],"found"," in the manual, as well as the ",[28,2515,2518],{"href":2516,"rel":2517},"https:\u002F\u002Flilypond.org\u002Fdoc\u002Fv2.25\u002FDocumentation\u002Fnotation\u002Fflexible-vertical-spacing-paper-variables",[32],"expected values in the spacing lists",[10,2520,2521,2522,2524,2525,2528],{},"Separately from the ",[87,2523,628],{}," block, the overall scale of the score, dictated by the fundamental unit of measurement, a stave-space (or staff-space in am. eng.), can be changed by setting the staff size (e.g. to 18pts) using ",[87,2526,2527],{},"#(set-global-staff-size 18)",". (The default is 20pts).",[10,2530,2531],{},[41,2532,2533],{},"2. Local spacing adjustments",[10,2535,2536],{},"With the score laid out and spaced out to your needs, you are still likely to find suboptimal placements of TextScripts, unfortunate line or page breaks, or places where the score is too busy and not well readable. Fortunately, LilyPond gives you almost complete control.",[10,2538,2539,2540,2543,2544,2547],{},"Let's start with system breaks and page breaks. For situations when you don't feel like setting system break points by hand, you can still customize the amount of \"breathing room\" LilyPond chooses to engrave by overriding ",[87,2541,2542],{},"Score.SpacingSpanner.base-shortest-duration",". As an example, setting this value to ",[87,2545,2546],{},"#(ly:make-moment 1\u002F32)"," will hint to LilyPond that the shortest duration used in your score will be a 1\u002F32 note, and so measures will tend to be wider and notes more spaced out than with the default, which I believe is 1\u002F8.",[10,2549,2550,2551,2554,2555,2558,2559,355,2562,2565,2566,355,2569,2572],{},"If this is not enough, you can resort to manually setting a system (line) break using ",[87,2552,2553],{},"\\break"," in a score, or forbidding one with ",[87,2556,2557],{},"\\noBreak",". Analogously, page breaks can be enforced or forbidden with ",[87,2560,2561],{},"\\pageBreak",[87,2563,2564],{},"\\noPageBreak"," respectively, and in a score context, also by ",[87,2567,2568],{},"\\pageTurn",[87,2570,2571],{},"\\noPageTurn",". (Besides \"Turn\" only being available in a score context, I have not observed a difference between \"Break\" and \"Turn\".) LilyPond will unconditionally respect these constraints and try its best to lay out the music between them.",[10,2574,2575],{},"On an even smaller level, you may need to insert horizontal space at a specific place. The two most convenient ways of doing this that I found were:",[2577,2578,2579,2589],"ol",{},[56,2580,2581,2584,2585,2588],{},[87,2582,2583],{},"\\once \\override Score.NoteColumn.X-offset = ?",", which offsets a note column by the specified amount (",[87,2586,2587],{},"?","), leaving blank space preceding it,",[56,2590,2591,2594],{},[87,2592,2593],{},"\\once \\override Score.BarLine.extra-spacing-width = #(-? . ?) \\bar \"|\"",", which adds the specified amount of horizontal space to the left and right of a bar line respectively. (The minus sign in front of the first placeholder hints that that number should be negative, so it extends to the left.) This property also exists on and is useful for many other grobs, for example, I used it with a RehearsalMark in one score.",[10,2596,2597,2598,1280,2601,2604,2605,2608],{},"Finally, a neat trick for when your music collides with or pushes a TextScript or RehearsalMark too far away, is the possibility to set ",[87,2599,2600],{},"\\textLengthOn",[87,2602,2603],{},"\\markLengthOn",". From that point onwards, music following a TextScript or RehearsalMark respectively will only continue after its horizontal end. When this is no longer wanted, symmetrical ",[87,2606,2607],{},"Off"," commands can be invoked.",[10,2610,2611],{},[41,2612,2613],{},"3. Text positioning",[10,2615,2616,2617,355,2620,2623,2624,2627,2628,2631,2632,2634,2635,2638,2639,2642],{},"In a majority of cases where adjusting text positioning is needed, you only need two properties: ",[87,2618,2619],{},"X-offset",[87,2621,2622],{},"outside-staff-padding",". The former is straight-forward, for grobs that implement it (which Frescobaldi's autocompletion will hint at), this has the effect of simply shifting the element left or right by the specified amount, ",[23,2625,2626],{},"while still avoiding collisions",". The latter is a property of a so called ",[87,2629,2630],{},"outside-staff-interface",". Just like in many functional and object-oriented programming languages, LilyPond uses interfaces (othertimes called traits, protocols, or contracts) to expose an abstract property of an object regardless of its material form. In this case, grobs that implement this interface are laid out according to rules specified in that interface's properties. In practical terms, ",[87,2633,2622],{}," determines the amount of space between the staff, the object, and any other outside-staff objects above or below it. Similarly, ",[87,2636,2637],{},"outside-staff-priority"," dictates the order, from top to bottom, in which the objects are placed, and other properties, such as ",[87,2640,2641],{},"outside-staff-horizontal-padding",", control other aspects of the layout.",[10,2644,2645],{},"To illustrate, consider this snippet:",[390,2647,2649],{"className":392,"code":2648,"language":394,"meta":395,"style":395},"\\makeRehearsalMark 75\n% \"\u003C>\" (empty chord) is a way to input no music but still be able to attach scripts to that location.\n% In this case, I didn't want to attach the text to the multi-measure rest, as that creates a different kind of grob.\n\u003C>^\"to Piccolo\"\n\\once \\override MultiMeasureRest.minimum-length = #36\n| \\compressMMRests { R1*3\u002F8*15 }\n\\time 1\u002F2\n\\once \\override Score.TextMark.break-align-symbols = #'(time-signature)\n\\once \\override Score.TextMark.self-alignment-X = #CENTER\n| \\textMark \\markup \\concat { \"(\" \\rhythm { 8 } \" = \" \\rhythm { 8 } \")\" } R1*1\u002F2\n\n\\break\n\\bar \"||\"\n\\time 2\u002F2\n",[87,2650,2651,2659,2664,2669,2674,2684,2694,2701,2710,2719,2743,2747,2752,2760],{"__ignoreMap":395},[92,2652,2653,2656],{"class":400,"line":401},[92,2654,2655],{"class":404},"\\makeRehearsalMark",[92,2657,2658],{"class":408}," 75\n",[92,2660,2661],{"class":400,"line":412},[92,2662,2663],{"class":575},"% \"\u003C>\" (empty chord) is a way to input no music but still be able to attach scripts to that location.\n",[92,2665,2666],{"class":400,"line":418},[92,2667,2668],{"class":575},"% In this case, I didn't want to attach the text to the multi-measure rest, as that creates a different kind of grob.\n",[92,2670,2671],{"class":400,"line":424},[92,2672,2673],{"class":408},"\u003C>^\"to Piccolo\"\n",[92,2675,2676,2679,2681],{"class":400,"line":528},[92,2677,2678],{"class":404},"\\once",[92,2680,913],{"class":404},[92,2682,2683],{"class":408}," MultiMeasureRest.minimum-length = #36\n",[92,2685,2686,2689,2691],{"class":400,"line":534},[92,2687,2688],{"class":408},"| ",[92,2690,1585],{"class":404},[92,2692,2693],{"class":408}," { R1*3\u002F8*15 }\n",[92,2695,2696,2698],{"class":400,"line":540},[92,2697,468],{"class":404},[92,2699,2700],{"class":408}," 1\u002F2\n",[92,2702,2703,2705,2707],{"class":400,"line":647},[92,2704,2678],{"class":404},[92,2706,913],{"class":404},[92,2708,2709],{"class":408}," Score.TextMark.break-align-symbols = #'(time-signature)\n",[92,2711,2712,2714,2716],{"class":400,"line":652},[92,2713,2678],{"class":404},[92,2715,913],{"class":404},[92,2717,2718],{"class":408}," Score.TextMark.self-alignment-X = #CENTER\n",[92,2720,2721,2723,2725,2727,2730,2733,2735,2738,2740],{"class":400,"line":660},[92,2722,2688],{"class":408},[92,2724,2023],{"class":404},[92,2726,2106],{"class":404},[92,2728,2729],{"class":404}," \\concat",[92,2731,2732],{"class":408}," { \"(\" ",[92,2734,2009],{"class":404},[92,2736,2737],{"class":408}," { 8 } \" = \" ",[92,2739,2009],{"class":404},[92,2741,2742],{"class":408}," { 8 } \")\" } R1*1\u002F2\n",[92,2744,2745],{"class":400,"line":668},[92,2746,623],{"emptyLinePlaceholder":622},[92,2748,2749],{"class":400,"line":674},[92,2750,2751],{"class":404},"\\break\n",[92,2753,2754,2757],{"class":400,"line":680},[92,2755,2756],{"class":404},"\\bar",[92,2758,2759],{"class":408}," \"||\"\n",[92,2761,2762,2764],{"class":400,"line":686},[92,2763,468],{"class":404},[92,2765,2766],{"class":408}," 2\u002F2\n",[10,2768,2769],{},[431,2770],{"alt":395,"src":2771},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F19-text-spacing-before.png",[10,2773,2774],{},"(The above snippet also showcases a mechanism to stretch multi-measure rests to a desired size.) I wanted to move the instrument switch directive a bit closer to the start of the measure to draw the player's eyes, and push it a little further from the staff.",[390,2776,2778],{"className":392,"code":2777,"language":394,"meta":395,"style":395},"\\once \\override TextScript.X-offset -2.5 \\once \\override TextScript.outside-staff-padding 1.5 \u003C>^\"to Piccolo\"\n",[87,2779,2780],{"__ignoreMap":395},[92,2781,2782,2784,2786,2789,2791,2793],{"class":400,"line":401},[92,2783,2678],{"class":404},[92,2785,913],{"class":404},[92,2787,2788],{"class":408}," TextScript.X-offset -2.5 ",[92,2790,2678],{"class":404},[92,2792,913],{"class":404},[92,2794,2795],{"class":408}," TextScript.outside-staff-padding 1.5 \u003C>^\"to Piccolo\"\n",[10,2797,2798],{},[431,2799],{"alt":395,"src":2800},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F20-text-spacing-after.png",[10,2802,2803],{},"Because I used these two overrides so often, I created music functions for them:",[390,2805,2807],{"className":392,"code":2806,"language":394,"meta":395,"style":395},"padText = #(define-music-function (padding) (number?)\n    #{\n      \\once \\override TextScript.outside-staff-padding = #padding\n    #})\n\noffsetText = #(define-music-function (offset) (number?)\n    #{\n      \\once \\override TextScript.X-offset = #offset\n    #})\n",[87,2808,2809,2814,2818,2827,2831,2835,2840,2844,2853],{"__ignoreMap":395},[92,2810,2811],{"class":400,"line":401},[92,2812,2813],{"class":408},"padText = #(define-music-function (padding) (number?)\n",[92,2815,2816],{"class":400,"line":412},[92,2817,2088],{"class":408},[92,2819,2820,2822,2824],{"class":400,"line":418},[92,2821,910],{"class":404},[92,2823,913],{"class":404},[92,2825,2826],{"class":408}," TextScript.outside-staff-padding = #padding\n",[92,2828,2829],{"class":400,"line":424},[92,2830,2195],{"class":408},[92,2832,2833],{"class":400,"line":528},[92,2834,623],{"emptyLinePlaceholder":622},[92,2836,2837],{"class":400,"line":534},[92,2838,2839],{"class":408},"offsetText = #(define-music-function (offset) (number?)\n",[92,2841,2842],{"class":400,"line":540},[92,2843,2088],{"class":408},[92,2845,2846,2848,2850],{"class":400,"line":647},[92,2847,910],{"class":404},[92,2849,913],{"class":404},[92,2851,2852],{"class":408}," TextScript.X-offset = #offset\n",[92,2854,2855],{"class":400,"line":652},[92,2856,2195],{"class":408},[10,2858,2859],{},"And the usage became much more simple.",[390,2861,2863],{"className":392,"code":2862,"language":394,"meta":395,"style":395},"\\offsetText -2.5 \\padText 1.5 \u003C>^\"to Piccolo\"\n",[87,2864,2865],{"__ignoreMap":395},[92,2866,2867,2870,2873,2876],{"class":400,"line":401},[92,2868,2869],{"class":404},"\\offsetText",[92,2871,2872],{"class":408}," -2.5 ",[92,2874,2875],{"class":404},"\\padText",[92,2877,2878],{"class":408}," 1.5 \u003C>^\"to Piccolo\"\n",[10,2880,2881,2882,1174,2884,2887,2888,2890],{},"Similarly to ",[87,2883,2619],{},[87,2885,2886],{},"Y-offset"," can be used to control the vertical position of elements without introducing padding on both top and bottom. Generally, the ",[87,2889,2619],{}," override is a powerful tool that works in many contexts, like NoteColumns mentioned before, but also RehearsalMarks, MetronomeMarks, etc.",[1158,2892,2894],{"id":2893},"beams-accidental-placement-and-slurs","Beams, Accidental Placement and Slurs",[10,2896,2897],{},"Like most major music engraving software, LilyPond has sane defaults for articulation placement, slurs, beams, and similar details an ordinary musician typically does not want to concern themselves with. In my case, as you may grow weary of me saying, I wanted precise control over these stylistic choices to match the source material. Here is a summary of what I've learned.",[10,2899,2900],{},[41,2901,2902],{},"1. Beams matching beat structure",[10,2904,2905,2906,355,2909,2912],{},"Instead of manually setting beam beginnings and ends with ",[87,2907,2908],{},"[",[87,2910,2911],{},"]",", you can set a “beat structure” to alter the automatic beaming.",[10,2914,2915],{},"For example, this is the default beaming of 8th notes in 3\u002F4 time:",[10,2917,2918],{},[431,2919],{"alt":395,"src":2920},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F10-no-beat-structure.png",[10,2922,2923],{},"And this is a modified beaming:",[390,2925,2927],{"className":392,"code":2926,"language":394,"meta":395,"style":395},"\\set Timing.beamExceptions = #'()\n\\set Timing.beatBase = #1\u002F8\n\\set Timing.beatStructure = 2,2,2\n\u003C>\\mf \\repeat unfold 6 cis'''8-.->\n",[87,2928,2929,2936,2942,2948],{"__ignoreMap":395},[92,2930,2931,2934],{"class":400,"line":401},[92,2932,2933],{"class":404},"\\set",[92,2935,1015],{"class":408},[92,2937,2938,2940],{"class":400,"line":412},[92,2939,2933],{"class":404},[92,2941,1023],{"class":408},[92,2943,2944,2946],{"class":400,"line":418},[92,2945,2933],{"class":404},[92,2947,1031],{"class":408},[92,2949,2950,2953,2955,2958],{"class":400,"line":424},[92,2951,2952],{"class":408},"\u003C>",[92,2954,1072],{"class":404},[92,2956,2957],{"class":404}," \\repeat",[92,2959,2960],{"class":408}," unfold 6 cis'''8-.->\n",[10,2962,2963],{},[431,2964],{"alt":395,"src":2965},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F11-beat-structure.png",[10,2967,2968],{},[41,2969,2970],{},"2. Beam subdivision",[10,2972,2973],{},"By default, LilyPond disables beam subdivision, so a run of 1\u002F32 notes may look like this:",[10,2975,2976],{},[431,2977],{"alt":395,"src":2978},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F12-no-beam-subdivision.png",[10,2980,2981,2982,2985],{},"To make the text more legible and organized, we can ",[87,2983,2984],{},"\\set subdivideBeams = ##t"," within a score.",[390,2987,2989],{"className":392,"code":2988,"language":394,"meta":395,"style":395},"\\score {\n  {\n  \\time 4\u002F8\n  \\set subdivideBeams = ##t\n  \\set beamMinimumSubdivision = #1\u002F8\n  \\set beamMaximumSubdivision = #1\u002F16\n  | \\relative { \\slurNeutral fis'32 g a! h c( h c) d! dis gis a! h c( h c) d! }\n  \\set beamMaximumSubdivision = #1\u002F8\n  | \\relative { dis'''32\\\u003C e fis g\\! a16-. r16 r4 }\n  }\n}\n",[87,2990,2991,2998,3003,3010,3017,3024,3031,3046,3053,3073,3077],{"__ignoreMap":395},[92,2992,2993,2996],{"class":400,"line":401},[92,2994,2995],{"class":404},"\\score",[92,2997,517],{"class":408},[92,2999,3000],{"class":400,"line":412},[92,3001,3002],{"class":408},"  {\n",[92,3004,3005,3007],{"class":400,"line":418},[92,3006,1835],{"class":404},[92,3008,3009],{"class":408}," 4\u002F8\n",[92,3011,3012,3014],{"class":400,"line":424},[92,3013,1827],{"class":404},[92,3015,3016],{"class":408}," subdivideBeams = ##t\n",[92,3018,3019,3021],{"class":400,"line":528},[92,3020,1827],{"class":404},[92,3022,3023],{"class":408}," beamMinimumSubdivision = #1\u002F8\n",[92,3025,3026,3028],{"class":400,"line":534},[92,3027,1827],{"class":404},[92,3029,3030],{"class":408}," beamMaximumSubdivision = #1\u002F16\n",[92,3032,3033,3036,3038,3040,3043],{"class":400,"line":540},[92,3034,3035],{"class":408},"  | ",[92,3037,811],{"class":404},[92,3039,814],{"class":408},[92,3041,3042],{"class":404},"\\slurNeutral",[92,3044,3045],{"class":408}," fis'32 g a! h c( h c) d! dis gis a! h c( h c) d! }\n",[92,3047,3048,3050],{"class":400,"line":647},[92,3049,1827],{"class":404},[92,3051,3052],{"class":408}," beamMaximumSubdivision = #1\u002F8\n",[92,3054,3055,3057,3059,3062,3064,3067,3070],{"class":400,"line":652},[92,3056,3035],{"class":408},[92,3058,811],{"class":404},[92,3060,3061],{"class":408}," { dis'''32",[92,3063,823],{"class":404},[92,3065,3066],{"class":408}," e fis g",[92,3068,3069],{"class":404},"\\!",[92,3071,3072],{"class":408}," a16-. r16 r4 }\n",[92,3074,3075],{"class":400,"line":660},[92,3076,537],{"class":408},[92,3078,3079],{"class":400,"line":668},[92,3080,427],{"class":408},[10,3082,3083],{},[431,3084],{"alt":395,"src":3085},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F13-beam-subdivision.png",[10,3087,3088,3089,3092,3093,2064],{},"The definitions for ",[87,3090,3091],{},"beam{Min,Max}imumSubdivision"," are somewhat confusing, but it's possible to get some basic intuition for them through trial and error. You can read more about subdividing beams ",[28,3094,3097],{"href":3095,"rel":3096},"https:\u002F\u002Flilypond.org\u002Fdoc\u002Fv2.25\u002FDocumentation\u002Fsnippets\u002Frhythms-_002d-subdividing-beams",[32],"in the documentation",[10,3099,3100],{},[41,3101,3102],{},"3. Slur direction and accidental collisions",[10,3104,3105,3106,355,3109,3112,3113,3115,3116,3119,3120,3123,3124,3126],{},"In some situations, you may wish to alter slurs so that they point downward rather than upwards, or vice versa. This can be done simply with ",[87,3107,3108],{},"\\slurUp",[87,3110,3111],{},"\\slurDown"," respectively, which toggle the direction of the slurs for as long as it is not changed again or reverted with ",[87,3114,3042],{},". (A similar set of macros exists for stem direction as well, i.e. ",[87,3117,3118],{},"\\stemUp",", etc.) Alternatively, you can override the ",[87,3121,3122],{},"Slur.direction"," property. Note that these macros must be invoked in the context in which the slur begins, so for example, when using grace notes, inside the ",[87,3125,817],{}," block. Grace functions, like acciaccaturas, are a special case mentioned further below.",[10,3128,3129,3130,3133,3134,3137,3138,3141,3142,3145],{},"Another problem I needed to solve was that slurs often crossed accidentals (sharps, flats, naturals, ...), which I did not like. This led me to discover the ",[87,3131,3132],{},"details"," property of ",[87,3135,3136],{},"Slur",", which is a list of values that control the shape and behaviour of slurs. One such value is called ",[87,3139,3140],{},"accidental-collision",". It defines the ",[23,3143,3144],{},"penalty"," value for slur configurations that collide with an accidental. Raising this value from the default 3 to 12.5 worked as a good compromise for me, although in some cases I still needed to tweak the slurs manually, which I will describe shortly.",[10,3147,3148,3149,3133,3152,3155,3156,1174,3159,1174,3162,355,3165,3168,3169,3173,3174,34],{},"Another useful way of preventing slurs from colliding with other symbols, particularly Scripts (i.e. articulations and similar), is by tweaking the ",[87,3150,3151],{},"avoid-slur",[87,3153,3154],{},"Script",". The acceptable values are ",[87,3157,3158],{},"inside",[87,3160,3161],{},"outside",[87,3163,3164],{},"around",[87,3166,3167],{},"ignore"," and are described ",[28,3170,3097],{"href":3171,"rel":3172},"https:\u002F\u002Flilypond.org\u002Fdoc\u002Fv2.25\u002FDocumentation\u002Finternals\u002Fscript_002dinterface",[32],". By overriding this property, you can place articulations which normally stay inside the slur outside and vice versa. For this, you can use ",[87,3175,3176],{},"\\tweak",[390,3178,3180],{"className":392,"code":3179,"language":394,"meta":395,"style":395},"% Place a marcato outside the overarching slur.\nc16\\tweak avoid-slur #'inside -^\n",[87,3181,3182,3187],{"__ignoreMap":395},[92,3183,3184],{"class":400,"line":401},[92,3185,3186],{"class":575},"% Place a marcato outside the overarching slur.\n",[92,3188,3189,3192,3194],{"class":400,"line":412},[92,3190,3191],{"class":408},"c16",[92,3193,3176],{"class":404},[92,3195,3196],{"class":408}," avoid-slur #'inside -^\n",[10,3198,3199,3200,3202,3203,3206,3207,3210,3211,3214],{},"It is possible to override the ",[87,3201,3151],{}," property globally per articulation symbol by reading and prepending ",[87,3204,3205],{},"default-script-alist"," with custom entries and passing this list to ",[87,3208,3209],{},"scriptDefinitions"," under ",[87,3212,3213],{},"\\layout \\context \\Score",", but this is an advanced topic for another day.",[10,3216,3217],{},[41,3218,3219],{},"4. Acciaccaturas and articulations",[10,3221,3222,3223,1174,3226,3229,3230,3233,3234,3237],{},"In a couple of places, LilyPond's placement of articulation symbols, like ",[23,3224,3225],{},"staccato",[23,3227,3228],{},"tenuto",", or ",[23,3231,3232],{},"marcato",", differed from the source material. This issue became especially difficult around ",[23,3235,3236],{},"acciaccaturas",", which are built into LilyPond, but don't look the best out of the box:",[390,3239,3241],{"className":392,"code":3240,"language":394,"meta":395,"style":395},"\\relative { r4 g'''8-. r \\acciaccatura as-> g-. r g-. r }\n",[87,3242,3243],{"__ignoreMap":395},[92,3244,3245,3247,3250,3252],{"class":400,"line":401},[92,3246,811],{"class":404},[92,3248,3249],{"class":408}," { r4 g'''8-. r ",[92,3251,1087],{"class":404},[92,3253,3254],{"class":408}," as-> g-. r g-. r }\n",[10,3256,3257],{},[431,3258],{"alt":395,"src":3259},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F14-acciaccatura-default.png",[10,3261,3262],{},"The simpler problem to solve is moving the accent above the note rather than below:",[390,3264,3266],{"className":392,"code":3265,"language":394,"meta":395,"style":395},"\\once \\override Score.Script.side-relative-direction = #1 \\acciaccatura as-> g-.\n",[87,3267,3268],{"__ignoreMap":395},[92,3269,3270,3272,3274,3277,3279],{"class":400,"line":401},[92,3271,2678],{"class":404},[92,3273,913],{"class":404},[92,3275,3276],{"class":408}," Score.Script.side-relative-direction = #1 ",[92,3278,1087],{"class":404},[92,3280,3281],{"class":408}," as-> g-.\n",[10,3283,3284,3285,3288,3289,3291],{},"However, to change the direction of the slur, we have to tap into the internals a little bit and define our own ",[23,3286,3287],{},"grace function",". Unlike the slurs of regular grace notes, which can be adjusted inside the ",[87,3290,817],{}," context using the previously described methods, acciaccaturas are “immune” to these. The following snippet can be used:",[390,3293,3295],{"className":392,"code":3294,"language":394,"meta":395,"style":395},"startAcciaccaturaUpMusic = {\n  \\slurUp\n  \u003C>\\startGraceSlur\n  \\temporary \\override Flag.stroke-style = \"grace\"\n}\n\nstartAcciaccaturaDownMusic = {\n  \\slurDown\n  \u003C>\\startGraceSlur\n  \\temporary \\override Flag.stroke-style = \"grace\"\n}\n\nstopAcciaccaturaMusic = {\n  \\revert Flag.stroke-style\n  \u003C>\\stopGraceSlur\n  \\slurNeutral\n}\n\naccUp =\n#(def-grace-function startAcciaccaturaUpMusic stopAcciaccaturaMusic\n   (_i \"Acciaccatura with slur pointing up.\"))\n\naccDown =\n#(def-grace-function startAcciaccaturaDownMusic stopAcciaccaturaMusic\n   (_i \"Acciaccatura with slur pointing down.\"))\n",[87,3296,3297,3302,3307,3315,3325,3329,3333,3338,3343,3349,3357,3361,3365,3370,3378,3385,3390,3394,3398,3403,3408,3413,3417,3422,3427],{"__ignoreMap":395},[92,3298,3299],{"class":400,"line":401},[92,3300,3301],{"class":408},"startAcciaccaturaUpMusic = {\n",[92,3303,3304],{"class":400,"line":412},[92,3305,3306],{"class":404},"  \\slurUp\n",[92,3308,3309,3312],{"class":400,"line":418},[92,3310,3311],{"class":408},"  \u003C>",[92,3313,3314],{"class":404},"\\startGraceSlur\n",[92,3316,3317,3320,3322],{"class":400,"line":424},[92,3318,3319],{"class":404},"  \\temporary",[92,3321,913],{"class":404},[92,3323,3324],{"class":408}," Flag.stroke-style = \"grace\"\n",[92,3326,3327],{"class":400,"line":528},[92,3328,427],{"class":408},[92,3330,3331],{"class":400,"line":534},[92,3332,623],{"emptyLinePlaceholder":622},[92,3334,3335],{"class":400,"line":540},[92,3336,3337],{"class":408},"startAcciaccaturaDownMusic = {\n",[92,3339,3340],{"class":400,"line":647},[92,3341,3342],{"class":404},"  \\slurDown\n",[92,3344,3345,3347],{"class":400,"line":652},[92,3346,3311],{"class":408},[92,3348,3314],{"class":404},[92,3350,3351,3353,3355],{"class":400,"line":660},[92,3352,3319],{"class":404},[92,3354,913],{"class":404},[92,3356,3324],{"class":408},[92,3358,3359],{"class":400,"line":668},[92,3360,427],{"class":408},[92,3362,3363],{"class":400,"line":674},[92,3364,623],{"emptyLinePlaceholder":622},[92,3366,3367],{"class":400,"line":680},[92,3368,3369],{"class":408},"stopAcciaccaturaMusic = {\n",[92,3371,3372,3375],{"class":400,"line":686},[92,3373,3374],{"class":404},"  \\revert",[92,3376,3377],{"class":408}," Flag.stroke-style\n",[92,3379,3380,3382],{"class":400,"line":692},[92,3381,3311],{"class":408},[92,3383,3384],{"class":404},"\\stopGraceSlur\n",[92,3386,3387],{"class":400,"line":697},[92,3388,3389],{"class":404},"  \\slurNeutral\n",[92,3391,3392],{"class":400,"line":702},[92,3393,427],{"class":408},[92,3395,3396],{"class":400,"line":708},[92,3397,623],{"emptyLinePlaceholder":622},[92,3399,3400],{"class":400,"line":720},[92,3401,3402],{"class":408},"accUp =\n",[92,3404,3405],{"class":400,"line":725},[92,3406,3407],{"class":408},"#(def-grace-function startAcciaccaturaUpMusic stopAcciaccaturaMusic\n",[92,3409,3410],{"class":400,"line":733},[92,3411,3412],{"class":408},"   (_i \"Acciaccatura with slur pointing up.\"))\n",[92,3414,3415],{"class":400,"line":741},[92,3416,623],{"emptyLinePlaceholder":622},[92,3418,3419],{"class":400,"line":747},[92,3420,3421],{"class":408},"accDown =\n",[92,3423,3424],{"class":400,"line":753},[92,3425,3426],{"class":408},"#(def-grace-function startAcciaccaturaDownMusic stopAcciaccaturaMusic\n",[92,3428,3429],{"class":400,"line":759},[92,3430,3431],{"class":408},"   (_i \"Acciaccatura with slur pointing down.\"))\n",[10,3433,3434,3435,355,3438,3441,3442,34],{},"Then, in the score, ",[87,3436,3437],{},"\\accUp",[87,3439,3440],{},"\\accDown"," can be used in place of a regular ",[87,3443,1087],{},[390,3445,3447],{"className":392,"code":3446,"language":394,"meta":395,"style":395},"\\relative {\n  r4 g'''8-. r\n  \\once \\override Score.Script.side-relative-direction = #1\n  \\accUp as-> g-.\n  r g-. r\n}\n",[87,3448,3449,3455,3460,3470,3477,3482],{"__ignoreMap":395},[92,3450,3451,3453],{"class":400,"line":401},[92,3452,811],{"class":404},[92,3454,517],{"class":408},[92,3456,3457],{"class":400,"line":412},[92,3458,3459],{"class":408},"  r4 g'''8-. r\n",[92,3461,3462,3465,3467],{"class":400,"line":418},[92,3463,3464],{"class":404},"  \\once",[92,3466,913],{"class":404},[92,3468,3469],{"class":408}," Score.Script.side-relative-direction = #1\n",[92,3471,3472,3475],{"class":400,"line":424},[92,3473,3474],{"class":404},"  \\accUp",[92,3476,3281],{"class":408},[92,3478,3479],{"class":400,"line":528},[92,3480,3481],{"class":408},"  r g-. r\n",[92,3483,3484],{"class":400,"line":534},[92,3485,427],{"class":408},[10,3487,3488],{},[431,3489],{"alt":395,"src":3490},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F15-acciaccatura-fixed.png",[10,3492,3493,3494,3497,3498,355,3501,3504,3505,3508,3509,3511,3512,3515],{},"For other tweaks related to articulations, you can always consult the documentation for the ",[28,3495,3154],{"href":3496},"..."," grob; the properties I found most useful were ",[87,3499,3500],{},"Script.side-relative-direction",[87,3502,3503],{},"Script.direction",". One more non-trivial trick worth mentioning is pushing articulations like ",[23,3506,3507],{},"staccatos"," outside the staff, for example to print the ",[23,3510,3225],{}," close together with an accent. This can be done, to me surprisingly, by overriding the ",[87,3513,3514],{},"Script.outside-staff-priority"," property and setting it to a high enough number, like 100.",[10,3517,3518],{},[41,3519,3520],{},"5. Fine-grained slur tweaks",[10,3522,3523],{},"If the layout of your score is final and you're willing to bring the engraving to perfection one slur at a time, LilyPond provides you with the tools you need to control almost every aspect of a slur.",[10,3525,3526,3527,3530,3531,3534,3535,3538,3539,3542,3543,1174,3548,2501],{},"The simpler tool you have at your disposal is overriding ",[87,3528,3529],{},"Slur.positions",". This is a pair of numbers (e.g. ",[87,3532,3533],{},"#(6 . 7)",") which offset the starting and ending point of the slur ",[23,3536,3537],{},"vertically"," by that amount (in staff-spaces). (The same approach also works e.g. with a ",[87,3540,3541],{},"TupletBracket",".) More on this approach can be found on the wiki (",[28,3544,3547],{"href":3545,"rel":3546},"https:\u002F\u002Fwiki.lilypond.community\u002Findex.php?title=Moving_slur_positions_vertically",[32],"using Slur.positions",[28,3549,3552],{"href":3550,"rel":3551},"https:\u002F\u002Fwiki.lilypond.community\u002Fwiki\u002FAdjusting_slur_positions_vertically",[32],"using a music function",[10,3554,3555,3556,34],{},"For the most amount of control, you can actually shape the curve freely by adjusting (offseting) the 4 points that define the slur's ",[28,3557,3560],{"href":3558,"rel":3559},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FB%C3%A9zier_curve",[32],"Bézier curve",[390,3562,3564],{"className":392,"code":3563,"language":394,"meta":395,"style":395},"\\relative {\n  r4 g'''8-. r\n  \\once \\override Score.Script.side-relative-direction = #1\n  \\shape #'((0.75 . -0.25) (0.50 . -0.50) (0.25 . -0.75) (-0.125 . -1)) Slur\n  \\accUp as-> g-.\n  r g-. r\n}\n",[87,3565,3566,3572,3576,3584,3592,3598,3602],{"__ignoreMap":395},[92,3567,3568,3570],{"class":400,"line":401},[92,3569,811],{"class":404},[92,3571,517],{"class":408},[92,3573,3574],{"class":400,"line":412},[92,3575,3459],{"class":408},[92,3577,3578,3580,3582],{"class":400,"line":418},[92,3579,3464],{"class":404},[92,3581,913],{"class":404},[92,3583,3469],{"class":408},[92,3585,3586,3589],{"class":400,"line":424},[92,3587,3588],{"class":404},"  \\shape",[92,3590,3591],{"class":408}," #'((0.75 . -0.25) (0.50 . -0.50) (0.25 . -0.75) (-0.125 . -1)) Slur\n",[92,3593,3594,3596],{"class":400,"line":528},[92,3595,3474],{"class":404},[92,3597,3281],{"class":408},[92,3599,3600],{"class":400,"line":534},[92,3601,3481],{"class":408},[92,3603,3604],{"class":400,"line":540},[92,3605,427],{"class":408},[10,3607,3608],{},[431,3609],{"alt":395,"src":3610},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F16-slur-shape.png",[10,3612,3613,3614,3617,3618,2064],{},"For more information on ",[87,3615,3616],{},"\\shape"," and Slurs, see the relevant ",[28,3619,3622],{"href":3620,"rel":3621},"https:\u002F\u002Fwiki.lilypond.community\u002Fwiki\u002FSetting_the_control_points_of_a_slur_manually",[32],"wiki entry",[1158,3624,3626],{"id":3625},"cues-and-ossias","Cues and Ossias",[10,3628,3629],{},"Yet another common occurrence in orchestral parts I needed to implement were cues, i.e. snippets of another instrument's part shown in the music to help the player know when their entrance is, especially after a long period of rests. These are printed with small noteheads and a label identifying the cued instrument (e.g. \"Ob.\" or \"Vlns.\").",[10,3631,3632,3633,3636],{},"To this end, LilyPond has a special type of Voice called a ",[87,3634,3635],{},"CueVoice",", which can be used like this:",[390,3638,3640],{"className":392,"code":3639,"language":394,"meta":395,"style":395},"\\relative {\u003C\u003C\n  { R1*6\u002F8 \\bar \"||\" \\time 12\u002F8 s2 a''1\\rest s2 a1\\rest }\n  \\new CueVoice {\n    \\stemDown e,4.\\rest e4\\rest\n    \\once \\override TextScript.outside-staff-padding = #1 e8--^\\markup \\center-align \\tiny \"Fl. 1\"\n    | e'( c a) f'( c as) e'( c a) e( c' a)\n    | e( dis a') as( f c' e) r r r4.\n  }\n>>}\n",[87,3641,3642,3649,3675,3683,3699,3722,3727,3732,3736],{"__ignoreMap":395},[92,3643,3644,3646],{"class":400,"line":401},[92,3645,811],{"class":404},[92,3647,3648],{"class":408}," {\u003C\u003C\n",[92,3650,3651,3654,3656,3659,3661,3664,3667,3670,3672],{"class":400,"line":412},[92,3652,3653],{"class":408},"  { R1*6\u002F8 ",[92,3655,2756],{"class":404},[92,3657,3658],{"class":408}," \"||\" ",[92,3660,468],{"class":404},[92,3662,3663],{"class":408}," 12\u002F8 s2 a''1",[92,3665,3666],{"class":404},"\\rest",[92,3668,3669],{"class":408}," s2 a1",[92,3671,3666],{"class":404},[92,3673,3674],{"class":408}," }\n",[92,3676,3677,3680],{"class":400,"line":418},[92,3678,3679],{"class":404},"  \\new",[92,3681,3682],{"class":408}," CueVoice {\n",[92,3684,3685,3688,3691,3693,3696],{"class":400,"line":424},[92,3686,3687],{"class":404},"    \\stemDown",[92,3689,3690],{"class":408}," e,4.",[92,3692,3666],{"class":404},[92,3694,3695],{"class":408}," e4",[92,3697,3698],{"class":404},"\\rest\n",[92,3700,3701,3703,3705,3708,3710,3713,3716,3719],{"class":400,"line":528},[92,3702,1637],{"class":404},[92,3704,913],{"class":404},[92,3706,3707],{"class":408}," TextScript.outside-staff-padding = #1 e8--^",[92,3709,925],{"class":404},[92,3711,3712],{"class":404}," \\center",[92,3714,3715],{"class":408},"-align ",[92,3717,3718],{"class":404},"\\tiny",[92,3720,3721],{"class":408}," \"Fl. 1\"\n",[92,3723,3724],{"class":400,"line":534},[92,3725,3726],{"class":408},"    | e'( c a) f'( c as) e'( c a) e( c' a)\n",[92,3728,3729],{"class":400,"line":540},[92,3730,3731],{"class":408},"    | e( dis a') as( f c' e) r r r4.\n",[92,3733,3734],{"class":400,"line":647},[92,3735,537],{"class":408},[92,3737,3738],{"class":400,"line":652},[92,3739,3740],{"class":408},">>}\n",[10,3742,3743],{},[431,3744],{"alt":395,"src":3745},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F17-cue-voice.png",[10,3747,3748,3749,3752],{},"Similarly, ",[23,3750,3751],{},"ossia"," staves are downscaled staves, but instead of quoting another instrument, they dictate an optional, alternative way of playing a passage. One such ossia is found at the end of the first flute part of the aforementioned piece “Witches, Wands and Wizards”.",[10,3754,3755,3756,3759,3760,3762,3763,3766,3767,34],{},"Although ossias are supported by LilyPond, one gotcha to keep in mind is that the staff downscaling doesn't work seamlessly with special barlines, such as the one at the end of a movement or piece (",[87,3757,3758],{},"\"|.\"","). The end of the barline wasn't properly aligned with the end of the staff and I had to find a way to conceal this misalignment, which I eventually managed to do by overriding the ",[87,3761,2619],{}," on the final ",[87,3764,3765],{},"BarLine"," of the ",[87,3768,3769],{},"Staff",[390,3771,3773],{"className":392,"code":3772,"language":394,"meta":395,"style":395},"\\numericTimeSignature\n\\time 4\u002F4\n\\relative {\n  g''!16( as) b-. c-. des\\tweak avoid-slur #'inside ->( es) f-. g!-. as8-^ r des,!8-. des,-.\n  \u003C\u003C\n    {\n      es'8-. es,-. e'-. e,-. g'-. r \\tuplet 6\u002F4 { c,,16 e\\\u003C g gis h\\! c }\n      \\once \\override Score.BarLine.extra-spacing-width = #'(1 . 1) \\bar \"|\"\n      | des8-^\\fff r r4 r2 \n    }\n\n    \\new Staff \\with {\n      \\remove Time_signature_engraver\n      alignAboveContext = \"main\"\n      \\magnifyStaff #2\u002F3\n      firstClef = ##f\n    }\n    {\n      \\once \\override TextScript.X-offset = #-2\n      \\once \\override TextScript.outside-staff-padding = #1\n      \u003C>^\\markup \\right-align \\small \"1. Ossia\"\n      es8-. es,-. e'-. e,-. g'-. r \\tuplet 6\u002F4 { e,16 g\\\u003C c e g a\\! }\n      | \\ottava #1 des8-^\\fff \\ottava #0\n      \\override Staff.BarLine.X-offset = #.4\n      r r4 r2\n    }\n  >>\n}\n\\bar \"|.\"\n",[87,3774,3775,3780,3787,3793,3803,3808,3813,3834,3848,3859,3863,3867,3879,3887,3892,3900,3905,3909,3913,3922,3931,3949,3968,3986,3994,3999,4003,4008,4012],{"__ignoreMap":395},[92,3776,3777],{"class":400,"line":401},[92,3778,3779],{"class":404},"\\numericTimeSignature\n",[92,3781,3782,3784],{"class":400,"line":412},[92,3783,468],{"class":404},[92,3785,3786],{"class":408}," 4\u002F4\n",[92,3788,3789,3791],{"class":400,"line":418},[92,3790,811],{"class":404},[92,3792,517],{"class":408},[92,3794,3795,3798,3800],{"class":400,"line":424},[92,3796,3797],{"class":408},"  g''!16( as) b-. c-. des",[92,3799,3176],{"class":404},[92,3801,3802],{"class":408}," avoid-slur #'inside ->( es) f-. g!-. as8-^ r des,!8-. des,-.\n",[92,3804,3805],{"class":400,"line":528},[92,3806,3807],{"class":408},"  \u003C\u003C\n",[92,3809,3810],{"class":400,"line":534},[92,3811,3812],{"class":408},"    {\n",[92,3814,3815,3818,3821,3824,3826,3829,3831],{"class":400,"line":540},[92,3816,3817],{"class":408},"      es'8-. es,-. e'-. e,-. g'-. r ",[92,3819,3820],{"class":404},"\\tuplet",[92,3822,3823],{"class":408}," 6\u002F4 { c,,16 e",[92,3825,823],{"class":404},[92,3827,3828],{"class":408}," g gis h",[92,3830,3069],{"class":404},[92,3832,3833],{"class":408}," c }\n",[92,3835,3836,3838,3840,3843,3845],{"class":400,"line":647},[92,3837,910],{"class":404},[92,3839,913],{"class":404},[92,3841,3842],{"class":408}," Score.BarLine.extra-spacing-width = #'(1 . 1) ",[92,3844,2756],{"class":404},[92,3846,3847],{"class":408}," \"|\"\n",[92,3849,3850,3853,3856],{"class":400,"line":652},[92,3851,3852],{"class":408},"      | des8-^",[92,3854,3855],{"class":404},"\\fff",[92,3857,3858],{"class":408}," r r4 r2 \n",[92,3860,3861],{"class":400,"line":660},[92,3862,762],{"class":408},[92,3864,3865],{"class":400,"line":668},[92,3866,623],{"emptyLinePlaceholder":622},[92,3868,3869,3871,3874,3877],{"class":400,"line":674},[92,3870,773],{"class":404},[92,3872,3873],{"class":408}," Staff ",[92,3875,3876],{"class":404},"\\with",[92,3878,517],{"class":408},[92,3880,3881,3884],{"class":400,"line":680},[92,3882,3883],{"class":404},"      \\remove",[92,3885,3886],{"class":408}," Time_signature_engraver\n",[92,3888,3889],{"class":400,"line":686},[92,3890,3891],{"class":408},"      alignAboveContext = \"main\"\n",[92,3893,3894,3897],{"class":400,"line":692},[92,3895,3896],{"class":404},"      \\magnifyStaff",[92,3898,3899],{"class":408}," #2\u002F3\n",[92,3901,3902],{"class":400,"line":697},[92,3903,3904],{"class":408},"      firstClef = ##f\n",[92,3906,3907],{"class":400,"line":702},[92,3908,762],{"class":408},[92,3910,3911],{"class":400,"line":708},[92,3912,3812],{"class":408},[92,3914,3915,3917,3919],{"class":400,"line":720},[92,3916,910],{"class":404},[92,3918,913],{"class":404},[92,3920,3921],{"class":408}," TextScript.X-offset = #-2\n",[92,3923,3924,3926,3928],{"class":400,"line":725},[92,3925,910],{"class":404},[92,3927,913],{"class":404},[92,3929,3930],{"class":408}," TextScript.outside-staff-padding = #1\n",[92,3932,3933,3936,3938,3941,3943,3946],{"class":400,"line":733},[92,3934,3935],{"class":408},"      \u003C>^",[92,3937,925],{"class":404},[92,3939,3940],{"class":404}," \\right",[92,3942,3715],{"class":408},[92,3944,3945],{"class":404},"\\small",[92,3947,3948],{"class":408}," \"1. Ossia\"\n",[92,3950,3951,3954,3956,3959,3961,3964,3966],{"class":400,"line":741},[92,3952,3953],{"class":408},"      es8-. es,-. e'-. e,-. g'-. r ",[92,3955,3820],{"class":404},[92,3957,3958],{"class":408}," 6\u002F4 { e,16 g",[92,3960,823],{"class":404},[92,3962,3963],{"class":408}," c e g a",[92,3965,3069],{"class":404},[92,3967,3674],{"class":408},[92,3969,3970,3972,3975,3978,3980,3983],{"class":400,"line":747},[92,3971,808],{"class":408},[92,3973,3974],{"class":404},"\\ottava",[92,3976,3977],{"class":408}," #1 des8-^",[92,3979,3855],{"class":404},[92,3981,3982],{"class":404}," \\ottava",[92,3984,3985],{"class":408}," #0\n",[92,3987,3988,3991],{"class":400,"line":753},[92,3989,3990],{"class":404},"      \\override",[92,3992,3993],{"class":408}," Staff.BarLine.X-offset = #.4\n",[92,3995,3996],{"class":400,"line":759},[92,3997,3998],{"class":408},"      r r4 r2\n",[92,4000,4001],{"class":400,"line":765},[92,4002,762],{"class":408},[92,4004,4005],{"class":400,"line":770},[92,4006,4007],{"class":408},"  >>\n",[92,4009,4010],{"class":400,"line":779},[92,4011,427],{"class":408},[92,4013,4014,4016],{"class":400,"line":787},[92,4015,2756],{"class":404},[92,4017,4018],{"class":408}," \"|.\"\n",[10,4020,4021],{},[431,4022],{"alt":395,"src":4023},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F18-ossia.png",[1158,4025,4027],{"id":4026},"uncommon-notation-and-extended-techniques","Uncommon Notation and Extended Techniques",[10,4029,4030,4031,4034],{},"The ultimate test of LilyPond's universality came when I was copying the Piccolo part from John Williams' ",[41,4032,4033],{},"“The Knight Bus”",". At various points in this score, the player is instructed to produce the \"highest pitch possible\", or to mimic wailing and screaming through various glissandos. Below is a showcase of what I was able to achieve.",[10,4036,4037],{},[431,4038],{"alt":395,"src":4039},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F21-knight-bus.png",[10,4041,4042],{},[41,4043,4044],{},"1. X notes with no ledger lines",[10,4046,4047,4048,4051,4052,4055,4056,4059,4060,2064],{},"X notes are first-class citizens in LilyPond, and can be engraved using the ",[87,4049,4050],{},"\\xNote"," context. The difficult part was removing the ledger lines, which are not present in the source score. Eventually I found a solution by overriding one of the properties on a ",[87,4053,4054],{},"StaffSymbol",": ",[87,4057,4058],{},"\\override Staff.StaffSymbol.ledger-positions = #'(0)",". To be honest, I'm not really sure what the semantics of this list are based on the ",[28,4061,4064],{"href":4062,"rel":4063},"https:\u002F\u002Flilypond.org\u002Fdoc\u002Fv2.25\u002FDocumentation\u002Fnotation\u002Fmodifying-single-staves",[32],"documentation",[10,4066,4067],{},[41,4068,4069],{},"2. Pitch bends",[10,4071,4072,4073,4076,4077,4080],{},"Curiously, pitch bends following a note are first-order citizens in LilyPond, too. The one in measure 2 of the above snippet was achieved with ",[87,4074,4075],{},"f'''4 \\bendAfter -6"," (dynamics and text omitted for brevity). One would assume that the opposite would be achieved with ",[87,4078,4079],{},"\\bendBefore"," — wrongly.",[10,4082,4083,4084,4089],{},"The solution I found online, ... well, in a ",[28,4085,4088],{"href":4086,"rel":4087},"https:\u002F\u002Flists.gnu.org\u002Farchive\u002Fhtml\u002Flilypond-user\u002F2020-05\u002Fmsg00581.html",[32],"mailing list archive",", if that can be considered online, is to add an invisible grace note tied to the base note. This approach works as long as no actual grace notes are required — in most sane scores, a pitch bend into a grace note will probably never occur, still, please don't mention this idea to any contemporary composers. This is the snippet for the \"wailing\" part:",[390,4091,4093],{"className":392,"code":4092,"language":394,"meta":395,"style":395},"\\relative {\n  \\once \\hideNotes \\grace h'-\\tweak extra-offset #'(-1.3 . .8)(^\\markup \\italic \"“Wail”\" es4->\\ff~) es8\n  \\once \\hideNotes \\grace h-\\tweak extra-offset #'(-1.3 . .8)( es4.->)\n  \\once \\hideNotes \\grace h-\\tweak extra-offset #'(-1.3 . .8)( es2->)\n}\n",[87,4094,4095,4101,4133,4149,4164],{"__ignoreMap":395},[92,4096,4097,4099],{"class":400,"line":401},[92,4098,811],{"class":404},[92,4100,517],{"class":408},[92,4102,4103,4105,4108,4111,4114,4116,4119,4121,4124,4127,4130],{"class":400,"line":412},[92,4104,3464],{"class":404},[92,4106,4107],{"class":404}," \\hideNotes",[92,4109,4110],{"class":404}," \\grace",[92,4112,4113],{"class":408}," h'-",[92,4115,3176],{"class":404},[92,4117,4118],{"class":408}," extra-offset #'(-1.3 . .8)(^",[92,4120,925],{"class":404},[92,4122,4123],{"class":404}," \\italic",[92,4125,4126],{"class":408}," \"“Wail”\" es4->",[92,4128,4129],{"class":404},"\\ff",[92,4131,4132],{"class":408},"~) es8\n",[92,4134,4135,4137,4139,4141,4144,4146],{"class":400,"line":418},[92,4136,3464],{"class":404},[92,4138,4107],{"class":404},[92,4140,4110],{"class":404},[92,4142,4143],{"class":408}," h-",[92,4145,3176],{"class":404},[92,4147,4148],{"class":408}," extra-offset #'(-1.3 . .8)( es4.->)\n",[92,4150,4151,4153,4155,4157,4159,4161],{"class":400,"line":424},[92,4152,3464],{"class":404},[92,4154,4107],{"class":404},[92,4156,4110],{"class":404},[92,4158,4143],{"class":408},[92,4160,3176],{"class":404},[92,4162,4163],{"class":408}," extra-offset #'(-1.3 . .8)( es2->)\n",[92,4165,4166],{"class":400,"line":528},[92,4167,427],{"class":408},[10,4169,4170],{},"In principle, any invisible note could be used; however, grace notes have the advantage that their duration does not count towards the length of the bar, so the score stays rhythmically sound and bar checks don't start failing afterwards.",[10,4172,4173],{},[41,4174,4175],{},"3. Glissandos without targets",[10,4177,4178],{},"Glissandos are first-class citizens as long they are attached to a final note. Like in the previous case, I hacked this by inserting an invisible note at the end of the measure. The following code is for the \"long drop\" in snippet measure 11, again stripped of markup for brevity.",[390,4180,4182],{"className":392,"code":4181,"language":394,"meta":395,"style":395},"\\xNote { f'''4-> \\glissando s4 s4. \\once \\hideNotes d'8 }\n",[87,4183,4184],{"__ignoreMap":395},[92,4185,4186,4188,4191,4194,4197,4199,4201],{"class":400,"line":401},[92,4187,4050],{"class":404},[92,4189,4190],{"class":408}," { f'''4-> ",[92,4192,4193],{"class":404},"\\glissando",[92,4195,4196],{"class":408}," s4 s4. ",[92,4198,2678],{"class":404},[92,4200,4107],{"class":404},[92,4202,4203],{"class":408}," d'8 }\n",[10,4205,4206],{},"To render the semibreve X note with a stem, I changed it to a quarter note and added spacers (like rests but invisible); this also allowed me to use a normal note instead of a grace note. This is not 100 % true to the source score, in which the glissando line continues until the next barline, but this was a level of detail I was willing to accept. I'm sure I could override more properties of the glissando spanner to match the source text closer yet.",[72,4208,4210],{"id":4209},"conclusion","Conclusion",[10,4212,4213],{},"The conclusion is that LilyPond is an underrated piece of music engraving software that, despite some shortcomings, can satisfy practically any stylistic requirement, given enough time and patience. Its steep learning curve can be daunting; valuable resources like snippets and in-depth explanations, scattered across documentation, forums and mailing lists, can be hard to come by, but in the age of LLMs, the significance of this issue is diminished.",[10,4215,4216,4217,4220],{},"I don't expect the average musician to read this post and start using LilyPond. I'm aware that my learning experience with LilyPond's syntax, logic and Scheme-based programming system would not be as smooth if it weren't for my computer science background. But for all 7 other people like me, LilyPond is an invaluable tool and this blog post aims to provide another angle of guidance compared to the official documentation. (Jokes aside, an affinity for music ",[23,4218,4219],{},"and"," computers is actually more common than you'd think.)",[10,4222,4223],{},"As a goodbye, I've copied a snippet from a John Williams flute part that is available online into LilyPond, so I could compare how close I can match the original. There are still differences in the music font, beam lengths, and slurs, but let's leave that for another day. I'll let you be the judge. Until next time!",[10,4225,4226],{},[431,4227],{"alt":395,"src":4228},"\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F22-jw-comparison.png",[10,4230,4231],{},[4232,4233,4234],"small",{},[23,4235,4236],{},"Disclaimer: Excerpts of third-party copyrighted works reproduced in this article are included for purposes of commentary, criticism, or education. Such use is intended to qualify under the fair use doctrine (17 U.S.C. § 107) and\u002For applicable quotation exceptions under EU copyright law. All rights in the original works remain with their respective owners.",[4238,4239,4240],"style",{},"html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}",{"title":395,"searchDepth":412,"depth":412,"links":4242},[4243,4244,4245,4246,4255],{"id":74,"depth":412,"text":75},{"id":371,"depth":412,"text":372},{"id":592,"depth":412,"text":593},{"id":1143,"depth":412,"text":1144,"children":4247},[4248,4249,4250,4251,4252,4253,4254],{"id":1160,"depth":418,"text":1161},{"id":1596,"depth":418,"text":1597},{"id":1951,"depth":418,"text":1952},{"id":2410,"depth":418,"text":2411},{"id":2893,"depth":418,"text":2894},{"id":3625,"depth":418,"text":3626},{"id":4026,"depth":418,"text":4027},{"id":4209,"depth":412,"text":4210},"2026-05-04","md",{"seoImage":4259},"https:\u002F\u002Fmilanspinka.com\u002Fimages\u002Fblog\u002F2026-05-04-engraving-music\u002F22-jw-comparison.png","\u002Fblog\u002F2026-05-04-engraving-music",{"title":5,"description":12},"blog\u002F2026-05-04-engraving-music","_NUxkMlla-bYsn_flV1aQkEXOZVwqPx2fH3UBtAN-KY",[4265,4266],null,{"title":4267,"path":4268,"stem":4269,"children":-1},"CTF Writeups","\u002Fblog\u002Fctf-writeups","blog\u002Fctf-writeups\u002Findex",[4271],{"title":4272,"path":4273,"stem":4274,"children":4275,"page":4360},"Blog","\u002Fblog","blog",[4276,4277],{"title":5,"path":4260,"stem":4262},{"title":4267,"path":4268,"stem":4269,"children":4278,"page":-1},[4279,4280,4318],{"title":4267,"path":4268,"stem":4269},{"title":4281,"path":4282,"stem":4283,"children":4284,"page":-1},"Flare-on CTF 2024","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024","blog\u002Fctf-writeups\u002Fflareon-2024\u002Findex",[4285,4286,4290,4294,4298,4302,4306,4310,4314],{"title":4281,"path":4282,"stem":4283},{"title":4287,"path":4288,"stem":4289},"Challenge 1 (\"frog\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024\u002F01-frog","blog\u002Fctf-writeups\u002Fflareon-2024\u002F01-frog",{"title":4291,"path":4292,"stem":4293},"Challenge 2 (\"checksum\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024\u002F02-checksum","blog\u002Fctf-writeups\u002Fflareon-2024\u002F02-checksum",{"title":4295,"path":4296,"stem":4297},"Challenge 3 (\"aray\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024\u002F03-aray","blog\u002Fctf-writeups\u002Fflareon-2024\u002F03-aray",{"title":4299,"path":4300,"stem":4301},"Challenge 4 (\"Meme Maker 3000\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024\u002F04-meme-maker-3000","blog\u002Fctf-writeups\u002Fflareon-2024\u002F04-meme-maker-3000",{"title":4303,"path":4304,"stem":4305},"Challenge 5 (\"sshd\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024\u002F05-sshd","blog\u002Fctf-writeups\u002Fflareon-2024\u002F05-sshd",{"title":4307,"path":4308,"stem":4309},"Challenge 6 (\"bloke2\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024\u002F06-bloke2","blog\u002Fctf-writeups\u002Fflareon-2024\u002F06-bloke2",{"title":4311,"path":4312,"stem":4313},"Challenge 7 (\"fullspeed\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024\u002F07-fullspeed","blog\u002Fctf-writeups\u002Fflareon-2024\u002F07-fullspeed",{"title":4315,"path":4316,"stem":4317},"Challenge 8 (\"clearlyfake\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2024\u002F08-clearlyfake","blog\u002Fctf-writeups\u002Fflareon-2024\u002F08-clearlyfake",{"title":4319,"path":4320,"stem":4321,"children":4322,"page":-1},"Flare-on CTF 2025","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025","blog\u002Fctf-writeups\u002Fflareon-2025\u002Findex",[4323,4324,4328,4332,4336,4340,4344,4348,4352,4356],{"title":4319,"path":4320,"stem":4321},{"title":4325,"path":4326,"stem":4327},"Challenge 1 (\"Drill Baby Drill!\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F01-drill-baby-drill","blog\u002Fctf-writeups\u002Fflareon-2025\u002F01-drill-baby-drill",{"title":4329,"path":4330,"stem":4331},"Challenge 2 (\"project_chimera\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F02-project-chimera","blog\u002Fctf-writeups\u002Fflareon-2025\u002F02-project-chimera",{"title":4333,"path":4334,"stem":4335},"Challenge 3 (\"pretty_devilish_file\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F03-pretty-devilish-file","blog\u002Fctf-writeups\u002Fflareon-2025\u002F03-pretty-devilish-file",{"title":4337,"path":4338,"stem":4339},"Challenge 4 (\"UnholyDragon\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F04-unholydragon","blog\u002Fctf-writeups\u002Fflareon-2025\u002F04-unholydragon",{"title":4341,"path":4342,"stem":4343},"Challenge 5 (\"ntfsm\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F05-ntfsm","blog\u002Fctf-writeups\u002Fflareon-2025\u002F05-ntfsm",{"title":4345,"path":4346,"stem":4347},"Challenge 6 (\"Chain of Demands\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F06-chain-of-demands","blog\u002Fctf-writeups\u002Fflareon-2025\u002F06-chain-of-demands",{"title":4349,"path":4350,"stem":4351},"Challenge 7 (\"The Boss Needs Help\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F07-the-boss-needs-help","blog\u002Fctf-writeups\u002Fflareon-2025\u002F07-the-boss-needs-help",{"title":4353,"path":4354,"stem":4355},"Challenge 8 (\"FlareAuthenticator\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F08-flareauthenticator","blog\u002Fctf-writeups\u002Fflareon-2025\u002F08-flareauthenticator",{"title":4357,"path":4358,"stem":4359},"Challenge 9 (\"10000\")","\u002Fblog\u002Fctf-writeups\u002Fflareon-2025\u002F09-10000","blog\u002Fctf-writeups\u002Fflareon-2025\u002F09-10000",false,1777936561094]