]> code.delx.au - pulseaudio/blob - src/pulsecore/speex/resample.c
merge 'lennart' branch back into trunk.
[pulseaudio] / src / pulsecore / speex / 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 }