
1. 從實際需求聊起LilyPond 做五線譜很順手簡譜卻要單獨想辦法做音樂排版的人應該都有過這種感覺LilyPond 處理五線譜就像開了掛一樣輸入\relative c { c4 d e f }輸出的 PDF 干凈漂亮譜面規整得像是出版社直接出的??梢坏┡錾虾喿V需求很多人第一反應是去網上搜“LilyPond 簡譜 插件”然后搜出來一堆年份久遠的帖子說“官方不支持建議轉用某某軟件”瞬間就蔫了。我當年接學校合唱團的總譜排版任務時就是這種情況。指揮要求每個聲部給一份五線譜同時還要給一份簡譜用于學生課后哼唱。當時我的主工具就是 LilyPond實在不想為了簡譜單獨換一套軟件更不想在小節里截圖貼圖。后來花了兩三天把幾條路都試了一遍踩了不少坑才整理出一套相對順手的方案。這篇博文就把我當時折騰出來的思路和做法完整寫下來給有同樣需求的人做個參考。先說清楚適用范圍本文主要面向需要用 LilyPond 輸出簡譜、并且希望排版效果能接近專業出版物水平的用戶。不管你是要排單聲部旋律譜還是要做五線譜與簡譜對照的合唱譜下面講的方法都能覆蓋。LilyPond 官方本身沒有內置原生的簡譜排版引擎這一點先說在前面免得大家抱著錯誤的期待去翻文檔。但缺省支持不代表做不了核心思路無非兩條要么在 LilyPond 內部把簡譜的視覺元素“造”出來要么借助外部工具完成簡譜排版后再與 LilyPond 輸出整合。兩條路各有優劣我后面會分別講清楚原理和實操過程。2. 先搞懂簡譜的本質再談怎么實現2.1 簡譜的記譜元素拆解簡譜看起來簡單數字 1 到 7 加加減減就完事但真要排版成規范的譜面字符層面的需求并不少。這里我把簡譜的視覺組成拆開來看方便后面講實現方案時大家能對上號?;疽舴? 到 7 七個數字外加 0 表示休止符。數字本身用斜體還是正體不同出版社會有不同規范國內大多數出版物習慣用正體或稍帶傾斜的數字。時值標記四分音符直接寫數字八分音符在數字下方畫一條橫線十六分音符畫兩條橫線。橫線要精確對在數字正下方不能歪。附點音符在數字右側加附點附點要貼近數字。高低音點高音在數字正上方加點低音在數字正下方加點。點的位置要和數字垂直對齊上下不能跑偏。延音線與連音線延音線是弧線連接同一音高的相鄰音表示時值相加連音線是弧線連接不同音高的音表示圓滑奏。這兩種線在簡譜里都要畫成曲線且要越過數字區域。小節線與終止線和五線譜類似小節線是單豎線終止線是細線加粗線。拍號與調號標記簡譜的拍號通常寫成分數形式比如 4/4 直接寫成豎排的數字分數調號則用“1G”或“1bB”這類形式標注在第 1 行。這套體系本質上是在用文本符號加“附加標記”表達音樂信息跟五線譜的“音高位置 符頭 符干”邏輯完全不同。LilyPond 默認的音樂字體和布局引擎是為五線譜設計的音符頭是橢圓形的音高靠縱向位置體現簡譜則是純橫向文本流加上下附加標記。這兩個模型的差異就是為什么 LilyPond 不能直接“切換模式”輸出簡譜的根本原因。2.2 為什么 LilyPond 沒能原生支持簡譜LilyPond 的核心理念是“讓音符自己找到合適的位置”它的內部間距算法圍繞五線譜的線間距離、符頭大小、聲部對齊來設計。簡譜的排版重心不在垂直音高關系上而在文本基線、下劃線長度、附點位置這些“文字排版”維度上。強行用五線譜的布局引擎去排簡譜就像用排版《辭?!返能浖ヅ怕媽υ捒蛞粯硬皇遣荒茏鍪且龃罅窟m配。另外簡譜在全球范圍內的使用群體高度集中在東亞LilyPond 的維護者以歐美用戶為主他們對簡譜的訴求并不強烈。GitHub 上確實有過相關 feature request但一直沒有進入正式開發計劃。我記得曾經有人寫過一個簡譜相關的 scheme 腳本但只是實驗性質功能覆蓋面有限離“開箱即用”差得很遠。所以如果你想用 LilyPond 出簡譜現實一點的態度是不指望官方自己去湊方案。2.3 社區常見的三條技術路線對比既然官方沒有原生方案社區里逐漸形成了三種做法。我按照從易到難的順序說一下你們可以根據自己的需求選。第一種是純 LilyPond 內部實現利用\markup機制把每個音符數字、下劃線、附點手工組合起來。優點是全流程不脫離 LilyPond輸出 PDF 統一字體風格可控缺點是非常繁瑣寫一行旋律要敲一大堆 markup 代碼效率偏低只適合短小的旋律片段。第二種是 LilyPond 與 LaTeX 混排用lilypond-book工具把 LilyPond 的譜例嵌入 LaTeX 文檔簡譜部分用 LaTeX 的簡譜宏包或者自建文本排版。優點是簡譜的文本排版質量高因為 LaTeX 本來就是搞文字排版的缺點是需要同時掌握 LilyPond 和 LaTeX 兩套工具鏈環境配置略麻煩。第三種是用 LilyPond 出五線譜再配合其他專業簡譜軟件比如作曲大師、TTComposer 一類的工具或者圖形編輯器手動排簡譜最后合成 PDF。優點是簡譜質量有保障缺點是兩個軟件的排版風格很難統一五線譜和簡譜放在同一頁里會顯得很“拼接”而且后期修改時要同時改兩個文件維護成本高。我個人的建議是如果只是偶爾出一兩頁簡譜選第二種也就是 LilyPond LaTeX 混排性價比最高如果你需要長期在同一個工程里維護大量五線譜和簡譜對照的譜例可以考慮用 Perl 或 Python 寫個腳本來生成 LilyPond 代碼把簡譜音符自動轉成 markup 形式進一步提升效率。下面我把第二條路線的詳細實操過程寫出來。3. 實操落地lilypond-book LaTeX 輸出規范簡譜3.1 環境準備與工具鏈安裝先交代一下我用的環境Ubuntu 22.04 系統LilyPond 版本 2.24.xTeX Live 2023。如果你的系統不一樣也沒關系核心思路是通用的只要裝上 LilyPond 和完整版 TeX Live 就行。LilyPond 的安裝不多說官網下載對應系統的安裝包即可。關鍵是要確保lilypond-book命令在終端里能用這個命令包含在 LilyPond 的安裝包里不需要額外裝。TeX Live 建議裝完整版因為簡譜宏包會依賴一些冷門宏包精簡版經常缺東西。Ubuntu 上直接sudo apt install texlive-full最省心就是安裝時間比較長我當年裝完花了差不多半小時建議找個不用電腦的時間段操作。我用到的簡譜宏包是 CTAN 上的jianpu宏包它是基于musixtex的。安裝方式很簡單在 LaTeX 文檔里\usepackage{jianpu}即可前提是你的 TeX Live 里要有這個宏包。完整版 TeX Live 應該自帶如果沒有用tlmgr install jianpu裝上。3.2 建立工程結構我建議把每個譜例單獨放在一個目錄里工程結構如下song/ ├── main.tex # LaTeX 主文檔 ├── score.ly # LilyPond 五線譜源文件 └── build.sh # 編譯腳本main.tex負責整體版式score.ly負責生成五線譜部分build.sh一鍵出 PDF。這個結構看起來簡單但長期維護多個譜例時特別順手換歌的時候復制整個目錄改內容就行不會污染其他工程。3.3 五線譜部分用 LilyPond 輸出先看score.ly的示例。假設我們要排一首 4/4 拍的簡單旋律C 調前四個小節是 do mi sol do 這樣遞進的旋律。\version 2.24.0 \header { title 練習曲 composer 佚名 } melody \relative c { \key c \major \time 4/4 c4 e g c | b4 a g e | d4 f a d | c2 r2 | } \score { \new Staff \with { \remove Time_signature_engraver } \melody }注意我在\with里移除了拍號因為簡譜部分已經標了拍號五線譜里再標一遍會重復。如果你希望五線譜保留拍號那就去掉這一行。這個文件編譯后會生成獨立的五線譜 PDF。但我們要做的是混排所以不用單獨編譯它而是把它嵌入 LaTeX。3.4 簡譜部分用 LaTeX jianpu 宏包實現接下來是重頭戲。jianpu宏包的基本用法是在jianpu環境里寫簡譜代碼它的語法也很有意思每個音符由\n加數字加時值表示。看下面的例子\begin{jianpu} \par \song{練習曲} { 1C \meter{4}{4} } \begin{center} \begin{music} \par \generalmeter{\meter{4}{4}} \startextract \Notes \n1 \Dqbla \n3 \Dqblg \n5 \Dqblc | \Dqbh \n1 | \Notes \Dqblb \Dqbla \Dqblg \Dqble | \Notes \Dqbla \Dqblf \Dqblj \Dqbh | \Notes \Dqblc \en \zendextract \end{music} \end{center} \end{jianpu}看到\Dqbla這張牙舞爪的寫法不要慌這是musixtex底層命令。\Dqbl表示八分音符D 是 double 的簡寫這里其實代表 eighth 類的命令前綴后面跟的音名小寫字母。如果你用宏觀視角來看這行的意思就是“一個八分音符 do、一個八分音符 mi、一個八分音符 sol、一個八分音符 do”。這里我直接使用宏包命令時會有一個學習成本所以更推薦的做法是寫一個簡單的映射表把常用的簡譜記譜轉成對應的 LaTeX 命令。我當時在博客里整理過一張速查表現在也放出來簡譜記法jianpu 宏包寫法含義1\n1do四分音符1 -\En或\qu類命令do二分音符具體情況看命令1 下方一橫\Dqbl 音名do八分音符1 下方兩橫\qqbl 音名do十六分音符高音 1上方一點\n1高音 do四分音符上標點低音 1下方一點\n_1或類似命令低音 do四分音符下標點附點八分音符組合命令附點時值參考宏包文檔說實話jianpu宏包的手冊寫得不算友好全是密密麻麻的命令表。我當時是打印了一份命令速查表邊查邊寫。這個投入在前期有點痛苦但寫了幾個譜例之后就會形成肌肉記憶速度會快很多。3.5 用 lilypond-book 整合兩類譜現在到了關鍵整合步驟。lilypond-book這個工具可以掃描 LaTeX 源文件中的\lilypondfile或\lilypond命令先單獨編譯 LilyPond 代碼再把生成的圖形插入 LaTeX 文檔。這樣我們就能在一個 LaTeX 文檔里同時放五線譜和簡譜。main.tex的核心內容如下\documentclass[12pt]{article} \usepackage{jianpu} \usepackage{graphicx} \usepackage{geometry} \geometry{a4paper, margin2cm} \begin{document} \section*{練習曲五線譜與簡譜對照} \subsection*{五線譜部分} \lilypondfile{score.ly} \subsection*{簡譜部分} \begin{jianpu} \song{練習曲} { 1C \meter{4}{4} } \begin{center} \begin{music} \startextract \Notes \n1 \Dqbla \n3 \Dqblg \n5 \Dqblc | \Dqbh \n1 | \Notes \Dqblb \Dqbla \Dqblg \Dqble | \Notes \Dqbla \Dqblf \Dqblj \Dqbh | \Notes \Dqblc \en \zendextract \end{music} \end{center} \end{jianpu} \end{document}然后寫一個編譯腳本build.sh#!/bin/bash lilypond-book --outputout main.tex cd out pdflatex main.tex pdflatex main.tex里面的--outputout表示把中間文件都生成到 out 子目錄里保持根目錄整潔。執行兩次pdflatex是為了讓交叉引用生效雖然我們這里沒有涉及引用但養成習慣總沒錯。這里有一個非常重要的細節系統里可能同時存在pdflatex和lualatexjianpu宏包對lualatex的支持不是很好主要是底層字體編碼處理不同容易出現數字顯示異常的問題。所以編譯時老老實實用pdflatex別折騰其他引擎。3.6 編譯過程與輸出檢查執行bash build.sh之后正常情況下 out 目錄里會出現main.pdf。打開看看你應該能看到五線譜和簡譜兩段內容各自排版風格統一。如果簡譜數字沒有出現而是顯示一堆亂碼大概率是字體路徑沒識別到后文會細說排查方法。如果編譯過程中報錯先定位是 LilyPond 報錯還是 LaTeX 報錯。LilyPond 報錯會顯示音符語法錯誤比如我最早把\Dqblg寫成\Dqgbl就報了“unknown command”的錯。LaTeX 報錯則通常和宏包依賴缺失有關常見的提示是File jianpu.sty not found這就說明你的 TeX Live 缺宏包跑一遍tlmgr install jianpu就能解決。4. 進階細節對齊、字體與混合排版4.1 五線譜與簡譜的對齊策略上文的方案是“上下排”五線譜在上、簡譜在下各自獨立成塊。這種排法大多數場景夠用了。但如果你想要的是“互相對齊”的緊湊譜比如每行上方是五線譜、行內嵌簡譜數字情況就復雜一些。我試過兩種對齊思路。第一種是在 LilyPond 里把簡譜數字作為“附加文本”標記掛到五線譜的每個音符頭上用^\markup實現。比如c4^\markup { \override #(font-size . 0) \number 1 } e4^\markup { \number 3 } g4^\markup { \number 5 }這樣數字會顯示在對應音符上方。優點是對齊天然精確因為 LilyPond 會把 markup 和音符綁定在同一個 X 坐標上缺點是整首曲子下來標記代碼冗長而且數字下方的時值線沒法自動畫只能再次用 markup 畫線或加下劃線符號。對于簡單旋律可以接受復雜節奏型會把自己搞瘋。第二種思路是在 LaTeX 里用表格或并排 minipage 的方式來對照。我在實際項目里用得比較多的是這種因為它能利用 jianpu 宏包的全部功能簡譜部分能做到自動畫時值線。做法是每行分成左側五線譜、右側簡譜兩個 minipage用\hfill填充間距。缺點是小節邊界需要手動調整保證兩邊的樂句切分大致同步不可能做到逐音符像素級對齊。4.2 自制簡譜字體的嘗試與回歸說到簡譜排版繞不開字體。jianpu宏包默認用的是 musixtex 字體數字是西文襯線風格跟國內常見的簡譜出版物的“圓潤黑體數字”風格有明顯差異。我一度想替換成自制字體研究過用 FontForge 改 musixtex 的字體但那等于重新做一套簡譜字體工作量遠超需求。后來我找到一條折中路徑如果只是想讓數字更好看可以在jianpu環境里臨時調整數字字體為 CTeX 提供的中文字體比如宋體或黑體。具體做法是在開頭加\renewcommand{\jianpuNumberFont}{\songti}或\renewcommand{\jianpuNumberFont}{\heiti}這樣簡譜數字會變成中文字體風格整體觀感更接近國內出版物。不過要注意這種替換可能會影響時值線的對齊因為不同字體的數字寬度不一樣。實測下來黑體的數字寬度比較均勻對齊問題最少宋體的數字在某些字號下會出現間距不均需要手動用\hspace微調。4.3 導出的圖像與矢量兼容問題有時候譜例不只是進入 PDF還要貼到公眾號文章或者 PPT 里。LilyPond 支持-dbackendsvg直接輸出 SVG 格式這個很好用。但lilypond-book生成的五線譜圖形默認是嵌入在 PDF 里的想把它們單獨撈出來需要額外處理。我的辦法是在 LilyPond 源文件里單獨編譯一個 PDF 或 SVG 版本作為圖片素材用lilypond -dbackendsvg score.ly lilypond -dbackendpdf score.ly這樣會生成score.svg和score.pdf可以單獨插入其他文檔。注意 SVG 里的中文字體比如標題里的“練習曲”會依賴系統字體換一臺電腦打開時可能字體缺失顯示成亂碼。如果需要跨平臺傳遞 SVG最好把標題文本去掉或者轉成路徑曲線。Inkscape 可以批量完成這個操作打開 SVG選擇文本對象Path - Object to Path然后保存。實測 SVG 文件體積會增加一些但換設備也不會亂碼了。4.4 拍號與小節號的補充規則簡譜的拍號要寫成豎排分數形式不能像五線譜那樣直接畫兩個數字疊起來。jianpu宏包已經處理了這個問題\meter{4}{4}會輸出規范的分數字符。但如果你用純 markup 方式在 LilyPond 里做簡譜拍號就要自己拼\markup { \column { \line { 4 } \line { 4 } } }這樣排出來的是一個上下居中的兩行文本視覺上基本能達到簡譜拍號的效果但間距比專業宏包略差。還有一個需要注意的是調號標記“1G”在jianpu宏包里直接寫在音樂開始前的文本區域即可不需要特殊命令{ 1G \meter{4}{4} }這個寫法在宏包文檔里叫“歌曲頭區”位置居中顯示在歌名下方、樂譜上方。如果你需要同時顯示作詞作曲信息也可以在頭區里自定義格式我一般寫成{ 1G \meter{4}{4} \par \centerline {\small 詞某某 曲某某} }實測效果還不錯視覺上不會太擠。5. 常見問題與排查技巧實錄5.1 jianpu 宏包安裝后依然報環境錯誤這個坑我印象非常深。有一臺電腦上裝好了完整版 TeX Live\usepackage{jianpu}這行也能順利通過但編譯到音樂環境時報錯Undefined control sequence指向\generalmeter。原因是jianpu宏包依賴musixtex的較新版本而舊 TeX Live 自帶的 musixtex 版本太老缺少這個命令。解決辦法是手動更新宏包用tlmgr update musixtex jianpu命令把它倆升級到最新版。升級完了要清空編譯臨時目錄再重新跑別直接在舊目錄里疊加編譯不然會碰到aux文件緩存導致新命令不生效的詭異問題。我后來養成了一個習慣凡是改了宏包版本必刪out目錄重來。5.2 LilyPond 音符和簡譜音符對不上這是最讓人頭疼的一個問題。LilyPond 源文件里的\relative c模式很容易讓人把音高寫錯尤其是跨八度的時候。比如我上面譜例里的d4 f a d如果少寫一個變成d4 f a d旋律整體就低了八度但簡譜部分寫的還是高八度的\Dqbh兩邊一對照聽起來和看起來全對不上。排查方法很簡單先把 LilyPond 單獨編譯成 MIDI用播放器聽一遍確認旋律走向符合原譜再對著簡譜逐小節數音高。我一般會用\relative c或者干脆不寫 relative直接用絕對音高模式c4、d4這樣雖然輸入繁瑣但音高至少不會因為相對模式計算錯誤。對簡譜敏感的場景我推薦用絕對模式出錯率低很多。5.3 簡譜數字溢出頁面右邊界當旋律跨度大、小節內音符密集時簡譜的文本容易超出頁面邊界。jianpu宏包默認的\Notes環境不會自動換行需要手動在適當位置斷開換成新的\Notes行。我在排版一首 16 小節的兒歌時遇到過這個問題后來總結出經驗每行最多排 4 個小節3/4 拍的歌可以排 5 個小節2/4 拍的歌可以排 6 個小節。超過這個量就先換行。具體操作是在音樂環境里插入\bar或\en終止當前行再重新開始新行。雖然有點手動調節的意思但換行位置恰好可以自己控制在樂句斷點效果反而比自動斷行更符合音樂表達。5.4 編譯時間過長怎么辦大譜例用lilypond-book編譯時會明顯變慢主要是因為每插入一個 LilyPond 譜例就要單獨啟動一次 LilyPond 進程。如果一首合唱曲里有七八個聲部譜例編譯時間輕松超過兩三分鐘。我的優化辦法是開發階段只保留當前在改的譜例其他譜例先用\iffalse注釋掉等所有內容都改完再把注釋去掉做最終編譯。另外可以給 LilyPond 加-dno-point-and-click參數這個參數的作用是不在 PDF 里嵌入點源文件跳轉信息能省一點編譯時間和文件體積lilypond-book --outputout --lilypond-option-dno-point-and-click main.tex實測對于大文檔這個選項能減少 10%-20% 的編譯時間不算很多但積少成多。5.5 快速排查流程總結我把平時排查問題的流程整理成下面這個順序遇到問題按序檢查基本能定位九成以上的毛病先查 LilyPond 部分單獨跑lilypond score.ly確認五線譜沒有報錯。有錯先改 LilyPond。再查 LaTeX 基礎環境把main.tex里的\lilypondfile先注釋掉只編譯簡譜部分確認 jianpu 宏包環境可用。最后查整合把五線譜加回來用lilypond-book --verbose模式跑看詳細日志里 LilyPond 和 LaTeX 各自的編譯狀態。如果 PDF 輸出不對但日志沒有報錯多半是緩存問題刪掉out目錄重來一次。6. 一些該說透的經驗總結整套流程走下來我對 LilyPond 輸出簡譜這件事情的結論是能做但需要接受“手動拼裝”的現實不能指望像五線譜那樣“寫完即所得”。如果你只是偶爾排一頁簡譜花一個下午搭好 LilyPond LaTeX jianpu 的環境后面每次只是填音符內容速度還是能接受的。我在排一首 30 小節的單旋律簡譜時從拿到譜子到輸出 PDF大約花 30 到 40 分鐘其中一半時間在打簡譜命令另一半在調整每行小節數和排版細節。如果換成純手工繪圖軟件一首歌至少兩三個小時起步還不算后續修改。另一個心得是如果你在團隊里協作最好把 LilyPond 源文件和 LaTeX 源文件都納入版本管理比如 Git。這比保存最終 PDF 有用得多因為譜子總有修改的時候。我見過不少同事直接改 PDF改完沒法回溯版本幾次迭代下來自己都忘了哪個版本是最終版。用源碼工程加 Git 管理每次改動都留痕返工成本低很多。這個內容后續還可以擴展的方向是把簡譜的映射規則腳本化。比如用 Python 寫一個轉換器輸入一段類似“C4 E4 G4 C5”這樣的音符序列自動生成對應的 jianpu 宏包命令這樣就能把五線譜內容批量轉成簡譜大幅減少手工錄入的出錯概率。我已經在自己項目里寫了第一版后續如果整理穩定了再寫一篇專門講這塊的文章。