After a lot of reading and head-scratching, I'm trying to write a sample playback engine using windowed sinc interpolation. When I pass integer values into my "interp(playhead)" function, everything is hunky-dory. But when I pass fractional values I get hideous ringing and the interpolated values are WAY off.
First off, I populate a table with the right-hand wing of a sinc function. I then multiply this table with the right-hand wing of a windowing function (Blackman-Harris in my case). I'm pretty damn sure that I'm populating and windowing my table correctly. There are (SINC_POINTS + 1) lobes in it.
Here is my naive implementation so far:
Code: Select all
#define SINC_RES 512 // resolution of each lobe of the sinc table
#define SINC_POINTS 16 // number of samples to use for interpolation
// on either side of the sample in question
float interp(double playhead) {
long playheadint = floor(playhead);
double playheadfrac = playhead - playheadint;
double accum = 0.0;
// Loop through every sample we're interested in...
int i;
for(i = -SINC_POINTS; i < SINC_POINTS + 1; i ++) {
long thissample = playheadint + i;
// HACK: To handle start and end points,
// we just duplicate the start and end samples.
// POSSIBLE FIX: mirror start/end of input?
if(thissample < 0) thissample = 0;
if(thissample >= frames) thissample = frames - 1;
double moo = input[thissample];
// Get index into sinc table
long sincindex = round(playheadfrac * SINC_RES);
// Offset index relative to centre sample
sincindex += abs(i) * SINC_RES;
moo *= sinctable[sincindex];
accum += moo;
}
return (float)accum;
}
Thanks for looking,
Chris