1cc4d49023364dc399bdb09fde3602c62b761564
[speexdsp.git] / libspeex / resample.c
1 /* Copyright (C) 2007 Jean-Marc Valin
2       
3    File: resample.c
4    Arbitrary resampling code
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions are
8    met:
9
10    1. Redistributions of source code must retain the above copyright notice,
11    this list of conditions and the following disclaimer.
12
13    2. Redistributions in binary form must reproduce the above copyright
14    notice, this list of conditions and the following disclaimer in the
15    documentation and/or other materials provided with the distribution.
16
17    3. The name of the author may not be used to endorse or promote products
18    derived from this software without specific prior written permission.
19
20    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23    DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30    POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34    The design goals of this code are:
35       - Very fast algorithm
36       - SIMD-friendly algorithm
37       - Low memory requirement
38       - Good *perceptual* quality (and not best SNR)
39
40    The code is working, but it's in a very early stage, so it may have
41    artifacts, noise or subliminal messages from satan. Also, the API 
42    isn't stable and I can actually promise that I *will* change the API
43    some time in the future.
44
45 TODO list:
46       - Variable calculation resolution depending on quality setting
47          - Single vs double in float mode
48          - 16-bit vs 32-bit (sinc only) in fixed-point mode
49       - Make sure the filter update works even when changing params 
50              after only a few samples procesed
51 */
52
53 #ifdef HAVE_CONFIG_H
54 #include "config.h"
55 #endif
56
57 #ifdef OUTSIDE_SPEEX
58 #include <stdlib.h>
59 static void *speex_alloc (int size) {return calloc(size,1);}
60 static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
61 static void speex_free (void *ptr) {free(ptr);}
62 #include "speex_resampler.h"
63 #include "arch.h"
64 #else /* OUTSIDE_SPEEX */
65                
66 #include "speex/speex_resampler.h"
67 #include "misc.h"
68 #endif /* OUTSIDE_SPEEX */
69
70 #include <math.h>
71
72 #ifndef M_PI
73 #define M_PI 3.14159263
74 #endif
75
76 #ifdef FIXED_POINT
77 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))  
78 #else
79 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))  
80 #endif
81                
82 /*#define float double*/
83 #define FILTER_SIZE 64
84 #define OVERSAMPLE 8
85
86 #define IMAX(a,b) ((a) > (b) ? (a) : (b))
87 #define IMIN(a,b) ((a) < (b) ? (a) : (b))
88
89 #ifndef NULL
90 #define NULL 0
91 #endif
92
93 typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
94
95 struct SpeexResamplerState_ {
96    spx_uint32_t in_rate;
97    spx_uint32_t out_rate;
98    spx_uint32_t num_rate;
99    spx_uint32_t den_rate;
100    
101    int    quality;
102    spx_uint32_t nb_channels;
103    spx_uint32_t filt_len;
104    spx_uint32_t mem_alloc_size;
105    int          int_advance;
106    int          frac_advance;
107    float  cutoff;
108    spx_uint32_t oversample;
109    int          initialised;
110    int          started;
111    
112    /* These are per-channel */
113    spx_int32_t  *last_sample;
114    spx_uint32_t *samp_frac_num;
115    spx_uint32_t *magic_samples;
116    
117    spx_word16_t *mem;
118    spx_word16_t *sinc_table;
119    spx_uint32_t sinc_table_length;
120    resampler_basic_func resampler_ptr;
121          
122    int    in_stride;
123    int    out_stride;
124 } ;
125
126 static double kaiser12_table[68] = {
127    0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
128    0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
129    0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
130    0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
131    0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
132    0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
133    0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
134    0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
135    0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
136    0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
137    0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
138    0.00001000, 0.00000000};
139 /*
140 static double kaiser12_table[36] = {
141    0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
142    0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
143    0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
144    0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
145    0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
146    0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
147 */
148 static double kaiser10_table[36] = {
149    0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
150    0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
151    0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
152    0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
153    0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
154    0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
155
156 static double kaiser8_table[36] = {
157    0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
158    0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
159    0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
160    0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
161    0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
162    0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
163    
164 static double kaiser6_table[36] = {
165    0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
166    0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
167    0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
168    0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
169    0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
170    0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
171
172 struct FuncDef {
173    double *table;
174    int oversample;
175 };
176       
177 static struct FuncDef _KAISER12 = {kaiser12_table, 64};
178 #define KAISER12 (&_KAISER12)
179 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
180 #define KAISER12 (&_KAISER12)*/
181 static struct FuncDef _KAISER10 = {kaiser10_table, 32};
182 #define KAISER10 (&_KAISER10)
183 static struct FuncDef _KAISER8 = {kaiser8_table, 32};
184 #define KAISER8 (&_KAISER8)
185 static struct FuncDef _KAISER6 = {kaiser6_table, 32};
186 #define KAISER6 (&_KAISER6)
187
188 struct QualityMapping {
189    int base_length;
190    int oversample;
191    float downsample_bandwidth;
192    float upsample_bandwidth;
193    struct FuncDef *window_func;
194 };
195
196
197 /* This table maps conversion quality to internal parameters. There are two
198    reasons that explain why the up-sampling bandwidth is larger than the 
199    down-sampling bandwidth:
200    1) When up-sampling, we can assume that the spectrum is already attenuated
201       close to the Nyquist rate (from an A/D or a previous resampling filter)
202    2) Any aliasing that occurs very close to the Nyquist rate will be masked
203       by the sinusoids/noise just below the Nyquist rate (guaranteed only for
204       up-sampling).
205 */
206 static const struct QualityMapping quality_map[11] = {
207    {  8,  4, 0.830f, 0.860f, KAISER6 }, /* Q0 */
208    { 16,  4, 0.850f, 0.880f, KAISER6 }, /* Q1 */
209    { 32,  4, 0.882f, 0.910f, KAISER6 }, /* Q2 */  /* 82.3% cutoff ( ~60 dB stop) 6  */
210    { 48,  8, 0.895f, 0.917f, KAISER8 }, /* Q3 */  /* 84.9% cutoff ( ~80 dB stop) 8  */
211    { 64,  8, 0.921f, 0.940f, KAISER8 }, /* Q4 */  /* 88.7% cutoff ( ~80 dB stop) 8  */
212    { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */  /* 89.1% cutoff (~100 dB stop) 10 */
213    { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */  /* 91.5% cutoff (~100 dB stop) 10 */
214    {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */  /* 93.1% cutoff (~100 dB stop) 10 */
215    {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */  /* 94.5% cutoff (~100 dB stop) 10 */
216    {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */  /* 95.5% cutoff (~100 dB stop) 10 */
217    {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
218 };
219 /*8,24,40,56,80,104,128,160,200,256,320*/
220 static double compute_func(float x, struct FuncDef *func)
221 {
222    float y, frac;
223    double interp[4];
224    int ind; 
225    y = x*func->oversample;
226    ind = (int)floor(y);
227    frac = (y-ind);
228    /* CSE with handle the repeated powers */
229    interp[3] =  -0.1666666667*frac + 0.1666666667*(frac*frac*frac);
230    interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac);
231    /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
232    interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
233    /* Just to make sure we don't have rounding problems */
234    interp[1] = 1.f-interp[3]-interp[2]-interp[0];
235    
236    /*sum = frac*accum[1] + (1-frac)*accum[2];*/
237    return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
238 }
239
240 #if 0
241 #include <stdio.h>
242 int main(int argc, char **argv)
243 {
244    int i;
245    for (i=0;i<256;i++)
246    {
247       printf ("%f\n", compute_func(i/256., KAISER12));
248    }
249    return 0;
250 }
251 #endif
252
253 #ifdef FIXED_POINT
254 /* The slow way of computing a sinc for the table. Should improve that some day */
255 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
256 {
257    /*fprintf (stderr, "%f ", x);*/
258    float xx = x * cutoff;
259    if (fabs(x)<1e-6f)
260       return WORD2INT(32768.*cutoff);
261    else if (fabs(x) > .5f*N)
262       return 0;
263    /*FIXME: Can it really be any slower than this? */
264    return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
265 }
266 #else
267 /* The slow way of computing a sinc for the table. Should improve that some day */
268 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
269 {
270    /*fprintf (stderr, "%f ", x);*/
271    float xx = x * cutoff;
272    if (fabs(x)<1e-6)
273       return cutoff;
274    else if (fabs(x) > .5*N)
275       return 0;
276    /*FIXME: Can it really be any slower than this? */
277    return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func);
278 }
279 #endif
280
281 #ifdef FIXED_POINT
282 static void cubic_coef(spx_word16_t x, spx_word16_t interp[4])
283 {
284    /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
285    but I know it's MMSE-optimal on a sinc */
286    spx_word16_t x2, x3;
287    x2 = MULT16_16_P15(x, x);
288    x3 = MULT16_16_P15(x, x2);
289    interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
290    interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
291    interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15);
292    /* Just to make sure we don't have rounding problems */
293    interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3];
294    if (interp[2]<32767)
295       interp[2]+=1;
296 }
297 #else
298 static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
299 {
300    /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
301    but I know it's MMSE-optimal on a sinc */
302    interp[0] =  -0.16667f*frac + 0.16667f*frac*frac*frac;
303    interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac;
304    /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
305    interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac;
306    /* Just to make sure we don't have rounding problems */
307    interp[2] = 1.-interp[0]-interp[1]-interp[3];
308 }
309 #endif
310
311 static int resampler_basic_direct_single(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)
312 {
313    int N = st->filt_len;
314    int out_sample = 0;
315    spx_word16_t *mem;
316    int last_sample = st->last_sample[channel_index];
317    spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
318    mem = st->mem + channel_index * st->mem_alloc_size;
319    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
320    {
321       int j;
322       spx_word32_t sum=0;
323       
324       /* We already have all the filter coefficients pre-computed in the table */
325       const spx_word16_t *ptr;
326       /* Do the memory part */
327       for (j=0;last_sample-N+1+j < 0;j++)
328       {
329          sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]);
330       }
331       
332       /* Do the new part */
333       ptr = in+st->in_stride*(last_sample-N+1+j);
334       for (;j<N;j++)
335       {
336          sum += MULT16_16(*ptr,st->sinc_table[samp_frac_num*st->filt_len+j]);
337          ptr += st->in_stride;
338       }
339    
340       *out = PSHR32(sum,15);
341       out += st->out_stride;
342       out_sample++;
343       last_sample += st->int_advance;
344       samp_frac_num += st->frac_advance;
345       if (samp_frac_num >= st->den_rate)
346       {
347          samp_frac_num -= st->den_rate;
348          last_sample++;
349       }
350    }
351    st->last_sample[channel_index] = last_sample;
352    st->samp_frac_num[channel_index] = samp_frac_num;
353    return out_sample;
354 }
355
356 #ifdef FIXED_POINT
357 #else
358 /* This is the same as the previous function, except with a double-precision accumulator */
359 static int resampler_basic_direct_double(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)
360 {
361    int N = st->filt_len;
362    int out_sample = 0;
363    spx_word16_t *mem;
364    int last_sample = st->last_sample[channel_index];
365    spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
366    mem = st->mem + channel_index * st->mem_alloc_size;
367    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
368    {
369       int j;
370       double sum=0;
371       
372       /* We already have all the filter coefficients pre-computed in the table */
373       const spx_word16_t *ptr;
374       /* Do the memory part */
375       for (j=0;last_sample-N+1+j < 0;j++)
376       {
377          sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
378       }
379       
380       /* Do the new part */
381       ptr = in+st->in_stride*(last_sample-N+1+j);
382       for (;j<N;j++)
383       {
384          sum += MULT16_16(*ptr,(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
385          ptr += st->in_stride;
386       }
387    
388       *out = sum;
389       out += st->out_stride;
390       out_sample++;
391       last_sample += st->int_advance;
392       samp_frac_num += st->frac_advance;
393       if (samp_frac_num >= st->den_rate)
394       {
395          samp_frac_num -= st->den_rate;
396          last_sample++;
397       }
398    }
399    st->last_sample[channel_index] = last_sample;
400    st->samp_frac_num[channel_index] = samp_frac_num;
401    return out_sample;
402 }
403 #endif
404
405 static int resampler_basic_interpolate_single(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)
406 {
407    int N = st->filt_len;
408    int out_sample = 0;
409    spx_word16_t *mem;
410    int last_sample = st->last_sample[channel_index];
411    spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
412    mem = st->mem + channel_index * st->mem_alloc_size;
413    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
414    {
415       int j;
416       spx_word32_t sum=0;
417       
418       /* We need to interpolate the sinc filter */
419       spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f};
420       spx_word16_t interp[4];
421       const spx_word16_t *ptr;
422       int offset;
423       spx_word16_t frac;
424       offset = samp_frac_num*st->oversample/st->den_rate;
425 #ifdef FIXED_POINT
426       frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
427 #else
428       frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
429 #endif
430          /* This code is written like this to make it easy to optimise with SIMD.
431       For most DSPs, it would be best to split the loops in two because most DSPs 
432       have only two accumulators */
433       for (j=0;last_sample-N+1+j < 0;j++)
434       {
435          spx_word16_t curr_mem = mem[last_sample+j];
436          accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
437          accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
438          accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
439          accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
440       }
441       ptr = in+st->in_stride*(last_sample-N+1+j);
442       /* Do the new part */
443       for (;j<N;j++)
444       {
445          spx_word16_t curr_in = *ptr;
446          ptr += st->in_stride;
447          accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
448          accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
449          accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
450          accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
451       }
452       cubic_coef(frac, interp);
453       sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
454    
455       *out = PSHR32(sum,15);
456       out += st->out_stride;
457       out_sample++;
458       last_sample += st->int_advance;
459       samp_frac_num += st->frac_advance;
460       if (samp_frac_num >= st->den_rate)
461       {
462          samp_frac_num -= st->den_rate;
463          last_sample++;
464       }
465    }
466    st->last_sample[channel_index] = last_sample;
467    st->samp_frac_num[channel_index] = samp_frac_num;
468    return out_sample;
469 }
470
471 #ifdef FIXED_POINT
472 #else
473 /* This is the same as the previous function, except with a double-precision accumulator */
474 static int resampler_basic_interpolate_double(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)
475 {
476    int N = st->filt_len;
477    int out_sample = 0;
478    spx_word16_t *mem;
479    int last_sample = st->last_sample[channel_index];
480    spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
481    mem = st->mem + channel_index * st->mem_alloc_size;
482    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
483    {
484       int j;
485       spx_word32_t sum=0;
486       
487       /* We need to interpolate the sinc filter */
488       double accum[4] = {0.f,0.f, 0.f, 0.f};
489       float interp[4];
490       const spx_word16_t *ptr;
491       float alpha = ((float)samp_frac_num)/st->den_rate;
492       int offset = samp_frac_num*st->oversample/st->den_rate;
493       float frac = alpha*st->oversample - offset;
494          /* This code is written like this to make it easy to optimise with SIMD.
495       For most DSPs, it would be best to split the loops in two because most DSPs 
496       have only two accumulators */
497       for (j=0;last_sample-N+1+j < 0;j++)
498       {
499          double curr_mem = mem[last_sample+j];
500          accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
501          accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
502          accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
503          accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
504       }
505       ptr = in+st->in_stride*(last_sample-N+1+j);
506       /* Do the new part */
507       for (;j<N;j++)
508       {
509          double curr_in = *ptr;
510          ptr += st->in_stride;
511          accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
512          accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
513          accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
514          accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
515       }
516       cubic_coef(frac, interp);
517       sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3];
518    
519       *out = PSHR32(sum,15);
520       out += st->out_stride;
521       out_sample++;
522       last_sample += st->int_advance;
523       samp_frac_num += st->frac_advance;
524       if (samp_frac_num >= st->den_rate)
525       {
526          samp_frac_num -= st->den_rate;
527          last_sample++;
528       }
529    }
530    st->last_sample[channel_index] = last_sample;
531    st->samp_frac_num[channel_index] = samp_frac_num;
532    return out_sample;
533 }
534 #endif
535
536 static void update_filter(SpeexResamplerState *st)
537 {
538    spx_uint32_t old_length;
539    
540    old_length = st->filt_len;
541    st->oversample = quality_map[st->quality].oversample;
542    st->filt_len = quality_map[st->quality].base_length;
543    
544    if (st->num_rate > st->den_rate)
545    {
546       /* down-sampling */
547       st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
548       /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
549       st->filt_len = st->filt_len*st->num_rate / st->den_rate;
550       /* Round down to make sure we have a multiple of 4 */
551       st->filt_len &= (~0x3);
552       if (2*st->den_rate < st->num_rate)
553          st->oversample >>= 1;
554       if (4*st->den_rate < st->num_rate)
555          st->oversample >>= 1;
556       if (8*st->den_rate < st->num_rate)
557          st->oversample >>= 1;
558       if (16*st->den_rate < st->num_rate)
559          st->oversample >>= 1;
560       if (st->oversample < 1)
561          st->oversample = 1;
562    } else {
563       /* up-sampling */
564       st->cutoff = quality_map[st->quality].upsample_bandwidth;
565    }
566
567    /* Choose the resampling type that requires the least amount of memory */
568    if (st->den_rate <= st->oversample)
569    {
570       spx_uint32_t i;
571       if (!st->sinc_table)
572          st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));
573       else if (st->sinc_table_length < st->filt_len*st->den_rate)
574       {
575          st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));
576          st->sinc_table_length = st->filt_len*st->den_rate;
577       }
578       for (i=0;i<st->den_rate;i++)
579       {
580          spx_int32_t j;
581          for (j=0;j<st->filt_len;j++)
582          {
583             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);
584          }
585       }
586 #ifdef FIXED_POINT
587       st->resampler_ptr = resampler_basic_direct_single;
588 #else
589       if (st->quality>8)
590          st->resampler_ptr = resampler_basic_direct_double;
591       else
592          st->resampler_ptr = resampler_basic_direct_single;
593 #endif
594       /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/
595    } else {
596       spx_int32_t i;
597       if (!st->sinc_table)
598          st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
599       else if (st->sinc_table_length < st->filt_len*st->oversample+8)
600       {
601          st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
602          st->sinc_table_length = st->filt_len*st->oversample+8;
603       }
604       for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)
605          st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func);
606 #ifdef FIXED_POINT
607       st->resampler_ptr = resampler_basic_interpolate_single;
608 #else
609       if (st->quality>8)
610          st->resampler_ptr = resampler_basic_interpolate_double;
611       else
612          st->resampler_ptr = resampler_basic_interpolate_single;
613 #endif
614       /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/
615    }
616    st->int_advance = st->num_rate/st->den_rate;
617    st->frac_advance = st->num_rate%st->den_rate;
618
619    
620    /* Here's the place where we update the filter memory to take into account
621       the change in filter length. It's probably the messiest part of the code
622       due to handling of lots of corner cases. */
623    if (!st->mem)
624    {
625       spx_uint32_t i;
626       st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
627       for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
628          st->mem[i] = 0;
629       st->mem_alloc_size = st->filt_len-1;
630       /*speex_warning("init filter");*/
631    } else if (!st->started)
632    {
633       spx_uint32_t i;
634       st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
635       for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
636          st->mem[i] = 0;
637       st->mem_alloc_size = st->filt_len-1;
638       /*speex_warning("reinit filter");*/
639    } else if (st->filt_len > old_length)
640    {
641       spx_int32_t i;
642       /* Increase the filter length */
643       /*speex_warning("increase filter size");*/
644       int old_alloc_size = st->mem_alloc_size;
645       if (st->filt_len-1 > st->mem_alloc_size)
646       {
647          st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
648          st->mem_alloc_size = st->filt_len-1;
649       }
650       for (i=st->nb_channels-1;i>=0;i--)
651       {
652          spx_int32_t j;
653          spx_uint32_t olen = old_length;
654          /*if (st->magic_samples[i])*/
655          {
656             /* Try and remove the magic samples as if nothing had happened */
657             
658             /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
659             olen = old_length + 2*st->magic_samples[i];
660             for (j=old_length-2+st->magic_samples[i];j>=0;j--)
661                st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
662             for (j=0;j<st->magic_samples[i];j++)
663                st->mem[i*st->mem_alloc_size+j] = 0;
664             st->magic_samples[i] = 0;
665          }
666          if (st->filt_len > olen)
667          {
668             /* If the new filter length is still bigger than the "augmented" length */
669             /* Copy data going backward */
670             for (j=0;j<olen-1;j++)
671                st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
672             /* Then put zeros for lack of anything better */
673             for (;j<st->filt_len-1;j++)
674                st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
675             /* Adjust last_sample */
676             st->last_sample[i] += (st->filt_len - olen)/2;
677          } else {
678             /* Put back some of the magic! */
679             st->magic_samples[i] = (olen - st->filt_len)/2;
680             for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
681                st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
682          }
683       }
684    } else if (st->filt_len < old_length)
685    {
686       spx_uint32_t i;
687       /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
688          samples so they can be used directly as input the next time(s) */
689       for (i=0;i<st->nb_channels;i++)
690       {
691          spx_uint32_t j;
692          spx_uint32_t old_magic = st->magic_samples[i];
693          st->magic_samples[i] = (old_length - st->filt_len)/2;
694          /* We must copy some of the memory that's no longer used */
695          /* Copy data going backward */
696          for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
697             st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
698          st->magic_samples[i] += old_magic;
699       }
700    }
701
702 }
703
704 SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
705 {
706    return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
707 }
708
709 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)
710 {
711    spx_uint32_t i;
712    SpeexResamplerState *st;
713    if (quality > 10 || quality < 0)
714    {
715       if (err)
716          *err = RESAMPLER_ERR_INVALID_ARG;
717       return NULL;
718    }
719    st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
720    st->initialised = 0;
721    st->started = 0;
722    st->in_rate = 0;
723    st->out_rate = 0;
724    st->num_rate = 0;
725    st->den_rate = 0;
726    st->quality = -1;
727    st->sinc_table_length = 0;
728    st->mem_alloc_size = 0;
729    st->filt_len = 0;
730    st->mem = 0;
731    st->resampler_ptr = 0;
732          
733    st->cutoff = 1.f;
734    st->nb_channels = nb_channels;
735    st->in_stride = 1;
736    st->out_stride = 1;
737    
738    /* Per channel data */
739    st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
740    st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
741    st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
742    for (i=0;i<nb_channels;i++)
743    {
744       st->last_sample[i] = 0;
745       st->magic_samples[i] = 0;
746       st->samp_frac_num[i] = 0;
747    }
748
749    speex_resampler_set_quality(st, quality);
750    speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
751
752    
753    update_filter(st);
754    
755    st->initialised = 1;
756    if (err)
757       *err = RESAMPLER_ERR_SUCCESS;
758
759    return st;
760 }
761
762 void speex_resampler_destroy(SpeexResamplerState *st)
763 {
764    speex_free(st->mem);
765    speex_free(st->sinc_table);
766    speex_free(st->last_sample);
767    speex_free(st->magic_samples);
768    speex_free(st->samp_frac_num);
769    speex_free(st);
770 }
771
772
773
774 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)
775 {
776    int j=0;
777    int N = st->filt_len;
778    int out_sample = 0;
779    spx_word16_t *mem;
780    spx_uint32_t tmp_out_len = 0;
781    mem = st->mem + channel_index * st->mem_alloc_size;
782    st->started = 1;
783    
784    /* Handle the case where we have samples left from a reduction in filter length */
785    if (st->magic_samples[channel_index])
786    {
787       int istride_save;
788       spx_uint32_t tmp_in_len;
789       spx_uint32_t tmp_magic;
790       
791       istride_save = st->in_stride;
792       tmp_in_len = st->magic_samples[channel_index];
793       tmp_out_len = *out_len;
794       /* magic_samples needs to be set to zero to avoid infinite recursion */
795       tmp_magic = st->magic_samples[channel_index];
796       st->magic_samples[channel_index] = 0;
797       st->in_stride = 1;
798       speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len);
799       st->in_stride = istride_save;
800       /*speex_warning_int("extra samples:", tmp_out_len);*/
801       /* If we couldn't process all "magic" input samples, save the rest for next time */
802       if (tmp_in_len < tmp_magic)
803       {
804          spx_uint32_t i;
805          st->magic_samples[channel_index] = tmp_magic-tmp_in_len;
806          for (i=0;i<st->magic_samples[channel_index];i++)
807             mem[N-1+i]=mem[N-1+i+tmp_in_len];
808       }
809       out += tmp_out_len*st->out_stride;
810       *out_len -= tmp_out_len;
811    }
812    
813    /* Call the right resampler through the function ptr */
814    out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len);
815    
816    if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
817       *in_len = st->last_sample[channel_index];
818    *out_len = out_sample+tmp_out_len;
819    st->last_sample[channel_index] -= *in_len;
820    
821    for (j=0;j<N-1-(spx_int32_t)*in_len;j++)
822       mem[j] = mem[j+*in_len];
823    for (;j<N-1;j++)
824       mem[j] = in[st->in_stride*(j+*in_len-N+1)];
825    
826    return RESAMPLER_ERR_SUCCESS;
827 }
828
829 #define FIXED_STACK_ALLOC 1024
830
831 #ifdef FIXED_POINT
832 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)
833 {
834    spx_uint32_t i;
835    int istride_save, ostride_save;
836 #ifdef VAR_ARRAYS
837    spx_word16_t x[*in_len];
838    spx_word16_t y[*out_len];
839    /*VARDECL(spx_word16_t *x);
840    VARDECL(spx_word16_t *y);
841    ALLOC(x, *in_len, spx_word16_t);
842    ALLOC(y, *out_len, spx_word16_t);*/
843    istride_save = st->in_stride;
844    ostride_save = st->out_stride;
845    for (i=0;i<*in_len;i++)
846       x[i] = WORD2INT(in[i*st->in_stride]);
847    st->in_stride = st->out_stride = 1;
848    speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
849    st->in_stride = istride_save;
850    st->out_stride = ostride_save;
851    for (i=0;i<*out_len;i++)
852       out[i*st->out_stride] = y[i];
853 #else
854    spx_word16_t x[FIXED_STACK_ALLOC];
855    spx_word16_t y[FIXED_STACK_ALLOC];
856    spx_uint32_t ilen=*in_len, olen=*out_len;
857    istride_save = st->in_stride;
858    ostride_save = st->out_stride;
859    while (ilen && olen)
860    {
861       spx_uint32_t ichunk, ochunk;
862       ichunk = ilen;
863       ochunk = olen;
864       if (ichunk>FIXED_STACK_ALLOC)
865          ichunk=FIXED_STACK_ALLOC;
866       if (ochunk>FIXED_STACK_ALLOC)
867          ochunk=FIXED_STACK_ALLOC;
868       for (i=0;i<ichunk;i++)
869          x[i] = WORD2INT(in[i*st->in_stride]);
870       st->in_stride = st->out_stride = 1;
871       speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
872       st->in_stride = istride_save;
873       st->out_stride = ostride_save;
874       for (i=0;i<ochunk;i++)
875          out[i*st->out_stride] = y[i];
876       out += ochunk;
877       in += ichunk;
878       ilen -= ichunk;
879       olen -= ochunk;
880    }
881    *in_len -= ilen;
882    *out_len -= olen;   
883 #endif
884    return RESAMPLER_ERR_SUCCESS;
885 }
886 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)
887 {
888    return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
889 }
890 #else
891 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)
892 {
893    return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
894 }
895 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)
896 {
897    spx_uint32_t i;
898    int istride_save, ostride_save;
899 #ifdef VAR_ARRAYS
900    spx_word16_t x[*in_len];
901    spx_word16_t y[*out_len];
902    /*VARDECL(spx_word16_t *x);
903    VARDECL(spx_word16_t *y);
904    ALLOC(x, *in_len, spx_word16_t);
905    ALLOC(y, *out_len, spx_word16_t);*/
906    istride_save = st->in_stride;
907    ostride_save = st->out_stride;
908    for (i=0;i<*in_len;i++)
909       x[i] = in[i*st->in_stride];
910    st->in_stride = st->out_stride = 1;
911    speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
912    st->in_stride = istride_save;
913    st->out_stride = ostride_save;
914    for (i=0;i<*out_len;i++)
915       out[i*st->out_stride] = WORD2INT(y[i]);
916 #else
917    spx_word16_t x[FIXED_STACK_ALLOC];
918    spx_word16_t y[FIXED_STACK_ALLOC];
919    spx_uint32_t ilen=*in_len, olen=*out_len;
920    istride_save = st->in_stride;
921    ostride_save = st->out_stride;
922    while (ilen && olen)
923    {
924       spx_uint32_t ichunk, ochunk;
925       ichunk = ilen;
926       ochunk = olen;
927       if (ichunk>FIXED_STACK_ALLOC)
928          ichunk=FIXED_STACK_ALLOC;
929       if (ochunk>FIXED_STACK_ALLOC)
930          ochunk=FIXED_STACK_ALLOC;
931       for (i=0;i<ichunk;i++)
932          x[i] = in[i*st->in_stride];
933       st->in_stride = st->out_stride = 1;
934       speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
935       st->in_stride = istride_save;
936       st->out_stride = ostride_save;
937       for (i=0;i<ochunk;i++)
938          out[i*st->out_stride] = WORD2INT(y[i]);
939       out += ochunk;
940       in += ichunk;
941       ilen -= ichunk;
942       olen -= ochunk;
943    }
944    *in_len -= ilen;
945    *out_len -= olen;   
946 #endif
947    return RESAMPLER_ERR_SUCCESS;
948 }
949 #endif
950
951 int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
952 {
953    spx_uint32_t i;
954    int istride_save, ostride_save;
955    spx_uint32_t bak_len = *out_len;
956    istride_save = st->in_stride;
957    ostride_save = st->out_stride;
958    st->in_stride = st->out_stride = st->nb_channels;
959    for (i=0;i<st->nb_channels;i++)
960    {
961       *out_len = bak_len;
962       speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
963    }
964    st->in_stride = istride_save;
965    st->out_stride = ostride_save;
966    return RESAMPLER_ERR_SUCCESS;
967 }
968
969                
970 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)
971 {
972    spx_uint32_t i;
973    int istride_save, ostride_save;
974    spx_uint32_t bak_len = *out_len;
975    istride_save = st->in_stride;
976    ostride_save = st->out_stride;
977    st->in_stride = st->out_stride = st->nb_channels;
978    for (i=0;i<st->nb_channels;i++)
979    {
980       *out_len = bak_len;
981       speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
982    }
983    st->in_stride = istride_save;
984    st->out_stride = ostride_save;
985    return RESAMPLER_ERR_SUCCESS;
986 }
987
988 int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
989 {
990    return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
991 }
992
993 void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
994 {
995    *in_rate = st->in_rate;
996    *out_rate = st->out_rate;
997 }
998
999 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)
1000 {
1001    spx_uint32_t fact;
1002    spx_uint32_t old_den;
1003    spx_uint32_t i;
1004    if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
1005       return RESAMPLER_ERR_SUCCESS;
1006    
1007    old_den = st->den_rate;
1008    st->in_rate = in_rate;
1009    st->out_rate = out_rate;
1010    st->num_rate = ratio_num;
1011    st->den_rate = ratio_den;
1012    /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
1013    for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
1014    {
1015       while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
1016       {
1017          st->num_rate /= fact;
1018          st->den_rate /= fact;
1019       }
1020    }
1021       
1022    if (old_den > 0)
1023    {
1024       for (i=0;i<st->nb_channels;i++)
1025       {
1026          st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
1027          /* Safety net */
1028          if (st->samp_frac_num[i] >= st->den_rate)
1029             st->samp_frac_num[i] = st->den_rate-1;
1030       }
1031    }
1032    
1033    if (st->initialised)
1034       update_filter(st);
1035    return RESAMPLER_ERR_SUCCESS;
1036 }
1037
1038 void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
1039 {
1040    *ratio_num = st->num_rate;
1041    *ratio_den = st->den_rate;
1042 }
1043
1044 int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
1045 {
1046    if (quality > 10 || quality < 0)
1047       return RESAMPLER_ERR_INVALID_ARG;
1048    if (st->quality == quality)
1049       return RESAMPLER_ERR_SUCCESS;
1050    st->quality = quality;
1051    if (st->initialised)
1052       update_filter(st);
1053    return RESAMPLER_ERR_SUCCESS;
1054 }
1055
1056 void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
1057 {
1058    *quality = st->quality;
1059 }
1060
1061 void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
1062 {
1063    st->in_stride = stride;
1064 }
1065
1066 void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1067 {
1068    *stride = st->in_stride;
1069 }
1070
1071 void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
1072 {
1073    st->out_stride = stride;
1074 }
1075
1076 void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1077 {
1078    *stride = st->out_stride;
1079 }
1080
1081 int speex_resampler_skip_zeros(SpeexResamplerState *st)
1082 {
1083    spx_uint32_t i;
1084    for (i=0;i<st->nb_channels;i++)
1085       st->last_sample[i] = st->filt_len/2;
1086    return RESAMPLER_ERR_SUCCESS;
1087 }
1088
1089 int speex_resampler_reset_mem(SpeexResamplerState *st)
1090 {
1091    spx_uint32_t i;
1092    for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
1093       st->mem[i] = 0;
1094    return RESAMPLER_ERR_SUCCESS;
1095 }
1096
1097 const char *speex_resampler_strerror(int err)
1098 {
1099    switch (err)
1100    {
1101       case RESAMPLER_ERR_SUCCESS:
1102          return "Success.";
1103       case RESAMPLER_ERR_ALLOC_FAILED:
1104          return "Memory allocation failed.";
1105       case RESAMPLER_ERR_BAD_STATE:
1106          return "Bad resampler state.";
1107       case RESAMPLER_ERR_INVALID_ARG:
1108          return "Invalid argument.";
1109       case RESAMPLER_ERR_PTR_OVERLAP:
1110          return "Input and output buffers overlap.";
1111       default:
1112          return "Unknown error. Bad error code or strange version mismatch.";
1113    }
1114 }