9

I typeset a book containing musical pieces using LaTeX and LilyPond (using lilypond-book). Each piece starts in a new page, and can be from less than a single page up to several pages long.

I want each piece to fill the required number of pages fully, so no space is left in the bottom part of the last page of the piece and the staves in all pages are evenly spaced. This can be achieved in LilyPond by setting ragged-last-bottom to ##f. Here is a simple example (music.ly):

#(set-global-staff-size 32)

\paper {
  paper-width = 18.5\cm
  ragged-last-bottom = ##f
}

\header{
  tagline = ##f
}

{
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
}

This will produce this output:

Page 1/2:
Page 1/2 of good output

Page 2/2:
Page 2/2 of good output

Now, when I try to use this in LaTeX, it doesn’t work, since lilypond-book splits the LilyPond output into .eps files each containing a single line and these files are included one after another by the generated .tex file.

So, this LaTeX file produces an output which does not fill the pages fully with evenly spaced staves (as you can easily see by looking on the last page):

\documentclass[a4paper]{article}
\usepackage{geometry}

\begin{document}

hello world

\lilypondfile{music.ly}

\end{document}

Page 1/3:
Page 1/3 of bad output

Page 2/3:
Page 2/3 of bad output

Page 3/3:
Page 3/3 of bad output

So my question is simple: how do I make LaTeX behave like LilyPond does with ragged-last-bottom set to ##f?

Thank you very much! ☺

15
  • Is my question not clear or nobody knows how to do this? Jan 9, 2015 at 19:33
  • Perhaps the latter. LaTeX shipouts a page immediately after it typesets enough materials. So it is hard (not impossible) to decide how many lines should be on the first page without knowing how many lines in total. By the way, 41 is prime... what do you expect in this case? (13,14,14) or (14,14,13) or (14,13,14)?
    – Symbol 1
    Jan 10, 2015 at 3:33
  • @Symbol1: So if no one will come with a LaTeX solution I will have no option but to embed PDF files produced by LilyPond (pdfpages), which is not an elegant solution, to say the least. Jan 10, 2015 at 18:53
  • @Symbol1: As for number of lines/staves which is not dividable by the number of pages: the grouping should be according to the slight differences in height (the spaces between lines should be as similar as possible in size). If all lines are of the same height, I guess the simplest rule will be to make the first pages more dense: 10 lines on 3 pages should be 4-3-3, 11 lines on 3 pages should be 4-4-3. Jan 10, 2015 at 18:55
  • Given that you are basically inputting the generated file, I'm not clear what kind of solution you are looking for. That is, I take it you want to not be editing that file, but then it is hard to see what can be done since the contents is not even available to manipulate as part of the document.
    – cfr
    Jan 11, 2015 at 4:04

1 Answer 1

11
+300

Interesting problem! Ultimately, lots of figuring out and legwork, but the solution ends up being very simple.

Thanks for introducing me to lillypond—cool stuff.

I'm still a bit confused because I've only been using it for about 5 minutes, but here's what I found.

You make this file, I called mine lillypond.ly:

#(set-global-staff-size 32)

\paper {
  paper-width = 18.5\cm
  ragged-last-bottom = ##f
}

\header{
  tagline = ##f
}

{
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
  c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
}

I took this straight from the your question.

Also straight from the your question is this file, I called mine lillypondtex.lytex (The .lytex extension is important and was difficult to figure out.)

\documentclass[a4paper]{article}
\usepackage{geometry}

\begin{document}

hello world

\lilypondfile{lillypond1.ly}

\end{document}

This file gets compiled with the command Applications/LilyPond.app/Contents/Resources/bin/lilypond-book --output=out --pdf lillypondtex.lytex at least, if you're on a mac and too lazy to follow the installation instructions. On a normal installation I think this command would be just lilypond-book --output=out --pdf lillypondtex.lytex.

That command generates a new directory, called out, which contains a directory called 5a (important later) and the files:

lillypondtex.dep
lillypondtex.tex
snippet-map--9077002354240704700.ly
snippet-names--9077002354240704700.ly

Now we're getting somewhere, finally an extension I know and love!

Running pdflatex on lillypondtex.tex gives the same output you saw and didn't like.

The lillypondtex.tex file contains this:

\documentclass[a4paper]{article}
\usepackage{geometry}

\usepackage{graphics}
\begin{document}

hello world

{%
\parindent 0pt
\noindent
\ifx\preLilyPondExample \undefined
\else
  \expandafter\preLilyPondExample
\fi
\def\lilypondbook{}%
\input{5a/lily-66b633c5-systems.tex}
\ifx\postLilyPondExample \undefined
\else
  \expandafter\postLilyPondExample
\fi
}

\end{document}

Still a little obfuscated, but the line \input{5a/lily-66b633c5-systems.tex} is the key.

Now, going into the 5a directory, we have the file called lily-66b633c5-systems.tex which is finally the layout code for the document.

