Skip to content

Conversation

roderickvd
Copy link
Member

This PR corrects the way HighPass dithering works with stereo or multi-channel audio, that I should have caught in the first place. Throwing a couple of other things in while at it.

Problem

The HighPass dither uses Blue noise, which is a high-pass filtered noise (white - prev_white). The problem was that in any audio beyond mono, we only had a single Blue noise generator. This meant the prev_white state was leaking across channel boundaries. This broke the high-pass filter characteristic and created correlation between channels.

Solution

Now HighPass dither creates per-channel generators with independent RNG seeds, so each channel maintains its own prev_white state. The other algorithms don't need this since they're stateless.

The implementation also handles dynamic channel count and sample rate changes at span boundaries.

Other improvements

  • Changed LSB amplitude calculation to use f64 intermediate precision to avoid overflow and precision loss. This makes the code more practical and correct for even the most theoretical of audio bit depths.

  • Added size_hint() and ExactSizeIterator implementation for Dither.

Fixes a bug where HighPass dithering incorrectly shared filter state
across channels in multi-channel audio. The Blue noise generator uses
prev_white state for high-pass filtering (white - prev_white), but in
interleaved audio (L, R, L, R...), this state was crossing channel
boundaries, breaking the filter characteristic and creating inter-channel
correlation.

Additionally fixes LSB amplitude calculation that incorrectly used
f32::MIN_POSITIVE for bit depths >= 24, making dither ineffective.
@roderickvd roderickvd added the bug label Oct 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant