On Mon, Feb 22, 2016 at 2:59 PM, Ross Bencina <rossb-li...@audiomulch.com> wrote:
> Hi Kjetil, > > On 22/02/2016 11:52 PM, Kjetil Matheussen wrote: > >> I wonder if anyone has a tip for a C or C++ of an implementation of a >> Cubic interpolating resampler. I'm not asking about the algorithm >> itself, that is all covered (currently I'm using a Catmull-Rom spline >> algorithm, but that is not so important here). What I'm asking about >> is a framework for using the algorithm. >> > > It's hard to suggest a framwork out of thin air. One thing: it probably > doesn't matter what kind of interpolation you use. The interface is > concerned with samples in, samples out, current interpolation phase, > conversion ratio. Here's a few questions that come to mind: > > Thanks Ross. I'm sorry I didn't provide more information. I did actually answer all your questions, through code, but I guess it was quite arrogant of me not to explain the somewhat hairy interface. > * Fixed or variable rate conversion? (maybe the conversion rate is an > input vector too?) > > Variable rate conversion. > * Is the conversion rate expressed as a ratio of integers, or a floating > point phase increment? Where does the current "phase" get stored? It it > observable? Is it okay if the phase accumulator is subject to accumulating > floating point rounding errors? Does the caller need to be able to perform > a calculation to know exactly how many samples the converter will produce > for a given number of input samples? > > For my usage, I ask for 64 frames at the time, but this might change. The method looks like this: virtual int read(double ratio, int num_frames, float *out) = 0; // 'out' is interleaved multi channel data > * Related: Can/will the resampler be reliably used in a random-access > mode, or will it only be used in a streaming setting. > > Only streaming. > * Push vs pull vs supervised-synchronous interface? ("here's X input > samples, give me some output" vs. "here's some input, give me Y output > samples" vs. "here's M input samples, give me N output samples" ). > > Pull interface. There's a callback function supplied for the 'init' method in the interface. > * Does the caller supply enough previous/future input data to act as > source for interpolation, or does the interpolator need to save the last > few input samples to interpolate at buffer boundaries? (this determines > whether it's a stateful or stateless interpolator) > > The callback only supplies samples. The interpolator needs to save the last few input samples for next time. > * Even if the caller supplies all data, would the caller prefer to supply > discontinuous data ranges (e.g. split at block buffer boundaries). > * Interleaved/non-interleaved input? output? always interpolate all > channels? > > Interleaved, always interpolate all channels. > The interface will be constrained differently depending on which way each > of the above points is decided. I'm sure there are many other > considerations that I've missed. And of course your intended use-cases will > dictate some of these decisions. > > The interface is super versatile, so I would think that someone would have made a library or some code that does something like this. It's basically just a C++ wrapper around libsamplerate. The SincInterpolator (calling libsamplerate) looks like this: struct SincResampler : public Resampler{ SRC_STATE *_src_state; double _last_ratio; SincResampler(src_callback_t callback, int num_channels, void *arg, int type){ //_src_state = src_callback_new(callback, SRC_SINC_FASTEST, num_channels, NULL, arg); const static int typemap[]={SRC_ZERO_ORDER_HOLD,SRC_LINEAR,-1,SRC_SINC_FASTEST,SRC_SINC_BEST_QUALITY}; _src_state = src_callback_new(callback, typemap[type], num_channels, NULL, arg); _last_ratio = -1.0; } ~SincResampler(){ src_delete(_src_state); } int read(double ratio,int num_frames, float *out){ if(_last_ratio != ratio){ if(_last_ratio >= 0.0) src_set_ratio(_src_state, ratio); _last_ratio = ratio; } int ret = src_callback_read(_src_state, ratio, num_frames, out); if(ret==0){ if(src_error(_src_state)!=0) printf("Error? %d: \"%s\". ratio: %f\n", src_error(_src_state), src_strerror(src_error(_src_state)), ratio); return 0; }else return ret; } void reset(){ src_reset(_src_state); } }; But I need a cubic interpolator (or something else with the same type of performance/quality ratio). libsamperate doesn't have a cubic interpolator.
_______________________________________________ dupswapdrop: music-dsp mailing list music-dsp@music.columbia.edu https://lists.columbia.edu/mailman/listinfo/music-dsp