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