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;
188 /* These are per-channel */
189 spx_int32_t *last_sample;
190 spx_uint32_t *samp_frac_num;
191 spx_uint32_t *magic_samples;
194 spx_word16_t *sinc_table;
195 spx_uint32_t sinc_table_length;
196 resampler_basic_func resampler_ptr;
205 static double kaiser12_table[68] = {
206 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
207 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
208 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
209 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
210 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
211 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
212 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
213 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
214 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
215 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
216 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
217 0.00001000, 0.00000000
221 static double kaiser12_table[36] = {
222 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
223 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
224 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
225 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
226 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
227 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
229 static double kaiser10_table[36] = {
230 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
231 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
232 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
233 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
234 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
235 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000
238 static double kaiser8_table[36] = {
239 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
240 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
241 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
242 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
243 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
244 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000
247 static double kaiser6_table[36] = {
248 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
249 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
250 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
251 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
252 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
253 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000
262 static struct FuncDef _KAISER12 = { kaiser12_table, 64 };
264 #define KAISER12 (&_KAISER12)
265 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
266 #define KAISER12 (&_KAISER12)*/
267 static struct FuncDef _KAISER10 = { kaiser10_table, 32 };
269 #define KAISER10 (&_KAISER10)
270 static struct FuncDef _KAISER8 = { kaiser8_table, 32 };
272 #define KAISER8 (&_KAISER8)
273 static struct FuncDef _KAISER6 = { kaiser6_table, 32 };
275 #define KAISER6 (&_KAISER6)
277 struct QualityMapping
281 float downsample_bandwidth;
282 float upsample_bandwidth;
283 struct FuncDef *window_func;
287 /* This table maps conversion quality to internal parameters. There are two
288 reasons that explain why the up-sampling bandwidth is larger than the
289 down-sampling bandwidth:
290 1) When up-sampling, we can assume that the spectrum is already attenuated
291 close to the Nyquist rate (from an A/D or a previous resampling filter)
292 2) Any aliasing that occurs very close to the Nyquist rate will be masked
293 by the sinusoids/noise just below the Nyquist rate (guaranteed only for
296 static const struct QualityMapping quality_map[11] = {
297 {8, 4, 0.830f, 0.860f, KAISER6}, /* Q0 */
298 {16, 4, 0.850f, 0.880f, KAISER6}, /* Q1 */
299 {32, 4, 0.882f, 0.910f, KAISER6}, /* Q2 *//* 82.3% cutoff ( ~60 dB stop) 6 */
300 {48, 8, 0.895f, 0.917f, KAISER8}, /* Q3 *//* 84.9% cutoff ( ~80 dB stop) 8 */
301 {64, 8, 0.921f, 0.940f, KAISER8}, /* Q4 *//* 88.7% cutoff ( ~80 dB stop) 8 */
302 {80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 *//* 89.1% cutoff (~100 dB stop) 10 */
303 {96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 *//* 91.5% cutoff (~100 dB stop) 10 */
304 {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 *//* 93.1% cutoff (~100 dB stop) 10 */
305 {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 *//* 94.5% cutoff (~100 dB stop) 10 */
306 {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 *//* 95.5% cutoff (~100 dB stop) 10 */
307 {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 *//* 96.6% cutoff (~100 dB stop) 10 */
310 /*8,24,40,56,80,104,128,160,200,256,320*/
311 #ifdef DOUBLE_PRECISION
313 compute_func (double x, struct FuncDef *func)
318 compute_func (float x, struct FuncDef *func)
324 y = x * func->oversample;
325 ind = (int) floor (y);
327 /* CSE with handle the repeated powers */
328 interp[3] = -0.1666666667 * frac + 0.1666666667 * (frac * frac * frac);
329 interp[2] = frac + 0.5 * (frac * frac) - 0.5 * (frac * frac * frac);
330 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
332 -0.3333333333 * frac + 0.5 * (frac * frac) -
333 0.1666666667 * (frac * frac * frac);
334 /* Just to make sure we don't have rounding problems */
335 interp[1] = 1.f - interp[3] - interp[2] - interp[0];
337 /*sum = frac*accum[1] + (1-frac)*accum[2]; */
338 return interp[0] * func->table[ind] + interp[1] * func->table[ind + 1] +
339 interp[2] * func->table[ind + 2] + interp[3] * func->table[ind + 3];
345 main (int argc, char **argv)
348 for (i = 0; i < 256; i++) {
349 printf ("%f\n", compute_func (i / 256., KAISER12));
356 /* The slow way of computing a sinc for the table. Should improve that some day */
358 sinc (float cutoff, float x, int N, struct FuncDef *window_func)
360 /*fprintf (stderr, "%f ", x); */
361 float xx = x * cutoff;
362 if (fabs (x) < 1e-6f)
363 return WORD2INT (32768. * cutoff);
364 else if (fabs (x) > .5f * N)
366 /*FIXME: Can it really be any slower than this? */
367 return WORD2INT (32768. * cutoff * sin (G_PI * xx) / (G_PI * xx) *
368 compute_func (fabs (2. * x / N), window_func));
371 /* The slow way of computing a sinc for the table. Should improve that some day */
372 #ifdef DOUBLE_PRECISION
374 sinc (double cutoff, double x, int N, struct FuncDef *window_func)
376 /*fprintf (stderr, "%f ", x); */
377 double xx = x * cutoff;
380 sinc (float cutoff, float x, int N, struct FuncDef *window_func)
382 /*fprintf (stderr, "%f ", x); */
383 float xx = x * cutoff;
387 else if (fabs (x) > .5 * N)
389 /*FIXME: Can it really be any slower than this? */
390 return cutoff * sin (G_PI * xx) / (G_PI * xx) * compute_func (fabs (2. * x /
397 cubic_coef (spx_word16_t x, spx_word16_t interp[4])
399 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
400 but I know it's MMSE-optimal on a sinc */
402 x2 = MULT16_16_P15 (x, x);
403 x3 = MULT16_16_P15 (x, x2);
405 PSHR32 (MULT16_16 (QCONST16 (-0.16667f, 15),
406 x) + MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
408 EXTRACT16 (EXTEND32 (x) + SHR32 (SUB32 (EXTEND32 (x2), EXTEND32 (x3)),
411 PSHR32 (MULT16_16 (QCONST16 (-0.33333f, 15),
412 x) + MULT16_16 (QCONST16 (.5f, 15),
413 x2) - MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
414 /* Just to make sure we don't have rounding problems */
415 interp[2] = Q15_ONE - interp[0] - interp[1] - interp[3];
416 if (interp[2] < 32767)
421 cubic_coef (spx_word16_t frac, spx_word16_t interp[4])
423 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
424 but I know it's MMSE-optimal on a sinc */
425 interp[0] = -0.16667f * frac + 0.16667f * frac * frac * frac;
426 interp[1] = frac + 0.5f * frac * frac - 0.5f * frac * frac * frac;
427 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
429 -0.33333f * frac + 0.5f * frac * frac - 0.16667f * frac * frac * frac;
430 /* Just to make sure we don't have rounding problems */
431 interp[2] = 1. - interp[0] - interp[1] - interp[3];
435 #ifndef DOUBLE_PRECISION
437 resampler_basic_direct_single (SpeexResamplerState * st,
438 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
439 spx_word16_t * out, spx_uint32_t * out_len)
441 const int N = st->filt_len;
443 int last_sample = st->last_sample[channel_index];
444 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
445 const spx_word16_t *sinc_table = st->sinc_table;
446 const int out_stride = st->out_stride;
447 const int int_advance = st->int_advance;
448 const int frac_advance = st->frac_advance;
449 const spx_uint32_t den_rate = st->den_rate;
453 while (!(last_sample >= (spx_int32_t) * in_len
454 || out_sample >= (spx_int32_t) * out_len)) {
455 const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
456 const spx_word16_t *iptr = &in[last_sample];
458 SSE_FALLBACK (INNER_PRODUCT_SINGLE)
460 for (j = 0; j < N; j++)
461 sum += MULT16_16 (sinc[j], iptr[j]);
463 /* This code is slower on most DSPs which have only 2 accumulators.
464 Plus this forces truncation to 32 bits and you lose the HW guard bits.
465 I think we can trust the compiler and let it vectorize and/or unroll itself.
466 spx_word32_t accum[4] = {0,0,0,0};
468 accum[0] += MULT16_16(sinc[j], iptr[j]);
469 accum[1] += MULT16_16(sinc[j+1], iptr[j+1]);
470 accum[2] += MULT16_16(sinc[j+2], iptr[j+2]);
471 accum[3] += MULT16_16(sinc[j+3], iptr[j+3]);
473 sum = accum[0] + accum[1] + accum[2] + accum[3];
475 #ifdef OVERRIDE_INNER_PRODUCT_SINGLE
476 SSE_IMPLEMENTATION (INNER_PRODUCT_SINGLE)
477 sum = inner_product_single (sinc, iptr, N);
478 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)
537 out[out_stride * out_sample++] = PSHR32 (sum, 15);
538 last_sample += int_advance;
539 samp_frac_num += frac_advance;
540 if (samp_frac_num >= den_rate) {
541 samp_frac_num -= den_rate;
546 st->last_sample[channel_index] = last_sample;
547 st->samp_frac_num[channel_index] = samp_frac_num;
552 #ifndef DOUBLE_PRECISION
554 resampler_basic_interpolate_single (SpeexResamplerState * st,
555 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
556 spx_word16_t * out, spx_uint32_t * out_len)
558 const int N = st->filt_len;
560 int last_sample = st->last_sample[channel_index];
561 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
562 const int out_stride = st->out_stride;
563 const int int_advance = st->int_advance;
564 const int frac_advance = st->frac_advance;
565 const spx_uint32_t den_rate = st->den_rate;
569 while (!(last_sample >= (spx_int32_t) * in_len
570 || out_sample >= (spx_int32_t) * out_len)) {
571 const spx_word16_t *iptr = &in[last_sample];
573 const int offset = samp_frac_num * st->oversample / st->den_rate;
575 const spx_word16_t frac =
576 PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
579 const spx_word16_t frac =
580 ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
583 spx_word16_t interp[4];
586 SSE_FALLBACK (INTERPOLATE_PRODUCT_SINGLE)
587 spx_word32_t accum[4] = { 0, 0, 0, 0 };
589 for (j = 0; j < N; j++) {
590 const spx_word16_t curr_in = iptr[j];
593 st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
596 st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
599 st->sinc_table[4 + (j + 1) * st->oversample - offset]);
602 st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
605 cubic_coef (frac, interp);
607 MULT16_32_Q15 (interp[0], SHR32 (accum[0],
608 1)) + MULT16_32_Q15 (interp[1], SHR32 (accum[1],
609 1)) + MULT16_32_Q15 (interp[2], SHR32 (accum[2],
610 1)) + MULT16_32_Q15 (interp[3], SHR32 (accum[3], 1));
611 #ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
612 SSE_IMPLEMENTATION (INTERPOLATE_PRODUCT_SINGLE)
613 cubic_coef (frac, interp);
615 interpolate_product_single (iptr,
616 st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
618 SSE_END (INTERPOLATE_PRODUCT_SINGLE)
621 out[out_stride * out_sample++] = SATURATE32 (PSHR32 (sum, 14), 32767);
622 last_sample += int_advance;
623 samp_frac_num += frac_advance;
624 if (samp_frac_num >= den_rate) {
625 samp_frac_num -= den_rate;
630 st->last_sample[channel_index] = last_sample;
631 st->samp_frac_num[channel_index] = samp_frac_num;
638 /* This is the same as the previous function, except with a double-precision accumulator */
640 resampler_basic_interpolate_double (SpeexResamplerState * st,
641 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
642 spx_word16_t * out, spx_uint32_t * out_len)
644 const int N = st->filt_len;
646 int last_sample = st->last_sample[channel_index];
647 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
648 const int out_stride = st->out_stride;
649 const int int_advance = st->int_advance;
650 const int frac_advance = st->frac_advance;
651 const spx_uint32_t den_rate = st->den_rate;
655 while (!(last_sample >= (spx_int32_t) * in_len
656 || out_sample >= (spx_int32_t) * out_len)) {
657 const spx_word16_t *iptr = &in[last_sample];
659 const int offset = samp_frac_num * st->oversample / st->den_rate;
661 const spx_word16_t frac =
662 PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
665 #ifdef DOUBLE_PRECISION
666 const spx_word16_t frac =
667 ((double) ((samp_frac_num * st->oversample) % st->den_rate)) /
670 const spx_word16_t frac =
671 ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
675 spx_word16_t interp[4];
678 SSE2_FALLBACK (INTERPOLATE_PRODUCT_DOUBLE)
679 double accum[4] = { 0, 0, 0, 0 };
681 for (j = 0; j < N; j++) {
682 const double curr_in = iptr[j];
685 st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
688 st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
691 st->sinc_table[4 + (j + 1) * st->oversample - offset]);
694 st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
697 cubic_coef (frac, interp);
699 MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
700 accum[1]) + MULT16_32_Q15 (interp[2],
701 accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
702 #ifdef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
703 SSE2_IMPLEMENTATION (INTERPOLATE_PRODUCT_DOUBLE)
704 cubic_coef (frac, interp);
706 interpolate_product_double (iptr,
707 st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
709 SSE2_END (INTERPOLATE_PRODUCT_DOUBLE)
712 out[out_stride * out_sample++] = PSHR32 (sum, 15);
713 last_sample += int_advance;
714 samp_frac_num += frac_advance;
715 if (samp_frac_num >= den_rate) {
716 samp_frac_num -= den_rate;
721 st->last_sample[channel_index] = last_sample;
722 st->samp_frac_num[channel_index] = samp_frac_num;
728 update_filter (SpeexResamplerState * st)
730 spx_uint32_t old_length;
732 old_length = st->filt_len;
733 st->oversample = quality_map[st->quality].oversample;
734 st->filt_len = quality_map[st->quality].base_length;
736 if (st->num_rate > st->den_rate) {
739 quality_map[st->quality].downsample_bandwidth * st->den_rate /
741 /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
742 st->filt_len = st->filt_len * st->num_rate / st->den_rate;
743 /* Round down to make sure we have a multiple of 4 */
744 st->filt_len &= (~0x3);
745 if (2 * st->den_rate < st->num_rate)
746 st->oversample >>= 1;
747 if (4 * st->den_rate < st->num_rate)
748 st->oversample >>= 1;
749 if (8 * st->den_rate < st->num_rate)
750 st->oversample >>= 1;
751 if (16 * st->den_rate < st->num_rate)
752 st->oversample >>= 1;
753 if (st->oversample < 1)
757 st->cutoff = quality_map[st->quality].upsample_bandwidth;
760 /* Choose the resampling type that requires the least amount of memory */
761 if (st->den_rate <= st->oversample) {
765 (spx_word16_t *) speex_alloc (st->filt_len * st->den_rate *
766 sizeof (spx_word16_t));
767 else if (st->sinc_table_length < st->filt_len * st->den_rate) {
769 (spx_word16_t *) speex_realloc (st->sinc_table,
770 st->filt_len * st->den_rate * sizeof (spx_word16_t));
771 st->sinc_table_length = st->filt_len * st->den_rate;
773 for (i = 0; i < st->den_rate; i++) {
775 for (j = 0; j < st->filt_len; j++) {
776 st->sinc_table[i * st->filt_len + j] =
777 sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
778 #ifdef DOUBLE_PRECISION
779 ((double) i) / st->den_rate), st->filt_len,
781 ((float) i) / st->den_rate), st->filt_len,
783 quality_map[st->quality].window_func);
787 st->resampler_ptr = resampler_basic_direct_single;
789 #ifdef DOUBLE_PRECISION
790 st->resampler_ptr = resampler_basic_direct_double;
793 st->resampler_ptr = resampler_basic_direct_double;
795 st->resampler_ptr = resampler_basic_direct_single;
798 /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
803 (spx_word16_t *) speex_alloc ((st->filt_len * st->oversample +
804 8) * sizeof (spx_word16_t));
805 else if (st->sinc_table_length < st->filt_len * st->oversample + 8) {
807 (spx_word16_t *) speex_realloc (st->sinc_table,
808 (st->filt_len * st->oversample + 8) * sizeof (spx_word16_t));
809 st->sinc_table_length = st->filt_len * st->oversample + 8;
811 for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
812 st->sinc_table[i + 4] =
813 #ifdef DOUBLE_PRECISION
814 sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2),
816 sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
818 st->filt_len, quality_map[st->quality].window_func);
820 st->resampler_ptr = resampler_basic_interpolate_single;
822 #ifdef DOUBLE_PRECISION
823 st->resampler_ptr = resampler_basic_interpolate_double;
826 st->resampler_ptr = resampler_basic_interpolate_double;
828 st->resampler_ptr = resampler_basic_interpolate_single;
831 /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
833 st->int_advance = st->num_rate / st->den_rate;
834 st->frac_advance = st->num_rate % st->den_rate;
837 /* Here's the place where we update the filter memory to take into account
838 the change in filter length. It's probably the messiest part of the code
839 due to handling of lots of corner cases. */
842 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
844 (spx_word16_t *) speex_alloc (st->nb_channels * st->mem_alloc_size *
845 sizeof (spx_word16_t));
846 for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
848 /*speex_warning("init filter"); */
849 } else if (!st->started) {
851 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
853 (spx_word16_t *) speex_realloc (st->mem,
854 st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
855 for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
857 /*speex_warning("reinit filter"); */
858 } else if (st->filt_len > old_length) {
860 /* Increase the filter length */
861 /*speex_warning("increase filter size"); */
862 int old_alloc_size = st->mem_alloc_size;
863 if ((st->filt_len - 1 + st->buffer_size) > st->mem_alloc_size) {
864 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
866 (spx_word16_t *) speex_realloc (st->mem,
867 st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
869 for (i = st->nb_channels - 1; i >= 0; i--) {
871 spx_uint32_t olen = old_length;
872 /*if (st->magic_samples[i]) */
874 /* Try and remove the magic samples as if nothing had happened */
876 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
877 olen = old_length + 2 * st->magic_samples[i];
878 for (j = old_length - 2 + st->magic_samples[i]; j >= 0; j--)
879 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]] =
880 st->mem[i * old_alloc_size + j];
881 for (j = 0; j < st->magic_samples[i]; j++)
882 st->mem[i * st->mem_alloc_size + j] = 0;
883 st->magic_samples[i] = 0;
885 if (st->filt_len > olen) {
886 /* If the new filter length is still bigger than the "augmented" length */
887 /* Copy data going backward */
888 for (j = 0; j < olen - 1; j++)
889 st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] =
890 st->mem[i * st->mem_alloc_size + (olen - 2 - j)];
891 /* Then put zeros for lack of anything better */
892 for (; j < st->filt_len - 1; j++)
893 st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] = 0;
894 /* Adjust last_sample */
895 st->last_sample[i] += (st->filt_len - olen) / 2;
897 /* Put back some of the magic! */
898 st->magic_samples[i] = (olen - st->filt_len) / 2;
899 for (j = 0; j < st->filt_len - 1 + st->magic_samples[i]; j++)
900 st->mem[i * st->mem_alloc_size + j] =
901 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
904 } else if (st->filt_len < old_length) {
906 /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
907 samples so they can be used directly as input the next time(s) */
908 for (i = 0; i < st->nb_channels; i++) {
910 spx_uint32_t old_magic = st->magic_samples[i];
911 st->magic_samples[i] = (old_length - st->filt_len) / 2;
912 /* We must copy some of the memory that's no longer used */
913 /* Copy data going backward */
914 for (j = 0; j < st->filt_len - 1 + st->magic_samples[i] + old_magic; j++)
915 st->mem[i * st->mem_alloc_size + j] =
916 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
917 st->magic_samples[i] += old_magic;
923 EXPORT SpeexResamplerState *
924 speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
925 spx_uint32_t out_rate, int quality, int *err)
927 return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate,
928 out_rate, quality, err);
931 #if defined HAVE_ORC && !defined DISABLE_ORC
933 check_insn_set (SpeexResamplerState * st, const char *name)
937 if (!strcmp (name, "sse"))
939 if (!strcmp (name, "sse2"))
940 st->use_sse = st->use_sse2 = 1;
944 EXPORT SpeexResamplerState *
945 speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
946 spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate,
947 int quality, int *err)
950 SpeexResamplerState *st;
951 if (quality > 10 || quality < 0) {
953 *err = RESAMPLER_ERR_INVALID_ARG;
956 st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState));
964 st->sinc_table_length = 0;
965 st->mem_alloc_size = 0;
968 st->resampler_ptr = 0;
971 st->nb_channels = nb_channels;
976 st->buffer_size = 160;
978 st->buffer_size = 160;
981 st->use_sse = st->use_sse2 = 0;
982 #if defined HAVE_ORC && !defined DISABLE_ORC
985 OrcTarget *target = orc_target_get_default ();
987 unsigned int flags = orc_target_get_default_flags (target);
988 check_insn_set (st, orc_target_get_name (target));
989 for (i = 0; i < 32; ++i) {
990 if (flags & (1 << i)) {
991 check_insn_set (st, orc_target_get_flag_name (target, i));
998 /* Per channel data */
999 st->last_sample = (spx_int32_t *) speex_alloc (nb_channels * sizeof (int));
1000 st->magic_samples = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
1001 st->samp_frac_num = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
1002 for (i = 0; i < nb_channels; i++) {
1003 st->last_sample[i] = 0;
1004 st->magic_samples[i] = 0;
1005 st->samp_frac_num[i] = 0;
1008 speex_resampler_set_quality (st, quality);
1009 speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate);
1014 st->initialised = 1;
1016 *err = RESAMPLER_ERR_SUCCESS;
1022 speex_resampler_destroy (SpeexResamplerState * st)
1024 speex_free (st->mem);
1025 speex_free (st->sinc_table);
1026 speex_free (st->last_sample);
1027 speex_free (st->magic_samples);
1028 speex_free (st->samp_frac_num);
1033 speex_resampler_process_native (SpeexResamplerState * st,
1034 spx_uint32_t channel_index, spx_uint32_t * in_len, spx_word16_t * out,
1035 spx_uint32_t * out_len)
1038 const int N = st->filt_len;
1040 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
1045 /* Call the right resampler through the function ptr */
1046 out_sample = st->resampler_ptr (st, channel_index, mem, in_len, out, out_len);
1048 if (st->last_sample[channel_index] < (spx_int32_t) * in_len)
1049 *in_len = st->last_sample[channel_index];
1050 *out_len = out_sample;
1051 st->last_sample[channel_index] -= *in_len;
1055 for (j = 0; j < N - 1; ++j)
1056 mem[j] = mem[j + ilen];
1058 return RESAMPLER_ERR_SUCCESS;
1062 speex_resampler_magic (SpeexResamplerState * st, spx_uint32_t channel_index,
1063 spx_word16_t ** out, spx_uint32_t out_len)
1065 spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
1066 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
1067 const int N = st->filt_len;
1069 speex_resampler_process_native (st, channel_index, &tmp_in_len, *out,
1072 st->magic_samples[channel_index] -= tmp_in_len;
1074 /* If we couldn't process all "magic" input samples, save the rest for next time */
1075 if (st->magic_samples[channel_index]) {
1077 for (i = 0; i < st->magic_samples[channel_index]; i++)
1078 mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len];
1080 *out += out_len * st->out_stride;
1086 speex_resampler_process_int (SpeexResamplerState * st,
1087 spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
1088 spx_int16_t * out, spx_uint32_t * out_len)
1090 #ifdef DOUBLE_PRECISION
1092 speex_resampler_process_float (SpeexResamplerState * st,
1093 spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len,
1094 double *out, spx_uint32_t * out_len)
1097 speex_resampler_process_float (SpeexResamplerState * st,
1098 spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
1099 float *out, spx_uint32_t * out_len)
1104 spx_uint32_t ilen = *in_len;
1105 spx_uint32_t olen = *out_len;
1106 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
1107 const int filt_offs = st->filt_len - 1;
1108 const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
1109 const int istride = st->in_stride;
1111 if (st->magic_samples[channel_index])
1112 olen -= speex_resampler_magic (st, channel_index, &out, olen);
1113 if (!st->magic_samples[channel_index]) {
1114 while (ilen && olen) {
1115 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
1116 spx_uint32_t ochunk = olen;
1119 for (j = 0; j < ichunk; ++j)
1120 x[j + filt_offs] = in[j * istride];
1122 for (j = 0; j < ichunk; ++j)
1123 x[j + filt_offs] = 0;
1125 speex_resampler_process_native (st, channel_index, &ichunk, out, &ochunk);
1128 out += ochunk * st->out_stride;
1130 in += ichunk * istride;
1135 return RESAMPLER_ERR_SUCCESS;
1140 speex_resampler_process_float (SpeexResamplerState * st,
1141 spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
1142 float *out, spx_uint32_t * out_len)
1145 speex_resampler_process_int (SpeexResamplerState * st,
1146 spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
1147 spx_int16_t * out, spx_uint32_t * out_len)
1151 const int istride_save = st->in_stride;
1152 const int ostride_save = st->out_stride;
1153 spx_uint32_t ilen = *in_len;
1154 spx_uint32_t olen = *out_len;
1155 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
1156 const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
1158 const unsigned int ylen =
1159 (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
1160 VARDECL (spx_word16_t * ystack);
1161 ALLOC (ystack, ylen, spx_word16_t);
1163 const unsigned int ylen = FIXED_STACK_ALLOC;
1164 spx_word16_t ystack[FIXED_STACK_ALLOC];
1169 while (ilen && olen) {
1170 spx_word16_t *y = ystack;
1171 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
1172 spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
1173 spx_uint32_t omagic = 0;
1175 if (st->magic_samples[channel_index]) {
1176 omagic = speex_resampler_magic (st, channel_index, &y, ochunk);
1180 if (!st->magic_samples[channel_index]) {
1182 for (j = 0; j < ichunk; ++j)
1184 x[j + st->filt_len - 1] = WORD2INT (in[j * istride_save]);
1186 x[j + st->filt_len - 1] = in[j * istride_save];
1189 for (j = 0; j < ichunk; ++j)
1190 x[j + st->filt_len - 1] = 0;
1193 speex_resampler_process_native (st, channel_index, &ichunk, y, &ochunk);
1199 for (j = 0; j < ochunk + omagic; ++j)
1201 out[j * ostride_save] = ystack[j];
1203 out[j * ostride_save] = WORD2INT (ystack[j]);
1208 out += (ochunk + omagic) * ostride_save;
1210 in += ichunk * istride_save;
1212 st->out_stride = ostride_save;
1216 return RESAMPLER_ERR_SUCCESS;
1219 #ifdef DOUBLE_PRECISION
1221 speex_resampler_process_interleaved_float (SpeexResamplerState * st,
1222 const double *in, spx_uint32_t * in_len, double *out,
1223 spx_uint32_t * out_len)
1226 speex_resampler_process_interleaved_float (SpeexResamplerState * st,
1227 const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
1231 int istride_save, ostride_save;
1232 spx_uint32_t bak_len = *out_len;
1233 istride_save = st->in_stride;
1234 ostride_save = st->out_stride;
1235 st->in_stride = st->out_stride = st->nb_channels;
1236 for (i = 0; i < st->nb_channels; i++) {
1239 speex_resampler_process_float (st, i, in + i, in_len, out + i, out_len);
1241 speex_resampler_process_float (st, i, NULL, in_len, out + i, out_len);
1243 st->in_stride = istride_save;
1244 st->out_stride = ostride_save;
1245 return RESAMPLER_ERR_SUCCESS;
1249 speex_resampler_process_interleaved_int (SpeexResamplerState * st,
1250 const spx_int16_t * in, spx_uint32_t * in_len, spx_int16_t * out,
1251 spx_uint32_t * out_len)
1254 int istride_save, ostride_save;
1255 spx_uint32_t bak_len = *out_len;
1256 istride_save = st->in_stride;
1257 ostride_save = st->out_stride;
1258 st->in_stride = st->out_stride = st->nb_channels;
1259 for (i = 0; i < st->nb_channels; i++) {
1262 speex_resampler_process_int (st, i, in + i, in_len, out + i, out_len);
1264 speex_resampler_process_int (st, i, NULL, in_len, out + i, out_len);
1266 st->in_stride = istride_save;
1267 st->out_stride = ostride_save;
1268 return RESAMPLER_ERR_SUCCESS;
1272 speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate,
1273 spx_uint32_t out_rate)
1275 return speex_resampler_set_rate_frac (st, in_rate, out_rate, in_rate,
1280 speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate,
1281 spx_uint32_t * out_rate)
1283 *in_rate = st->in_rate;
1284 *out_rate = st->out_rate;
1288 speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num,
1289 spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
1292 spx_uint32_t old_den;
1294 if (st->in_rate == in_rate && st->out_rate == out_rate
1295 && st->num_rate == ratio_num && st->den_rate == ratio_den)
1296 return RESAMPLER_ERR_SUCCESS;
1298 old_den = st->den_rate;
1299 st->in_rate = in_rate;
1300 st->out_rate = out_rate;
1301 st->num_rate = ratio_num;
1302 st->den_rate = ratio_den;
1303 /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
1304 for (fact = 2; fact <= IMIN (st->num_rate, st->den_rate); fact++) {
1305 while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) {
1306 st->num_rate /= fact;
1307 st->den_rate /= fact;
1312 for (i = 0; i < st->nb_channels; i++) {
1313 st->samp_frac_num[i] = st->samp_frac_num[i] * st->den_rate / old_den;
1315 if (st->samp_frac_num[i] >= st->den_rate)
1316 st->samp_frac_num[i] = st->den_rate - 1;
1320 if (st->initialised)
1322 return RESAMPLER_ERR_SUCCESS;
1326 speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num,
1327 spx_uint32_t * ratio_den)
1329 *ratio_num = st->num_rate;
1330 *ratio_den = st->den_rate;
1334 speex_resampler_set_quality (SpeexResamplerState * st, int quality)
1336 if (quality > 10 || quality < 0)
1337 return RESAMPLER_ERR_INVALID_ARG;
1338 if (st->quality == quality)
1339 return RESAMPLER_ERR_SUCCESS;
1340 st->quality = quality;
1341 if (st->initialised)
1343 return RESAMPLER_ERR_SUCCESS;
1347 speex_resampler_get_quality (SpeexResamplerState * st, int *quality)
1349 *quality = st->quality;
1353 speex_resampler_set_input_stride (SpeexResamplerState * st, spx_uint32_t stride)
1355 st->in_stride = stride;
1359 speex_resampler_get_input_stride (SpeexResamplerState * st,
1360 spx_uint32_t * stride)
1362 *stride = st->in_stride;
1366 speex_resampler_set_output_stride (SpeexResamplerState * st,
1367 spx_uint32_t stride)
1369 st->out_stride = stride;
1373 speex_resampler_get_output_stride (SpeexResamplerState * st,
1374 spx_uint32_t * stride)
1376 *stride = st->out_stride;
1380 speex_resampler_get_input_latency (SpeexResamplerState * st)
1382 return st->filt_len / 2;
1386 speex_resampler_get_output_latency (SpeexResamplerState * st)
1388 return ((st->filt_len / 2) * st->den_rate +
1389 (st->num_rate >> 1)) / st->num_rate;
1393 speex_resampler_get_filt_len (SpeexResamplerState * st)
1395 return st->filt_len;
1399 speex_resampler_skip_zeros (SpeexResamplerState * st)
1402 for (i = 0; i < st->nb_channels; i++)
1403 st->last_sample[i] = st->filt_len / 2;
1404 return RESAMPLER_ERR_SUCCESS;
1408 speex_resampler_reset_mem (SpeexResamplerState * st)
1411 for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++)
1413 return RESAMPLER_ERR_SUCCESS;
1417 speex_resampler_strerror (int err)
1420 case RESAMPLER_ERR_SUCCESS:
1422 case RESAMPLER_ERR_ALLOC_FAILED:
1423 return "Memory allocation failed.";
1424 case RESAMPLER_ERR_BAD_STATE:
1425 return "Bad resampler state.";
1426 case RESAMPLER_ERR_INVALID_ARG:
1427 return "Invalid argument.";
1428 case RESAMPLER_ERR_PTR_OVERLAP:
1429 return "Input and output buffers overlap.";
1431 return "Unknown error. Bad error code or strange version mismatch.";