# DTS core decoded nothing from streams other encoders wrote - #201
Merged
Conversation
Every libavcodec-encoded core stream came back empty. The per-channel arrays holding the sample code-book selector and the scale-factor adjustment were sized to the ten code-book groups, but the subframe header allows a bit-allocation index up to 26, so the first wide-band subband indexed past the end and the frame was abandoned. Our own encoder only ever writes small indices, which is why nothing caught it. Behind that sat three more faults, each of which the reader had been hiding: - The QMF synthesis fed the filterbank a half-IMDCT with the wrong modulation phase, so a 997 Hz tone came out as full-amplitude images at 2.0, 2.5 and 3.5 kHz. The stage is the second half of a 64-point IMDCT over the 32 subband values; the kernel now says so. - The filterbank output was left in the subband domain instead of being scaled to the +/-1 range the caller quantizes from, so every sample clipped. - The quantizer step sizes were stored as short decimals. The finest six steps are 0.14 percent away from the values the format defines, which put a level error on anything coded at high resolution; they are now the exact Q22 integers. - The LFE interpolation FIR reaches back past the first decimated sample of a frame, but the buffer was cleared each frame, restarting the filter from silence once per frame. Decoded PCM now comes out in the ITU/WAVE interleave order rather than the bit stream's centre-first AMODE order. Verified against ffmpeg n9.0.1 over 44 streams (mono through 5.1, 32/44.1/48 kHz, 384-1411 kbit/s, tones, noise, chirps, squares, transients, silence): all decode at full length, no sample differs by more than one LSB, and 99 to 100 percent of samples are identical.
Hawkynt
force-pushed
the
fix/dts-sync
branch
from
September 6, 2026 15:45
3265799 to
18c34d4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every libavcodec DTS stream returned zero bytes — 14 of 14. Our own encoder's output decoded, which is why nothing caught it.
Faults
The one that returned nothing:
DtsFrameDecodersized the code-book-selector and scale-factor-adjust arrays at 11 — the number of code-book groups — while the subframe header allows a bit-allocation index up to 26. The first wide-band subband indexed past the end and the frame was abandoned. That single bound was the entire symptom.Behind it, three more, none of which could surface while the decoder returned nothing:
0.00008against336/2²²). That was exactly the 1.00136 level error measured before the cause was found.Output is also now in ITU/WAVE channel order rather than the bit stream's own.
Measured, against ffmpeg's decode of the same bytes
Tests
DtsForeignStreamTestsembeds ffmpeg-produced streams and ffmpeg's decode of them, asserting sample by sample. Five original faults were re-introduced one at a time and each is caught: theabitsarray size, the IMDCT phase, the quantiser step table, the channel map, and the LFE history.45 passed, 0 failed for
~Dts. Full suite on the source tree: 29030 passed, 0 failed, 1355 skipped.Flagged, not fixed
Joint-intensity coding is parsed but not reconstructed, and the
DYNFdynamic-range byte is not skipped — a latent desync on any stream that sets it. Neither is exercised by ffmpeg-encoded material, so both were left alone rather than changed on speculation.DtsCodec's doc claimed it was "a faithful managed port of the FFmpeg reference decoder" without the vendoring records AGENTS.md requires; the wording is corrected in the files touched here.DtsCodec.Encodestill carries a similar claim aboutdcaenc.cand deserves the same look.