Note: This is a fork of the original python-samplerate maintained by the LedFx team.
Why this fork exists:
- The original python-samplerate project is sporadically active
- We need Python 3.14 support with pre-built wheels on PyPI
- We require the latest fixes and improvements from the main branch of python-samplerate
- LedFx depends on python-samplerate and needs a reliable, up-to-date release
All credit for python-samplerate goes to the original authors. This fork exists solely to provide maintained releases for projects that depend on python-samplerate.
Original project:https://github.com/tuxu/python-samplerate
This fork:https://github.com/LedFx/python-samplerate-ledfx
This is a wrapper around Erik de Castro Lopo's libsamplerate (aka Secret Rabbit Code) for high-quality sample rate conversion.
It implements all three APIs available in libsamplerate:
- Simple API: for resampling a large chunk of data with a single library call
- Full API: for obtaining the resampled signal from successive chunks of data
- Callback API: like Full API, but input samples are provided by a callback function
The libsamplerate library is statically built together with the python bindings using pybind11.
$ pip install samplerate-ledfx
Binary wheels of samplerate-ledfx are available. A C++ 14 or above compiler is required to build the package.
importnumpyasnpimportsamplerate# Synthesize datafs=1000.t=np.arange(fs*2) /fsinput_data=np.sin(2*np.pi*5*t)
# Simple APIratio=1.5converter='sinc_best'# or 'sinc_fastest', ...output_data_simple=samplerate.resample(input_data, ratio, converter)
# Full APIresampler=samplerate.Resampler(converter, channels=1)
output_data_full=resampler.process(input_data, ratio, end_of_input=True)
# The result is the same for both APIs.assertnp.allclose(output_data_simple, output_data_full)
# See `samplerate.CallbackResampler` for the Callback API, or# `examples/play_modulation.py` for an example.# Callback API Exampledefproducer():
# Generate data in chunksforiinrange(10):
yieldnp.random.uniform(-1, 1, 1024).astype(np.float32)
yieldNone# Signal end of streamdata_iter=producer()
callback=lambda: next(data_iter)
resampler=samplerate.CallbackResampler(callback, ratio, converter)
output_chunks= []
whileTrue:
# Read chunks of resampled datachunk=resampler.read(512) ifchunk.shape[0] ==0:
breakoutput_chunks.append(chunk)To get the maximum performance from samplerate:
- Use
np.float32: The underlyinglibsampleratelibrary operates on 32-bit floats. Passingnp.float64(default numpy float) or integer arrays triggers an implicit copy and cast, which can be expensive.# Fast (no copy)data=np.zeros(1000, dtype=np.float32) samplerate.resample(data, 1.5) # Slower (implicit copy + cast)data=np.zeros(1000, dtype=np.float64) samplerate.resample(data, 1.5)
- Use C-Contiguous Arrays: Ensure your input arrays are C-contiguous (row-major). Non-contiguous arrays (e.g., column slices) will also trigger a copy.
- Adjust GIL Threshold: If you are processing many small chunks in a multi-threaded application, the default "auto" GIL release threshold (1000 frames) might be too high or too low. You can tune it:
# Release GIL even for small chunks (e.g. > 100 frames)samplerate.set_gil_release_threshold(100)
All resampling methods support a release_gil parameter that controls Python's Global Interpreter Lock (GIL) during resampling operations. This is useful for optimizing performance in different scenarios:
importsamplerate# Default: "auto" mode - releases GIL only for large data (>= 1000 frames)# Balances single-threaded performance with multi-threading capability# The threshold is configurable: samplerate.set_gil_release_threshold(2000)output=samplerate.resample(input_data, ratio)
# Force GIL release - best for multi-threaded applications# Allows other Python threads to run during resamplingoutput=samplerate.resample(input_data, ratio, release_gil=True)
# Disable GIL release - best for single-threaded applications with small data# Avoids the ~1-5µs overhead of GIL release/acquireoutput=samplerate.resample(input_data, ratio, release_gil=False)The same parameter is available on Resampler.process() and CallbackResampler.read():
resampler=samplerate.Resampler('sinc_best', channels=1)
output=resampler.process(input_data, ratio, release_gil=True)- scikits.samplerate implements only the Simple API and uses Cython for extern calls. The resample function of scikits.samplerate and this package share the same function signature for compatiblity.
- resampy: sample rate conversion in Python + Cython.
This project is licensed under the MIT license.
As of version 0.1.9, libsamplerate is licensed under the 2-clause BSD license.