An LFO belongs to its channel, not to the whole device
The two LFOs lived in the Synth, so four channels shared them and whichever patch loaded last owned them for every voice at once. A sound with its LFO switched off silenced the trill under a sound that was still playing - which is what made Lunar Porter's low fuel warning intermittent: the first landing, docking or crash of a run took its trill away, and it was right again next time the machine started. The engine fix went upstream to soundThing and has come back. synth.c and synth.h are re-vendored at 71e3cb2, character for character bar the ASCII transliteration, and now carry two changes: the LFOs moved into the Voice, and synthSyncVoices carries a free LFO's cycle down alongside its rate. That second hunk does nothing here - it only matters to a caller that syncs voices, and this device never does, because syncing would flatten four channels into one instrument. It is taken so the vendored file stays identical in both trees, and it is commented as such. Upstream also found a bug in the original patch, in patchLoad, which is soundThing's own file and does not travel. Downstream the LFO parameter groups 0x60 and 0x70 now read the selected channel like every parameter beside them, so an LFO written to one channel is inaudible on the other three. Everything else about the device is unchanged. Lunar Porter keeps loading each patch immediately before its note, but for the smaller reason that now applies: the bang and the latch share channel three, and a channel used by two sounds has to be told which of them it is about to be. The comment that said otherwise, and the manual's warning about sharing, are rewritten as history rather than as a caveat. Tests/sound.sh's shared-LFO check is inverted to assert the fixed behaviour, with a third leg added: after proving another channel's patch leaves this one alone, it switches this channel's OWN LFO off and requires the pitch to move. Without that, both checks would pass on a device where writing an LFO did nothing at all. Routing either group back to voice 0 is caught. Cost, measured: four channels sounding continuously for 400 seconds of audio takes 5.0 s of wall clock against 4.59 s before, about 9% of total emulator time. Half of that is wasted on voices that cannot sound, since VOICE_COUNT is 8 and there are four channels; recovering it would mean diverging the vendored file, which is not worth it at this price.
This commit is contained in:
@@ -1075,9 +1075,9 @@ Anywhere a setting asks *what modulates* something, the answer is one of these:
|
||||
| 3 | LFO 0. |
|
||||
| 4 | LFO 1. |
|
||||
|
||||
**The two LFOs belong to the device and not to a channel**, so writing 0x60 to 0x7F ignores
|
||||
whichever channel is selected. That is what makes them useful: a vibrato that every voice
|
||||
shares is one wobble rather than four that drift apart.
|
||||
**Each channel has its own pair of LFOs**, so writing 0x60 to 0x7F sets them on whichever
|
||||
channel is selected, exactly like every parameter above. Four channels are four independent
|
||||
instruments, and an LFO is part of how an instrument sounds.
|
||||
|
||||
### What A Byte Means:
|
||||
|
||||
@@ -1148,25 +1148,30 @@ The consequence is worth knowing rather than fixing: a retriggered noise source
|
||||
repeatable, so every hit is literally the same noise, the way a sampler is. On a hi-hat that
|
||||
can read as machine-gunny. Where variation is wanted, leave that LFO or that voice free.
|
||||
|
||||
### A Warning About Sharing Them:
|
||||
### They Used To Be Shared, And The Fault That Caused:
|
||||
|
||||
**An LFO belongs to the device and not to a channel.** There are two of them against four
|
||||
voices, so setting one from a patch meant for channel three changes what channel nought hears,
|
||||
immediately and for as long as nothing sets it back.
|
||||
Worth knowing, because it is the shape of bug this device is built to avoid and the manual
|
||||
said the opposite for a while.
|
||||
|
||||
That matters because a patch naturally carries LFO settings along with everything else - it is
|
||||
one instrument, and its LFO is part of how it sounds. A program that loads its instruments once
|
||||
at startup therefore ends up with whichever of them was written *last*, for all of them.
|
||||
The two LFOs used to belong to the **device**, so setting one from a patch meant for channel
|
||||
three changed what channel nought heard, immediately and for as long as nothing set it back.
|
||||
A patch naturally carries LFO settings along with everything else, so a program that loaded
|
||||
its instruments once at startup ended up with whichever of them was written *last*, for all
|
||||
of them.
|
||||
|
||||
The failure this produces is unpleasant to diagnose, because it is intermittent by nature: a
|
||||
The failure that produces is unpleasant to diagnose, because it is intermittent by nature: a
|
||||
sound is correct until some unrelated thing plays, and correct again next time the machine
|
||||
starts. A game here lost a warning's trill after the first landing of each run, because the
|
||||
landing's patch happened to carry an LFO that was switched off.
|
||||
|
||||
**Load a patch immediately before the note that needs it.** A patch is forty-odd writes and
|
||||
this costs nothing at a moment that is already making a sound. What it cannot fix is two
|
||||
sounds overlapping - they still share the LFOs, and with two between four voices that is in
|
||||
the nature of the device.
|
||||
A program could work around the first half of that by loading each patch immediately before
|
||||
the note that needed it. It could not work around the second: two sounds **overlapping** still
|
||||
interfered, and no amount of care in the program could separate them. So the device was
|
||||
changed rather than the programs, and an LFO now belongs to the channel it was written to.
|
||||
|
||||
**Loading a patch immediately before its note is still good practice**, for the different
|
||||
reason that a channel used by two sounds has to be told which of them it is about to be. A
|
||||
patch is forty-odd writes and costs nothing at a moment already making a sound.
|
||||
|
||||
### Knowing When It Has Finished:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user