High quality, one-dimensional sample-rate conversion library for Python
npx @tessl/cli install tessl/pypi-soxr@0.5.0High quality, one-dimensional sample-rate conversion library for Python. Python-SoXR is a Python wrapper around libsoxr, providing both batch processing and streaming capabilities for audio resampling with exceptional quality and performance.
pip install soxrimport soxrimport soxr
import numpy as np
# Create sample audio data (1 second at 44.1 kHz)
x = np.random.randn(44100).astype(np.float32)
# Batch resampling from 44.1 kHz to 16 kHz
y = soxr.resample(x, 44100, 16000)
# For streaming (real-time or very long signals)
resampler = soxr.ResampleStream(44100, 16000, 1, dtype='float32')
# Process chunks
chunk_size = 1024
for i in range(0, len(x), chunk_size):
chunk = x[i:i+chunk_size]
is_last = (i + chunk_size) >= len(x)
resampled_chunk = resampler.resample_chunk(chunk, last=is_last)
# Process resampled_chunk...High-quality resampling for complete signals using the resample() function.
def resample(x: ArrayLike, in_rate: float, out_rate: float, quality: Union[str, int] = 'HQ') -> np.ndarray:
"""
Resample signal using high-quality libsoxr algorithm.
Parameters:
- x: Input array (1D mono or 2D multi-channel [frame, channel])
- in_rate: Input sample rate in Hz
- out_rate: Output sample rate in Hz
- quality: Quality setting - 'QQ', 'LQ', 'MQ', 'HQ', 'VHQ' or constants (default: 'HQ')
Returns:
np.ndarray with same dtype and ndim as input
"""def _resample_oneshot(x: np.ndarray, in_rate: float, out_rate: float, quality: Union[str, int] = 'HQ') -> np.ndarray:
"""
Internal one-shot resampling using libsoxr's soxr_oneshot().
Note: For testing purposes. Becomes slow with long inputs. Use resample() for general use.
Parameters:
- x: Input numpy array
- in_rate: Input sample rate in Hz
- out_rate: Output sample rate in Hz
- quality: Quality setting - 'QQ', 'LQ', 'MQ', 'HQ', 'VHQ' or constants
Returns:
np.ndarray with resampled data
"""Real-time resampling using the ResampleStream class for processing long signals or real-time audio.
class ResampleStream:
"""Streaming resampler for real-time processing or very long signals."""
def __init__(self, in_rate: float, out_rate: float, num_channels: int,
dtype: str = 'float32', quality: Union[str, int] = 'HQ'):
"""
Initialize streaming resampler.
Parameters:
- in_rate: Input sample rate in Hz
- out_rate: Output sample rate in Hz
- num_channels: Number of audio channels
- dtype: Data type - 'float32', 'float64', 'int16', 'int32'
- quality: Quality setting - 'QQ', 'LQ', 'MQ', 'HQ', 'VHQ' or constants
"""
def resample_chunk(self, x: np.ndarray, last: bool = False) -> np.ndarray:
"""
Resample audio chunk.
Parameters:
- x: Input chunk (1D mono or 2D multi-channel [frame, channel])
- last: True for final chunk to flush remaining output
Returns:
np.ndarray with resampled chunk
"""
def num_clips(self) -> int:
"""
Get clip counter for integer I/O.
Returns:
Count of clipped samples
"""
def delay(self) -> float:
"""
Get current algorithmic delay.
Returns:
Current delay in output samples
"""
def clear(self) -> None:
"""Reset resampler state for fresh signal with same configuration."""
def engine(self) -> str:
"""
Get the resampler engine name.
Returns:
Name of the resampling engine being used
"""Pre-defined quality settings for different speed/quality trade-offs.
QQ: int # Quick and dirty - lowest quality, fastest
LQ: int # Low quality
MQ: int # Medium quality
HQ: int # High quality (default)
VHQ: int # Very high quality - best quality, slowestLow-level data type constants from the soxr_ext module.
from soxr import soxr_ext
# Internal data type constants (advanced use)
soxr_ext.SOXR_FLOAT32_I: int # Float32 interleaved
soxr_ext.SOXR_FLOAT64_I: int # Float64 interleaved
soxr_ext.SOXR_INT32_I: int # Int32 interleaved
soxr_ext.SOXR_INT16_I: int # Int16 interleavedPackage and library version information.
__version__: str # Package version
__libsoxr_version__: str # Underlying libsoxr versionfrom typing import Union, Literal
from numpy.typing import ArrayLike
import numpy as np
# Supported data types for resampling
SupportedDType = Literal['float32', 'float64', 'int16', 'int32']
# Quality settings
QualitySetting = Union[Literal['QQ', 'LQ', 'MQ', 'HQ', 'VHQ'], int]import soxr
import numpy as np
# Load 48 kHz audio data
audio_48k = np.random.randn(480000).astype(np.float32)
# Convert to CD quality (44.1 kHz) with very high quality
audio_44k = soxr.resample(audio_48k, 48000, 44100, quality='VHQ')
print(f"Original: {len(audio_48k)} samples at 48 kHz")
print(f"Resampled: {len(audio_44k)} samples at 44.1 kHz")import soxr
import numpy as np
# Setup for stereo streaming: 44.1 kHz -> 16 kHz
channels = 2
resampler = soxr.ResampleStream(44100, 16000, channels, dtype='float32', quality='HQ')
# Simulate streaming chunks
chunk_size = 4410 # 100ms at 44.1 kHz
total_samples = 44100 # 1 second
for i in range(0, total_samples, chunk_size):
# Create stereo chunk [frames, channels]
chunk = np.random.randn(min(chunk_size, total_samples - i), channels).astype(np.float32)
is_last = (i + chunk_size) >= total_samples
# Resample chunk
resampled = resampler.resample_chunk(chunk, last=is_last)
print(f"Chunk {i//chunk_size + 1}: {chunk.shape} -> {resampled.shape}")
# Process resampled audio...
if is_last:
break
# Check for any clipping (when using integer types)
print(f"Clipped samples: {resampler.num_clips()}")import soxr
import numpy as np
# Float32 (default, recommended for most uses)
x_f32 = np.random.randn(44100).astype(np.float32)
y_f32 = soxr.resample(x_f32, 44100, 22050)
# Float64 (higher precision)
x_f64 = np.random.randn(44100).astype(np.float64)
y_f64 = soxr.resample(x_f64, 44100, 22050)
# Int16 (16-bit integer, common in audio)
x_i16 = (np.random.randn(44100) * 32767).astype(np.int16)
y_i16 = soxr.resample(x_i16, 44100, 22050)
# Int32 (32-bit integer)
x_i32 = (np.random.randn(44100) * 2147483647).astype(np.int32)
y_i32 = soxr.resample(x_i32, 44100, 22050)
print("All data types preserve input dtype in output")Common errors and their causes:
import soxr
import numpy as np
try:
# This will raise ValueError for negative sample rate
soxr.resample(np.array([1, 2, 3]), -44100, 16000)
except ValueError as e:
print(f"Invalid parameters: {e}")
try:
# This will raise TypeError for unsupported dtype
soxr.resample(np.array([1, 2, 3], dtype=np.int8), 44100, 16000)
except TypeError as e:
print(f"Unsupported data type: {e}")