diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2016-04-17 15:17:38 +0200 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2016-04-17 16:49:39 +0200 |
commit | 9de121109db5ca60462d35e4e45b7e5219f28503 (patch) | |
tree | e0aaf1d5ce770b5f0a5494b3319b4aa00ea32bbb /src/common/samplerate.c | |
parent | 05402283dfd4da630c254cd1e3852ac3900abd3e (diff) |
common code: Sample rate conversion now supports any rate above 8000 Hz
Diffstat (limited to 'src/common/samplerate.c')
-rw-r--r-- | src/common/samplerate.c | 93 |
1 files changed, 23 insertions, 70 deletions
diff --git a/src/common/samplerate.c b/src/common/samplerate.c index 9f01bce..43b2fe7 100644 --- a/src/common/samplerate.c +++ b/src/common/samplerate.c @@ -21,21 +21,21 @@ #include <stdint.h> #include <errno.h> #include <string.h> +#include <stdlib.h> #include "samplerate.h" -/* generally use filter, but disable for test using quick and dirty replacement */ -#define USE_FILTER - /* NOTE: This is quick and dirtry. */ -int init_samplerate(samplerate_t *state, int samplerate) +int init_samplerate(samplerate_t *state, double samplerate) { +#if 0 if ((samplerate % 8000)) { fprintf(stderr, "Sample rate must be a muliple of 8000 to support MNCC socket interface, aborting!\n"); return -EINVAL; } +#endif memset(state, 0, sizeof(*state)); - state->factor = samplerate / 8000; + state->factor = samplerate / 8000.0; biquad_init(&state->up.bq, 4000.0, samplerate); biquad_init(&state->down.bq, 4000.0, samplerate); @@ -46,10 +46,9 @@ int init_samplerate(samplerate_t *state, int samplerate) /* convert input sample rate to 8000 Hz */ int samplerate_downsample(samplerate_t *state, int16_t *input, int input_num, int16_t *output) { -#ifdef USE_FILTER - int output_num, i, j; - int factor = state->factor; - double spl[input_num]; + int output_num, i; + double factor = state->factor, step; + double spl[input_num + 10]; /* add some safety */ int32_t value; /* convert samples to double */ @@ -58,62 +57,42 @@ int samplerate_downsample(samplerate_t *state, int16_t *input, int input_num, in /* filter down */ biquad_process(&state->down.bq, spl, input_num, 1); - output_num = input_num / factor; + output_num = (int)((double)input_num / factor); /* resample filtered result */ - for (i = 0, j = 0; i < output_num; i++, j += factor) { - value = spl[j] * 32768.0; + for (i = 0, step = 0.5 / (double)output_num; i < output_num; i++, step += factor) { + value = spl[(int)step] * 32768.0; if (value < -32768) value = -32768; else if (value > 32767) value = 32767; *output++ = value; } - - return output_num; -#else - int output_num = 0, i; - double sum; - int factor, sum_count; - -//memcpy(output, input, input_num*2); -//return input_num; - sum = state->down.sum; - sum_count = state->down.sum_count; - factor = state->factor; - - for (i = 0; i < input_num; i++) { - sum += *input++; - sum_count++; - if (sum_count == factor) { - *output++ = sum / (double)sum_count; - output_num++; - sum = 0; - sum_count = 0; - } + if ((int)(step - factor) >= input_num) { + fprintf(stderr, "Error: input_num is %d, so step should be close to 0.5 below that, but it is %.4f. Please fix!\n", input_num, step); + abort(); } - state->down.sum = sum; - state->down.sum_count = sum_count; - return output_num; -#endif } /* convert 8000 Hz sample rate to output sample rate */ int samplerate_upsample(samplerate_t *state, int16_t *input, int input_num, int16_t *output) { -#ifdef USE_FILTER int output_num, i; - int factor = state->factor; - double spl[input_num * factor]; + double factor = 1.0 / state->factor, step; + double spl[(int)((double)input_num / factor + 0.5) + 10]; /* add some fafety */ int32_t value; - output_num = input_num * factor; + output_num = (int)((double)input_num / factor + 0.5); /* resample input */ - for (i = 0; i < output_num; i++) - spl[i] = input[i / factor] / 32768.0; + for (i = 0, step = 0.5 / (double)output_num; i < output_num; i++, step += factor) + spl[i] = input[(int)step] / 32768.0; + if ((int)(step - factor) >= input_num) { + fprintf(stderr, "Error: input_num is %d, so step should be close to 0.5 below that, but it is %.4f. Please fix!\n", input_num, step); + abort(); + } /* filter up */ biquad_process(&state->up.bq, spl, output_num, 1); @@ -129,31 +108,5 @@ int samplerate_upsample(samplerate_t *state, int16_t *input, int input_num, int1 } return output_num; -#else - int output_num = 0, i, j; - double last_sample, sample, slope; - int factor; - - last_sample = state->up.last_sample; - factor = state->factor; - - for (i = 0; i < input_num; i++) { - sample = *input++; - slope = (double)(sample - last_sample) / (double)factor; -//int jolly = (int)last_sample; - for (j = 0; j < factor; j++) { -// if (last_sample > 32767 || last_sample < -32767) -// printf("%.5f sample=%.0f, last_sample=%d, slope=%.5f\n", last_sample, sample, jolly, slope); - *output++ = last_sample; - output_num++; - last_sample += slope; - } - last_sample = sample; - } - - state->up.last_sample = last_sample; - - return output_num; -#endif } |