1 /* Copyright (C) 2007-2008 Jean-Marc Valin
2 Copyright (C) 2008 Thorvald Natvig
5 Arbitrary resampling code
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are
11 1. Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
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.
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.
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.
35 The design goals of this code are:
37 - SIMD-friendly algorithm
38 - Low memory requirement
39 - Good *perceptual* quality (and not best SNR)
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.
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/.
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.
77 #define EXPORT G_GNUC_INTERNAL
80 #ifndef HAVE_XMMINTRIN_H
86 #ifndef HAVE_EMMINTRIN_H
92 speex_alloc (int size)
94 return g_malloc0 (size);
98 speex_realloc (void *ptr, int size)
100 return g_realloc (ptr, size);
104 speex_free (void *ptr)
109 #include "speex_resampler.h"
111 #else /* OUTSIDE_SPEEX */
113 #include "../include/speex/speex_resampler.h"
115 #include "os_support.h"
116 #endif /* OUTSIDE_SPEEX */
121 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
123 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
126 #define IMAX(a,b) ((a) > (b) ? (a) : (b))
127 #define IMIN(a,b) ((a) < (b) ? (a) : (b))
133 #if defined _USE_SSE || defined _USE_SSE2
134 #include "resample_sse.h"
137 /* Numer of elements to allocate on the stack */
139 #define FIXED_STACK_ALLOC 8192
141 #define FIXED_STACK_ALLOC 1024
144 /* Allow selecting SSE or not when compiled with SSE support */
146 #define SSE_FALLBACK(macro) \
147 if (st->use_sse) goto sse_##macro##_sse; {
148 #define SSE_IMPLEMENTATION(macro) \
149 goto sse_##macro##_end; } sse_##macro##_sse: {
150 #define SSE_END(macro) sse_##macro##_end:; }
152 #define SSE_FALLBACK(macro)
156 #define SSE2_FALLBACK(macro) \
157 if (st->use_sse2) goto sse2_##macro##_sse2; {
158 #define SSE2_IMPLEMENTATION(macro) \
159 goto sse2_##macro##_end; } sse2_##macro##_sse2: {
160 #define SSE2_END(macro) sse2_##macro##_end:; }
162 #define SSE2_FALLBACK(macro)
166 typedef int (*resampler_basic_func) (SpeexResamplerState *, spx_uint32_t,
167 const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
169 struct SpeexResamplerState_
171 spx_uint32_t in_rate;
172 spx_uint32_t out_rate;
173 spx_uint32_t num_rate;
174 spx_uint32_t den_rate;
177 spx_uint32_t nb_channels;
178 spx_uint32_t filt_len;
179 spx_uint32_t mem_alloc_size;
180 spx_uint32_t buffer_size;
184 spx_uint32_t oversample;
187 int use_full_sinc_table;
189 /* These are per-channel */
190 spx_int32_t *last_sample;
191 spx_uint32_t *samp_frac_num;
192 spx_uint32_t *magic_samples;
195 spx_word16_t *sinc_table;
196 spx_uint32_t sinc_table_length;
197 resampler_basic_func resampler_ptr;
206 static double kaiser12_table[68] = {
207 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
208 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
209 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
210 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
211 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
212 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
213 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
214 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
215 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
216 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
217 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
218 0.00001000, 0.00000000
222 static double kaiser12_table[36] = {
223 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
224 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
225 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
226 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
227 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
228 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
230 static double kaiser10_table[36] = {
231 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
232 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
233 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
234 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
235 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
236 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000
239 static double kaiser8_table[36] = {
240 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
241 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
242 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
243 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
244 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
245 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000
248 static double kaiser6_table[36] = {
249 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
250 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
251 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
252 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
253 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
254 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000
263 static struct FuncDef _KAISER12 = { kaiser12_table, 64 };
265 #define KAISER12 (&_KAISER12)
266 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
267 #define KAISER12 (&_KAISER12)*/
268 static struct FuncDef _KAISER10 = { kaiser10_table, 32 };
270 #define KAISER10 (&_KAISER10)
271 static struct FuncDef _KAISER8 = { kaiser8_table, 32 };
273 #define KAISER8 (&_KAISER8)
274 static struct FuncDef _KAISER6 = { kaiser6_table, 32 };
276 #define KAISER6 (&_KAISER6)
278 struct QualityMapping
282 float downsample_bandwidth;
283 float upsample_bandwidth;
284 struct FuncDef *window_func;
288 /* This table maps conversion quality to internal parameters. There are two
289 reasons that explain why the up-sampling bandwidth is larger than the
290 down-sampling bandwidth:
291 1) When up-sampling, we can assume that the spectrum is already attenuated
292 close to the Nyquist rate (from an A/D or a previous resampling filter)
293 2) Any aliasing that occurs very close to the Nyquist rate will be masked
294 by the sinusoids/noise just below the Nyquist rate (guaranteed only for
297 static const struct QualityMapping quality_map[11] = {
298 {8, 4, 0.830f, 0.860f, KAISER6}, /* Q0 */
299 {16, 4, 0.850f, 0.880f, KAISER6}, /* Q1 */
300 {32, 4, 0.882f, 0.910f, KAISER6}, /* Q2 *//* 82.3% cutoff ( ~60 dB stop) 6 */
301 {48, 8, 0.895f, 0.917f, KAISER8}, /* Q3 *//* 84.9% cutoff ( ~80 dB stop) 8 */
302 {64, 8, 0.921f, 0.940f, KAISER8}, /* Q4 *//* 88.7% cutoff ( ~80 dB stop) 8 */
303 {80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 *//* 89.1% cutoff (~100 dB stop) 10 */
304 {96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 *//* 91.5% cutoff (~100 dB stop) 10 */
305 {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 *//* 93.1% cutoff (~100 dB stop) 10 */
306 {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 *//* 94.5% cutoff (~100 dB stop) 10 */
307 {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 *//* 95.5% cutoff (~100 dB stop) 10 */
308 {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 *//* 96.6% cutoff (~100 dB stop) 10 */
311 /*8,24,40,56,80,104,128,160,200,256,320*/
312 #ifdef DOUBLE_PRECISION
314 compute_func (double x, struct FuncDef *func)
319 compute_func (float x, struct FuncDef *func)
325 y = x * func->oversample;
326 ind = (int) floor (y);
328 /* CSE with handle the repeated powers */
329 interp[3] = -0.1666666667 * frac + 0.1666666667 * (frac * frac * frac);
330 interp[2] = frac + 0.5 * (frac * frac) - 0.5 * (frac * frac * frac);
331 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
333 -0.3333333333 * frac + 0.5 * (frac * frac) -
334 0.1666666667 * (frac * frac * frac);
335 /* Just to make sure we don't have rounding problems */
336 interp[1] = 1.f - interp[3] - interp[2] - interp[0];
338 /*sum = frac*accum[1] + (1-frac)*accum[2]; */
339 return interp[0] * func->table[ind] + interp[1] * func->table[ind + 1] +
340 interp[2] * func->table[ind + 2] + interp[3] * func->table[ind + 3];
346 main (int argc, char **argv)
349 for (i = 0; i < 256; i++) {
350 printf ("%f\n", compute_func (i / 256., KAISER12));
357 /* The slow way of computing a sinc for the table. Should improve that some day */
359 sinc (float cutoff, float x, int N, struct FuncDef *window_func)
361 /*fprintf (stderr, "%f ", x); */
362 float xx = x * cutoff;
363 if (fabs (x) < 1e-6f)
364 return WORD2INT (32768. * cutoff);
365 else if (fabs (x) > .5f * N)
367 /*FIXME: Can it really be any slower than this? */
368 return WORD2INT (32768. * cutoff * sin (G_PI * xx) / (G_PI * xx) *
369 compute_func (fabs (2. * x / N), window_func));
372 /* The slow way of computing a sinc for the table. Should improve that some day */
373 #ifdef DOUBLE_PRECISION
375 sinc (double cutoff, double x, int N, struct FuncDef *window_func)
377 /*fprintf (stderr, "%f ", x); */
378 double xx = x * cutoff;
381 sinc (float cutoff, float x, int N, struct FuncDef *window_func)
383 /*fprintf (stderr, "%f ", x); */
384 float xx = x * cutoff;
388 else if (fabs (x) > .5 * N)
390 /*FIXME: Can it really be any slower than this? */
391 return cutoff * sin (G_PI * xx) / (G_PI * xx) * compute_func (fabs (2. * x /
398 cubic_coef (spx_word16_t x, spx_word16_t interp[4])
400 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
401 but I know it's MMSE-optimal on a sinc */
403 x2 = MULT16_16_P15 (x, x);
404 x3 = MULT16_16_P15 (x, x2);
406 PSHR32 (MULT16_16 (QCONST16 (-0.16667f, 15),
407 x) + MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
409 EXTRACT16 (EXTEND32 (x) + SHR32 (SUB32 (EXTEND32 (x2), EXTEND32 (x3)),
412 PSHR32 (MULT16_16 (QCONST16 (-0.33333f, 15),
413 x) + MULT16_16 (QCONST16 (.5f, 15),
414 x2) - MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
415 /* Just to make sure we don't have rounding problems */
416 interp[2] = Q15_ONE - interp[0] - interp[1] - interp[3];
417 if (interp[2] < 32767)
422 cubic_coef (spx_word16_t frac, spx_word16_t interp[4])
424 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
425 but I know it's MMSE-optimal on a sinc */
426 interp[0] = -0.16667f * frac + 0.16667f * frac * frac * frac;
427 interp[1] = frac + 0.5f * frac * frac - 0.5f * frac * frac * frac;
428 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
430 -0.33333f * frac + 0.5f * frac * frac - 0.16667f * frac * frac * frac;
431 /* Just to make sure we don't have rounding problems */
432 interp[2] = 1. - interp[0] - interp[1] - interp[3];
436 #ifndef DOUBLE_PRECISION
438 resampler_basic_direct_single (SpeexResamplerState * st,
439 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
440 spx_word16_t * out, spx_uint32_t * out_len)
442 const int N = st->filt_len;
444 int last_sample = st->last_sample[channel_index];
445 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
446 const spx_word16_t *sinc_table = st->sinc_table;
447 const int out_stride = st->out_stride;
448 const int int_advance = st->int_advance;
449 const int frac_advance = st->frac_advance;
450 const spx_uint32_t den_rate = st->den_rate;
454 while (!(last_sample >= (spx_int32_t) * in_len
455 || out_sample >= (spx_int32_t) * out_len)) {
456 const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
457 const spx_word16_t *iptr = &in[last_sample];
459 SSE_FALLBACK (INNER_PRODUCT_SINGLE)
461 for (j = 0; j < N; j++)
462 sum += MULT16_16 (sinc[j], iptr[j]);
464 /* This code is slower on most DSPs which have only 2 accumulators.
465 Plus this forces truncation to 32 bits and you lose the HW guard bits.
466 I think we can trust the compiler and let it vectorize and/or unroll itself.
467 spx_word32_t accum[4] = {0,0,0,0};
469 accum[0] += MULT16_16(sinc[j], iptr[j]);
470 accum[1] += MULT16_16(sinc[j+1], iptr[j+1]);
471 accum[2] += MULT16_16(sinc[j+2], iptr[j+2]);
472 accum[3] += MULT16_16(sinc[j+3], iptr[j+3]);
474 sum = accum[0] + accum[1] + accum[2] + accum[3];
476 #ifdef OVERRIDE_INNER_PRODUCT_SINGLE
477 SSE_IMPLEMENTATION (INNER_PRODUCT_SINGLE)
478 sum = inner_product_single (sinc, iptr, N);
479 SSE_END (INNER_PRODUCT_SINGLE)
481 out[out_stride * out_sample++] = SATURATE32 (PSHR32 (sum, 15), 32767);
482 last_sample += int_advance;
483 samp_frac_num += frac_advance;
484 if (samp_frac_num >= den_rate) {
485 samp_frac_num -= den_rate;
490 st->last_sample[channel_index] = last_sample;
491 st->samp_frac_num[channel_index] = samp_frac_num;
498 /* This is the same as the previous function, except with a double-precision accumulator */
500 resampler_basic_direct_double (SpeexResamplerState * st,
501 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
502 spx_word16_t * out, spx_uint32_t * out_len)
504 const int N = st->filt_len;
506 int last_sample = st->last_sample[channel_index];
507 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
508 const spx_word16_t *sinc_table = st->sinc_table;
509 const int out_stride = st->out_stride;
510 const int int_advance = st->int_advance;
511 const int frac_advance = st->frac_advance;
512 const spx_uint32_t den_rate = st->den_rate;
516 while (!(last_sample >= (spx_int32_t) * in_len
517 || out_sample >= (spx_int32_t) * out_len)) {
518 const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
519 const spx_word16_t *iptr = &in[last_sample];
521 SSE2_FALLBACK (INNER_PRODUCT_DOUBLE)
522 double accum[4] = { 0, 0, 0, 0 };
524 for (j = 0; j < N; j += 4) {
525 accum[0] += sinc[j] * iptr[j];
526 accum[1] += sinc[j + 1] * iptr[j + 1];
527 accum[2] += sinc[j + 2] * iptr[j + 2];
528 accum[3] += sinc[j + 3] * iptr[j + 3];
530 sum = accum[0] + accum[1] + accum[2] + accum[3];
531 #ifdef OVERRIDE_INNER_PRODUCT_DOUBLE
532 SSE2_IMPLEMENTATION (INNER_PRODUCT_DOUBLE)
533 sum = inner_product_double (sinc, iptr, N);
534 SSE2_END (INNER_PRODUCT_DOUBLE)
536 out[out_stride * out_sample++] = PSHR32 (sum, 15);
537 last_sample += int_advance;
538 samp_frac_num += frac_advance;
539 if (samp_frac_num >= den_rate) {
540 samp_frac_num -= den_rate;
545 st->last_sample[channel_index] = last_sample;
546 st->samp_frac_num[channel_index] = samp_frac_num;
551 #ifndef DOUBLE_PRECISION
553 resampler_basic_interpolate_single (SpeexResamplerState * st,
554 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
555 spx_word16_t * out, spx_uint32_t * out_len)
557 const int N = st->filt_len;
559 int last_sample = st->last_sample[channel_index];
560 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
561 const int out_stride = st->out_stride;
562 const int int_advance = st->int_advance;
563 const int frac_advance = st->frac_advance;
564 const spx_uint32_t den_rate = st->den_rate;
568 while (!(last_sample >= (spx_int32_t) * in_len
569 || out_sample >= (spx_int32_t) * out_len)) {
570 const spx_word16_t *iptr = &in[last_sample];
572 const int offset = samp_frac_num * st->oversample / st->den_rate;
574 const spx_word16_t frac =
575 PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
578 const spx_word16_t frac =
579 ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
582 spx_word16_t interp[4];
585 SSE_FALLBACK (INTERPOLATE_PRODUCT_SINGLE)
586 spx_word32_t accum[4] = { 0, 0, 0, 0 };
588 for (j = 0; j < N; j++) {
589 const spx_word16_t curr_in = iptr[j];
592 st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
595 st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
598 st->sinc_table[4 + (j + 1) * st->oversample - offset]);
601 st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
604 cubic_coef (frac, interp);
606 MULT16_32_Q15 (interp[0], SHR32 (accum[0],
607 1)) + MULT16_32_Q15 (interp[1], SHR32 (accum[1],
608 1)) + MULT16_32_Q15 (interp[2], SHR32 (accum[2],
609 1)) + MULT16_32_Q15 (interp[3], SHR32 (accum[3], 1));
610 #ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
611 SSE_IMPLEMENTATION (INTERPOLATE_PRODUCT_SINGLE)
612 cubic_coef (frac, interp);
614 interpolate_product_single (iptr,
615 st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
617 SSE_END (INTERPOLATE_PRODUCT_SINGLE)
619 out[out_stride * out_sample++] = SATURATE32 (PSHR32 (sum, 14), 32767);
620 last_sample += int_advance;
621 samp_frac_num += frac_advance;
622 if (samp_frac_num >= den_rate) {
623 samp_frac_num -= den_rate;
628 st->last_sample[channel_index] = last_sample;
629 st->samp_frac_num[channel_index] = samp_frac_num;
636 /* This is the same as the previous function, except with a double-precision accumulator */
638 resampler_basic_interpolate_double (SpeexResamplerState * st,
639 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
640 spx_word16_t * out, spx_uint32_t * out_len)
642 const int N = st->filt_len;
644 int last_sample = st->last_sample[channel_index];
645 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
646 const int out_stride = st->out_stride;
647 const int int_advance = st->int_advance;
648 const int frac_advance = st->frac_advance;
649 const spx_uint32_t den_rate = st->den_rate;
653 while (!(last_sample >= (spx_int32_t) * in_len
654 || out_sample >= (spx_int32_t) * out_len)) {
655 const spx_word16_t *iptr = &in[last_sample];
657 const int offset = samp_frac_num * st->oversample / st->den_rate;
659 const spx_word16_t frac =
660 PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
663 #ifdef DOUBLE_PRECISION
664 const spx_word16_t frac =
665 ((double) ((samp_frac_num * st->oversample) % st->den_rate)) /
668 const spx_word16_t frac =
669 ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
673 spx_word16_t interp[4];
676 SSE2_FALLBACK (INTERPOLATE_PRODUCT_DOUBLE)
677 double accum[4] = { 0, 0, 0, 0 };
679 for (j = 0; j < N; j++) {
680 const double curr_in = iptr[j];
683 st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
686 st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
689 st->sinc_table[4 + (j + 1) * st->oversample - offset]);
692 st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
695 cubic_coef (frac, interp);
697 MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
698 accum[1]) + MULT16_32_Q15 (interp[2],
699 accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
700 #ifdef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
701 SSE2_IMPLEMENTATION (INTERPOLATE_PRODUCT_DOUBLE)
702 cubic_coef (frac, interp);
704 interpolate_product_double (iptr,
705 st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
707 SSE2_END (INTERPOLATE_PRODUCT_DOUBLE)
709 out[out_stride * out_sample++] = PSHR32 (sum, 15);
710 last_sample += int_advance;
711 samp_frac_num += frac_advance;
712 if (samp_frac_num >= den_rate) {
713 samp_frac_num -= den_rate;
718 st->last_sample[channel_index] = last_sample;
719 st->samp_frac_num[channel_index] = samp_frac_num;
725 update_filter (SpeexResamplerState * st)
727 spx_uint32_t old_length;
729 old_length = st->filt_len;
730 st->oversample = quality_map[st->quality].oversample;
731 st->filt_len = quality_map[st->quality].base_length;
733 if (st->num_rate > st->den_rate) {
736 quality_map[st->quality].downsample_bandwidth * st->den_rate /
738 /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
739 st->filt_len = st->filt_len * st->num_rate / st->den_rate;
740 /* Round down to make sure we have a multiple of 4 */
741 st->filt_len &= (~0x3);
742 if (2 * st->den_rate < st->num_rate)
743 st->oversample >>= 1;
744 if (4 * st->den_rate < st->num_rate)
745 st->oversample >>= 1;
746 if (8 * st->den_rate < st->num_rate)
747 st->oversample >>= 1;
748 if (16 * st->den_rate < st->num_rate)
749 st->oversample >>= 1;
750 if (st->oversample < 1)
754 st->cutoff = quality_map[st->quality].upsample_bandwidth;
757 /* Choose the resampling type that requires the least amount of memory */
758 /* Or if the full sinc table is explicitely requested, use that */
759 if (st->use_full_sinc_table || (st->den_rate <= st->oversample)) {
763 (spx_word16_t *) speex_alloc (st->filt_len * st->den_rate *
764 sizeof (spx_word16_t));
765 else if (st->sinc_table_length < st->filt_len * st->den_rate) {
767 (spx_word16_t *) speex_realloc (st->sinc_table,
768 st->filt_len * st->den_rate * sizeof (spx_word16_t));
769 st->sinc_table_length = st->filt_len * st->den_rate;
771 for (i = 0; i < st->den_rate; i++) {
773 for (j = 0; j < st->filt_len; j++) {
774 st->sinc_table[i * st->filt_len + j] =
775 sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
776 #ifdef DOUBLE_PRECISION
777 ((double) i) / st->den_rate), st->filt_len,
779 ((float) i) / st->den_rate), st->filt_len,
781 quality_map[st->quality].window_func);
785 st->resampler_ptr = resampler_basic_direct_single;
787 #ifdef DOUBLE_PRECISION
788 st->resampler_ptr = resampler_basic_direct_double;
791 st->resampler_ptr = resampler_basic_direct_double;
793 st->resampler_ptr = resampler_basic_direct_single;
796 /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
801 (spx_word16_t *) speex_alloc ((st->filt_len * st->oversample +
802 8) * sizeof (spx_word16_t));
803 else if (st->sinc_table_length < st->filt_len * st->oversample + 8) {
805 (spx_word16_t *) speex_realloc (st->sinc_table,
806 (st->filt_len * st->oversample + 8) * sizeof (spx_word16_t));
807 st->sinc_table_length = st->filt_len * st->oversample + 8;
809 for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
810 st->sinc_table[i + 4] =
811 #ifdef DOUBLE_PRECISION
812 sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2),
814 sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
816 st->filt_len, quality_map[st->quality].window_func);
818 st->resampler_ptr = resampler_basic_interpolate_single;
820 #ifdef DOUBLE_PRECISION
821 st->resampler_ptr = resampler_basic_interpolate_double;
824 st->resampler_ptr = resampler_basic_interpolate_double;
826 st->resampler_ptr = resampler_basic_interpolate_single;
829 /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
831 st->int_advance = st->num_rate / st->den_rate;
832 st->frac_advance = st->num_rate % st->den_rate;
835 /* Here's the place where we update the filter memory to take into account
836 the change in filter length. It's probably the messiest part of the code
837 due to handling of lots of corner cases. */
840 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
842 (spx_word16_t *) speex_alloc (st->nb_channels * st->mem_alloc_size *
843 sizeof (spx_word16_t));
844 for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
846 /*speex_warning("init filter"); */
847 } else if (!st->started) {
849 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
851 (spx_word16_t *) speex_realloc (st->mem,
852 st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
853 for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
855 /*speex_warning("reinit filter"); */
856 } else if (st->filt_len > old_length) {
858 /* Increase the filter length */
859 /*speex_warning("increase filter size"); */
860 int old_alloc_size = st->mem_alloc_size;
861 if ((st->filt_len - 1 + st->buffer_size) > st->mem_alloc_size) {
862 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
864 (spx_word16_t *) speex_realloc (st->mem,
865 st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
867 for (i = st->nb_channels - 1; i >= 0; i--) {
869 spx_uint32_t olen = old_length;
870 /*if (st->magic_samples[i]) */
872 /* Try and remove the magic samples as if nothing had happened */
874 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
875 olen = old_length + 2 * st->magic_samples[i];
876 for (j = old_length - 2 + st->magic_samples[i]; j >= 0; j--)
877 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]] =
878 st->mem[i * old_alloc_size + j];
879 for (j = 0; j < st->magic_samples[i]; j++)
880 st->mem[i * st->mem_alloc_size + j] = 0;
881 st->magic_samples[i] = 0;
883 if (st->filt_len > olen) {
884 /* If the new filter length is still bigger than the "augmented" length */
885 /* Copy data going backward */
886 for (j = 0; j < olen - 1; j++)
887 st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] =
888 st->mem[i * st->mem_alloc_size + (olen - 2 - j)];
889 /* Then put zeros for lack of anything better */
890 for (; j < st->filt_len - 1; j++)
891 st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] = 0;
892 /* Adjust last_sample */
893 st->last_sample[i] += (st->filt_len - olen) / 2;
895 /* Put back some of the magic! */
896 st->magic_samples[i] = (olen - st->filt_len) / 2;
897 for (j = 0; j < st->filt_len - 1 + st->magic_samples[i]; j++)
898 st->mem[i * st->mem_alloc_size + j] =
899 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
902 } else if (st->filt_len < old_length) {
904 /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
905 samples so they can be used directly as input the next time(s) */
906 for (i = 0; i < st->nb_channels; i++) {
908 spx_uint32_t old_magic = st->magic_samples[i];
909 st->magic_samples[i] = (old_length - st->filt_len) / 2;
910 /* We must copy some of the memory that's no longer used */
911 /* Copy data going backward */
912 for (j = 0; j < st->filt_len - 1 + st->magic_samples[i] + old_magic; j++)
913 st->mem[i * st->mem_alloc_size + j] =
914 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
915 st->magic_samples[i] += old_magic;
921 EXPORT SpeexResamplerState *
922 speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
923 spx_uint32_t out_rate, int quality, SpeexResamplerSincFilterMode sinc_filter_mode,
924 spx_uint32_t sinc_filter_auto_threshold, int *err)
926 return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate,
927 out_rate, quality, sinc_filter_mode, sinc_filter_auto_threshold, err);
930 #if defined HAVE_ORC && !defined DISABLE_ORC
932 check_insn_set (SpeexResamplerState * st, const char *name)
936 if (!strcmp (name, "sse"))
938 if (!strcmp (name, "sse2"))
939 st->use_sse = st->use_sse2 = 1;
943 EXPORT SpeexResamplerState *
944 speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
945 spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate,
946 int quality, SpeexResamplerSincFilterMode sinc_filter_mode,
947 spx_uint32_t sinc_filter_auto_threshold, int *err)
950 SpeexResamplerState *st;
951 int use_full_sinc_table = 0;
952 if (quality > 10 || quality < 0) {
954 *err = RESAMPLER_ERR_INVALID_ARG;
957 switch (sinc_filter_mode) {
958 case RESAMPLER_SINC_FILTER_INTERPOLATED:
959 use_full_sinc_table = 0;
961 case RESAMPLER_SINC_FILTER_FULL:
962 use_full_sinc_table = 1;
964 case RESAMPLER_SINC_FILTER_AUTO:
969 *err = RESAMPLER_ERR_INVALID_ARG;
973 st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState));
981 st->sinc_table_length = 0;
982 st->mem_alloc_size = 0;
985 st->resampler_ptr = 0;
986 st->use_full_sinc_table = use_full_sinc_table;
989 st->nb_channels = nb_channels;
994 st->buffer_size = 160;
996 st->buffer_size = 160;
999 st->use_sse = st->use_sse2 = 0;
1000 #if defined HAVE_ORC && !defined DISABLE_ORC
1003 OrcTarget *target = orc_target_get_default ();
1005 unsigned int flags = orc_target_get_default_flags (target);
1006 check_insn_set (st, orc_target_get_name (target));
1007 for (i = 0; i < 32; ++i) {
1008 if (flags & (1 << i)) {
1009 check_insn_set (st, orc_target_get_flag_name (target, i));
1016 /* Per channel data */
1017 st->last_sample = (spx_int32_t *) speex_alloc (nb_channels * sizeof (int));
1018 st->magic_samples = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
1019 st->samp_frac_num = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
1020 for (i = 0; i < nb_channels; i++) {
1021 st->last_sample[i] = 0;
1022 st->magic_samples[i] = 0;
1023 st->samp_frac_num[i] = 0;
1026 speex_resampler_set_quality (st, quality);
1027 speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate);
1029 if (sinc_filter_mode == RESAMPLER_SINC_FILTER_AUTO) {
1031 Estimate how big the filter table would become if the full mode were to be used
1032 calculations used correspond to the ones in update_filter()
1033 if the size is bigger than the threshold, use interpolated sinc instead
1035 spx_uint32_t base_filter_length = st->filt_len = quality_map[st->quality].base_length;
1036 spx_uint32_t filter_table_size = base_filter_length * st->den_rate * sizeof(spx_uint16_t);
1037 st->use_full_sinc_table = (filter_table_size > sinc_filter_auto_threshold) ? 0 : 1;
1042 st->initialised = 1;
1044 *err = RESAMPLER_ERR_SUCCESS;
1050 speex_resampler_destroy (SpeexResamplerState * st)
1052 speex_free (st->mem);
1053 speex_free (st->sinc_table);
1054 speex_free (st->last_sample);
1055 speex_free (st->magic_samples);
1056 speex_free (st->samp_frac_num);
1061 speex_resampler_process_native (SpeexResamplerState * st,
1062 spx_uint32_t channel_index, spx_uint32_t * in_len, spx_word16_t * out,
1063 spx_uint32_t * out_len)
1066 const int N = st->filt_len;
1068 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
1073 /* Call the right resampler through the function ptr */
1074 out_sample = st->resampler_ptr (st, channel_index, mem, in_len, out, out_len);
1076 if (st->last_sample[channel_index] < (spx_int32_t) * in_len)
1077 *in_len = st->last_sample[channel_index];
1078 *out_len = out_sample;
1079 st->last_sample[channel_index] -= *in_len;
1083 for (j = 0; j < N - 1; ++j)
1084 mem[j] = mem[j + ilen];
1086 return RESAMPLER_ERR_SUCCESS;
1090 speex_resampler_magic (SpeexResamplerState * st, spx_uint32_t channel_index,
1091 spx_word16_t ** out, spx_uint32_t out_len)
1093 spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
1094 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
1095 const int N = st->filt_len;
1097 speex_resampler_process_native (st, channel_index, &tmp_in_len, *out,
1100 st->magic_samples[channel_index] -= tmp_in_len;
1102 /* If we couldn't process all "magic" input samples, save the rest for next time */
1103 if (st->magic_samples[channel_index]) {
1105 for (i = 0; i < st->magic_samples[channel_index]; i++)
1106 mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len];
1108 *out += out_len * st->out_stride;
1114 speex_resampler_process_int (SpeexResamplerState * st,
1115 spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
1116 spx_int16_t * out, spx_uint32_t * out_len)
1118 #ifdef DOUBLE_PRECISION
1120 speex_resampler_process_float (SpeexResamplerState * st,
1121 spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len,
1122 double *out, spx_uint32_t * out_len)
1125 speex_resampler_process_float (SpeexResamplerState * st,
1126 spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
1127 float *out, spx_uint32_t * out_len)
1132 spx_uint32_t ilen = *in_len;
1133 spx_uint32_t olen = *out_len;
1134 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
1135 const int filt_offs = st->filt_len - 1;
1136 const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
1137 const int istride = st->in_stride;
1139 if (st->magic_samples[channel_index])
1140 olen -= speex_resampler_magic (st, channel_index, &out, olen);
1141 if (!st->magic_samples[channel_index]) {
1142 while (ilen && olen) {
1143 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
1144 spx_uint32_t ochunk = olen;
1147 for (j = 0; j < ichunk; ++j)
1148 x[j + filt_offs] = in[j * istride];
1150 for (j = 0; j < ichunk; ++j)
1151 x[j + filt_offs] = 0;
1153 speex_resampler_process_native (st, channel_index, &ichunk, out, &ochunk);
1156 out += ochunk * st->out_stride;
1158 in += ichunk * istride;
1163 return RESAMPLER_ERR_SUCCESS;
1168 speex_resampler_process_float (SpeexResamplerState * st,
1169 spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
1170 float *out, spx_uint32_t * out_len)
1173 speex_resampler_process_int (SpeexResamplerState * st,
1174 spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
1175 spx_int16_t * out, spx_uint32_t * out_len)
1179 const int istride_save = st->in_stride;
1180 const int ostride_save = st->out_stride;
1181 spx_uint32_t ilen = *in_len;
1182 spx_uint32_t olen = *out_len;
1183 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
1184 const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
1186 const unsigned int ylen =
1187 (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
1188 VARDECL (spx_word16_t * ystack);
1189 ALLOC (ystack, ylen, spx_word16_t);
1191 const unsigned int ylen = FIXED_STACK_ALLOC;
1192 spx_word16_t ystack[FIXED_STACK_ALLOC];
1197 while (ilen && olen) {
1198 spx_word16_t *y = ystack;
1199 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
1200 spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
1201 spx_uint32_t omagic = 0;
1203 if (st->magic_samples[channel_index]) {
1204 omagic = speex_resampler_magic (st, channel_index, &y, ochunk);
1208 if (!st->magic_samples[channel_index]) {
1210 for (j = 0; j < ichunk; ++j)
1212 x[j + st->filt_len - 1] = WORD2INT (in[j * istride_save]);
1214 x[j + st->filt_len - 1] = in[j * istride_save];
1217 for (j = 0; j < ichunk; ++j)
1218 x[j + st->filt_len - 1] = 0;
1221 speex_resampler_process_native (st, channel_index, &ichunk, y, &ochunk);
1227 for (j = 0; j < ochunk + omagic; ++j)
1229 out[j * ostride_save] = ystack[j];
1231 out[j * ostride_save] = WORD2INT (ystack[j]);
1236 out += (ochunk + omagic) * ostride_save;
1238 in += ichunk * istride_save;
1240 st->out_stride = ostride_save;
1244 return RESAMPLER_ERR_SUCCESS;
1247 #ifdef DOUBLE_PRECISION
1249 speex_resampler_process_interleaved_float (SpeexResamplerState * st,
1250 const double *in, spx_uint32_t * in_len, double *out,
1251 spx_uint32_t * out_len)
1254 speex_resampler_process_interleaved_float (SpeexResamplerState * st,
1255 const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
1259 int istride_save, ostride_save;
1260 spx_uint32_t bak_len = *out_len;
1261 istride_save = st->in_stride;
1262 ostride_save = st->out_stride;
1263 st->in_stride = st->out_stride = st->nb_channels;
1264 for (i = 0; i < st->nb_channels; i++) {
1267 speex_resampler_process_float (st, i, in + i, in_len, out + i, out_len);
1269 speex_resampler_process_float (st, i, NULL, in_len, out + i, out_len);
1271 st->in_stride = istride_save;
1272 st->out_stride = ostride_save;
1273 return RESAMPLER_ERR_SUCCESS;
1277 speex_resampler_process_interleaved_int (SpeexResamplerState * st,
1278 const spx_int16_t * in, spx_uint32_t * in_len, spx_int16_t * out,
1279 spx_uint32_t * out_len)
1282 int istride_save, ostride_save;
1283 spx_uint32_t bak_len = *out_len;
1284 istride_save = st->in_stride;
1285 ostride_save = st->out_stride;
1286 st->in_stride = st->out_stride = st->nb_channels;
1287 for (i = 0; i < st->nb_channels; i++) {
1290 speex_resampler_process_int (st, i, in + i, in_len, out + i, out_len);
1292 speex_resampler_process_int (st, i, NULL, in_len, out + i, out_len);
1294 st->in_stride = istride_save;
1295 st->out_stride = ostride_save;
1296 return RESAMPLER_ERR_SUCCESS;
1300 speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate,
1301 spx_uint32_t out_rate)
1303 return speex_resampler_set_rate_frac (st, in_rate, out_rate, in_rate,
1308 speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate,
1309 spx_uint32_t * out_rate)
1311 *in_rate = st->in_rate;
1312 *out_rate = st->out_rate;
1316 speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num,
1317 spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
1320 spx_uint32_t old_den;
1322 if (st->in_rate == in_rate && st->out_rate == out_rate
1323 && st->num_rate == ratio_num && st->den_rate == ratio_den)
1324 return RESAMPLER_ERR_SUCCESS;
1326 old_den = st->den_rate;
1327 st->in_rate = in_rate;
1328 st->out_rate = out_rate;
1329 st->num_rate = ratio_num;
1330 st->den_rate = ratio_den;
1331 /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
1332 for (fact = 2; fact <= IMIN (st->num_rate, st->den_rate); fact++) {
1333 while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) {
1334 st->num_rate /= fact;
1335 st->den_rate /= fact;
1340 for (i = 0; i < st->nb_channels; i++) {
1341 st->samp_frac_num[i] = st->samp_frac_num[i] * st->den_rate / old_den;
1343 if (st->samp_frac_num[i] >= st->den_rate)
1344 st->samp_frac_num[i] = st->den_rate - 1;
1348 if (st->initialised)
1350 return RESAMPLER_ERR_SUCCESS;
1354 speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num,
1355 spx_uint32_t * ratio_den)
1357 *ratio_num = st->num_rate;
1358 *ratio_den = st->den_rate;
1362 speex_resampler_set_quality (SpeexResamplerState * st, int quality)
1364 if (quality > 10 || quality < 0)
1365 return RESAMPLER_ERR_INVALID_ARG;
1366 if (st->quality == quality)
1367 return RESAMPLER_ERR_SUCCESS;
1368 st->quality = quality;
1369 if (st->initialised)
1371 return RESAMPLER_ERR_SUCCESS;
1375 speex_resampler_get_quality (SpeexResamplerState * st, int *quality)
1377 *quality = st->quality;
1381 speex_resampler_set_input_stride (SpeexResamplerState * st, spx_uint32_t stride)
1383 st->in_stride = stride;
1387 speex_resampler_get_input_stride (SpeexResamplerState * st,
1388 spx_uint32_t * stride)
1390 *stride = st->in_stride;
1394 speex_resampler_set_output_stride (SpeexResamplerState * st,
1395 spx_uint32_t stride)
1397 st->out_stride = stride;
1401 speex_resampler_get_output_stride (SpeexResamplerState * st,
1402 spx_uint32_t * stride)
1404 *stride = st->out_stride;
1408 speex_resampler_get_input_latency (SpeexResamplerState * st)
1410 return st->filt_len / 2;
1414 speex_resampler_get_output_latency (SpeexResamplerState * st)
1416 return ((st->filt_len / 2) * st->den_rate +
1417 (st->num_rate >> 1)) / st->num_rate;
1421 speex_resampler_get_filt_len (SpeexResamplerState * st)
1423 return st->filt_len;
1427 speex_resampler_get_sinc_filter_mode (SpeexResamplerState * st)
1429 return st->use_full_sinc_table;
1433 speex_resampler_skip_zeros (SpeexResamplerState * st)
1436 for (i = 0; i < st->nb_channels; i++)
1437 st->last_sample[i] = st->filt_len / 2;
1438 return RESAMPLER_ERR_SUCCESS;
1442 speex_resampler_reset_mem (SpeexResamplerState * st)
1445 for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++)
1447 return RESAMPLER_ERR_SUCCESS;
1451 speex_resampler_strerror (int err)
1454 case RESAMPLER_ERR_SUCCESS:
1456 case RESAMPLER_ERR_ALLOC_FAILED:
1457 return "Memory allocation failed.";
1458 case RESAMPLER_ERR_BAD_STATE:
1459 return "Bad resampler state.";
1460 case RESAMPLER_ERR_INVALID_ARG:
1461 return "Invalid argument.";
1462 case RESAMPLER_ERR_PTR_OVERLAP:
1463 return "Input and output buffers overlap.";
1465 return "Unknown error. Bad error code or strange version mismatch.";