initial support for changing the filter length on the fly...
authorjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Fri, 2 Feb 2007 14:03:39 +0000 (14:03 +0000)
committerjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Fri, 2 Feb 2007 14:03:39 +0000 (14:03 +0000)
git-svn-id: http://svn.xiph.org/trunk/speex@12415 0101bb08-14d6-0310-b084-bc0e0c8e3800

include/speex/speex_resampler.h
libspeex/resample.c
libspeex/testresample.c

index a5fdf52..300b887 100644 (file)
 extern "C" {
 #endif
 
 extern "C" {
 #endif
 
+#define SPEEX_RESAMPLER_QUALITY_MAX 10
+#define SPEEX_RESAMPLER_QUALITY_MIN 0
+#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
+#define SPEEX_RESAMPLER_QUALITY_VOIP 3
+#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
+   
 struct SpeexResamplerState_;
 typedef struct SpeexResamplerState_ SpeexResamplerState;
 //typedef SpeexResamplerState;
 struct SpeexResamplerState_;
 typedef struct SpeexResamplerState_ SpeexResamplerState;
 //typedef SpeexResamplerState;
@@ -76,17 +82,17 @@ void speex_resampler_process_int(SpeexResamplerState *st, int channel_index, con
 
 void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, int *in_len, float *out, int *out_len);
 
 
 void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, int *in_len, float *out, int *out_len);
 
-void speex_resample_set_rate(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate);
+void speex_resampler_set_rate(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate);
 
 
-void speex_resample_set_quality(SpeexResamplerState *st, int quality);
+void speex_resampler_set_quality(SpeexResamplerState *st, int quality);
 
 
-void speex_resample_set_input_stride(SpeexResamplerState *st, int stride);
+void speex_resampler_set_input_stride(SpeexResamplerState *st, int stride);
 
 void speex_resample_set_output_stride(SpeexResamplerState *st, int stride);
 
 
 void speex_resample_set_output_stride(SpeexResamplerState *st, int stride);
 
-void speex_resample_skip_zeros(SpeexResamplerState *st);
+void speex_resampler_skip_zeros(SpeexResamplerState *st);
 
 
-void speex_resample_reset_mem(SpeexResamplerState *st);
+void speex_resampler_reset_mem(SpeexResamplerState *st);
 
 #ifdef __cplusplus
 }
 
 #ifdef __cplusplus
 }
