From 7de7cb96c3aec248eb1fb20c95b850ba7fe80e60 Mon Sep 17 00:00:00 2001 From: rouggy Date: Sun, 30 Aug 2026 02:25:37 +0200 Subject: [PATCH] fix(icom): one sequence space for everything sent on the audio stream The voice keyer and the live microphone each numbered their packets from 1. A message played after a talk session re-used sequence numbers the rig had already seen and was discarded wholesale: the PTT keyed for the full length of the message and none of it was modulated. PlayTX now feeds the same framer and counters as the microphone. --- internal/cat/icomaudio.go | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/internal/cat/icomaudio.go b/internal/cat/icomaudio.go index 5bb1b24..aeae5f9 100644 --- a/internal/cat/icomaudio.go +++ b/internal/cat/icomaudio.go @@ -260,11 +260,14 @@ func (a *icomAudio) PlayTX(pcm []byte, rate, ch, bits int, stop <-chan struct{}) if rate > 0 && rate != 16000 { mono = resampleLinear(mono, rate, 16000) } + // Through the SAME framer and counters as the live microphone. Each of the + // two used to number its own packets from 1, and a voice-keyer message sent + // after a talk session re-used sequence numbers the rig had already seen — + // it keyed for the full length of the message and modulated none of it. const frame = 320 // samples per packet: 20 ms at 16 kHz, the rig's own cadence tick := time.NewTicker(20 * time.Millisecond) defer tick.Stop() - var outerSeq uint16 = 1 - var sendSeq uint16 + buf := make([]byte, frame*2) for pos := 0; pos < len(mono); pos += frame { select { case <-stop: @@ -273,28 +276,21 @@ func (a *icomAudio) PlayTX(pcm []byte, rate, ch, bits int, stop <-chan struct{}) return fmt.Errorf("the audio stream closed mid-message") case <-tick.C: } - pkt := make([]byte, 0x18+frame*2) - icnLE.PutUint32(pkt[0:], uint32(len(pkt))) - icnLE.PutUint16(pkt[6:], outerSeq) - icnLE.PutUint32(pkt[8:], a.aID) - icnLE.PutUint32(pkt[12:], a.aRemote) - pkt[0x10], pkt[0x11] = 0x81, 0x01 - icnBE.PutUint16(pkt[0x12:], sendSeq) - icnBE.PutUint32(pkt[0x14:], frame*2) - for i := 0; i < frame && pos+i < len(mono); i++ { - v := mono[pos+i] * 32767 + for i := 0; i < frame; i++ { + var v float32 + if pos+i < len(mono) { + v = mono[pos+i] * 32767 + } if v > 32767 { v = 32767 } else if v < -32768 { v = -32768 } - icnLE.PutUint16(pkt[0x18+i*2:], uint16(int16(v))) + icnLE.PutUint16(buf[i*2:], uint16(int16(v))) } - if _, err := a.conn.Write(pkt); err != nil { - return fmt.Errorf("sending audio to the rig: %w", err) + if err := a.SendTXChunk(buf); err != nil { + return err } - outerSeq++ - sendSeq++ } return nil }