aboutsummaryrefslogtreecommitdiffstats
path: root/src/common/samplerate.c
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-02-05 13:16:39 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2017-02-18 21:02:51 +0100
commit4c0f8e7e953232f1242b23d0cb9516948d9c187b (patch)
treedc0a5a063cc23f8ed0e22edc47424c68da477bee /src/common/samplerate.c
parent47f74b38ce1f0488205b0aad82d86573fe77461a (diff)
Rework of sample rate conversion by using linear interpolation
Diffstat (limited to 'src/common/samplerate.c')
-rw-r--r--src/common/samplerate.c50
1 files changed, 38 insertions, 12 deletions
diff --git a/src/common/samplerate.c b/src/common/samplerate.c
index 66b763f..6eb4729 100644
--- a/src/common/samplerate.c
+++ b/src/common/samplerate.c
@@ -25,8 +25,6 @@
#include "sample.h"
#include "samplerate.h"
-/* NOTE: This is quick and dirtry. */
-
int init_samplerate(samplerate_t *state, double samplerate)
{
#if 0
@@ -38,8 +36,8 @@ int init_samplerate(samplerate_t *state, double samplerate)
memset(state, 0, sizeof(*state));
state->factor = samplerate / 8000.0;
- filter_lowpass_init(&state->up.lp, 4000.0, samplerate, 1);
- filter_lowpass_init(&state->down.lp, 4000.0, samplerate, 1);
+ filter_lowpass_init(&state->up.lp, 3300.0, samplerate, 2);
+ filter_lowpass_init(&state->down.lp, 3300.0, samplerate, 2);
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 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_process(&state->down.lp, samples, input_num);
+ /* get last sample for interpolation */
+ last_sample = state->down.last_sample;
+
/* resample filtered result */
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 (idx >= input_num)
break;
- /* copy value from input to output */
- samples[i] = samples[idx];
+ /* linear interpolation */
+ 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 */
output_num++;
/* increment input index */
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 */
in_index -= (double)input_num;
/* 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;
+ /* copy samples */
+ for (i = 0; i < output_num; i++)
+ *samples++ = output[i];
+
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 output_num = 0, i, idx;
- double factor = 1.0 / state->factor, in_index;
- sample_t buff[(int)((double)input_num / factor + 0.5) + 10]; /* add some fafety */
- sample_t *samples;
+ double factor = 1.0 / state->factor, in_index, diff;
+ sample_t buff[(int)((double)input_num / factor + 0.5) + 10]; /* add some safety */
+ sample_t *samples, last_sample;
+
+ /* get last sample for interpolation */
+ last_sample = state->up.last_sample;
if (input == output)
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 (idx >= input_num)
break;
- /* copy value */
- samples[i] = input[idx];
+ /* linear interpolation */
+ 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 */
output_num++;
/* increment input index */
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 */
in_index -= (double)input_num;
/* in_index cannot be negative, excpet due to rounding error, so... */