From b9e5ff70f5b8f5f13c401a352356e94439ad8446 Mon Sep 17 00:00:00 2001 From: atsunatsu Date: Sat, 1 Aug 2026 19:25:27 +0800 Subject: [PATCH] feat(cw): add continuous pitch tracking for Doppler drift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - After initial pitch lock, re-scan every ~8 seconds in a narrow ±100 Hz window around the current pitch estimate - Only re-lock if pitch change > 20 Hz (avoids jitter) - Helps maintain lock when Doppler tracking has residual error --- .../look4sat/core/domain/cw/CwDecoder.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/cw/CwDecoder.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/cw/CwDecoder.kt index b73d0ea1..dfc84610 100644 --- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/cw/CwDecoder.kt +++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/cw/CwDecoder.kt @@ -178,6 +178,25 @@ class CwDecoder( goertzel.init(BASE_SAMPLE_RATE, pitch) } } + } else { + // Continuous pitch tracking: re-check periodically to handle Doppler drift + pitchConfidenceCounter++ + if (pitchConfidenceCounter >= PITCH_DETECT_INTERVAL * 5) { + pitchConfidenceCounter = 0 + // Narrow scan: ±100 Hz around current pitch estimate + val narrowDetector = CwPitchDetector( + BASE_SAMPLE_RATE, + (pitchEstimate - 100f).coerceAtLeast(200f), + (pitchEstimate + 100f).coerceAtMost(1200f), + 5f + ) + val pitch = narrowDetector.findPitch(resampled) + if (pitch != null && kotlin.math.abs(pitch - pitchEstimate) > 20f) { + pitchEstimate = pitch + _estimatedPitch.value = pitch + goertzel.init(BASE_SAMPLE_RATE, pitch) + } + } } // Push latest decoded text