Play a recording on phone, and record it in a window

A phone function key names a wav file instead of words, which is what N1MM's
own SSB file holds: `F1 CQ,{WAVDIR}\Cq.wav`. `{WAVDIR}` is the folder named
after whoever is at the microphone, a name is taken relative to `Wav`, and
commas play several files in a row. An SSB `.mc` file written for N1MM plays
here.

Window ▸ Voice Keyer lists every recording the messages name, says which of
them are there for the operator picked at the top, plays one, and records over
one. The recording is written beside the wanted file and moved over it at the
end, so a recorder that will not start takes nothing away.

`CommandSoundCard` runs `aplay` and `arecord`, and both commands are settings:
the audio path belongs to whatever the station runs, and a library would pick
one of them for the operator. A recorder is stopped with an interrupt so it
closes its wav file, and killed only if it ignores that. PTT is cwdaemon's
`<ESC>a` for as long as the recording plays, off for a station on VOX.

Two things follow. The QTC window sends on SSB: N1MM's four recordings on the
Ready, Agn, Cfm and Close buttons, with the lines still read out by the
operator. And alternating CQ duels on phone, because the voice keyer says when
a recording has finished — which it had to, since the CQ message is picked by
the radio's mode and would otherwise have been keyed as Morse.

Nothing here has been played on a radio: this machine has no sound card, so
what is tested is the program being run, the file filled in, the exit code and
the interrupt, with shell commands standing in for the two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0157i7PiZyqBkquxS9A6FTdQ
This commit is contained in:
2026-09-11 07:51:58 +00:00
co-authored by Claude Opus 5
parent dae1f4f197
commit 082fa75a40
28 changed files with 1564 additions and 86 deletions
+39 -1
View File
@@ -1,6 +1,6 @@
# How CW gets on the air, and why
Written 2026-08-27.
Written 2026-08-27. The voice keyer was added 2026-09-11.
Nonemm has two keying paths and neither of them times the Morse itself:
@@ -85,3 +85,41 @@ Alternating CQ needs the end of a message, and both paths report it:
Timing the message from the length of its text was rejected. The guess runs
short exactly when the operator has turned the speed up, and a short guess keys
the second radio while the first is still sending.
## The voice keyer
A phone message is a recording rather than characters, so nothing has to be
timed: the file is played, and the transmitter stays keyed until it has been.
Two decisions are worth writing down.
**The sound card is a program, not a library.** `CommandSoundCard` runs
`aplay` and `arecord`, and both commands are settings. The reason is the reason
above: the audio path belongs to whatever the station runs — ALSA, PulseAudio,
PipeWire, JACK — and a library picks one of them for the operator. A station
that routes its audio some other way writes its own command with `{file}` in
it, and a station on Windows, which has no player on the path, gets a
PowerShell line that plays through .NET's own `SoundPlayer`.
The cost is a process per message. It is a few milliseconds at the front of a
recording that runs for seconds, and no part of a voice message needs the
timing that CW needs.
**A recorder is stopped with an interrupt, not a kill.** `arecord` closes the
wav file and writes its header when it is interrupted; killed outright it
leaves a file with a header that says nothing was recorded, which nothing can
play. So the stop is `SIGINT`, and the kill is only what follows two seconds
later for a command that ignores it. The recording is written beside the wanted
file and moved over it at the end, so a recorder that will not start takes
nothing away.
**PTT is cwdaemon's `<ESC>a`**, which keys the transmitter and leaves it keyed.
That is the only way into the keying port from here, so a station with a
WinKeyer, or with no CW keyer at all, runs the voice keyer on VOX. The
`<ESC>b` request, which tells cwdaemon whether the SSB audio comes from the
microphone or the sound card, is not sent: what it switches is the daemon's own
wiring, and a station that needs it has already set it.
None of this has been run against a radio. This machine has no sound card, so
what has been exercised is the program being run, the file being filled in, the
exit code and the interrupt — with ordinary shell commands standing in for
`aplay` and `arecord`.