Rework of sample rate conversion by using linear interpolation

This commit is contained in:
Andreas Eversberg
2017-02-05 13:16:39 +01:00
parent 47f74b38ce
commit 4c0f8e7e95
2 changed files with 40 additions and 12 deletions

View File

@@ -25,8 +25,6 @@
#include "sample.h" #include "sample.h"
#include "samplerate.h" #include "samplerate.h"
/* NOTE: This is quick and dirtry. */
int init_samplerate(samplerate_t *state, double samplerate) int init_samplerate(samplerate_t *state, double samplerate)
{ {
#if 0 #if 0
@@ -38,8 +36,8 @@ int init_samplerate(samplerate_t *state, double samplerate)
memset(state, 0, sizeof(*state)); memset(state, 0, sizeof(*state));
state->factor = samplerate / 8000.0; state->factor = samplerate / 8000.0;
filter_lowpass_init(&state->up.lp, 4000.0, samplerate, 1); filter_lowpass_init(&state->up.lp, 3300.0, samplerate, 2);
filter_lowpass_init(&state->down.lp, 4000.0, samplerate, 1); filter_lowpass_init(&state->down.lp, 3300.0, samplerate, 2);
return 0; return 0;
} }
@@ -48,11 +46,16 @@ int init_samplerate(samplerate_t *state, double samplerate)
int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num) int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num)
{ {
int output_num = 0, i, idx; int output_num = 0, i, idx;
double factor = state->factor, in_index; double factor = state->factor, in_index, diff;
sample_t output[(int)((double)input_num / factor + 0.5) + 10]; /* add some safety */
sample_t last_sample;
/* filter down */ /* filter down */
filter_process(&state->down.lp, samples, input_num); filter_process(&state->down.lp, samples, input_num);
/* get last sample for interpolation */
last_sample = state->down.last_sample;
/* resample filtered result */ /* resample filtered result */
in_index = state->down.in_index; in_index = state->down.in_index;
@@ -62,14 +65,22 @@ int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num)
/* if index is outside input sample range, we are done */ /* if index is outside input sample range, we are done */
if (idx >= input_num) if (idx >= input_num)
break; break;
/* copy value from input to output */ /* linear interpolation */
samples[i] = samples[idx]; diff = in_index - (double)idx;
if (idx)
output[i] = samples[idx - 1] * (1.0 - diff) + samples[idx] * diff;
else
output[i] = last_sample * (1.0 - diff) + samples[idx] * diff;
/* count output number */ /* count output number */
output_num++; output_num++;
/* increment input index */ /* increment input index */
in_index += factor; in_index += factor;
} }
/* store last sample for interpolation */
if (input_num)
state->down.last_sample = samples[input_num - 1];
/* remove number of input samples from index */ /* remove number of input samples from index */
in_index -= (double)input_num; in_index -= (double)input_num;
/* in_index cannot be negative, excpet due to rounding error, so... */ /* in_index cannot be negative, excpet due to rounding error, so... */
@@ -78,6 +89,10 @@ int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num)
state->down.in_index = in_index; state->down.in_index = in_index;
/* copy samples */
for (i = 0; i < output_num; i++)
*samples++ = output[i];
return output_num; return output_num;
} }
@@ -85,9 +100,12 @@ int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num)
int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sample_t *output) int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sample_t *output)
{ {
int output_num = 0, i, idx; int output_num = 0, i, idx;
double factor = 1.0 / state->factor, in_index; double factor = 1.0 / state->factor, in_index, diff;
sample_t buff[(int)((double)input_num / factor + 0.5) + 10]; /* add some fafety */ sample_t buff[(int)((double)input_num / factor + 0.5) + 10]; /* add some safety */
sample_t *samples; sample_t *samples, last_sample;
/* get last sample for interpolation */
last_sample = state->up.last_sample;
if (input == output) if (input == output)
samples = buff; samples = buff;
@@ -103,14 +121,22 @@ int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sam
/* if index is outside input sample range, we are done */ /* if index is outside input sample range, we are done */
if (idx >= input_num) if (idx >= input_num)
break; break;
/* copy value */ /* linear interpolation */
samples[i] = input[idx]; diff = in_index - (double)idx;
if (idx)
samples[i] = input[idx - 1] * (1.0 - diff) + input[idx] * diff;
else
samples[i] = last_sample * (1.0 - diff) + input[idx] * diff;
/* count output number */ /* count output number */
output_num++; output_num++;
/* increment input index */ /* increment input index */
in_index += factor; in_index += factor;
} }
/* store last sample for interpolation */
if (input_num)
state->up.last_sample = input[input_num - 1];
/* remove number of input samples from index */ /* remove number of input samples from index */
in_index -= (double)input_num; in_index -= (double)input_num;
/* in_index cannot be negative, excpet due to rounding error, so... */ /* in_index cannot be negative, excpet due to rounding error, so... */

View File

@@ -4,10 +4,12 @@ typedef struct samplerate {
double factor; double factor;
struct { struct {
filter_t lp; filter_t lp;
sample_t last_sample;
double in_index; double in_index;
} down; } down;
struct { struct {
filter_t lp; filter_t lp;
sample_t last_sample;
double in_index; double in_index;
} up; } up;
} samplerate_t; } samplerate_t;