]> git.alsa-project.org Git - alsa-plugins.git/commitdiff
Update speex rate converter code
authorTakashi Iwai <tiwai@suse.de>
Tue, 14 Aug 2007 14:21:52 +0000 (16:21 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 14 Aug 2007 14:21:52 +0000 (16:21 +0200)
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
pph/resample.c
pph/speex_resampler.h

index 9eb33b98a4938ee786050f2fac91c1f98002ff01..38244b6d11b53d2f28996e3cf5b81be83289d533 100644 (file)
@@ -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;
    }
index 281cb32f43f755c58063b94cbda619cd22304f04..1cc4d49023364dc399bdb09fde3602c62b761564 100644 (file)
@@ -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.";
+   }
+}
index 1499ce0d9393cd928b8f95a2100818d5f5aad59c..c44fbcd0d1d322a7f30b7439622d39e5125f9b5f 100644 (file)
 #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
 }