diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2017-02-05 13:16:39 +0100 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2017-02-18 21:02:51 +0100 |
commit | 4c0f8e7e953232f1242b23d0cb9516948d9c187b (patch) | |
tree | dc0a5a063cc23f8ed0e22edc47424c68da477bee /src/common/samplerate.c | |
parent | 47f74b38ce1f0488205b0aad82d86573fe77461a (diff) |
Rework of sample rate conversion by using linear interpolation
Diffstat (limited to 'src/common/samplerate.c')
-rw-r--r-- | src/common/samplerate.c | 50 |
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... */ |