formats: XMA1 is not a WAVEFORMATEX -- audio info was reading three wrong fields

parse_riff_wave read every fmt chunk as a WAVEFORMATEX. XMA1 (tag 0x0165) is
not one, so audio info reported the disc s movie voices as 16 channels,
4310 Hz, 2-bit: 16 is wBitsPerSample read as a channel count and 4310 is
wEncodeOptions (0x10d6) read as a sample rate. This misled me earlier in the
session and I recorded it as a limitation before finding the cause.

XMA1 carries XMAWAVEFORMAT followed by one XMASTREAMFORMAT per stream. The
reader now branches on the tag and reads bits at +2, PsuedoBytesPerSec at +12,
SampleRate at +16 and Channels at +29. The same three files now report 2
channels, 48000 Hz, 16-bit.

The consequence worth having: this crate has no XMA decoder, and
data_bytes / PsuedoBytesPerSec is the only route to a duration. Checked against
durations decoded independently by the port:

  ADV presentation 1   137.34 s declared   137.324 s decoded   +0.012 percent
  ADV presentation 2   137.33 s declared   137.324 s decoded   +0.004 percent
  S00A presentation 1   93.71 s declared    93.694 s decoded   +0.017 percent

So the corpus can now get XMA1 durations off the disc without a decoder, which
is a capability I had written down as absent. It is a declared rate rather than
a measurement of the samples, and the CLI labels it as such.

Regression test pins the real on-disc header bytes and asserts the duration
against the independently decoded 137.324 s. 115 lib tests and 3 media disc
tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
This commit is contained in:
sylph-decoder
2026-08-29 15:42:52 +00:00
parent 9f34829776
commit a98a66190e
3 changed files with 147 additions and 13 deletions

View File

@@ -299,11 +299,42 @@ undermine it. What it touches is the *explanation*: "more bytes means a
duplicated channel, not better fidelity" is true of `ADV` and is **not** a fact
about the format. It should not harden into one.
⚠️ Note for anyone reading our own tooling: `sylpheed-cli audio info` reports
these chunks as *16 channels, 4310 Hz, 2-bit*. Those are the `wBitsPerSample`
(16), `wEncodeOptions` (`0x10d6` = 4310) and channel fields read at the wrong
offsets. The header above is the correct layout; the CLI's reader is misaligned
for XMA1 and should not be used on these.
### ✅ FIXED 2026-08-29 — and the disc will now tell you a duration without a decoder
`sylpheed-cli audio info` used to report these chunks as *16 channels, 4310 Hz,
2-bit*. The cause: `parse_riff_wave` read every `fmt ` chunk as a
`WAVEFORMATEX`, and **XMA1 is not one**. 16 is `wBitsPerSample` read as a channel
count; 4310 is `wEncodeOptions` (`0x10d6`) read as a sample rate.
XMA1 carries `XMAWAVEFORMAT` followed by one `XMASTREAMFORMAT` per stream, and
the reader now branches on the tag. Same three files:
```
Channels : 2 Sample rate: 48000 Hz Bit depth : 16-bit
Byte rate : 8142 B/s (declared)
Duration : 137.34 s (from the declared byte rate, not decoded)
```
✅ **The duration is the part that matters, because this crate has no XMA
decoder.** `data_bytes / PsuedoBytesPerSec` is the only route to one, and it was
checked against durations the port decoded independently:
| stream | declared-rate duration | independently decoded | error |
|---|---|---|---|
| `ADV` presentation 1 | 137.34 s | 137.324 s | **+0.012 %** |
| `ADV` presentation 2 | 137.33 s | 137.324 s | **+0.004 %** |
| `S00A` presentation 1 | 93.71 s | 93.694 s | **+0.017 %** |
⚠️ It is a *declared* rate, so this is the file's own claim about itself rather
than a measurement of the samples — but on the three streams where an independent
decode exists, the claim is accurate to 0.02 %. Regression test
`xma1_fmt_is_not_a_waveformatex` pins the real on-disc header bytes.
⚠️ **Retroactive note:** several statements earlier in this session said this
container could not obtain a duration for these streams. That was true of the
decoder and *not* of the file, which had been declaring it at `fmt +0x20` the
whole time. The tool was misreading it, and a broken tool reported as a missing
capability is worth more than the fix.
⚠️ **Do not "fix" it by concatenating.** The port measured a concatenated region
at 359 s against a 137 s movie.