07675626dc
The segment-channel scoring analyzer (from scratch/next_experiment_skeleton.py) ran and immediately confirmed the rotation hypothesis: SP0 seg 0: best fit Vert 508/508 ✓ SP0 seg 1: best fit Long 508/508 ✓ SP0 seg 3: best fit Tran 508/508 ✓ (Tran continuation) SP0 seg 5: best fit Long 508/508 ✓ SP0 seg 9: best fit Long 508/508 ✓ V70 seg 0: best fit Vert 508/508 ✓ V70 seg 1: best fit Long 508/508 ✓ Channels rotate Tran → Vert → Long → MicL per 40 02 segment header. Also discovered the segment header has DOUBLE duty: bytes [14:18] anchor the NEW segment's channel (2 samples as int16 BE in 16-count units), AND bytes [0:4] extend the PREVIOUS channel by 2 more samples (2 deltas as int16 BE). This is the same "2 anchors + delta stream" structure as the body preamble for Tran. decode_waveform_v2 now returns full per-channel sample dicts. Byte-exact verified ranges: V70: Tran 512, Vert 512, Long 512 (all first segments) JQ0: Tran 512, Vert 258 SP0: Long 1536 (all 3 L segments) Still open: the 30 NN block format (high-amplitude packed deltas) — appears mid-segment when single-byte deltas can't carry the magnitude. 6 new tests bring the count to 46. All passing.
33 lines
1.2 KiB
Python
33 lines
1.2 KiB
Python
"""Verify decode_waveform_v2 against BW ASCII truth for all fixtures."""
|
|
import sys
|
|
sys.path.insert(0, ".")
|
|
from analysis.load_bundle import _parse_txt
|
|
from minimateplus.waveform_codec import decode_waveform_v2
|
|
|
|
|
|
def main():
|
|
for stem in ("M529LL1A.SP0", "M529LL1A.SS0", "M529LL1A.SV0",
|
|
"M529LL1L.JQ0", "M529LL1L.V70"):
|
|
path = f"tests/fixtures/5-11-26/{stem}"
|
|
with open(path, "rb") as f:
|
|
body = f.read()[43:-26]
|
|
_, samples = _parse_txt(path + ".TXT")
|
|
decoded = decode_waveform_v2(body)
|
|
if decoded is None:
|
|
print(f"{stem}: decoder returned None")
|
|
continue
|
|
|
|
print(f"\n=== {stem} ===")
|
|
for ch in ("Tran", "Vert", "Long"):
|
|
truth = [round(v * 200) for v in samples[ch]]
|
|
pred = decoded[ch]
|
|
n = min(len(pred), len(truth))
|
|
matches = sum(1 for i in range(n) if pred[i] == truth[i])
|
|
div = next((i for i in range(n) if pred[i] != truth[i]), -1)
|
|
print(f" {ch}: decoded={len(pred):>5} truth={len(truth):>5} "
|
|
f"matches={matches:>5}/{n:<5} first div={div}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|