ReSinc is a lightweight, real-time safe, header-only C++ library for audio oversampling and asynchronous resampling.
It is designed for real-time audio applications (like VST/AU plugins) where running non-linear processes (distortion, saturation, compression) at a higher sample rate is necessary to prevent aliasing artifacts. The library uses a pre-calculated, windowed Sinc filter for high-fidelity interpolation and decimation.
- Real-Time Safe: All memory is pre-allocated during configuration. Processing functions are guaranteed not to allocate heap memory, lock, or block.
- Flexible I/O: Supports multiple data formats directly:
- Standard Containers:
std::vector<float>,std::vector<std::vector<float>>,std::array. - JUCE Framework: Directly accepts
juce::AudioBuffer<float>/juce::AudioBuffer<double>. - Raw Pointers: Standard
float**arrays.
- Standard Containers:
- High-Quality: Uses a Kaiser-windowed Sinc filter for near-perfect reconstruction.
- Header-Only: Single file
ReSinc.hpp. No linking required.
The Oversampler is optimized for fixed integer-ratio upsampling (2x, 4x, etc.). It is the ideal choice for internal DSP effects.
// <TYPE, OVERSAMPLE_FACTOR, SINC_RADIUS>
Oversampler<float, 4, 32> oversampler;
void setup() {
oversampler.configure(44100.0f, 2, 512);
}
void process(std::vector<std::vector<float>>& buffer) {
oversampler.interpolate(buffer); // Input -> 4x Internal Buffer
oversampler.process([&](std::vector<std::vector<float>>& upsampled) {
// High-rate processing happens here
});
oversampler.decimate(buffer); // 4x Internal Buffer -> Output
}The Resampler handles asynchronous rate conversion where the ratio is not an integer (e.g., converting a 48kHz file for 44.1kHz playback).
// <TYPE, SINC_RADIUS, PHASE_RESOLUTION>
Resampler<float, 32, 256> resampler;
void setup() {
// 48kHz -> 44.1kHz
resampler.configure(48000.0f, 44100.0f, 2, 512);
}
void process(std::vector<std::vector<float>>& input,
std::vector<std::vector<float>>& output) {
// Returns the actual number of output samples produced
int produced = resampler.resample(input, output);
}For offline processing, asset loading, or scenarios where you do not need to maintain history between blocks, use the global resample() functions. These are "one-shot" and treat the boundaries of the input as silence (zero-padding).
#include "ReSinc.hpp"
void convertAsset() {
std::vector<std::vector<double>> inputVec = /* ... */;
std::vector<std::vector<double>> outputVec = /* ... */;
// Perform a one-shot conversion
// <TYPE, SINC_RADIUS, PHASE_RESOLUTION>
int produced = resample<double, 32, 256>(inputVec, outputVec, 48000.0, 44100.0);
}The stateless functions re-calculate the Sinc filter table on every call. For repeated real-time block processing, the Resampler or Oversampler classes are significantly more efficient.
This library uses linear-phase (symmetric) filters.
- Oversampler Latency:
2 * SINC_RADIUS(input samples). - Resampler Latency:
SINC_RADIUS(input samples). - Stateless: No class-based latency, but boundaries are zero-padded.
To maintain perfect alignment in a DAW, you must report these values to the host for Latency Compensation.
This is a header-only library.
-
Copy
include/ReSinc.hppto your project. -
#include "ReSinc.hpp" -
Compile with C++17 or higher.
-
(Optional) For best performance, enable SIMD/Vectorization flags (
-O3 -march=native).
This project is licensed under the MIT License. See the LICENSE file for details.