Repository navigation
stb_vorbis: fix type-2 residue decoding for multichannel audio - #2023
Closed
ohxiaoguang wants to merge 1 commit into
Closed
ohxiaoguang wants to merge 1 commit into
ohxiaoguang wants to merge 1 commit into
Conversation
Use the participating channel count for type-2 interleaving and include the full channel bound in the advertised scratch-memory requirement. Add synthetic heap/arena and pull/push regression coverage.
Owner
How do you figure that? |
Author
I felt this bug was important enough to report and propose a fix. Although I used AI assistance, the resulting changes are straightforward and easy to understand and review. That's why I decided to submit the PR. I understand and respect the project's policy and your decision. |
Owner
|
AI |
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.
Problem
The type-2 residue decoder clamps the interleaved vector to
n*2, even when more than two channels participate. This truncates residue decoding and desynchronizes subsequent codebook reads, producing severe distortion in 5.1 streams.Vorbis I section 8.5 defines the type-2 vector as
n*ch, wherechis the number of channels in the current submap: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.htmlFix
decode_residue().start_decoder(). The stream channel count is a conservative upper bound for any submap. This is necessary for caller-owned allocation buffers: changing only the decoding length causes the new synthetic six-channel test to fail with insufficient scratch memory.make -C tests test_vorbis_multichanneltarget. No external encoder or audio fixtures are required.The scratch-space change is related to #1487 and the closed, unmerged #1889, but accounts for arbitrary supported channel counts rather than assuming stereo. Types 0 and 1 retain their existing bounds. Muted channels retain their positions in type-2 interleaving.
Reproduction and validation
Both six-channel inputs (
test1.ogg,test2.ogg) attached to #1594 reproduce the failure on unmodified master, and decode correctly with this patch. Each input has 2,660,352 frames at 48 kHz. Full-stream float32 comparisons against FFmpeg 9.0.2 use the appropriate Vorbis-to-FFmpeg channel permutation, with zero sample offset and no head/tail trimming, gain adjustment, or filtering. Both outputs contain the same frame count as the reference.Float RMS error is at most 2.19e-8 per channel after the fix. PCM16 figures apply the same rounding and saturation to both float outputs. The two rear channels in these public files are silent; the synthetic test separately checks every channel's residue coefficients.
Tests run on Apple Silicon with Apple Clang 21:
STB_VORBIS_DIVIDES_IN_RESIDUEbuilds pass ASan/UBSan: 192 configuration/API/allocation combinations in total. Partial/all-channel skip paths are checked directly.inlinemacro adapted via-Dinline=__inline__, including-Werror=declaration-after-statement.Earlier, separate nxnative testing reproduced this problem in Link's Awakening's 5.1 Vorbis movie audio. The patched macOS build was verified by listening; its three tested movie tracks were within one PCM16 unit of FFmpeg. That earlier game verification is distinct from the new upstream/public-fixture tests above. iOS device audio has not been verified. No commercial assets or public audio attachments are included in this PR.
Fixes #1594.
Related to #879: no public input was available for independent reproduction, so this PR does not claim to establish the same root cause or close that issue.
Disclosure: AI tools assisted with the implementation, synthetic regression test, numerical analysis, and this PR description. This disclosure does not imply an exception to the repository's contribution policy.