From 1ee7b56befc16d0940bd162f3ac9b6ae66e85f0b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Aug 2007 16:21:52 +0200 Subject: Update speex rate converter code Take speex rate converter code from speex SVN tree, which includes the fix for the noises with simple conversion (signed / unsigned mismatch). --- pph/rate_speexrate.c | 3 +- pph/resample.c | 213 ++++++++++++++++++++++++++++++++++++-------------- pph/speex_resampler.h | 65 +++++++-------- 3 files changed, 191 insertions(+), 90 deletions(-) diff --git a/pph/rate_speexrate.c b/pph/rate_speexrate.c index 9eb33b9..38244b6 100644 --- a/pph/rate_speexrate.c +++ b/pph/rate_speexrate.c @@ -77,12 +77,13 @@ static void pcm_src_free(void *obj) static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info) { struct rate_src *rate = obj; + int err; if (! rate->st || rate->channels != info->channels) { if (rate->st) speex_resampler_destroy(rate->st); rate->channels = info->channels; - rate->st = speex_resampler_init_frac(rate->channels, info->in.period_size, info->out.period_size, info->in.rate, info->out.rate, rate->quality); + rate->st = speex_resampler_init_frac(rate->channels, info->in.period_size, info->out.period_size, info->in.rate, info->out.rate, rate->quality, &err); if (! rate->st) return -EINVAL; } diff --git a/pph/resample.c b/pph/resample.c index 281cb32..1cc4d49 100644 --- a/pph/resample.c +++ b/pph/resample.c @@ -56,9 +56,9 @@ TODO list: #ifdef OUTSIDE_SPEEX #include -void *speex_alloc (int size) {return calloc(size,1);} -void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} -void speex_free (void *ptr) {free(ptr);} +static void *speex_alloc (int size) {return calloc(size,1);} +static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} +static void speex_free (void *ptr) {free(ptr);} #include "speex_resampler.h" #include "arch.h" #else /* OUTSIDE_SPEEX */ @@ -84,7 +84,11 @@ void speex_free (void *ptr) {free(ptr);} #define OVERSAMPLE 8 #define IMAX(a,b) ((a) > (b) ? (a) : (b)) +#define IMIN(a,b) ((a) < (b) ? (a) : (b)) +#ifndef NULL +#define NULL 0 +#endif typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); @@ -205,12 +209,12 @@ static const struct QualityMapping quality_map[11] = { { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ - { 80, 8, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ - { 96, 8, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ + { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ + { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ - {192, 16, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ - {256, 16, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ + {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ + {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ }; /*8,24,40,56,80,104,128,160,200,256,320*/ static double compute_func(float x, struct FuncDef *func) @@ -545,16 +549,23 @@ static void update_filter(SpeexResamplerState *st) st->filt_len = st->filt_len*st->num_rate / st->den_rate; /* Round down to make sure we have a multiple of 4 */ st->filt_len &= (~0x3); + if (2*st->den_rate < st->num_rate) + st->oversample >>= 1; + if (4*st->den_rate < st->num_rate) + st->oversample >>= 1; + if (8*st->den_rate < st->num_rate) + st->oversample >>= 1; + if (16*st->den_rate < st->num_rate) + st->oversample >>= 1; + if (st->oversample < 1) + st->oversample = 1; } else { /* up-sampling */ st->cutoff = quality_map[st->quality].upsample_bandwidth; } /* Choose the resampling type that requires the least amount of memory */ - /* FIXME: The direct sinc table can be noisy in some conditions. - * Disable it as a temporary workaround. - */ - if (0 /*st->den_rate <= st->oversample*/) + if (st->den_rate <= st->oversample) { spx_uint32_t i; if (!st->sinc_table) @@ -566,10 +577,10 @@ static void update_filter(SpeexResamplerState *st) } for (i=0;iden_rate;i++) { - spx_uint32_t j; + spx_int32_t j; for (j=0;jfilt_len;j++) { - st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func); + st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func); } } #ifdef FIXED_POINT @@ -605,6 +616,10 @@ static void update_filter(SpeexResamplerState *st) st->int_advance = st->num_rate/st->den_rate; st->frac_advance = st->num_rate%st->den_rate; + + /* Here's the place where we update the filter memory to take into account + the change in filter length. It's probably the messiest part of the code + due to handling of lots of corner cases. */ if (!st->mem) { spx_uint32_t i; @@ -623,7 +638,7 @@ static void update_filter(SpeexResamplerState *st) /*speex_warning("reinit filter");*/ } else if (st->filt_len > old_length) { - spx_uint32_t i; + spx_int32_t i; /* Increase the filter length */ /*speex_warning("increase filter size");*/ int old_alloc_size = st->mem_alloc_size; @@ -632,46 +647,76 @@ static void update_filter(SpeexResamplerState *st) st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); st->mem_alloc_size = st->filt_len-1; } - for (i=0;inb_channels;i++) + for (i=st->nb_channels-1;i>=0;i--) { - spx_uint32_t j; - /* Copy data going backward */ - for (j=0;jmem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*old_alloc_size+(old_length-2-j)]; - /* Then put zeros for lack of anything better */ - for (;jfilt_len-1;j++) - st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; - /* Adjust last_sample */ - st->last_sample[i] += (st->filt_len - old_length)/2; + spx_int32_t j; + spx_uint32_t olen = old_length; + /*if (st->magic_samples[i])*/ + { + /* Try and remove the magic samples as if nothing had happened */ + + /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ + olen = old_length + 2*st->magic_samples[i]; + for (j=old_length-2+st->magic_samples[i];j>=0;j--) + st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; + for (j=0;jmagic_samples[i];j++) + st->mem[i*st->mem_alloc_size+j] = 0; + st->magic_samples[i] = 0; + } + if (st->filt_len > olen) + { + /* If the new filter length is still bigger than the "augmented" length */ + /* Copy data going backward */ + for (j=0;jmem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)]; + /* Then put zeros for lack of anything better */ + for (;jfilt_len-1;j++) + st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; + /* Adjust last_sample */ + st->last_sample[i] += (st->filt_len - olen)/2; + } else { + /* Put back some of the magic! */ + st->magic_samples[i] = (olen - st->filt_len)/2; + for (j=0;jfilt_len-1+st->magic_samples[i];j++) + st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; + } } } else if (st->filt_len < old_length) { spx_uint32_t i; - /* Reduce filter length, this a bit tricky */ - /*speex_warning("decrease filter size (unimplemented)");*/ - /* Adjust last_sample (which will likely end up negative) */ - /*st->last_sample += (st->filt_len - old_length)/2;*/ + /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" + samples so they can be used directly as input the next time(s) */ for (i=0;inb_channels;i++) { spx_uint32_t j; + spx_uint32_t old_magic = st->magic_samples[i]; st->magic_samples[i] = (old_length - st->filt_len)/2; + /* We must copy some of the memory that's no longer used */ /* Copy data going backward */ - for (j=0;jfilt_len-1+st->magic_samples[i];j++) + for (j=0;jfilt_len-1+st->magic_samples[i]+old_magic;j++) st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; + st->magic_samples[i] += old_magic; } } } -SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality) +SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) { - return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality); + return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); } -SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality) +SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) { spx_uint32_t i; - SpeexResamplerState *st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); + SpeexResamplerState *st; + if (quality > 10 || quality < 0) + { + if (err) + *err = RESAMPLER_ERR_INVALID_ARG; + return NULL; + } + st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); st->initialised = 0; st->started = 0; st->in_rate = 0; @@ -708,6 +753,9 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin update_filter(st); st->initialised = 1; + if (err) + *err = RESAMPLER_ERR_SUCCESS; + return st; } @@ -723,7 +771,7 @@ void speex_resampler_destroy(SpeexResamplerState *st) -static void speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) +static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) { int j=0; int N = st->filt_len; @@ -736,15 +784,19 @@ static void speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t /* Handle the case where we have samples left from a reduction in filter length */ if (st->magic_samples[channel_index]) { + int istride_save; spx_uint32_t tmp_in_len; spx_uint32_t tmp_magic; + + istride_save = st->in_stride; tmp_in_len = st->magic_samples[channel_index]; tmp_out_len = *out_len; - /* FIXME: Need to handle the case where the out array is too small */ /* magic_samples needs to be set to zero to avoid infinite recursion */ tmp_magic = st->magic_samples[channel_index]; st->magic_samples[channel_index] = 0; + st->in_stride = 1; speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len); + st->in_stride = istride_save; /*speex_warning_int("extra samples:", tmp_out_len);*/ /* If we couldn't process all "magic" input samples, save the rest for next time */ if (tmp_in_len < tmp_magic) @@ -754,7 +806,8 @@ static void speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t for (i=0;imagic_samples[channel_index];i++) mem[N-1+i]=mem[N-1+i+tmp_in_len]; } - out += tmp_out_len; + out += tmp_out_len*st->out_stride; + *out_len -= tmp_out_len; } /* Call the right resampler through the function ptr */ @@ -770,12 +823,13 @@ static void speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t for (;jin_stride*(j+*in_len-N+1)]; + return RESAMPLER_ERR_SUCCESS; } #define FIXED_STACK_ALLOC 1024 #ifdef FIXED_POINT -void speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) +int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) { spx_uint32_t i; int istride_save, ostride_save; @@ -827,17 +881,18 @@ void speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel *in_len -= ilen; *out_len -= olen; #endif + return RESAMPLER_ERR_SUCCESS; } -void speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) +int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) { - speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); + return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); } #else -void speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) +int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) { - speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); + return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); } -void speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) +int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) { spx_uint32_t i; int istride_save, ostride_save; @@ -889,42 +944,50 @@ void speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_i *in_len -= ilen; *out_len -= olen; #endif + return RESAMPLER_ERR_SUCCESS; } #endif -void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) { spx_uint32_t i; int istride_save, ostride_save; + spx_uint32_t bak_len = *out_len; istride_save = st->in_stride; ostride_save = st->out_stride; st->in_stride = st->out_stride = st->nb_channels; for (i=0;inb_channels;i++) { + *out_len = bak_len; speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); } st->in_stride = istride_save; st->out_stride = ostride_save; + return RESAMPLER_ERR_SUCCESS; } -void speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) + +int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) { spx_uint32_t i; int istride_save, ostride_save; + spx_uint32_t bak_len = *out_len; istride_save = st->in_stride; ostride_save = st->out_stride; st->in_stride = st->out_stride = st->nb_channels; for (i=0;inb_channels;i++) { + *out_len = bak_len; speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); } st->in_stride = istride_save; st->out_stride = ostride_save; + return RESAMPLER_ERR_SUCCESS; } -void speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) +int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) { - speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); + return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); } void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) @@ -933,18 +996,21 @@ void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, sp *out_rate = st->out_rate; } -void speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) +int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) { - int fact; + spx_uint32_t fact; + spx_uint32_t old_den; + spx_uint32_t i; if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) - return; + return RESAMPLER_ERR_SUCCESS; + old_den = st->den_rate; st->in_rate = in_rate; st->out_rate = out_rate; st->num_rate = ratio_num; st->den_rate = ratio_den; /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ - for (fact=2;fact<=sqrt(IMAX(in_rate, out_rate));fact++) + for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) { while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) { @@ -953,8 +1019,20 @@ void speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_n } } + if (old_den > 0) + { + for (i=0;inb_channels;i++) + { + st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; + /* Safety net */ + if (st->samp_frac_num[i] >= st->den_rate) + st->samp_frac_num[i] = st->den_rate-1; + } + } + if (st->initialised) update_filter(st); + return RESAMPLER_ERR_SUCCESS; } void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) @@ -963,17 +1041,16 @@ void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, *ratio_den = st->den_rate; } -void speex_resampler_set_quality(SpeexResamplerState *st, int quality) +int speex_resampler_set_quality(SpeexResamplerState *st, int quality) { - if (quality < 0) - quality = 0; - if (quality > 10) - quality = 10; + if (quality > 10 || quality < 0) + return RESAMPLER_ERR_INVALID_ARG; if (st->quality == quality) - return; + return RESAMPLER_ERR_SUCCESS; st->quality = quality; if (st->initialised) update_filter(st); + return RESAMPLER_ERR_SUCCESS; } void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) @@ -1001,17 +1078,37 @@ void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *st *stride = st->out_stride; } -void speex_resampler_skip_zeros(SpeexResamplerState *st) +int speex_resampler_skip_zeros(SpeexResamplerState *st) { spx_uint32_t i; for (i=0;inb_channels;i++) st->last_sample[i] = st->filt_len/2; + return RESAMPLER_ERR_SUCCESS; } -void speex_resampler_reset_mem(SpeexResamplerState *st) +int speex_resampler_reset_mem(SpeexResamplerState *st) { spx_uint32_t i; for (i=0;inb_channels*(st->filt_len-1);i++) st->mem[i] = 0; + return RESAMPLER_ERR_SUCCESS; } +const char *speex_resampler_strerror(int err) +{ + switch (err) + { + case RESAMPLER_ERR_SUCCESS: + return "Success."; + case RESAMPLER_ERR_ALLOC_FAILED: + return "Memory allocation failed."; + case RESAMPLER_ERR_BAD_STATE: + return "Bad resampler state."; + case RESAMPLER_ERR_INVALID_ARG: + return "Invalid argument."; + case RESAMPLER_ERR_PTR_OVERLAP: + return "Input and output buffers overlap."; + default: + return "Unknown error. Bad error code or strange version mismatch."; + } +} diff --git a/pph/speex_resampler.h b/pph/speex_resampler.h index 1499ce0..c44fbcd 100644 --- a/pph/speex_resampler.h +++ b/pph/speex_resampler.h @@ -69,31 +69,16 @@ #define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality) #define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride) #define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride) -#define speex_resample_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resample_set_output_stride) -#define speex_resample_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resample_get_output_stride) +#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride) +#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride) #define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros) #define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) +#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) #define spx_int16_t short #define spx_int32_t int #define spx_uint16_t unsigned short #define spx_uint32_t unsigned int - -#if 0 -#ifdef FIXED_POINT -/*#define spx_word16_t spx_int16_t -#define spx_word32_t spx_int32_t*/ -#include "arch.h" - -#else /* FIXED_POINT */ - -#define spx_word16_t float -#define spx_word32_t float -#define MULT16_16(a,b) ((a)*(b)) -#define MULT16_32_Q15(a,b) ((a)*(b)) -#define PSHR32(a,b) (a) -#endif /* FIXED_POINT */ -#endif #else /* OUTSIDE_SPEEX */ @@ -110,7 +95,17 @@ extern "C" { #define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 #define SPEEX_RESAMPLER_QUALITY_VOIP 3 #define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 + +enum { + RESAMPLER_ERR_SUCCESS = 0, + RESAMPLER_ERR_ALLOC_FAILED = 1, + RESAMPLER_ERR_BAD_STATE = 2, + RESAMPLER_ERR_INVALID_ARG = 3, + RESAMPLER_ERR_PTR_OVERLAP = 4, + RESAMPLER_ERR_MAX_ERROR +}; + struct SpeexResamplerState_; typedef struct SpeexResamplerState_ SpeexResamplerState; @@ -126,7 +121,8 @@ typedef struct SpeexResamplerState_ SpeexResamplerState; SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, - int quality); + int quality, + int *err); /** Create a new resampler with fractional input/output rates. The sampling * rate ratio is an arbitrary rational number with both the numerator and @@ -146,7 +142,8 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, - int quality); + int quality, + int *err); /** Destroy a resampler state. * @param st Resampler state @@ -163,7 +160,7 @@ void speex_resampler_destroy(SpeexResamplerState *st); * @param out Output buffer * @param out_len Size of the output buffer. Returns the number of samples written */ -void speex_resampler_process_float(SpeexResamplerState *st, +int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, @@ -180,7 +177,7 @@ void speex_resampler_process_float(SpeexResamplerState *st, * @param out Output buffer * @param out_len Size of the output buffer. Returns the number of samples written */ -void speex_resampler_process_int(SpeexResamplerState *st, +int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, @@ -196,7 +193,7 @@ void speex_resampler_process_int(SpeexResamplerState *st, * @param out_len Size of the output buffer. Returns the number of samples written. * This is all per-channel. */ -void speex_resampler_process_interleaved_float(SpeexResamplerState *st, +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, @@ -211,7 +208,7 @@ void speex_resampler_process_interleaved_float(SpeexResamplerState *st, * @param out_len Size of the output buffer. Returns the number of samples written. * This is all per-channel. */ -void speex_resampler_process_interleaved_int(SpeexResamplerState *st, +int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, @@ -222,7 +219,7 @@ void speex_resampler_process_interleaved_int(SpeexResamplerState *st, * @param in_rate Input sampling rate (integer number of Hz). * @param out_rate Output sampling rate (integer number of Hz). */ -void speex_resampler_set_rate(SpeexResamplerState *st, +int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate); @@ -243,7 +240,7 @@ void speex_resampler_get_rate(SpeexResamplerState *st, * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). */ -void speex_resampler_set_rate_frac(SpeexResamplerState *st, +int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, @@ -264,7 +261,7 @@ void speex_resampler_get_ratio(SpeexResamplerState *st, * @param quality Resampling quality between 0 and 10, where 0 has poor * quality and 10 has very high quality. */ -void speex_resampler_set_quality(SpeexResamplerState *st, +int speex_resampler_set_quality(SpeexResamplerState *st, int quality); /** Get the conversion quality. @@ -293,14 +290,14 @@ void speex_resampler_get_input_stride(SpeexResamplerState *st, * @param st Resampler state * @param stride Output stride */ -void speex_resample_set_output_stride(SpeexResamplerState *st, +void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride); /** Get the output stride. * @param st Resampler state copied * @param stride Output stride */ -void speex_resample_get_output_stride(SpeexResamplerState *st, +void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride); /** Make sure that the first samples to go out of the resamplers don't have @@ -311,12 +308,18 @@ void speex_resample_get_output_stride(SpeexResamplerState *st, * is the same for the first frame). * @param st Resampler state */ -void speex_resampler_skip_zeros(SpeexResamplerState *st); +int speex_resampler_skip_zeros(SpeexResamplerState *st); /** Reset a resampler so a new (unrelated) stream can be processed. * @param st Resampler state */ -void speex_resampler_reset_mem(SpeexResamplerState *st); +int speex_resampler_reset_mem(SpeexResamplerState *st); + +/** Returns the English meaning for an error code + * @param err Error code + * @return English string + */ +const char *speex_resampler_strerror(int err); #ifdef __cplusplus } -- cgit