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:
@@ -2796,26 +2796,34 @@ runPend:
|
||||
|
||||
; ---- Why every sound loads its patch at the moment it plays ----
|
||||
;
|
||||
; THE LFOs BELONG TO THE DEVICE AND NOT TO A CHANNEL. There are two of them against four
|
||||
; voices, and a patch carries LFO settings the way it carries everything else - so whichever
|
||||
; patch was loaded last owns them, for every channel at once.
|
||||
; CHANNEL THREE IS TWO INSTRUMENTS. The bang and the latch share it, and a patch is the whole
|
||||
; voice, so the channel has to be told which of them it is about to be. Loading at the moment
|
||||
; of the note costs fifty writes at a moment already doing more than fifty, and means a sound
|
||||
; is what its patch says whatever played before it.
|
||||
;
|
||||
; The other three channels have one sound each and could be set up once at startup. They are
|
||||
; not, because a single rule is worth more here than the writes it saves: every sound loads
|
||||
; its own patch, so there is no question of which sounds are safe to set up early and which
|
||||
; are not.
|
||||
;
|
||||
; ---- What this used to be working around ----
|
||||
;
|
||||
; The LFOs belonged to the DEVICE and not to a channel: two of them against four voices, with
|
||||
; a patch carrying LFO settings the way it carries everything else, so whichever patch loaded
|
||||
; last owned them for every channel at once.
|
||||
;
|
||||
; That is what made the low fuel warning sound right sometimes and not others. Its trill is a
|
||||
; saw LFO on the pitch, and the patches on channel three - the bang and the latch - carry an
|
||||
; LFO that is switched OFF. Those load at the moment they are used, so the first landing,
|
||||
; docking or crash of a run took the warning's trill away and left a plain tone. Before any of
|
||||
; them it was right, which is exactly the shape an intermittent fault has.
|
||||
; saw LFO on the pitch, and the patches on channel three carry an LFO that is switched OFF, so
|
||||
; the first landing, docking or crash of a run took the warning's trill away and left a plain
|
||||
; tone. Before any of them it was right, which is exactly the shape an intermittent fault has.
|
||||
;
|
||||
; It also meant the rumble never had its own LFO at all: the instruments were set up in order
|
||||
; at startup and the warning's settings, written last, sat on top of the rumble's.
|
||||
; Loading at the moment of the note made each sound correct AS IT STARTED, which was as far as
|
||||
; a program could get on its own. It could not fix two sounds OVERLAPPING - a warning going off
|
||||
; mid-burn still re-tuned the rumble's LFO for as long as it lasted.
|
||||
;
|
||||
; So nothing is set up once any more. Each sound loads immediately before its note, which
|
||||
; costs fifty writes at a moment already doing more than that, and means a sound is what its
|
||||
; patch says whatever played before it.
|
||||
;
|
||||
; What that does not fix, because it cannot: two sounds overlapping still share one pair of
|
||||
; LFOs, so a warning going off mid-burn re-tunes the rumble's LFO for as long as it lasts.
|
||||
; With two between four, that is in the nature of the device.
|
||||
; The device was fixed instead: an LFO now belongs to the channel it was written to, so four
|
||||
; channels are four independent instruments in this respect as in every other. Overlapping
|
||||
; sounds no longer interfere, and the paragraph above is history rather than a caveat.
|
||||
|
||||
; ---- Lit or not, and only the CHANGES matter ----
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user