After listening to the original music in a Mac emulator (which
unfortunately doesn't handle the music very well), I can only
conclude that note value 1 means the note should continue playing.
At first I thought maybe it was supposed to fade the current note,
or perhaps change its volume, but I can't hear any traces of
either. So I'm going to assume it just means "hold the current
note", though for the life of me I cannot think of any valid
reason for such a command. So it may be wrong, but it sounds
closer to the emulator than it did before.
In looped music, prevent the music channels from drifting out of
sync over time. This was noticeable after a few minutes in the
SCUMM Bar. We do this by extending the last note (which is just
zeroes, so we didn't even use to play it) so that it has the
exact number of samples needed to make all channels the exact
same length. (This is calculated when the music is loaded, so it
does not need any extra data in the save games, thankfully.)
As a result, the getNextNote() is now responsible for converting
the duration to number of samples (out of necessity) and for
converting the note to a pitch modifier (out of symmetry). I made
several false starts before I realized how much easier it would
be this way.
At least on my computer, when the note ended abruptly there would
be an annoying "pop" at the end. This was particularly noticeable
at the end of the distaff notes in Loom. To get around this, fade
out the last 100 samples. There's nothing magical about 100 in
particular, but it's a nice even number and it should be short
enough that it's never a noticeable part of the note, even at low
sample rates.
This keeps the music from breaking when loading a savegame that was
made with a different sample rate than the current one. It also
breaks all savegames made in the past eight hours, but I don't think
it's necessary to maintain savegame compatibility within a pull
request, as long as it still works with savegames made before it.
Note that while this removes _townsPlayer->saveLoadWithSerializer(s)
it really shouldn't break anything because _musicEngine also points
to the FM Towns player. Famous last words...
The Monkey Island and Loom mac music is really quite similar. The
data layout is a bit different, but most of the code was easy to
separate into its own class. The Loom player doesn't do looped music
but I don't remember off-hand if it ever should.