]> code.delx.au - pulseaudio/blob - src/pulsecore/speex/resample.c
beefup proplist handling for sound events
[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 Warning: This resampler is relatively new. Although I think I got rid of
41 all the major bugs and I don't expect the API to change anymore, there
42 may be something I've missed. So use with caution.
43
44 This algorithm is based on this original resampling algorithm:
45 Smith, Julius O. Digital Audio Resampling Home Page
46 Center for Computer Research in Music and Acoustics (CCRMA),
47 Stanford University, 2007.
48 Web published at http://www-ccrma.stanford.edu/~jos/resample/.
49
50 There is one main difference, though. This resampler uses cubic
51 interpolation instead of linear interpolation in the above paper. This
52 makes the table much smaller and makes it possible to compute that table
53 on a per-stream basis. In turn, being able to tweak the table for each
54 stream makes it possible to both reduce complexity on simple ratios
55 (e.g. 2/3), and get rid of the rounding operations in the inner loop.
56 The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
57 */
58
59 #ifdef HAVE_CONFIG_H
60 #include "config.h"
61 #endif
62
63 #ifdef OUTSIDE_SPEEX
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 #else /* OUTSIDE_SPEEX */
71
72 #include "speex/speex_resampler.h"
73 #include "arch.h"
74 #include "os_support.h"
75 #endif /* OUTSIDE_SPEEX */
76
77 #include <math.h>
78
79 #ifndef M_PI
80 #define M_PI 3.14159263
81 #endif
82
83 #ifdef FIXED_POINT
84 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
85 #else
86 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
87 #endif
88
89 /*#define float double*/
90 #define FILTER_SIZE 64
91 #define OVERSAMPLE 8
92
93 #define IMAX(a,b) ((a) > (b) ? (a) : (b))
94 #define IMIN(a,b) ((a) < (b) ? (a) : (b))
95
96 #ifndef NULL
97 #define NULL 0
98 #endif
99
100 typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
101
102 struct SpeexResamplerState_ {
103 spx_uint32_t in_rate;
104 spx_uint32_t out_rate;
105 spx_uint32_t num_rate;
106 spx_uint32_t den_rate;
107
108 int quality;
109 spx_uint32_t nb_channels;
110 spx_uint32_t filt_len;
111 spx_uint32_t mem_alloc_size;
112 int int_advance;
113 int frac_advance;
114 float cutoff;
115 spx_uint32_t oversample;
116 int initialised;
117 int started;
118
119 /* These are per-channel */
120 spx_int32_t *last_sample;
121 spx_uint32_t *samp_frac_num;
122 spx_uint32_t *magic_samples;
123
124 spx_word16_t *mem;
125 spx_word16_t *sinc_table;
126 spx_uint32_t sinc_table_length;
127 resampler_basic_func resampler_ptr;
128
129 int in_stride;
130 int out_stride;
131 } ;
132
133 static double kaiser12_table[68] = {
134 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
135 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
136 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
137 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
138 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
139 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
140 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
141 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
142 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
143 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
144 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
145 0.00001000, 0.00000000};
146 /*
147 static double kaiser12_table[36] = {
148 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
149 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
150 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
151 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
152 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
153 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
154 */
155 static double kaiser10_table[36] = {
156 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
157 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
158 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
159 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
160 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
161 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
162
163 static double kaiser8_table[36] = {
164 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
165 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
166 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
167 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
168 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
169 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
170
171 static double kaiser6_table[36] = {
172 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
173 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
174 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
175 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
176 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
177 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
178
179 struct FuncDef {
180 double *table;
181 int oversample;
182 };
183
184 static struct FuncDef _KAISER12 = {kaiser12_table, 64};
185 #define KAISER12 (&_KAISER12)
186 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
187 #define KAISER12 (&_KAISER12)*/
188 static struct FuncDef _KAISER10 = {kaiser10_table, 32};
189 #define KAISER10 (&_KAISER10)
190 static struct FuncDef _KAISER8 = {kaiser8_table, 32};
191 #define KAISER8 (&_KAISER8)
192 static struct FuncDef _KAISER6 = {kaiser6_table, 32};
193 #define KAISER6 (&_KAISER6)
194
195 struct QualityMapping {
196 int base_length;
197 int oversample;
198 float downsample_bandwidth;
199 float upsample_bandwidth;
200 struct FuncDef *window_func;
201 };
202
203
204 /* This table maps conversion quality to internal parameters. There are two
205 reasons that explain why the up-sampling bandwidth is larger than the
206 down-sampling bandwidth:
207 1) When up-sampling, we can assume that the spectrum is already attenuated
208 close to the Nyquist rate (from an A/D or a previous resampling filter)
209 2) Any aliasing that occurs very close to the Nyquist rate will be masked
210 by the sinusoids/noise just below the Nyquist rate (guaranteed only for
211 up-sampling).
212 */
213 static const struct QualityMapping quality_map[11] = {
214 { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */
215 { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */
216 { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */
217 { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */
218 { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */
219 { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */
220 { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */
221 {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */
222 {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */
223 {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */
224 {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
225 };
226 /*8,24,40,56,80,104,128,160,200,256,320*/
227 static double compute_func(float x, struct FuncDef *func)
228 {
229 float y, frac;
230 double interp[4];
231 int ind;
232 y = x*func->oversample;
233 ind = (int)floor(y);
234 frac = (y-ind);
235 /* CSE with handle the repeated powers */
236 interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac);
237 interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac);
238 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
239 interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
240 /* Just to make sure we don't have rounding problems */
241 interp[1] = 1.f-interp[3]-interp[2]-interp[0];
242
243 /*sum = frac*accum[1] + (1-frac)*accum[2];*/
244 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
245 }
246
247 #if 0
248 #include <stdio.h>
249 int main(int argc, char **argv)
250 {
251 int i;
252 for (i=0;i<256;i++)
253 {
254 printf ("%f\n", compute_func(i/256., KAISER12));
255 }
256 return 0;
257 }
258 #endif
259
260 #ifdef FIXED_POINT
261 /* The slow way of computing a sinc for the table. Should improve that some day */
262 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
263 {
264 /*fprintf (stderr, "%f ", x);*/
265 float xx = x * cutoff;
266 if (fabs(x)<1e-6f)
267 return WORD2INT(32768.*cutoff);
268 else if (fabs(x) > .5f*N)
269 return 0;
270 /*FIXME: Can it really be any slower than this? */
271 return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
272 }
273 #else
274 /* The slow way of computing a sinc for the table. Should improve that some day */
275 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
276 {
277 /*fprintf (stderr, "%f ", x);*/
278 float xx = x * cutoff;
279 if (fabs(x)<1e-6)
280 return cutoff;
281 else if (fabs(x) > .5*N)
282 return 0;
283 /*FIXME: Can it really be any slower than this? */
284 return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func);
285 }
286 #endif
287
288 #ifdef FIXED_POINT
289 static void cubic_coef(spx_word16_t x, spx_word16_t interp[4])
290 {
291 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
292 but I know it's MMSE-optimal on a sinc */
293 spx_word16_t x2, x3;
294 x2 = MULT16_16_P15(x, x);
295 x3 = MULT16_16_P15(x, x2);
296 interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
297 interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
298 interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15);
299 /* Just to make sure we don't have rounding problems */
300 interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3];
301 if (interp[2]<32767)
302 interp[2]+=1;
303 }
304 #else
305 static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
306 {
307 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
308 but I know it's MMSE-optimal on a sinc */
309 interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac;
310 interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac;
311 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
312 interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac;
313 /* Just to make sure we don't have rounding problems */
314 interp[2] = 1.-interp[0]-interp[1]-interp[3];
315 }
316 #endif
317
318 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)
319 {
320 int N = st->filt_len;
321 int out_sample = 0;
322 spx_word16_t *mem;
323 int last_sample = st->last_sample[channel_index];
324 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
325 mem = st->mem + channel_index * st->mem_alloc_size;
326 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
327 {
328 int j;
329 spx_word32_t sum=0;
330
331 /* We already have all the filter coefficients pre-computed in the table */
332 const spx_word16_t *ptr;
333 /* Do the memory part */
334 for (j=0;last_sample-N+1+j < 0;j++)
335 {
336 sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]);
337 }
338
339 /* Do the new part */
340 ptr = in+st->in_stride*(last_sample-N+1+j);
341 for (;j<N;j++)
342 {
343 sum += MULT16_16(*ptr,st->sinc_table[samp_frac_num*st->filt_len+j]);
344 ptr += st->in_stride;
345 }
346
347 *out = PSHR32(sum,15);
348 out += st->out_stride;
349 out_sample++;
350 last_sample += st->int_advance;
351 samp_frac_num += st->frac_advance;
352 if (samp_frac_num >= st->den_rate)
353 {
354 samp_frac_num -= st->den_rate;
355 last_sample++;
356 }
357 }
358 st->last_sample[channel_index] = last_sample;
359 st->samp_frac_num[channel_index] = samp_frac_num;
360 return out_sample;
361 }
362
363 #ifdef FIXED_POINT
364 #else
365 /* This is the same as the previous function, except with a double-precision accumulator */
366 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)
367 {
368 int N = st->filt_len;
369 int out_sample = 0;
370 spx_word16_t *mem;
371 int last_sample = st->last_sample[channel_index];
372 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
373 mem = st->mem + channel_index * st->mem_alloc_size;
374 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
375 {
376 int j;
377 double sum=0;
378
379 /* We already have all the filter coefficients pre-computed in the table */
380 const spx_word16_t *ptr;
381 /* Do the memory part */
382 for (j=0;last_sample-N+1+j < 0;j++)
383 {
384 sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
385 }
386
387 /* Do the new part */
388 ptr = in+st->in_stride*(last_sample-N+1+j);
389 for (;j<N;j++)
390 {
391 sum += MULT16_16(*ptr,(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
392 ptr += st->in_stride;
393 }
394
395 *out = sum;
396 out += st->out_stride;
397 out_sample++;
398 last_sample += st->int_advance;
399 samp_frac_num += st->frac_advance;
400 if (samp_frac_num >= st->den_rate)
401 {
402 samp_frac_num -= st->den_rate;
403 last_sample++;
404 }
405 }
406 st->last_sample[channel_index] = last_sample;
407 st->samp_frac_num[channel_index] = samp_frac_num;
408 return out_sample;
409 }
410 #endif
411
412 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)
413 {
414 int N = st->filt_len;
415 int out_sample = 0;
416 spx_word16_t *mem;
417 int last_sample = st->last_sample[channel_index];
418 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
419 mem = st->mem + channel_index * st->mem_alloc_size;
420 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
421 {
422 int j;
423 spx_word32_t sum=0;
424
425 /* We need to interpolate the sinc filter */
426 spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f};
427 spx_word16_t interp[4];
428 const spx_word16_t *ptr;
429 int offset;
430 spx_word16_t frac;
431 offset = samp_frac_num*st->oversample/st->den_rate;
432 #ifdef FIXED_POINT
433 frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
434 #else
435 frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
436 #endif
437 /* This code is written like this to make it easy to optimise with SIMD.
438 For most DSPs, it would be best to split the loops in two because most DSPs
439 have only two accumulators */
440 for (j=0;last_sample-N+1+j < 0;j++)
441 {
442 spx_word16_t curr_mem = mem[last_sample+j];
443 accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
444 accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
445 accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
446 accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
447 }
448 ptr = in+st->in_stride*(last_sample-N+1+j);
449 /* Do the new part */
450 for (;j<N;j++)
451 {
452 spx_word16_t curr_in = *ptr;
453 ptr += st->in_stride;
454 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
455 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
456 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
457 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
458 }
459 cubic_coef(frac, interp);
460 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]);
461
462 *out = PSHR32(sum,15);
463 out += st->out_stride;
464 out_sample++;
465 last_sample += st->int_advance;
466 samp_frac_num += st->frac_advance;
467 if (samp_frac_num >= st->den_rate)
468 {
469 samp_frac_num -= st->den_rate;
470 last_sample++;
471 }
472 }
473 st->last_sample[channel_index] = last_sample;
474 st->samp_frac_num[channel_index] = samp_frac_num;
475 return out_sample;
476 }
477
478 #ifdef FIXED_POINT
479 #else
480 /* This is the same as the previous function, except with a double-precision accumulator */
481 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)
482 {
483 int N = st->filt_len;
484 int out_sample = 0;
485 spx_word16_t *mem;
486 int last_sample = st->last_sample[channel_index];
487 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
488 mem = st->mem + channel_index * st->mem_alloc_size;
489 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
490 {
491 int j;
492 spx_word32_t sum=0;
493
494 /* We need to interpolate the sinc filter */
495 double accum[4] = {0.f,0.f, 0.f, 0.f};
496 float interp[4];
497 const spx_word16_t *ptr;
498 float alpha = ((float)samp_frac_num)/st->den_rate;
499 int offset = samp_frac_num*st->oversample/st->den_rate;
500 float frac = alpha*st->oversample - offset;
501 /* This code is written like this to make it easy to optimise with SIMD.
502 For most DSPs, it would be best to split the loops in two because most DSPs
503 have only two accumulators */
504 for (j=0;last_sample-N+1+j < 0;j++)
505 {
506 double curr_mem = mem[last_sample+j];
507 accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
508 accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
509 accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
510 accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
511 }
512 ptr = in+st->in_stride*(last_sample-N+1+j);
513 /* Do the new part */
514 for (;j<N;j++)
515 {
516 double curr_in = *ptr;
517 ptr += st->in_stride;
518 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
519 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
520 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
521 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
522 }
523 cubic_coef(frac, interp);
524 sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3];
525
526 *out = PSHR32(sum,15);
527 out += st->out_stride;
528 out_sample++;
529 last_sample += st->int_advance;
530 samp_frac_num += st->frac_advance;
531 if (samp_frac_num >= st->den_rate)
532 {
533 samp_frac_num -= st->den_rate;
534 last_sample++;
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 = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
634 for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
635 st->mem[i] = 0;
636 st->mem_alloc_size = st->filt_len-1;
637 /*speex_warning("init filter");*/
638 } else if (!st->started)
639 {
640 spx_uint32_t i;
641 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
642 for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
643 st->mem[i] = 0;
644 st->mem_alloc_size = st->filt_len-1;
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->mem_alloc_size)
653 {
654 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
655 st->mem_alloc_size = st->filt_len-1;
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 /* Per channel data */
746 st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
747 st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
748 st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
749 for (i=0;i<nb_channels;i++)
750 {
751 st->last_sample[i] = 0;
752 st->magic_samples[i] = 0;
753 st->samp_frac_num[i] = 0;
754 }
755
756 speex_resampler_set_quality(st, quality);
757 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
758
759
760 update_filter(st);
761
762 st->initialised = 1;
763 if (err)
764 *err = RESAMPLER_ERR_SUCCESS;
765
766 return st;
767 }
768
769 void speex_resampler_destroy(SpeexResamplerState *st)
770 {
771 speex_free(st->mem);
772 speex_free(st->sinc_table);
773 speex_free(st->last_sample);
774 speex_free(st->magic_samples);
775 speex_free(st->samp_frac_num);
776 speex_free(st);
777 }
778
779
780
781 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)
782 {
783 int j=0;
784 int N = st->filt_len;
785 int out_sample = 0;
786 spx_word16_t *mem;
787 spx_uint32_t tmp_out_len = 0;
788 mem = st->mem + channel_index * st->mem_alloc_size;
789 st->started = 1;
790
791 /* Handle the case where we have samples left from a reduction in filter length */
792 if (st->magic_samples[channel_index])
793 {
794 int istride_save;
795 spx_uint32_t tmp_in_len;
796 spx_uint32_t tmp_magic;
797
798 istride_save = st->in_stride;
799 tmp_in_len = st->magic_samples[channel_index];
800 tmp_out_len = *out_len;
801 /* magic_samples needs to be set to zero to avoid infinite recursion */
802 tmp_magic = st->magic_samples[channel_index];
803 st->magic_samples[channel_index] = 0;
804 st->in_stride = 1;
805 speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len);
806 st->in_stride = istride_save;
807 /*speex_warning_int("extra samples:", tmp_out_len);*/
808 /* If we couldn't process all "magic" input samples, save the rest for next time */
809 if (tmp_in_len < tmp_magic)
810 {
811 spx_uint32_t i;
812 st->magic_samples[channel_index] = tmp_magic-tmp_in_len;
813 for (i=0;i<st->magic_samples[channel_index];i++)
814 mem[N-1+i]=mem[N-1+i+tmp_in_len];
815 }
816 out += tmp_out_len*st->out_stride;
817 *out_len -= tmp_out_len;
818 }
819
820 /* Call the right resampler through the function ptr */
821 out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len);
822
823 if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
824 *in_len = st->last_sample[channel_index];
825 *out_len = out_sample+tmp_out_len;
826 st->last_sample[channel_index] -= *in_len;
827
828 for (j=0;j<N-1-(spx_int32_t)*in_len;j++)
829 mem[j] = mem[j+*in_len];
830 for (;j<N-1;j++)
831 mem[j] = in[st->in_stride*(j+*in_len-N+1)];
832
833 return RESAMPLER_ERR_SUCCESS;
834 }
835
836 #define FIXED_STACK_ALLOC 1024
837
838 #ifdef FIXED_POINT
839 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)
840 {
841 spx_uint32_t i;
842 int istride_save, ostride_save;
843 #ifdef VAR_ARRAYS
844 spx_word16_t x[*in_len];
845 spx_word16_t y[*out_len];
846 /*VARDECL(spx_word16_t *x);
847 VARDECL(spx_word16_t *y);
848 ALLOC(x, *in_len, spx_word16_t);
849 ALLOC(y, *out_len, spx_word16_t);*/
850 istride_save = st->in_stride;
851 ostride_save = st->out_stride;
852 for (i=0;i<*in_len;i++)
853 x[i] = WORD2INT(in[i*st->in_stride]);
854 st->in_stride = st->out_stride = 1;
855 speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
856 st->in_stride = istride_save;
857 st->out_stride = ostride_save;
858 for (i=0;i<*out_len;i++)
859 out[i*st->out_stride] = y[i];
860 #else
861 spx_word16_t x[FIXED_STACK_ALLOC];
862 spx_word16_t y[FIXED_STACK_ALLOC];
863 spx_uint32_t ilen=*in_len, olen=*out_len;
864 istride_save = st->in_stride;
865 ostride_save = st->out_stride;
866 while (ilen && olen)
867 {
868 spx_uint32_t ichunk, ochunk;
869 ichunk = ilen;
870 ochunk = olen;
871 if (ichunk>FIXED_STACK_ALLOC)
872 ichunk=FIXED_STACK_ALLOC;
873 if (ochunk>FIXED_STACK_ALLOC)
874 ochunk=FIXED_STACK_ALLOC;
875 for (i=0;i<ichunk;i++)
876 x[i] = WORD2INT(in[i*st->in_stride]);
877 st->in_stride = st->out_stride = 1;
878 speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
879 st->in_stride = istride_save;
880 st->out_stride = ostride_save;
881 for (i=0;i<ochunk;i++)
882 out[i*st->out_stride] = y[i];
883 out += ochunk;
884 in += ichunk;
885 ilen -= ichunk;
886 olen -= ochunk;
887 }
888 *in_len -= ilen;
889 *out_len -= olen;
890 #endif
891 return RESAMPLER_ERR_SUCCESS;
892 }
893 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)
894 {
895 return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
896 }
897 #else
898 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)
899 {
900 return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
901 }
902 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)
903 {
904 spx_uint32_t i;
905 int istride_save, ostride_save;
906 #ifdef VAR_ARRAYS
907 spx_word16_t x[*in_len];
908 spx_word16_t y[*out_len];
909 /*VARDECL(spx_word16_t *x);
910 VARDECL(spx_word16_t *y);
911 ALLOC(x, *in_len, spx_word16_t);
912 ALLOC(y, *out_len, spx_word16_t);*/
913 istride_save = st->in_stride;
914 ostride_save = st->out_stride;
915 for (i=0;i<*in_len;i++)
916 x[i] = in[i*st->in_stride];
917 st->in_stride = st->out_stride = 1;
918 speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
919 st->in_stride = istride_save;
920 st->out_stride = ostride_save;
921 for (i=0;i<*out_len;i++)
922 out[i*st->out_stride] = WORD2INT(y[i]);
923 #else
924 spx_word16_t x[FIXED_STACK_ALLOC];
925 spx_word16_t y[FIXED_STACK_ALLOC];
926 spx_uint32_t ilen=*in_len, olen=*out_len;
927 istride_save = st->in_stride;
928 ostride_save = st->out_stride;
929 while (ilen && olen)
930 {
931 spx_uint32_t ichunk, ochunk;
932 ichunk = ilen;
933 ochunk = olen;
934 if (ichunk>FIXED_STACK_ALLOC)
935 ichunk=FIXED_STACK_ALLOC;
936 if (ochunk>FIXED_STACK_ALLOC)
937 ochunk=FIXED_STACK_ALLOC;
938 for (i=0;i<ichunk;i++)
939 x[i] = in[i*st->in_stride];
940 st->in_stride = st->out_stride = 1;
941 speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
942 st->in_stride = istride_save;
943 st->out_stride = ostride_save;
944 for (i=0;i<ochunk;i++)
945 out[i*st->out_stride] = WORD2INT(y[i]);
946 out += ochunk;
947 in += ichunk;
948 ilen -= ichunk;
949 olen -= ochunk;
950 }
951 *in_len -= ilen;
952 *out_len -= olen;
953 #endif
954 return RESAMPLER_ERR_SUCCESS;
955 }
956 #endif
957
958 int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
959 {
960 spx_uint32_t i;
961 int istride_save, ostride_save;
962 spx_uint32_t bak_len = *out_len;
963 istride_save = st->in_stride;
964 ostride_save = st->out_stride;
965 st->in_stride = st->out_stride = st->nb_channels;
966 for (i=0;i<st->nb_channels;i++)
967 {
968 *out_len = bak_len;
969 speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
970 }
971 st->in_stride = istride_save;
972 st->out_stride = ostride_save;
973 return RESAMPLER_ERR_SUCCESS;
974 }
975
976
977 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)
978 {
979 spx_uint32_t i;
980 int istride_save, ostride_save;
981 spx_uint32_t bak_len = *out_len;
982 istride_save = st->in_stride;
983 ostride_save = st->out_stride;
984 st->in_stride = st->out_stride = st->nb_channels;
985 for (i=0;i<st->nb_channels;i++)
986 {
987 *out_len = bak_len;
988 speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
989 }
990 st->in_stride = istride_save;
991 st->out_stride = ostride_save;
992 return RESAMPLER_ERR_SUCCESS;
993 }
994
995 int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
996 {
997 return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
998 }
999
1000 void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
1001 {
1002 *in_rate = st->in_rate;
1003 *out_rate = st->out_rate;
1004 }
1005
1006 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)
1007 {
1008 spx_uint32_t fact;
1009 spx_uint32_t old_den;
1010 spx_uint32_t i;
1011 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
1012 return RESAMPLER_ERR_SUCCESS;
1013
1014 old_den = st->den_rate;
1015 st->in_rate = in_rate;
1016 st->out_rate = out_rate;
1017 st->num_rate = ratio_num;
1018 st->den_rate = ratio_den;
1019 /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
1020 for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
1021 {
1022 while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
1023 {
1024 st->num_rate /= fact;
1025 st->den_rate /= fact;
1026 }
1027 }
1028
1029 if (old_den > 0)
1030 {
1031 for (i=0;i<st->nb_channels;i++)
1032 {
1033 st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
1034 /* Safety net */
1035 if (st->samp_frac_num[i] >= st->den_rate)
1036 st->samp_frac_num[i] = st->den_rate-1;
1037 }
1038 }
1039
1040 if (st->initialised)
1041 update_filter(st);
1042 return RESAMPLER_ERR_SUCCESS;
1043 }
1044
1045 void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
1046 {
1047 *ratio_num = st->num_rate;
1048 *ratio_den = st->den_rate;
1049 }
1050
1051 int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
1052 {
1053 if (quality > 10 || quality < 0)
1054 return RESAMPLER_ERR_INVALID_ARG;
1055 if (st->quality == quality)
1056 return RESAMPLER_ERR_SUCCESS;
1057 st->quality = quality;
1058 if (st->initialised)
1059 update_filter(st);
1060 return RESAMPLER_ERR_SUCCESS;
1061 }
1062
1063 void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
1064 {
1065 *quality = st->quality;
1066 }
1067
1068 void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
1069 {
1070 st->in_stride = stride;
1071 }
1072
1073 void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1074 {
1075 *stride = st->in_stride;
1076 }
1077
1078 void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
1079 {
1080 st->out_stride = stride;
1081 }
1082
1083 void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1084 {
1085 *stride = st->out_stride;
1086 }
1087
1088 int speex_resampler_skip_zeros(SpeexResamplerState *st)
1089 {
1090 spx_uint32_t i;
1091 for (i=0;i<st->nb_channels;i++)
1092 st->last_sample[i] = st->filt_len/2;
1093 return RESAMPLER_ERR_SUCCESS;
1094 }
1095
1096 int speex_resampler_reset_mem(SpeexResamplerState *st)
1097 {
1098 spx_uint32_t i;
1099 for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
1100 st->mem[i] = 0;
1101 return RESAMPLER_ERR_SUCCESS;
1102 }
1103
1104 const char *speex_resampler_strerror(int err)
1105 {
1106 switch (err)
1107 {
1108 case RESAMPLER_ERR_SUCCESS:
1109 return "Success.";
1110 case RESAMPLER_ERR_ALLOC_FAILED:
1111 return "Memory allocation failed.";
1112 case RESAMPLER_ERR_BAD_STATE:
1113 return "Bad resampler state.";
1114 case RESAMPLER_ERR_INVALID_ARG:
1115 return "Invalid argument.";
1116 case RESAMPLER_ERR_PTR_OVERLAP:
1117 return "Input and output buffers overlap.";
1118 default:
1119 return "Unknown error. Bad error code or strange version mismatch.";
1120 }
1121 }