diff options
| -rw-r--r-- | pph/rate_speexrate.c | 3 | ||||
| -rw-r--r-- | pph/resample.c | 213 | ||||
| -rw-r--r-- | 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 <stdlib.h> -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;i<st->den_rate;i++)        { -         spx_uint32_t j; +         spx_int32_t j;           for (j=0;j<st->filt_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;i<st->nb_channels;i++) +      for (i=st->nb_channels-1;i>=0;i--)        { -         spx_uint32_t j; -         /* Copy data going backward */ -         for (j=0;j<old_length-1;j++) -            st->mem[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 (;j<st->filt_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;j<st->magic_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;j<olen-1;j++) +               st->mem[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 (;j<st->filt_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;j<st->filt_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;i<st->nb_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;j<st->filt_len-1+st->magic_samples[i];j++) +         for (j=0;j<st->filt_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;i<st->magic_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 (;j<N-1;j++)        mem[j] = in[st->in_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;i<st->nb_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;i<st->nb_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;i<st->nb_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;i<st->nb_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;i<st->nb_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  } | 
