Skip to content

Replace linear interpolation with libsoxr for high-quality audio resampling#38

Merged
ssarunic merged 7 commits intomainfrom
claude/fix-resampling-quality-Q03MF
Mar 11, 2026
Merged

Replace linear interpolation with libsoxr for high-quality audio resampling#38
ssarunic merged 7 commits intomainfrom
claude/fix-resampling-quality-Q03MF

Conversation

@ssarunic
Copy link
Owner

Summary

Replace the naive linear interpolation resampling in AudioBuffer with libsoxr's polyphase resampling filter. This eliminates spectral aliasing that occurs when downsampling (e.g., 48 kHz → 16 kHz) and provides configurable quality profiles for different use cases.

Changes

  • Audio resampling: Replaced np.interp() with soxr.resample() in AudioBuffer._resample_if_needed() to use anti-aliased polyphase resampling instead of linear interpolation
  • Quality profiles: Added configurable resampling quality via resample_quality parameter with three profiles:
    • "fast" (MQ): Low CPU, suitable for telephony-grade input
    • "balanced" (HQ): Good default for real-time paths
    • "high" (VHQ): Broadcast quality, higher CPU cost
  • Configuration: Added resample_quality to SessionConfig and AudioBuffer.__init__(), with environment variable support (DALSTON_REALTIME_RESAMPLE_QUALITY)
  • Metrics: Added observe_realtime_resample_duration() to track resampling performance with labels for source/target sample rates
  • Validation: Added parameter validation in RealtimeSession to ensure resample_quality is one of the supported profiles
  • Dependencies: Added soxr>=0.3.0 to pyproject.toml

Testing

  • Added comprehensive unit tests in tests/unit/test_realtime_audio_buffer.py:
    • Verify no-op when sample rates match
    • Confirm low-frequency content is preserved across downsampling
    • Verify above-Nyquist content is properly attenuated (anti-aliasing works)
    • Test upsampling output length
    • Parametrized tests for all quality profiles
    • Fallback behavior for unknown profiles
  • All tests pass locally with pytest

Related Issues

Resolves the TODO comment about replacing linear interpolation with proper polyphase resampling to avoid spectral aliasing in downsampling scenarios.

https://claude.ai/code/session_017AKfpaH2v1TG2oxCo4dVSp

claude and others added 7 commits March 11, 2026 08:44
…ality

The previous np.interp-based resampling caused spectral aliasing when
downsampling (e.g. 48 kHz → 16 kHz client audio to worker rate), degrading
transcription accuracy. Replace with libsoxr which applies a proper
anti-aliasing low-pass filter and polyphase resampling.

- Add soxr>=0.3.0 dependency to realtime-sdk
- Use soxr.resample() with HQ quality preset in AudioBuffer._resample_if_needed
- Add unit tests verifying alias attenuation and frequency preservation

https://claude.ai/code/session_017AKfpaH2v1TG2oxCo4dVSp
- Add configurable resample_quality parameter ("fast", "balanced", "high")
  mapping to soxr MQ/HQ/VHQ presets for CPU/latency tradeoff control
- Wire through SessionConfig, AudioBuffer, and connection params parsing
- Add DALSTON_REALTIME_RESAMPLE_QUALITY env var for server-wide default
- Add dalston_realtime_resample_duration_seconds histogram metric to
  track resampler latency per sample-rate conversion path
- Add parametrized tests verifying all profiles attenuate aliases and
  preserve in-band content

https://claude.ai/code/session_017AKfpaH2v1TG2oxCo4dVSp
- Migrate LiteProfile from (str, Enum) to StrEnum (ruff UP042)
- Use `import alembic.command` instead of `from alembic import command` (mypy attr-defined)

https://claude.ai/code/session_017AKfpaH2v1TG2oxCo4dVSp
The specific type: ignore[misc,assignment] was not being recognized by
CI's mypy version. Use unqualified type: ignore for the Redis fallback.
- Move soxr import from module level to _resample_if_needed() so tests
  that transitively import session.py don't fail when soxr isn't installed
  (it's in the realtime-sdk extra, not dev)
- Fix ruff format in base.py (long line wrapping)
soxr is in the realtime-sdk extra, not dev. Mark the entire test module
as skip when soxr is unavailable so CI tests pass.
soxr is needed to run resampling tests in CI. Add it to the dev extra
rather than skipping the tests when it's missing.
@ssarunic ssarunic merged commit 16eb900 into main Mar 11, 2026
6 checks passed
@ssarunic ssarunic deleted the claude/fix-resampling-quality-Q03MF branch March 11, 2026 14:08
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.

2 participants