codec-re: 00 NN is RLE; full Tran segment-0 decode (4 of 5 events)
User uploaded a Vert-heavy event (JQ0) and a Mic-heavy event (V70). Those two were exactly what was needed to crack the next piece: - 00 NN block = run-length-encoded zero deltas in the current channel. Append NN copies of the current cumulative value (no change). - find_data_start now recognizes 00 NN as a valid first tag (some events begin with a leading 00 NN RLE block). - decode_tran_initial now decodes the FULL segment 0 (not just the first data block). Results across 5 fixture events: - M529LL1A.SP0 (loud-all-channels) : 510 / 510 ✓ - M529LL1L.JQ0 (Vert-heavy) : 510 / 510 ✓ - M529LL1L.V70 (Mic-heavy) : 510 / 510 ✓ - M529LL1A.SV0 (loud-from-start) : 58 / 58 ✓ - M529LL1A.SS0 (loud-from-start) : 42 / 502 (stops at first 30 04) The 30 04 block (only seen in loud-from-start events) hasn't been decoded yet — likely a channel-switch marker for the high-amplitude regime. Also discovered: segment header (40 02) payload bytes [0:2] = T_delta at first sample of new segment, [6:8] = byte length to next segment. Multi-segment Tran decoding still diverges after sample 512 because the per-segment channel ordering after the header is unknown. Tests: 40 pass (up from 36). Files: - minimateplus/waveform_codec.py: find_data_start fix, RLE handling, full segment-0 decode in decode_tran_initial - tests/test_waveform_codec.py: synthetic RLE test, full segment 0 tests for JQ0 and V70 - tests/fixtures/5-11-26/: M529LL1L.JQ0, M529LL1L.V70 + TXT exports - docs/instantel_protocol_reference.md §7.6.1: RLE + segment-header docs
This commit is contained in:
@@ -971,28 +971,64 @@ in the form ``f3/f4/f5`` near ``20 10`` markers strongly resemble
|
||||
int8 channel-bias values around -12). Detailed decoding of the
|
||||
trailer is outside the path needed for sample reconstruction.
|
||||
|
||||
##### Tran channel codec — CONFIRMED 2026-05-11
|
||||
##### Tran channel codec — CONFIRMED 2026-05-11 (segment 0)
|
||||
|
||||
The first data block (immediately after the 7-byte preamble) carries
|
||||
Tran-channel deltas starting at sample 2. Two block types in alternation:
|
||||
After the 7-byte preamble, the body's segment 0 carries Tran deltas
|
||||
via three block types:
|
||||
|
||||
- ``10 NN``: ``NN/2`` bytes of payload. Each byte = two 4-bit signed
|
||||
nibbles (high nibble first; 0..7 → 0..+7, 8..F → -8..-1). Each
|
||||
nibble is one Tran delta in 16-count units.
|
||||
nibble is one Tran delta in 16-count units (LSB = 0.005 in/s).
|
||||
|
||||
- ``20 NN``: ``NN`` bytes of payload. Each byte = one int8 signed delta
|
||||
in 16-count units.
|
||||
- ``20 NN``: ``NN`` bytes of payload. Each byte = one int8 signed
|
||||
delta in 16-count units. Used when deltas don't fit in 4 bits.
|
||||
|
||||
Verified against all 3 May-11 fixture events:
|
||||
- ``00 NN``: a 2-byte marker. Run-length-encoded zero deltas — append
|
||||
NN copies of the current cumulative Tran value (no change). Used
|
||||
heavily for silent stretches.
|
||||
|
||||
| Event | First block | # T samples decoded | Matches truth |
|
||||
Segment 0 ends at the first ``40 02`` segment header. Segment 0 typically
|
||||
covers ~510 sample-sets for events with mostly-quiet Tran, fewer for
|
||||
events with rapid Tran changes.
|
||||
|
||||
Verified against all bundled fixture events (5-8 and 5-11 bundles):
|
||||
|
||||
| Event | Tran character | Segment 0 size | Matches truth |
|
||||
|---|---|---|---|
|
||||
| SP0 | ``10 14`` (10 bytes / 20 nibbles) | 22 (= 2 preamble + 20 deltas) | 22/22 ✓ |
|
||||
| SS0 | ``10 28`` (20 bytes / 40 nibbles) | 42 | 42/42 ✓ |
|
||||
| SV0 | ``20 2c`` (44 int8 bytes) | 46 | 46/46 ✓ |
|
||||
| SP0 (loud all-channels, pretrig=0.25s) | small near sample 0 | 510 | 510/510 ✓ |
|
||||
| SS0 (loud-from-start) | big from sample 0 | 42* | 42/42 ✓ |
|
||||
| SV0 (loud-from-start) | big from sample 0 | 58* | 58/58 ✓ |
|
||||
| JQ0 (Vert-heavy) | near zero | 510 | 510/510 ✓ |
|
||||
| V70 (Mic-heavy) | near zero | 510 | 510/510 ✓ |
|
||||
|
||||
\* SS0 and SV0 decode stops early because their segment 0 contains
|
||||
``30 04`` blocks whose internal format hasn't been decoded yet (likely
|
||||
a channel-switch marker for the high-amplitude regime). The two events
|
||||
where the codec is most complex stop at the first ``30 04``.
|
||||
|
||||
Implementation: :func:`minimateplus.waveform_codec.decode_tran_initial`.
|
||||
|
||||
##### Segment header T-delta (PARTIAL 2026-05-11)
|
||||
|
||||
The 20-byte ``40 02`` segment header has its first 2 bytes ([0:2] of
|
||||
payload) as an int16 BE Tran delta for the first sample of the new
|
||||
segment. Verified across V70 (3 segments with 0 deltas) and SP0/JQ0
|
||||
(1 segment with +1 delta). Other bytes of the segment header payload
|
||||
are partially understood:
|
||||
|
||||
| Payload offset | Field | Status |
|
||||
|---|---|---|
|
||||
| [0:2] | T_delta at first sample of new segment (int16 BE) | ✅ confirmed |
|
||||
| [2:4] | unknown (often 0; not a simple V or T delta) | ❓ open |
|
||||
| [4:6] | unknown (varies per event; possibly a checksum) | ❓ open |
|
||||
| [6:8] | byte length to next segment header − 2 (uint16 BE) | ✅ confirmed |
|
||||
| [8:12] | monotonic uint32 LE counter | ✅ confirmed |
|
||||
| [12:14] | constant ``02 00`` | ✅ confirmed |
|
||||
| [14:18] | unknown 4-byte field | ❓ open |
|
||||
|
||||
Multi-segment Tran decoding diverges after sample ~512 — the per-segment
|
||||
channel ordering after the header is still unknown.
|
||||
|
||||
##### What's still open
|
||||
|
||||
- **Tran past the first data block.** After the first block, the
|
||||
|
||||
Reference in New Issue
Block a user