The operator asked the right question: why wait 1.5 s at all, when the mode is
known from CAT?
Because the wait is not the problem — what happened during it was. The drift
guard, meant for two sound cards running on their own clocks, saw a starved
source as a one-second skew and trimmed the radio audio to match. So the opening
of every CW recording was thrown away although it had been captured.
The guard now applies only while BOTH sources are actually delivering. Waiting
then costs nothing: everything buffered is written whole the moment the silent
source is written off, which a test now pins with three seconds of audio.
Using the CAT mode to skip the wait would have been a second mechanism for a
case this one already covers — and it would not cover the others: a device
switched off, unplugged, or held by another program.
The log read:
recorder: the second audio source is silent — recording the radio alone
recorder: no audio at all from "DAX Mic" after 3 s — nothing is streaming
Both true, and together they read as a fault while the recording was going
perfectly well — it was saved seconds later. On CW the mic channel legitimately
delivers nothing; the mixer already said what it was doing about it.
The watchdog now mentions the mic only when the radio is silent too, which is
the case where the recording really is empty.
The operator said it from the start: in CW there is no sidetone, only reception.
My previous fix did not cover it — it wrote off a source that STOPPED, but a
source that never starts has no last-delivery time, so it stayed forever "not
yet dry" and held the mixer at min(A,B)=0. Three empty recordings while the
radio audio streamed perfectly.
A source with no delivery is now measured from when capture started. Tested both
ways: nothing is written off in the first moments, and a source that has never
spoken is written off once the grace period has passed.
Third empty recording, same station, and the sequence was as plain as it gets:
type the call, click record, log the QSO. The device opened and never streamed.
Endpoint ids are what gets stored, and a DAX channel that is reconfigured,
disabled or recreated comes back with a DIFFERENT id. The stale one opens
without complaint on some drivers and simply never delivers — indistinguishable
from a quiet band until the file turns out to be empty.
The recorder now checks the id against the current endpoint list when it starts,
which takes milliseconds, and says outright that the configured input is gone —
on screen, not only in the log. If it IS still there, the answer is equally
useful: the device exists and the fault is upstream, in whatever should be
feeding it.
The watchdog fired exactly as intended and said:
no audio at all from "{0.0.1.00000000}.{6a27abfd-f277-496b-b6f1-f92ec284c636}"
which tells the operator nothing they can act on. "DAX RX 1 (FlexRadio DAX)"
points straight at the DAX panel.
Endpoint ids are what gets CONFIGURED and stored, so they are what the recorder
holds; the friendly name is resolved only when something has gone wrong. When
the endpoint cannot be found at all the id is still shown — a device that has
disappeared explains an empty recording too.
Second empty recording from the same station, and this time NEITHER source had
delivered a sample — so the fix for a silent second source could not apply, and
the log still said only "recording was empty" at the end of the QSO.
Two blind spots, both now closed:
- captureStream's error was discarded. A device that cannot be opened — renamed,
unplugged, held by another program — looked exactly like one that is merely
quiet.
- A WASAPI device can open cleanly and then produce nothing at all. A DAX
channel with no stream behind it does precisely that, and it is
indistinguishable from silence until the file turns out to be empty.
A watchdog now reports both, three seconds in, and the first goes to the OPERATOR
as a toast rather than only to the log: they are mid-QSO, and by the time they
find out at save time the audio is gone for good.
From an operator's log: a Flex with From Radio on DAX RX and Recording mic on
DAX Mic, a full CW QSO recorded, and at log time "snapshot failed: recording
was empty".
The mixer took min(len(A), len(B)) samples. In CW the mic path does not run, so
DAX Mic delivered nothing, min stayed 0, and the drift guard then threw the
radio audio away a second at a time. Two devices configured meant the recording
depended on the quieter one being alive.
A source that has delivered nothing for 1.5 s is now treated as absent and the
other is recorded alone, with one line in the log saying so — half a recording
is worth having, silence is not. Both are mixed again the moment the missing one
comes back.
Neither is written off before it has EVER spoken: at startup both timestamps are
zero, and declaring one dead then would clip the opening of every recording.
That case is tested too.
The situation, in the operator's words: working VP2MAA, recording, and he asks
to hear his own signal. So: stop, play, and the recording is still saved with
the QSO.
Stopping FREEZES the take rather than ending it — nothing more is captured,
nothing is discarded, and logging writes the file exactly as before. Playback
reuses the voice keyer's path: same output device, same PTT keying and release
with its generation guard, so a replay cannot be cut short by a stale unkey.
Playing is refused while still recording. The transmitted audio would feed back
into the same take on any rig monitoring its own transmission, and stopping is
one click the operator has already made — it is their statement that the take is
finished, not a hoop.
The elapsed clock freezes with the recording and resumes from where it stopped,
because it now shows the LENGTH OF THE FILE rather than the time since the QSO
began. Only a fresh take returns it to zero.