index 929c060..29ddb59 100644 (file)
@@ -110,15 +110,18 @@ struct SpeexResamplerState_ {
    
    int    quality;
    int    nb_channels;
    
    int    quality;
    int    nb_channels;
-   int    last_sample;
-   int    samp_frac_num;
    int    filt_len;
    int    filt_len;
+   int    mem_alloc_size;
    int    int_advance;
    int    frac_advance;
    float  cutoff;
    int    oversample;
    int    initialised;
    int    int_advance;
    int    frac_advance;
    float  cutoff;
    int    oversample;
    int    initialised;
+   int    started;
    
    
+   /* FIXME: Need those per-channel */
+   int    last_sample;
+   int    samp_frac_num;
    
    spx_word16_t *mem;
    spx_word16_t *sinc_table;
    
    spx_word16_t *mem;
    spx_word16_t *sinc_table;
@@ -159,7 +162,9 @@ static spx_word16_t sinc(float cutoff, float x, int N)
 static void update_filter(SpeexResamplerState *st)
 {
    int i;
 static void update_filter(SpeexResamplerState *st)
 {
    int i;
+   int old_length;
    
    
+   old_length = st->filt_len;
    st->oversample = quality_map[st->quality].oversample;
    st->filt_len = quality_map[st->quality].base_length;
    
    st->oversample = quality_map[st->quality].oversample;
    st->filt_len = quality_map[st->quality].base_length;
    
@@ -213,11 +218,39 @@ static void update_filter(SpeexResamplerState *st)
    st->frac_advance = st->num_rate%st->den_rate;
 
    if (!st->mem)
    st->frac_advance = st->num_rate%st->den_rate;
 
    if (!st->mem)
+   {
       st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
       st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
-   else
+      for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
+         st->mem[i] = 0;
+      speex_warning("init filter");
+   } else if (!st->started)
+   {
       st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
       st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
-   for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
-      st->mem[i] = 0;
+      for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
+         st->mem[i] = 0;
+      speex_warning("reinit filter");
+   } else if (st->filt_len > old_length)
+   {
+      /* Increase the filter length */
+      speex_warning("increase filter size");
+      st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
+      for (i=0;i<st->nb_channels;i++)
+      {
+         int j;
+         /* Copy data going backward */
+         for (j=0;j<old_length-1;j++)
+            st->mem[i*(st->filt_len-1)+(st->filt_len-2-j)] = st->mem[i*(old_length-1)+(old_length-2-j)];
+         /* Then put zeros for lack of anything better */
+         for (;j<st->filt_len-1;j++)
+            st->mem[i*(st->filt_len-1)+(st->filt_len-2-j)] = 0;
+         /* Adjust last_sample */
+         st->last_sample += (st->filt_len - old_length)/2;
+      }
+   } else if (st->filt_len < old_length)
+   {
+      /* Reduce filter length */
+      speex_warning("decrease filter size (unimplemented)");
+   }
 
 }
 
 
 }
 
@@ -226,12 +259,15 @@ SpeexResamplerState *speex_resampler_init(int nb_channels, int ratio_num, int ra
 {
    SpeexResamplerState *st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
    st->initialised = 0;
 {
    SpeexResamplerState *st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
    st->initialised = 0;
+   st->started = 0;
    st->in_rate = 0;
    st->out_rate = 0;
    st->num_rate = 0;
    st->den_rate = 0;
    st->quality = -1;
    st->sinc_table_length = 0;
    st->in_rate = 0;
    st->out_rate = 0;
    st->num_rate = 0;
    st->den_rate = 0;
    st->quality = -1;
    st->sinc_table_length = 0;
+   st->mem_alloc_size = 0;
+   st->filt_len = 0;
    st->mem = 0;
    
    st->cutoff = 1.f;
    st->mem = 0;
    
    st->cutoff = 1.f;
@@ -241,8 +277,8 @@ SpeexResamplerState *speex_resampler_init(int nb_channels, int ratio_num, int ra
    st->in_stride = 1;
    st->out_stride = 1;
 
    st->in_stride = 1;
    st->out_stride = 1;
 
-   speex_resample_set_quality(st, quality);
-   speex_resample_set_rate(st, ratio_num, ratio_den, in_rate, out_rate);
+   speex_resampler_set_quality(st, quality);
+   speex_resampler_set_rate(st, ratio_num, ratio_den, in_rate, out_rate);
 
    
    update_filter(st);
 
    
    update_filter(st);
@@ -265,6 +301,7 @@ static void speex_resampler_process_native(SpeexResamplerState *st, int channel_
    int out_sample = 0;
    spx_word16_t *mem;
    mem = st->mem + channel_index * (N-1);
    int out_sample = 0;
    spx_word16_t *mem;
    mem = st->mem + channel_index * (N-1);
+   st->started = 1;
    while (!(st->last_sample >= *in_len || out_sample >= *out_len))
    {
       int j;
    while (!(st->last_sample >= *in_len || out_sample >= *out_len))
    {
       int j;
@@ -402,7 +439,7 @@ void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const fl
 }
 
 
 }
 
 
-void speex_resample_set_rate(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate)
+void speex_resampler_set_rate(SpeexResamplerState *st, int ratio_num, int ratio_den, int in_rate, int out_rate)
 {
    int fact;
    if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
 {
    int fact;
    if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
@@ -426,7 +463,7 @@ void speex_resample_set_rate(SpeexResamplerState *st, int ratio_num, int ratio_d
       update_filter(st);
 }
 
       update_filter(st);
 }
 
-void speex_resample_set_quality(SpeexResamplerState *st, int quality)
+void speex_resampler_set_quality(SpeexResamplerState *st, int quality)
 {
    if (quality < 0)
       quality = 0;
 {
    if (quality < 0)
       quality = 0;
@@ -439,22 +476,22 @@ void speex_resample_set_quality(SpeexResamplerState *st, int quality)
       update_filter(st);
 }
 
       update_filter(st);
 }
 
-void speex_resample_set_input_stride(SpeexResamplerState *st, int stride)
+void speex_resampler_set_input_stride(SpeexResamplerState *st, int stride)
 {
    st->in_stride = stride;
 }
 
 {
    st->in_stride = stride;
 }
 
-void speex_resample_set_output_stride(SpeexResamplerState *st, int stride)
+void speex_resampler_set_output_stride(SpeexResamplerState *st, int stride)
 {
    st->out_stride = stride;
 }
 
 {
    st->out_stride = stride;
 }
 
-void speex_resample_skip_zeros(SpeexResamplerState *st)
+void speex_resampler_skip_zeros(SpeexResamplerState *st)
 {
    st->last_sample = st->filt_len/2;
 }
 
 {
    st->last_sample = st->filt_len/2;
 }
 
-void speex_resample_reset_mem(SpeexResamplerState *st)
+void speex_resampler_reset_mem(SpeexResamplerState *st)
 {
    int i;
    for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
 {
    int i;
    for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
index 77db562..f361327 100644 (file)
@@ -47,9 +47,10 @@ int main(int argc, char **argv)
    short *in;
    short *out;
    float *fin, *fout;
    short *in;
    short *out;
    float *fin, *fout;
-   SpeexResamplerState *st = speex_resampler_init(1, 8000, 12000, 8000, 12000, 10);
-   speex_resample_set_rate(st, 8000, 15999, 8000, 15999);
-   speex_resample_skip_zeros(st);
+   int count = 0;
+   SpeexResamplerState *st = speex_resampler_init(1, 8000, 12000, 8000, 12000, 5);
+   speex_resampler_set_rate(st, 16000, 8001, 8000, 15999);
+   speex_resampler_skip_zeros(st);
    
    in = malloc(NN*sizeof(short));
    out = malloc(2*NN*sizeof(short));
    
    in = malloc(NN*sizeof(short));
    out = malloc(2*NN*sizeof(short));
@@ -66,10 +67,13 @@ int main(int argc, char **argv)
          fin[i]=3.f*in[i];
       in_len = NN;
       out_len = 2*NN;
          fin[i]=3.f*in[i];
       in_len = NN;
       out_len = 2*NN;
+      if (count==2)
+         speex_resampler_set_quality(st, 10);
       speex_resampler_process_float(st, 0, fin, &in_len, fout, &out_len);
       for (i=0;i<out_len;i++)
          out[i]=floor(.5+fout[i]);
       fwrite(out, sizeof(short), out_len, stdout);
       speex_resampler_process_float(st, 0, fin, &in_len, fout, &out_len);
       for (i=0;i<out_len;i++)
          out[i]=floor(.5+fout[i]);
       fwrite(out, sizeof(short), out_len, stdout);
+      count++;
    }
    speex_resampler_destroy(st);
    free(in);
    }
    speex_resampler_destroy(st);
    free(in);