codec-re: 30 NN block CRACKED — codec fully decoded
User intuition (16-bit) + 12-bit packing hypothesis + the int16 ADC
range constraint led to the final piece.
30 NN block format (CONFIRMED across all 14 blocks in the fixture
bundle):
NN 12-bit signed deltas packed as NN/4 groups of 6 bytes each.
Within each group:
bytes [0:2] = 16 bits = 4 × 4-bit high nibbles (MSB-first)
bytes [2:6] = 4 × int8 low bytes
delta[k] = sign_extend_12((high_nibble[k] << 8) | low_byte[k])
Block length = NN × 1.5 + 2 bytes (tag included). Earlier walker
used NN × 4 which is only correct in the TRAILER section.
Why 12-bit: ±2047 in 16-count units ≈ ±10 in/s = the geophone's
full-scale range at Normal sensitivity. The codec sizes its widest
delta to cover the worst-case sample-to-sample change.
Results: every decoded sample across all fixture events matches truth
byte-exact. ZERO divergences.
event-a: 9984 samples (full event, all 3 geos)
event-c: 3840 (full event)
event-d: 3840 (full event)
JQ0: 9984 (full event)
V70: 9984 (full event)
SP0: 5122 (walker stops early on edge cases)
SS0: 1758
SV0: 2114
event-b: 738
TOTAL: 47,364 ADC samples verified, zero errors.
Three full 3-sec events decode end-to-end across all three geo
channels. The events where fewer samples decode (SP0/SS0/SV0/event-b)
are limited by walker robustness issues past the first few segments,
NOT by decoder correctness.
64 tests pass (up from 55). Files: minimateplus/waveform_codec.py
(new 30 NN decode + corrected walker length), tests/test_waveform_codec.py
(new full-event regression tests), docs/* (updated status everywhere),
analysis/test_30nn_hybrid.py (new — the analysis script that confirmed
the format).
This commit is contained in:
@@ -252,31 +252,38 @@ def test_decode_waveform_v2_returns_dict(event_name):
|
||||
# for THIS segment's channel plus 2 continuation deltas (bytes [0:4]) for
|
||||
# the PREVIOUS channel.
|
||||
MULTICHANNEL_FIXTURES = [
|
||||
# V70 (Mic-heavy, geos all near zero): perfect decode through first segment of each channel.
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.V70"), "Tran", 512),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.V70"), "Vert", 512),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.V70"), "Long", 512),
|
||||
# JQ0 (Vert-heavy): first 512 samples per channel decode byte-exact.
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.JQ0"), "Tran", 512),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.JQ0"), "Vert", 258),
|
||||
# SP0 (loud all): Long all 3 segments byte-exact (1536 samples).
|
||||
# ALL geo channels fully decoded (3328 samples × 3 = 9984 per event), byte-exact:
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.V70"), "Tran", 3328),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.V70"), "Vert", 3328),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.V70"), "Long", 3328),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.JQ0"), "Tran", 3328),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.JQ0"), "Vert", 3328),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1L.JQ0"), "Long", 3328),
|
||||
# SP0 (loud all-channels with 30 NN blocks): all decoded samples match truth.
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SP0"), "Tran", 2048),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SP0"), "Vert", 1538),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SP0"), "Long", 1536),
|
||||
# SS0 / SV0 (loud-from-start): walker reaches a limited number of segments
|
||||
# but every decoded sample matches truth.
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SS0"), "Tran", 734),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SS0"), "Vert", 512),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SS0"), "Long", 512),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SV0"), "Tran", 1024),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SV0"), "Vert", 578),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "5-11-26", "M529LL1A.SV0"), "Long", 512),
|
||||
# 5-8-26 quiet bundle: events without 30 NN blocks decode FULLY across all channels.
|
||||
# event-a: 3328 samples × 3 channels = 9984 samples, all byte-exact.
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "decode-re-5-8-26",
|
||||
"event-a", "M529LKVQ.6S0"), "Tran", 3328),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "decode-re-5-8-26",
|
||||
"event-a", "M529LKVQ.6S0"), "Vert", 3328),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "decode-re-5-8-26",
|
||||
"event-a", "M529LKVQ.6S0"), "Long", 3328),
|
||||
# event-c: 1280 samples × 3 channels
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "decode-re-5-8-26",
|
||||
"event-c", "M529LK44.AB0"), "Tran", 1280),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "decode-re-5-8-26",
|
||||
"event-c", "M529LK44.AB0"), "Vert", 1280),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "decode-re-5-8-26",
|
||||
"event-c", "M529LK44.AB0"), "Long", 1280),
|
||||
# event-d: 1280 samples × 3 channels
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "decode-re-5-8-26",
|
||||
"event-d", "M529LK2V.470"), "Tran", 1280),
|
||||
(os.path.join(os.path.dirname(__file__), "fixtures", "decode-re-5-8-26",
|
||||
|
||||
Reference in New Issue
Block a user