Skip to content

Bitcrush: Use industry-standard quantization formula for signed audio#465

Open
gijzelaerr wants to merge 2 commits intospotify:masterfrom
gijzelaerr:fix/bitcrush-formula-396
Open

Bitcrush: Use industry-standard quantization formula for signed audio#465
gijzelaerr wants to merge 2 commits intospotify:masterfrom
gijzelaerr:fix/bitcrush-formula-396

Conversation

@gijzelaerr
Copy link
Copy Markdown
Member

@gijzelaerr gijzelaerr commented Mar 18, 2026

Summary

  • Fixes the BitCrush scale factor from pow(2, bitDepth) (unsigned) to pow(2, bitDepth - 1) (industry standard for signed audio)
  • The previous formula treated the range as unsigned, causing overscaling and clipping
  • The corrected formula maps audio to [-1.0, 0.9999...], matching FFmpeg, JUCE, and VST SDK conventions
  • Adds 6 new tests verifying quantization symmetry, output range, and level counts across bit depths

Closes #396
Supersedes #397

Test plan

  • test_output_is_quantized - output samples snap to discrete quantized levels (bit_depth 1, 2, 4, 8, 16)
  • test_bit_depth_8_output_range_signed - output stays in [-1, 1] with both positive and negative values
  • test_quantization_symmetric_around_zero - quantize(-x) == -quantize(x) (bit_depth 2, 4, 8, 16)
  • test_bit_depth_1_produces_few_levels - edge case for minimum useful bit depth
  • test_bit_depth_16_preserves_signal_closely - high bit depth produces near-lossless output
  • test_number_of_quantization_levels - distinct output levels match expected count

🤖 Generated with Claude Code

gijzelaerr and others added 2 commits March 18, 2026 12:11
…metry

The scale factor was `pow(2, bitDepth)` which doesn't properly center
quantization around zero for signed audio. Changed to
`pow(2, bitDepth - 1) + 1` so that the quantization is symmetric.

Added tests verifying quantization correctness, symmetry around zero,
output range for signed audio, edge cases (bit_depth=1 and 16), and
expected number of quantization levels.

Fixes spotify#396
Related: spotify#397

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous fix used pow(2, bitDepth - 1) + 1 which, while symmetric,
can cause the negative peak (-2^(n-1)) to exceed -1.0 and clip. The
industry standard (used by FFmpeg, JUCE, VST SDKs) is pow(2, bitDepth - 1)
which maps the range to [-1.0, 0.9999...], preserving full dynamic range
without risk of clipping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gijzelaerr gijzelaerr changed the title Bitcrush: fix quantization formula and add tests for signed audio symmetry Bitcrush: Use industry-standard quantization formula for signed audio Mar 18, 2026
@gijzelaerr
Copy link
Copy Markdown
Member Author

Note: The CI failures (Illegal instruction / SIGILL crash at import) are not caused by this PR. The crash is due to -march=native producing AVX instructions unsupported by some GitHub Actions runners. This is fixed by #466 — merging that PR first should resolve the CI failures here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrong formula used for BitCrush

1 participant