\includegraphics{5a/lily-66b633c5-1}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{1}%
\fi
\includegraphics{5a/lily-66b633c5-2}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{2}%
\fi
\includegraphics{5a/lily-66b633c5-3}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{3}%
\fi
\includegraphics{5a/lily-66b633c5-4}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{4}%
\fi
\includegraphics{5a/lily-66b633c5-5}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{5}%
\fi
\includegraphics{5a/lily-66b633c5-6}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{6}%
\fi
\includegraphics{5a/lily-66b633c5-7}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{7}%
\fi
\includegraphics{5a/lily-66b633c5-8}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{8}%
\fi
\includegraphics{5a/lily-66b633c5-9}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{9}%
\fi
\includegraphics{5a/lily-66b633c5-10}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{10}%
\fi
\includegraphics{5a/lily-66b633c5-11}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{11}%
\fi
\includegraphics{5a/lily-66b633c5-12}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{12}%
\fi
\includegraphics{5a/lily-66b633c5-13}%
\ifx\betweenLilyPondSystem \undefined
  \linebreak
\else
  \expandafter\betweenLilyPondSystem{13}%
\fi
\includegraphics{5a/lily-66b633c5-14}%
% eof

These \linebreak commands are the problem, that's why LaTeX is treating the music as a single paragraph and not spreading it out evenly.

Any changes made here will effect the output of lillypond.tex. From here, I'm sure there are more experienced people here who can tweak this further than I can.


However, a couple simple solutions:

Simply find-replacing all cases of \linebreak with \par will allow \flushbottom to be used as expected in lillypond.tex. output:

enter image description here

This fixes spacing between all the lines and text. Making each line of music a paragraph is the solution I would choose if I were writing a book using this, as it would work with \flushbottom and flow around text well. Also, at this point, David Carlisle's asnwer of pasting \setlength\parskip{\fill} into the lillypond.tex file will work as he intended.

Another option is to replace each \linebreak with \vfill, which gets us closer to OP's desired outcome by filling the full last page.

From here it's just a matter of shrinking the margins to make them similar to lillypond's output. A margin of .75" top and bottom gives this output:

enter image description here

Even spacing, pages fully filled, I believe this is what you're asking for.

Final lillypond.tex file:

\documentclass[a4paper]{article}
\usepackage[margin=.75in]{geometry}

\usepackage{graphics}
\begin{document}
\flushbottom

\centering
hello world

{%
\parindent 0pt
\noindent
\ifx\preLilyPondExample \undefined
\else
  \expandafter\preLilyPondExample
\fi
\def\lilypondbook{}%
\input{5a/lily-66b633c5-systems.tex}
\ifx\postLilyPondExample \undefined
\else
  \expandafter\postLilyPondExample
\fi
}

\end{document}

Another option I just thought of is to use \pagebreaks in conjunction with \vfill to explicitly declare how many lines to show per page.


If you want default Article margins:

How to space out lines so they're evenly distributed with article class default margins: Use \par between the lines of music and then define \parskip like this:

\setlength\parskip{26pt plus 36pt minus 0pt}

This tells LaTeX that each line must have 26pt in between, and it's allowed to satisfy \flushbottom by stretching each line by 36pt but not allowed to compress the lines closer together.

Here's the result:

enter image description here

LaTeX breaks it up into two pages of five lines and one page of four lines.

Here's the code I used to make it:

\documentclass[a4paper]{article}
\usepackage[]{geometry}

\usepackage{graphics}
\begin{document}
\flushbottom

hello world

{%
\parindent 0pt
\noindent
\setlength\parskip{26pt plus 36pt minus 0pt}
\ifx\preLilyPondExample \undefined
\else
  \expandafter\preLilyPondExample
\fi
\def\lilypondbook{}%
\input{5a/lily-66b633c5-systems.tex}
\ifx\postLilyPondExample \undefined
\else
  \expandafter\postLilyPondExample
\fi
}

\end{document}
8
  • Thank you very much for the effort and looking into it! You can change the \linebreak into \par by defining \betweenLilyPondSystem, like this: \newcommand{\betweenLilyPondSystem}[1]{\par}. However, even with \setlength\parskip{\fill} and \flushbottom I get the first n-1 pages dense and the last page possible very sparse (depending on the input and the page dimensions). Jan 15, 2015 at 13:11
  • In the given example the last page has only two lines: one on the top and one on the bottom. This should not be so, it should have 4 or 5 lines, just as the first two pages. Jan 15, 2015 at 20:15
  • @JúdaRonén That's an issue of margins, I showed how to adjust the margins to get output like the lillypond output. If you use the default {article} margins, you obviously won't get the same number of lines per page. I'll update my answer showing how to space them out though.
    – Ryan
    Jan 15, 2015 at 20:42
  • @JúdaRonén I've updated the answer to include an example showing normal article margins.
    – Ryan
    Jan 15, 2015 at 20:51
  • Perhaps I misunderstand you, but if we shorten the musical piece the last page will have a lesser number of lines, won’t it? Jan 15, 2015 at 21:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .