mirror of
https://github.com/smittix/intercept.git
synced 2026-04-25 07:10:00 -07:00
fix: Preserve image-start samples across VIS-to-decoder boundary
VISDetector._process_window() was calling self.reset() inside the STOP_BIT handler, wiping self._buffer before feed() could advance past the triggering window. All audio samples buffered after the VIS STOP_BIT (the start of the first scan line) were silently discarded, causing the image decoder to begin decoding mid-stream with no alignment reference. The result was every scan line being desynchronised from the first, producing the diagonal stripes and scrambled colours seen in decoded images. Fix: remove the premature reset() from _process_window(). The STOP_BIT handler now sets state=DETECTED and returns the result. A new remaining_buffer property exposes the post-VIS samples. _decode_audio_stream() and decode_file() capture those samples before calling reset(), then immediately feed them into the newly created SSTVImageDecoder so decoding begins from sample 0 of the first sync pulse. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -145,6 +145,16 @@ class VISDetector:
|
||||
def state(self) -> VISState:
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def remaining_buffer(self) -> np.ndarray:
|
||||
"""Unprocessed samples left after VIS detection.
|
||||
|
||||
Valid immediately after feed() returns a detection result and before
|
||||
reset() is called. These samples are the start of the SSTV image and
|
||||
must be forwarded to the image decoder.
|
||||
"""
|
||||
return self._buffer
|
||||
|
||||
def feed(self, samples: np.ndarray) -> tuple[int, str] | None:
|
||||
"""Feed audio samples and attempt VIS detection.
|
||||
|
||||
@@ -288,9 +298,22 @@ class VISDetector:
|
||||
|
||||
if self._tone_counter >= self._bit_windows:
|
||||
result = self._validate_and_decode()
|
||||
self.reset()
|
||||
# Do NOT call reset() here. self._buffer still holds samples
|
||||
# that arrived after the STOP_BIT window — those are the very
|
||||
# first samples of the image. Wiping the buffer here causes all
|
||||
# of them to be lost, making the image decoder start mid-stream
|
||||
# and producing garbled/diagonal output.
|
||||
# feed() will advance past the current window, leaving
|
||||
# self._buffer pointing at the image start. The caller must
|
||||
# read remaining_buffer and then call reset() explicitly.
|
||||
self._state = VISState.DETECTED
|
||||
return result
|
||||
|
||||
elif self._state == VISState.DETECTED:
|
||||
# Waiting for caller to call reset() after reading remaining_buffer.
|
||||
# Don't process any windows in this state.
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
def _decode_bit(self, samples: np.ndarray) -> int:
|
||||
|
||||
Reference in New Issue
Block a user