Repeats
The idea of using the event listeners to extract when notes are played shows its limits quite well in the handling of repeats. The event listeners reports events as it sees them in the lilypond's input file. For example on the following music sheet
the la
should be played twice. However the generated events are
0.00000000 tempo 400.00000000
0.00000000 note 69 4 0.25000000 point-and-click 6 37
when using the default event-listener provided by lilypond. That is the exact same events as generated
This issue here is due to the fact that the default event-listener doesn't pay attention to repeat events. I tried modifying it in several ways so that it would also report on repeat events. However I could not get what was repeated which is quite important to say the least.
if we have the following music sheet,
\repeat volta 2 { la' sol' }
We need to extract that this is equivalent to la' sol' la' sol'
.
With my several attempts based only on the event-listener, I was getting the following events.:
t=0 play la' duration quarter-time
t=quarter-time play sol' duration quarter-time
t=2 * quarter-time display-repeat-bar
This is not good enough, as the same output was produced for this different music:
la' \repeat volta 2 { sol' }
which is equivalent to la' sol' sol'
.
Here the solution was to unfold all repeats first.
Lilypond handle the following kind of repeats as described in its documentation:
- volta
- unfold
- percent
- tremolo
Below is a table showing the effect of each repeat type on the event-listener output
music sheet | source | generated events |
---|---|---|
| \repeat volta 2 { la' } | |
| \repeat unfold 2 { la' } | |
| \repeat percent 2 { la' } | |
| \repeat tremolo 2 { la' } |
Percent
and tremolo
repeats are still something I can't really understand even after reading the documentation on short repeats.
Therefore I just ignore them. However, when focusing on volta
and unfold
repeat, we see on the generated events that unfolded repeats
produce the correct events about notes being played and when. Therefore when encoutering a volta
repeat, one can simply change it to
an unfold
ed one to get the right music events. This leads to another issue though. It changes the generated output. One goal of the
project was to work on real music sheets, just like the ones a pianist would use. Not a simplified equivalent one. This issue will
be treated later on, in the part about matching a note to where it appears on the music sheet.
For now, to solve the current issue due to repeats, let's just replace all volta
repeats by unfold
repeats.
There are several ways to do so. Since lilypond's input file are simply text files, one way would be to
programmatically edit the text to replace volta
by unfold
everywhere it appears, and then start processing
the music sheet. Another way would be to modify lilypond so that every time it encounters a volta
repeat it
would treat it just like an unfold
one. I went for the second solution as it is the most stable one as
modifying the source would lead to other issues later on.
Reading lilypond's source code, I found the place where it decide how to treat a repeat.
simply changing VoltaRepeatedMusic
by UnfoldedRepeatedMusic
. Modifying lilypond implies recompiling
it, which also implies having the right compile-time dependencies and other inconveniences. Fortunately,
the file requiring the modification is actually interpreted, hence simply modifying and re-running lilypond
is enough. And to avoid file-system related issues, the modification is made on the fly when lilypond opens
that file. This is done by using a library that overwrites the system's open
and fopen
function and is set
via LD_PRELOAD
environment variable.