The three changes that went up came back as part of soundThing, along
with two more that they made possible. The engine here is now b73e5c0
character for character, except that em-dashes and arrows in comments are
written as ASCII because this tree is ASCII only - a local rule, not an
improvement, and not sent up.
So synth.h's "what was changed" list is gone. There is nothing to list:
what has to be kept current is only that if either copy changes, the
other one has to be told.
---- What came back ----
A VOICE CAN END ITSELF. Naming the level's source said what shapes a
voice; nothing said what ends one, so the only thing that could ever
finish one was a key coming up. A game is nearly all one-shots and not
one of them wants its length decided by how long a note was held. Exposed
as parameter 0x51: 0 gated, 1 triggered.
AND A ONE-SHOT IS THE SAME ONE-SHOT TWICE. A triggered voice re-arms its
oscillators, and an LFO can be told to start over with each voice -
parameter 3 of either LFO. Both halves are needed and the check proves
it: with the LFO left free, two triggered hits still differ.
Their note warned that whatever applies a patch to a channel has to set
these or they hold synthInit's defaults. Checked: Voyager never calls
synthSyncVoices, so their 0001 is a no-op here as they predicted, and
nothing reaches into an LFO's phase, so the struct split is safe.
---- What it is for ----
Lander's crash is a triggered voice now, so boomOff is gone. Nothing has
to remember to end a bang.
SoundPatch learnt voice_levelSource, voice_gate and lfo<N>_mode, which
the new soundThing writes - without that it would have refused every
patch saved from it, since an unknown field stops the tool on purpose. A
patch from before those fields still converts, and says in its own
comments that it predates the level routing.
Three checks, each seen to fail on its own break: a gated voice still
sounding with nothing holding it, a triggered one down to nothing with no
gate ever dropped, and two hits identical sample for sample.
One test bug worth keeping: the first version of the repeatability check
struck the second note while the first was still ringing, so what it
found and compared as "the second hit" was a point in the middle of the
first one's tail. It now looks for sound after SILENCE rather than sound
after an offset.
The bang was guessed at directly in bytes and came out as a low gurgle,
which is what guessing at bytes gets you: a cutoff of 40 looks small and
is 57 Hz, so the filter sweep ended almost shut. Voyager's sound device
is soundThing's voice engine with the editor taken off, so a patch
designed in soundThing - where there is a screen, a keyboard and a pair
of ears - makes the same sound here. What differs is only how it arrives.
SoundPatch converts one into the other. Every parameter the device takes
is a documented function of a natural value and all of them invert: times
are squared into four seconds, cutoff and rate are exponential, depths
and detune are centred on 128. It writes a table of a count and that many
parameter and value pairs, and playPatch hands it to the device - so
every sound after this costs a table and a call rather than forty lines
of its own.
Two things the conversion has to say out loud. soundThing has no field
for the level routing, because there it is always the amplitude envelope,
so the table says so explicitly - a channel keeps its patch between notes
and a leftover from a previous one would otherwise be carried in. And a
field the tool does not recognise STOPS it: a patch format that has moved
on would otherwise produce a table that quietly means something else.
THE BUILD DOES NOT DEPEND ON IT. soundThing lives in its own repository
and is not needed to build anything here; the tables are checked in and
the tool is for when a sound is being changed.
Lander's crash now plays Kick808 as a stand-in until a bang is designed
for it, and the difference is the point: the hand-guessed patch wandered
between 1600 and 8200 for eight tenths of a second, and this decays
3492, 2743, 2037, 1515, 1040, 614, 87, nothing.
The docs check caught the tool count in two manuals, which is what it is
for.