Skip to content

Instantly share code, notes, and snippets.

@kode54
Created April 17, 2014 06:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kode54/10956504 to your computer and use it in GitHub Desktop.
Save kode54/10956504 to your computer and use it in GitHub Desktop.
Add-on for my resampler.c, which adds a sinc coefficient set generator, producing the minimum number of phases against the pre-generated sinc table, for either upsampling or downsampling.
short * resampler_generate_phase_set(double ratio, int * count)
{
int phase_inc;
int j;
int phase;
short * phases, * phase_ptr;
int step, window_step;
// determine number of sub-phases that yield lowest error
const int max_res = RESAMPLER_RESOLUTION;
double ratio_ = 0.0;
int res = -1;
{
double least_error = 2;
double pos = 0;
int r;
for ( r = 1; r <= max_res; r++ )
{
pos += ratio;
double nearest = floor( pos + 0.5 );
double error = fabs( pos - nearest );
if ( error < least_error )
{
res = r;
ratio_ = nearest / res;
least_error = error;
}
}
}
phases = (short *) malloc(res * (SINC_WIDTH * 2 + 2) * sizeof(short));
if ( !phases )
return 0;
phase_ptr = phases;
phase_inc = (int)(ratio_ * RESAMPLER_RESOLUTION);
step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION;
window_step = RESAMPLER_RESOLUTION;
for (phase = 0, j = 0; j < res; ++j)
{
float kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
int i = SINC_WIDTH;
int phase_adj = phase * step / RESAMPLER_RESOLUTION;
for (; i >= -SINC_WIDTH + 1; --i)
{
int pos = i * step;
int window_pos = i * window_step;
kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase - window_pos)];
}
kernel_sum = (1.0 / kernel_sum) * 32768.0;
for (i = 0; i < SINC_WIDTH * 2; ++i)
*phase_ptr++ = (short)(int)(kernel[i] * kernel_sum);
phase += phase_inc;
i = phase >> RESAMPLER_SHIFT;
phase &= RESAMPLER_RESOLUTION - 1;
*phase_ptr++ = (short)((i - SINC_WIDTH * 2) * sizeof(short));
*phase_ptr++ = sizeof(short) * 4;
}
phase_ptr[-1] -= (short)(int)((char *)phase_ptr - (char *)phases);
*count = res;
return phases;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment