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

Reply via email to