Never call a string of Morse tones "words"
A repeater identifying itself in CW over an FM carrier came back from the recogniser as "2-2-2-3-3-5-2-7-0-5-9-7-0-8-1-0" -- one digit per tone, sixteen characters of nothing, which cleared the five-character bar and cost the capture its waterfall. The rule now lives in one place, waterfall.is_readable, shared by the scanner and the waterfall command: voice, no Morse, and more than a handful of characters. bandsaunter waterfall --check-morse runs the CW decoder over the recordings a sidecar calls readable, for sidecars written before the decoder could hear an ident over an FM carrier, and draws -- and records the ident in -- the ones that have one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
This commit is contained in:
parent
dee262e130
commit
a8a8548369
9 changed files with 190 additions and 29 deletions
|
|
@ -139,6 +139,9 @@ examples:
|
|||
help="draw again where a picture already exists")
|
||||
wf.add_argument("--min-chars", type=int, default=None, metavar="N",
|
||||
help="a transcript shorter than this counts as none")
|
||||
wf.add_argument("--check-morse", action="store_true",
|
||||
help="listen for a CW ident in the recordings a sidecar "
|
||||
"calls readable, and draw the ones that have one")
|
||||
|
||||
# -- devices ----------------------------------------------------------
|
||||
d = sub.add_parser("devices", help="list attached RTL-SDR devices")
|
||||
|
|
@ -729,8 +732,9 @@ def cmd_transcribe(args) -> int:
|
|||
def cmd_waterfall(args) -> int:
|
||||
"""Draw the captures nobody can read, for a directory already recorded."""
|
||||
import json as _json
|
||||
from .morse import find_morse
|
||||
from .recorder import read_wav
|
||||
from .waterfall import draw_for_recording, waterfall_path
|
||||
from .waterfall import draw_for_recording, is_readable, waterfall_path
|
||||
|
||||
cfg, _ = load_default()
|
||||
floor = args.min_chars if args.min_chars is not None \
|
||||
|
|
@ -776,9 +780,8 @@ def cmd_waterfall(args) -> int:
|
|||
# The same rule the scanner applies as it records: voice that
|
||||
# produced words worth the name is readable, and everything else is
|
||||
# a picture waiting to be drawn.
|
||||
readable = (str(hit.get("category") or "") == "voice"
|
||||
and len(transcript) > floor)
|
||||
if readable and not args.all:
|
||||
readable = is_readable(hit, transcript, floor)
|
||||
if readable and not args.all and not args.check_morse:
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
|
|
@ -788,6 +791,21 @@ def cmd_waterfall(args) -> int:
|
|||
console.print(f"[red]{wav.name}: {exc}[/red]")
|
||||
failed += 1
|
||||
continue
|
||||
|
||||
# A sidecar written before the decoder could hear an ident over an
|
||||
# FM carrier calls a repeater readable, because the recogniser turned
|
||||
# its tones into a long string of digits. Listening again is the
|
||||
# only way to know, and it is only worth it for the ones that would
|
||||
# otherwise be skipped.
|
||||
ident = None
|
||||
if readable and not args.all:
|
||||
ident = find_morse(audio, rate)
|
||||
if ident is None or not ident.is_morse:
|
||||
skipped += 1
|
||||
continue
|
||||
console.print(f" [grey62]{wav.name}: CW ident "
|
||||
f'"{ident.complete_text}"[/grey62]')
|
||||
|
||||
iq = str(hit.get("iq_path") or "")
|
||||
try:
|
||||
picture = draw_for_recording(
|
||||
|
|
@ -812,6 +830,13 @@ def cmd_waterfall(args) -> int:
|
|||
body = _json.loads(meta.read_text())
|
||||
if isinstance(body.get("hit"), dict):
|
||||
body["hit"]["waterfall_path"] = picture.path
|
||||
if ident is not None:
|
||||
# Found the hard way; worth keeping, so the browser
|
||||
# shows the ident and the next run knows without
|
||||
# listening again.
|
||||
body["hit"]["morse_text"] = ident.text
|
||||
body["hit"]["morse_complete"] = ident.complete_text
|
||||
body["hit"]["morse_wpm"] = round(ident.wpm, 1)
|
||||
meta.write_text(_json.dumps(body, indent=2, default=str))
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue