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
98 speex_alloc (int size)
100 return g_malloc0 (size);
104 speex_realloc (void *ptr, int size)
106 return g_realloc (ptr, size);
110 speex_free (void *ptr)
115 #include "speex_resampler.h"
117 #else /* OUTSIDE_SPEEX */
119 #include "../include/speex/speex_resampler.h"
121 #include "os_support.h"
122 #endif /* OUTSIDE_SPEEX */
127 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
129 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
132 #define IMAX(a,b) ((a) > (b) ? (a) : (b))
133 #define IMIN(a,b) ((a) < (b) ? (a) : (b))
139 #if defined _USE_SSE || defined _USE_SSE2
140 #include "resample_sse.h"
144 #include "resample_neon.h"
147 /* Numer of elements to allocate on the stack */
149 #define FIXED_STACK_ALLOC 8192
151 #define FIXED_STACK_ALLOC 1024
154 /* Allow selecting SSE or not when compiled with SSE support */
156 #define SSE_FALLBACK(macro) \
157 if (st->use_sse) goto sse_##macro##_sse; {
158 #define SSE_IMPLEMENTATION(macro) \
159 goto sse_##macro##_end; } sse_##macro##_sse: {
160 #define SSE_END(macro) sse_##macro##_end:; }
162 #define SSE_FALLBACK(macro)
166 #define SSE2_FALLBACK(macro) \
167 if (st->use_sse2) goto sse2_##macro##_sse2; {
168 #define SSE2_IMPLEMENTATION(macro) \
169 goto sse2_##macro##_end; } sse2_##macro##_sse2: {
170 #define SSE2_END(macro) sse2_##macro##_end:; }
172 #define SSE2_FALLBACK(macro)
176 #define NEON_FALLBACK(macro) \
177 if (st->use_neon) goto neon_##macro##_neon; {
178 #define NEON_IMPLEMENTATION(macro) \
179 goto neon_##macro##_end; } neon_##macro##_neon: {
180 #define NEON_END(macro) neon_##macro##_end:; }
182 #define NEON_FALLBACK(macro)
186 typedef int (*resampler_basic_func) (SpeexResamplerState *, spx_uint32_t,
187 const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
189 struct SpeexResamplerState_
191 spx_uint32_t in_rate;
192 spx_uint32_t out_rate;
193 spx_uint32_t num_rate;
194 spx_uint32_t den_rate;
197 spx_uint32_t nb_channels;
198 spx_uint32_t filt_len;
199 spx_uint32_t mem_alloc_size;
200 spx_uint32_t buffer_size;
204 spx_uint32_t oversample;
207 int use_full_sinc_table;
209 /* These are per-channel */
210 spx_int32_t *last_sample;
211 spx_uint32_t *samp_frac_num;
212 spx_uint32_t *magic_samples;
215 spx_word16_t *sinc_table;
216 spx_uint32_t sinc_table_length;
217 resampler_basic_func resampler_ptr;
227 static double kaiser12_table[68] = {
228 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
229 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
230 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
231 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
232 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
233 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
234 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
235 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
236 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
237 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
238 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
239 0.00001000, 0.00000000
243 static double kaiser12_table[36] = {
244 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
245 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
246 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
247 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
248 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
249 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
251 static double kaiser10_table[36] = {
252 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
253 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
254 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
255 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
256 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
257 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000
260 static double kaiser8_table[36] = {
261 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
262 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
263 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
264 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
265 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
266 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000
269 static double kaiser6_table[36] = {
270 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
271 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
272 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
273 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
274 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
275 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000
284 static struct FuncDef _KAISER12 = { kaiser12_table, 64 };
286 #define KAISER12 (&_KAISER12)
287 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
288 #define KAISER12 (&_KAISER12)*/
289 static struct FuncDef _KAISER10 = { kaiser10_table, 32 };
291 #define KAISER10 (&_KAISER10)
292 static struct FuncDef _KAISER8 = { kaiser8_table, 32 };
294 #define KAISER8 (&_KAISER8)
295 static struct FuncDef _KAISER6 = { kaiser6_table, 32 };
297 #define KAISER6 (&_KAISER6)
299 struct QualityMapping
303 float downsample_bandwidth;
304 float upsample_bandwidth;
305 struct FuncDef *window_func;
309 /* This table maps conversion quality to internal parameters. There are two
310 reasons that explain why the up-sampling bandwidth is larger than the
311 down-sampling bandwidth:
312 1) When up-sampling, we can assume that the spectrum is already attenuated
313 close to the Nyquist rate (from an A/D or a previous resampling filter)
314 2) Any aliasing that occurs very close to the Nyquist rate will be masked
315 by the sinusoids/noise just below the Nyquist rate (guaranteed only for
318 static const struct QualityMapping quality_map[11] = {
319 {8, 4, 0.830f, 0.860f, KAISER6}, /* Q0 */
320 {16, 4, 0.850f, 0.880f, KAISER6}, /* Q1 */
321 {32, 4, 0.882f, 0.910f, KAISER6}, /* Q2 *//* 82.3% cutoff ( ~60 dB stop) 6 */
322 {48, 8, 0.895f, 0.917f, KAISER8}, /* Q3 *//* 84.9% cutoff ( ~80 dB stop) 8 */
323 {64, 8, 0.921f, 0.940f, KAISER8}, /* Q4 *//* 88.7% cutoff ( ~80 dB stop) 8 */
324 {80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 *//* 89.1% cutoff (~100 dB stop) 10 */
325 {96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 *//* 91.5% cutoff (~100 dB stop) 10 */
326 {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 *//* 93.1% cutoff (~100 dB stop) 10 */
327 {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 *//* 94.5% cutoff (~100 dB stop) 10 */
328 {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 *//* 95.5% cutoff (~100 dB stop) 10 */
329 {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 *//* 96.6% cutoff (~100 dB stop) 10 */
332 /*8,24,40,56,80,104,128,160,200,256,320*/
333 #ifdef DOUBLE_PRECISION
335 compute_func (double x, struct FuncDef *func)
340 compute_func (float x, struct FuncDef *func)
346 y = x * func->oversample;
347 ind = (int) floor (y);
349 /* CSE with handle the repeated powers */
350 interp[3] = -0.1666666667 * frac + 0.1666666667 * (frac * frac * frac);
351 interp[2] = frac + 0.5 * (frac * frac) - 0.5 * (frac * frac * frac);
352 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
354 -0.3333333333 * frac + 0.5 * (frac * frac) -
355 0.1666666667 * (frac * frac * frac);
356 /* Just to make sure we don't have rounding problems */
357 interp[1] = 1.f - interp[3] - interp[2] - interp[0];
359 /*sum = frac*accum[1] + (1-frac)*accum[2]; */
360 return interp[0] * func->table[ind] + interp[1] * func->table[ind + 1] +
361 interp[2] * func->table[ind + 2] + interp[3] * func->table[ind + 3];
367 main (int argc, char **argv)
370 for (i = 0; i < 256; i++) {
371 printf ("%f\n", compute_func (i / 256., KAISER12));
378 /* The slow way of computing a sinc for the table. Should improve that some day */
380 sinc (float cutoff, float x, int N, struct FuncDef *window_func)
382 /*fprintf (stderr, "%f ", x); */
383 float xx = x * cutoff;
384 if (fabs (x) < 1e-6f)
385 return WORD2INT (32768. * cutoff);
386 else if (fabs (x) > .5f * N)
388 /*FIXME: Can it really be any slower than this? */
389 return WORD2INT (32768. * cutoff * sin (G_PI * xx) / (G_PI * xx) *
390 compute_func (fabs (2. * x / N), window_func));
393 /* The slow way of computing a sinc for the table. Should improve that some day */
394 #ifdef DOUBLE_PRECISION
396 sinc (double cutoff, double x, int N, struct FuncDef *window_func)
398 /*fprintf (stderr, "%f ", x); */
399 double xx = x * cutoff;
402 sinc (float cutoff, float x, int N, struct FuncDef *window_func)
404 /*fprintf (stderr, "%f ", x); */
405 float xx = x * cutoff;
409 else if (fabs (x) > .5 * N)
411 /*FIXME: Can it really be any slower than this? */
412 return cutoff * sin (G_PI * xx) / (G_PI * xx) * compute_func (fabs (2. * x /
419 cubic_coef (spx_word16_t x, spx_word16_t interp[4])
421 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
422 but I know it's MMSE-optimal on a sinc */
424 x2 = MULT16_16_P15 (x, x);
425 x3 = MULT16_16_P15 (x, x2);
427 PSHR32 (MULT16_16 (QCONST16 (-0.16667f, 15),
428 x) + MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
430 EXTRACT16 (EXTEND32 (x) + SHR32 (SUB32 (EXTEND32 (x2), EXTEND32 (x3)),
433 PSHR32 (MULT16_16 (QCONST16 (-0.33333f, 15),
434 x) + MULT16_16 (QCONST16 (.5f, 15),
435 x2) - MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
436 /* Just to make sure we don't have rounding problems */
437 interp[2] = Q15_ONE - interp[0] - interp[1] - interp[3];
438 if (interp[2] < 32767)
443 cubic_coef (spx_word16_t frac, spx_word16_t interp[4])
445 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
446 but I know it's MMSE-optimal on a sinc */
447 interp[0] = -0.16667f * frac + 0.16667f * frac * frac * frac;
448 interp[1] = frac + 0.5f * frac * frac - 0.5f * frac * frac * frac;
449 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
451 -0.33333f * frac + 0.5f * frac * frac - 0.16667f * frac * frac * frac;
452 /* Just to make sure we don't have rounding problems */
453 interp[2] = 1. - interp[0] - interp[1] - interp[3];
457 #ifndef DOUBLE_PRECISION
459 resampler_basic_direct_single (SpeexResamplerState * st,
460 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
461 spx_word16_t * out, spx_uint32_t * out_len)
463 const int N = st->filt_len;
465 int last_sample = st->last_sample[channel_index];
466 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
467 const spx_word16_t *sinc_table = st->sinc_table;
468 const int out_stride = st->out_stride;
469 const int int_advance = st->int_advance;
470 const int frac_advance = st->frac_advance;
471 const spx_uint32_t den_rate = st->den_rate;
475 while (!(last_sample >= (spx_int32_t) * in_len
476 || out_sample >= (spx_int32_t) * out_len)) {
477 const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
478 const spx_word16_t *iptr = &in[last_sample];
480 SSE_FALLBACK (INNER_PRODUCT_SINGLE)
481 NEON_FALLBACK (INNER_PRODUCT_SINGLE)
483 for (j = 0; j < N; j++)
484 sum += MULT16_16 (sinc[j], iptr[j]);
486 /* This code is slower on most DSPs which have only 2 accumulators.
487 Plus this forces truncation to 32 bits and you lose the HW guard bits.
488 I think we can trust the compiler and let it vectorize and/or unroll itself.
489 spx_word32_t accum[4] = {0,0,0,0};
491 accum[0] += MULT16_16(sinc[j], iptr[j]);
492 accum[1] += MULT16_16(sinc[j+1], iptr[j+1]);
493 accum[2] += MULT16_16(sinc[j+2], iptr[j+2]);
494 accum[3] += MULT16_16(sinc[j+3], iptr[j+3]);
496 sum = accum[0] + accum[1] + accum[2] + accum[3];
498 #if defined(OVERRIDE_INNER_PRODUCT_SINGLE) && defined(_USE_NEON)
499 NEON_IMPLEMENTATION (INNER_PRODUCT_SINGLE)
500 sum = inner_product_single (sinc, iptr, N);
501 NEON_END(INNER_PRODUCT_SINGLE)
502 #elif defined(OVERRIDE_INNER_PRODUCT_SINGLE) && defined(_USE_SSE)
503 SSE_IMPLEMENTATION (INNER_PRODUCT_SINGLE)
504 sum = inner_product_single (sinc, iptr, N);
505 SSE_END (INNER_PRODUCT_SINGLE)
507 out[out_stride * out_sample++] = SATURATE32PSHR(sum, 15, 32767);
508 last_sample += int_advance;
509 samp_frac_num += frac_advance;
510 if (samp_frac_num >= den_rate) {
511 samp_frac_num -= den_rate;
516 st->last_sample[channel_index] = last_sample;
517 st->samp_frac_num[channel_index] = samp_frac_num;
524 /* This is the same as the previous function, except with a double-precision accumulator */
526 resampler_basic_direct_double (SpeexResamplerState * st,
527 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
528 spx_word16_t * out, spx_uint32_t * out_len)
530 const int N = st->filt_len;
532 int last_sample = st->last_sample[channel_index];
533 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
534 const spx_word16_t *sinc_table = st->sinc_table;
535 const int out_stride = st->out_stride;
536 const int int_advance = st->int_advance;
537 const int frac_advance = st->frac_advance;
538 const spx_uint32_t den_rate = st->den_rate;
542 while (!(last_sample >= (spx_int32_t) * in_len
543 || out_sample >= (spx_int32_t) * out_len)) {
544 const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
545 const spx_word16_t *iptr = &in[last_sample];
547 SSE2_FALLBACK (INNER_PRODUCT_DOUBLE)
548 double accum[4] = { 0, 0, 0, 0 };
550 for (j = 0; j < N; j += 4) {
551 accum[0] += sinc[j] * iptr[j];
552 accum[1] += sinc[j + 1] * iptr[j + 1];
553 accum[2] += sinc[j + 2] * iptr[j + 2];
554 accum[3] += sinc[j + 3] * iptr[j + 3];
556 sum = accum[0] + accum[1] + accum[2] + accum[3];
557 #if defined(OVERRIDE_INNER_PRODUCT_DOUBLE) && defined(_USE_SSE2)
558 SSE2_IMPLEMENTATION (INNER_PRODUCT_DOUBLE)
559 sum = inner_product_double (sinc, iptr, N);
560 SSE2_END (INNER_PRODUCT_DOUBLE)
562 out[out_stride * out_sample++] = PSHR32 (sum, 15);
563 last_sample += int_advance;
564 samp_frac_num += frac_advance;
565 if (samp_frac_num >= den_rate) {
566 samp_frac_num -= den_rate;
571 st->last_sample[channel_index] = last_sample;
572 st->samp_frac_num[channel_index] = samp_frac_num;
577 #ifndef DOUBLE_PRECISION
579 resampler_basic_interpolate_single (SpeexResamplerState * st,
580 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
581 spx_word16_t * out, spx_uint32_t * out_len)
583 const int N = st->filt_len;
585 int last_sample = st->last_sample[channel_index];
586 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
587 const int out_stride = st->out_stride;
588 const int int_advance = st->int_advance;
589 const int frac_advance = st->frac_advance;
590 const spx_uint32_t den_rate = st->den_rate;
594 while (!(last_sample >= (spx_int32_t) * in_len
595 || out_sample >= (spx_int32_t) * out_len)) {
596 const spx_word16_t *iptr = &in[last_sample];
598 const int offset = samp_frac_num * st->oversample / st->den_rate;
600 const spx_word16_t frac =
601 PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
604 const spx_word16_t frac =
605 ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
608 spx_word16_t interp[4];
611 SSE_FALLBACK (INTERPOLATE_PRODUCT_SINGLE)
612 spx_word32_t accum[4] = { 0, 0, 0, 0 };
614 for (j = 0; j < N; j++) {
615 const spx_word16_t curr_in = iptr[j];
618 st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
621 st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
624 st->sinc_table[4 + (j + 1) * st->oversample - offset]);
627 st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
630 cubic_coef (frac, interp);
632 MULT16_32_Q15 (interp[0], SHR32 (accum[0],
633 1)) + MULT16_32_Q15 (interp[1], SHR32 (accum[1],
634 1)) + MULT16_32_Q15 (interp[2], SHR32 (accum[2],
635 1)) + MULT16_32_Q15 (interp[3], SHR32 (accum[3], 1));
636 #if defined(OVERRIDE_INTERPOLATE_PRODUCT_SINGLE) && defined(_USE_SSE)
637 SSE_IMPLEMENTATION (INTERPOLATE_PRODUCT_SINGLE)
638 cubic_coef (frac, interp);
640 interpolate_product_single (iptr,
641 st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
643 SSE_END (INTERPOLATE_PRODUCT_SINGLE)
645 out[out_stride * out_sample++] = SATURATE32PSHR(sum, 14, 32767);
646 last_sample += int_advance;
647 samp_frac_num += frac_advance;
648 if (samp_frac_num >= den_rate) {
649 samp_frac_num -= den_rate;
654 st->last_sample[channel_index] = last_sample;
655 st->samp_frac_num[channel_index] = samp_frac_num;
662 /* This is the same as the previous function, except with a double-precision accumulator */
664 resampler_basic_interpolate_double (SpeexResamplerState * st,
665 spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
666 spx_word16_t * out, spx_uint32_t * out_len)
668 const int N = st->filt_len;
670 int last_sample = st->last_sample[channel_index];
671 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
672 const int out_stride = st->out_stride;
673 const int int_advance = st->int_advance;
674 const int frac_advance = st->frac_advance;
675 const spx_uint32_t den_rate = st->den_rate;
679 while (!(last_sample >= (spx_int32_t) * in_len
680 || out_sample >= (spx_int32_t) * out_len)) {
681 const spx_word16_t *iptr = &in[last_sample];
683 const int offset = samp_frac_num * st->oversample / st->den_rate;
685 const spx_word16_t frac =
686 PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
689 #ifdef DOUBLE_PRECISION
690 const spx_word16_t frac =
691 ((double) ((samp_frac_num * st->oversample) % st->den_rate)) /
694 const spx_word16_t frac =
695 ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
699 spx_word16_t interp[4];
702 SSE2_FALLBACK (INTERPOLATE_PRODUCT_DOUBLE)
703 double accum[4] = { 0, 0, 0, 0 };
705 for (j = 0; j < N; j++) {
706 const double curr_in = iptr[j];
709 st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
712 st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
715 st->sinc_table[4 + (j + 1) * st->oversample - offset]);
718 st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
721 cubic_coef (frac, interp);
723 MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
724 accum[1]) + MULT16_32_Q15 (interp[2],
725 accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
726 #if defined(OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE) && defined(_USE_SSE2)
727 SSE2_IMPLEMENTATION (INTERPOLATE_PRODUCT_DOUBLE)
728 cubic_coef (frac, interp);
730 interpolate_product_double (iptr,
731 st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
733 SSE2_END (INTERPOLATE_PRODUCT_DOUBLE)
735 out[out_stride * out_sample++] = PSHR32 (sum, 15);
736 last_sample += int_advance;
737 samp_frac_num += frac_advance;
738 if (samp_frac_num >= den_rate) {
739 samp_frac_num -= den_rate;
744 st->last_sample[channel_index] = last_sample;
745 st->samp_frac_num[channel_index] = samp_frac_num;
751 update_filter (SpeexResamplerState * st)
753 spx_uint32_t old_length;
755 old_length = st->filt_len;
756 st->oversample = quality_map[st->quality].oversample;
757 st->filt_len = quality_map[st->quality].base_length;
759 if (st->num_rate > st->den_rate) {
762 quality_map[st->quality].downsample_bandwidth * st->den_rate /
764 /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
765 st->filt_len = st->filt_len * st->num_rate / st->den_rate;
766 /* Round down to make sure we have a multiple of 4 */
767 st->filt_len &= (~0x3);
768 if (2 * st->den_rate < st->num_rate)
769 st->oversample >>= 1;
770 if (4 * st->den_rate < st->num_rate)
771 st->oversample >>= 1;
772 if (8 * st->den_rate < st->num_rate)
773 st->oversample >>= 1;
774 if (16 * st->den_rate < st->num_rate)
775 st->oversample >>= 1;
776 if (st->oversample < 1)
780 st->cutoff = quality_map[st->quality].upsample_bandwidth;
783 /* Choose the resampling type that requires the least amount of memory */
784 /* Or if the full sinc table is explicitely requested, use that */
785 if (st->use_full_sinc_table || (st->den_rate <= st->oversample)) {
789 (spx_word16_t *) speex_alloc (st->filt_len * st->den_rate *
790 sizeof (spx_word16_t));
791 else if (st->sinc_table_length < st->filt_len * st->den_rate) {
793 (spx_word16_t *) speex_realloc (st->sinc_table,
794 st->filt_len * st->den_rate * sizeof (spx_word16_t));
795 st->sinc_table_length = st->filt_len * st->den_rate;
797 for (i = 0; i < st->den_rate; i++) {
799 for (j = 0; j < st->filt_len; j++) {
800 st->sinc_table[i * st->filt_len + j] =
801 sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
802 #ifdef DOUBLE_PRECISION
803 ((double) i) / st->den_rate), st->filt_len,
805 ((float) i) / st->den_rate), st->filt_len,
807 quality_map[st->quality].window_func);
811 st->resampler_ptr = resampler_basic_direct_single;
813 #ifdef DOUBLE_PRECISION
814 st->resampler_ptr = resampler_basic_direct_double;
817 st->resampler_ptr = resampler_basic_direct_double;
819 st->resampler_ptr = resampler_basic_direct_single;
822 /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
827 (spx_word16_t *) speex_alloc ((st->filt_len * st->oversample +
828 8) * sizeof (spx_word16_t));
829 else if (st->sinc_table_length < st->filt_len * st->oversample + 8) {
831 (spx_word16_t *) speex_realloc (st->sinc_table,
832 (st->filt_len * st->oversample + 8) * sizeof (spx_word16_t));
833 st->sinc_table_length = st->filt_len * st->oversample + 8;
835 for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
836 st->sinc_table[i + 4] =
837 #ifdef DOUBLE_PRECISION
838 sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2),
840 sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
842 st->filt_len, quality_map[st->quality].window_func);
844 st->resampler_ptr = resampler_basic_interpolate_single;
846 #ifdef DOUBLE_PRECISION
847 st->resampler_ptr = resampler_basic_interpolate_double;
850 st->resampler_ptr = resampler_basic_interpolate_double;
852 st->resampler_ptr = resampler_basic_interpolate_single;
855 /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
857 st->int_advance = st->num_rate / st->den_rate;
858 st->frac_advance = st->num_rate % st->den_rate;
861 /* Here's the place where we update the filter memory to take into account
862 the change in filter length. It's probably the messiest part of the code
863 due to handling of lots of corner cases. */
866 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
868 (spx_word16_t *) speex_alloc (st->nb_channels * st->mem_alloc_size *
869 sizeof (spx_word16_t));
870 for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
872 /*speex_warning("init filter"); */
873 } else if (!st->started) {
875 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
877 (spx_word16_t *) speex_realloc (st->mem,
878 st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
879 for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
881 /*speex_warning("reinit filter"); */
882 } else if (st->filt_len > old_length) {
884 /* Increase the filter length */
885 /*speex_warning("increase filter size"); */
886 int old_alloc_size = st->mem_alloc_size;
887 if ((st->filt_len - 1 + st->buffer_size) > st->mem_alloc_size) {
888 st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
890 (spx_word16_t *) speex_realloc (st->mem,
891 st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
893 for (i = st->nb_channels - 1; i >= 0; i--) {
895 spx_uint32_t olen = old_length;
896 /*if (st->magic_samples[i]) */
898 /* Try and remove the magic samples as if nothing had happened */
900 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
901 olen = old_length + 2 * st->magic_samples[i];
902 for (j = old_length - 2 + st->magic_samples[i]; j >= 0; j--)
903 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]] =
904 st->mem[i * old_alloc_size + j];
905 for (j = 0; j < st->magic_samples[i]; j++)
906 st->mem[i * st->mem_alloc_size + j] = 0;
907 st->magic_samples[i] = 0;
909 if (st->filt_len > olen) {
910 /* If the new filter length is still bigger than the "augmented" length */
911 /* Copy data going backward */
912 for (j = 0; j < olen - 1; j++)
913 st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] =
914 st->mem[i * st->mem_alloc_size + (olen - 2 - j)];
915 /* Then put zeros for lack of anything better */
916 for (; j < st->filt_len - 1; j++)
917 st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] = 0;
918 /* Adjust last_sample */
919 st->last_sample[i] += (st->filt_len - olen) / 2;
921 /* Put back some of the magic! */
922 st->magic_samples[i] = (olen - st->filt_len) / 2;
923 for (j = 0; j < st->filt_len - 1 + st->magic_samples[i]; j++)
924 st->mem[i * st->mem_alloc_size + j] =
925 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
928 } else if (st->filt_len < old_length) {
930 /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
931 samples so they can be used directly as input the next time(s) */
932 for (i = 0; i < st->nb_channels; i++) {
934 spx_uint32_t old_magic = st->magic_samples[i];
935 st->magic_samples[i] = (old_length - st->filt_len) / 2;
936 /* We must copy some of the memory that's no longer used */
937 /* Copy data going backward */
938 for (j = 0; j < st->filt_len - 1 + st->magic_samples[i] + old_magic; j++)
939 st->mem[i * st->mem_alloc_size + j] =
940 st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
941 st->magic_samples[i] += old_magic;
947 EXPORT SpeexResamplerState *
948 speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
949 spx_uint32_t out_rate, int quality, SpeexResamplerSincFilterMode sinc_filter_mode,
950 spx_uint32_t sinc_filter_auto_threshold, int *err)
952 return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate,
953 out_rate, quality, sinc_filter_mode, sinc_filter_auto_threshold, err);
956 #if defined HAVE_ORC && !defined DISABLE_ORC
958 check_insn_set (SpeexResamplerState * st, const char *name)
963 if (!strcmp (name, "sse"))
967 if (!strcmp (name, "sse2"))
968 st->use_sse = st->use_sse2 = 1;
971 if (!strcmp (name, "neon"))
977 EXPORT SpeexResamplerState *
978 speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
979 spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate,
980 int quality, SpeexResamplerSincFilterMode sinc_filter_mode,
981 spx_uint32_t sinc_filter_auto_threshold, int *err)
984 SpeexResamplerState *st;
985 int use_full_sinc_table = 0;
986 if (quality > 10 || quality < 0) {
988 *err = RESAMPLER_ERR_INVALID_ARG;
991 switch (sinc_filter_mode) {
992 case RESAMPLER_SINC_FILTER_INTERPOLATED:
993 use_full_sinc_table = 0;
995 case RESAMPLER_SINC_FILTER_FULL:
996 use_full_sinc_table = 1;
998 case RESAMPLER_SINC_FILTER_AUTO:
1003 *err = RESAMPLER_ERR_INVALID_ARG;
1007 st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState));
1008 st->initialised = 0;
1015 st->sinc_table_length = 0;
1016 st->mem_alloc_size = 0;
1019 st->resampler_ptr = 0;
1020 st->use_full_sinc_table = use_full_sinc_table;
1023 st->nb_channels = nb_channels;
1028 st->buffer_size = 160;
1030 st->buffer_size = 160;
1033 st->use_sse = st->use_sse2 = 0;
1035 #if defined HAVE_ORC && !defined DISABLE_ORC
1038 OrcTarget *target = orc_target_get_default ();
1040 unsigned int flags = orc_target_get_default_flags (target);
1041 check_insn_set (st, orc_target_get_name (target));
1042 for (i = 0; i < 32; ++i) {
1043 if (flags & (1 << i)) {
1044 check_insn_set (st, orc_target_get_flag_name (target, i));
1051 /* Per channel data */
1052 st->last_sample = (spx_int32_t *) speex_alloc (nb_channels * sizeof (int));
1053 st->magic_samples = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
1054 st->samp_frac_num = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
1055 for (i = 0; i < nb_channels; i++) {
1056 st->last_sample[i] = 0;
1057 st->magic_samples[i] = 0;
1058 st->samp_frac_num[i] = 0;
1061 speex_resampler_set_quality (st, quality);
1062 speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate);
1064 if (sinc_filter_mode == RESAMPLER_SINC_FILTER_AUTO) {
1066 Estimate how big the filter table would become if the full mode were to be used
1067 calculations used correspond to the ones in update_filter()
1068 if the size is bigger than the threshold, use interpolated sinc instead
1070 spx_uint32_t base_filter_length = st->filt_len = quality_map[st->quality].base_length;
1071 spx_uint32_t filter_table_size = base_filter_length * st->den_rate * sizeof(spx_uint16_t);
1072 st->use_full_sinc_table = (filter_table_size > sinc_filter_auto_threshold) ? 0 : 1;
1077 st->initialised = 1;
1079 *err = RESAMPLER_ERR_SUCCESS;
1085 speex_resampler_destroy (SpeexResamplerState * st)
1087 speex_free (st->mem);
1088 speex_free (st->sinc_table);
1089 speex_free (st->last_sample);
1090 speex_free (st->magic_samples);
1091 speex_free (st->samp_frac_num);
1096 speex_resampler_process_native (SpeexResamplerState * st,
1097 spx_uint32_t channel_index, spx_uint32_t * in_len, spx_word16_t * out,
1098 spx_uint32_t * out_len)
1101 const int N = st->filt_len;
1103 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
1108 /* Call the right resampler through the function ptr */
1109 out_sample = st->resampler_ptr (st, channel_index, mem, in_len, out, out_len);
1111 if (st->last_sample[channel_index] < (spx_int32_t) * in_len)
1112 *in_len = st->last_sample[channel_index];
1113 *out_len = out_sample;
1114 st->last_sample[channel_index] -= *in_len;
1118 for (j = 0; j < N - 1; ++j)
1119 mem[j] = mem[j + ilen];
1121 return RESAMPLER_ERR_SUCCESS;
1125 speex_resampler_magic (SpeexResamplerState * st, spx_uint32_t channel_index,
1126 spx_word16_t ** out, spx_uint32_t out_len)
1128 spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
1129 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
1130 const int N = st->filt_len;
1132 speex_resampler_process_native (st, channel_index, &tmp_in_len, *out,
1135 st->magic_samples[channel_index] -= tmp_in_len;
1137 /* If we couldn't process all "magic" input samples, save the rest for next time */
1138 if (st->magic_samples[channel_index]) {
1140 for (i = 0; i < st->magic_samples[channel_index]; i++)
1141 mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len];
1143 *out += out_len * st->out_stride;
1149 speex_resampler_process_int (SpeexResamplerState * st,
1150 spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
1151 spx_int16_t * out, spx_uint32_t * out_len)
1153 #ifdef DOUBLE_PRECISION
1155 speex_resampler_process_float (SpeexResamplerState * st,
1156 spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len,
1157 double *out, spx_uint32_t * out_len)
1160 speex_resampler_process_float (SpeexResamplerState * st,
1161 spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
1162 float *out, spx_uint32_t * out_len)
1167 spx_uint32_t ilen = *in_len;
1168 spx_uint32_t olen = *out_len;
1169 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
1170 const int filt_offs = st->filt_len - 1;
1171 const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
1172 const int istride = st->in_stride;
1174 if (st->magic_samples[channel_index])
1175 olen -= speex_resampler_magic (st, channel_index, &out, olen);
1176 if (!st->magic_samples[channel_index]) {
1177 while (ilen && olen) {
1178 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
1179 spx_uint32_t ochunk = olen;
1182 for (j = 0; j < ichunk; ++j)
1183 x[j + filt_offs] = in[j * istride];
1185 for (j = 0; j < ichunk; ++j)
1186 x[j + filt_offs] = 0;
1188 speex_resampler_process_native (st, channel_index, &ichunk, out, &ochunk);
1191 out += ochunk * st->out_stride;
1193 in += ichunk * istride;
1198 return RESAMPLER_ERR_SUCCESS;
1203 speex_resampler_process_float (SpeexResamplerState * st,
1204 spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
1205 float *out, spx_uint32_t * out_len)
1208 speex_resampler_process_int (SpeexResamplerState * st,
1209 spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
1210 spx_int16_t * out, spx_uint32_t * out_len)
1214 const int istride_save = st->in_stride;
1215 const int ostride_save = st->out_stride;
1216 spx_uint32_t ilen = *in_len;
1217 spx_uint32_t olen = *out_len;
1218 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
1219 const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
1221 const unsigned int ylen =
1222 (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
1223 VARDECL (spx_word16_t * ystack);
1224 ALLOC (ystack, ylen, spx_word16_t);
1226 const unsigned int ylen = FIXED_STACK_ALLOC;
1227 spx_word16_t ystack[FIXED_STACK_ALLOC];
1232 while (ilen && olen) {
1233 spx_word16_t *y = ystack;
1234 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
1235 spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
1236 spx_uint32_t omagic = 0;
1238 if (st->magic_samples[channel_index]) {
1239 omagic = speex_resampler_magic (st, channel_index, &y, ochunk);
1243 if (!st->magic_samples[channel_index]) {
1245 for (j = 0; j < ichunk; ++j)
1247 x[j + st->filt_len - 1] = WORD2INT (in[j * istride_save]);
1249 x[j + st->filt_len - 1] = in[j * istride_save];
1252 for (j = 0; j < ichunk; ++j)
1253 x[j + st->filt_len - 1] = 0;
1256 speex_resampler_process_native (st, channel_index, &ichunk, y, &ochunk);
1262 for (j = 0; j < ochunk + omagic; ++j)
1264 out[j * ostride_save] = ystack[j];
1266 out[j * ostride_save] = WORD2INT (ystack[j]);
1271 out += (ochunk + omagic) * ostride_save;
1273 in += ichunk * istride_save;
1275 st->out_stride = ostride_save;
1279 return RESAMPLER_ERR_SUCCESS;
1282 #ifdef DOUBLE_PRECISION
1284 speex_resampler_process_interleaved_float (SpeexResamplerState * st,
1285 const double *in, spx_uint32_t * in_len, double *out,
1286 spx_uint32_t * out_len)
1289 speex_resampler_process_interleaved_float (SpeexResamplerState * st,
1290 const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
1294 int istride_save, ostride_save;
1295 spx_uint32_t bak_len = *out_len;
1296 istride_save = st->in_stride;
1297 ostride_save = st->out_stride;
1298 st->in_stride = st->out_stride = st->nb_channels;
1299 for (i = 0; i < st->nb_channels; i++) {
1302 speex_resampler_process_float (st, i, in + i, in_len, out + i, out_len);
1304 speex_resampler_process_float (st, i, NULL, in_len, out + i, out_len);
1306 st->in_stride = istride_save;
1307 st->out_stride = ostride_save;
1308 return RESAMPLER_ERR_SUCCESS;
1312 speex_resampler_process_interleaved_int (SpeexResamplerState * st,
1313 const spx_int16_t * in, spx_uint32_t * in_len, spx_int16_t * out,
1314 spx_uint32_t * out_len)
1317 int istride_save, ostride_save;
1318 spx_uint32_t bak_len = *out_len;
1319 istride_save = st->in_stride;
1320 ostride_save = st->out_stride;
1321 st->in_stride = st->out_stride = st->nb_channels;
1322 for (i = 0; i < st->nb_channels; i++) {
1325 speex_resampler_process_int (st, i, in + i, in_len, out + i, out_len);
1327 speex_resampler_process_int (st, i, NULL, in_len, out + i, out_len);
1329 st->in_stride = istride_save;
1330 st->out_stride = ostride_save;
1331 return RESAMPLER_ERR_SUCCESS;
1335 speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate,
1336 spx_uint32_t out_rate)
1338 return speex_resampler_set_rate_frac (st, in_rate, out_rate, in_rate,
1343 speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate,
1344 spx_uint32_t * out_rate)
1346 *in_rate = st->in_rate;
1347 *out_rate = st->out_rate;
1351 speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num,
1352 spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
1355 spx_uint32_t old_den;
1357 if (st->in_rate == in_rate && st->out_rate == out_rate
1358 && st->num_rate == ratio_num && st->den_rate == ratio_den)
1359 return RESAMPLER_ERR_SUCCESS;
1361 old_den = st->den_rate;
1362 st->in_rate = in_rate;
1363 st->out_rate = out_rate;
1364 st->num_rate = ratio_num;
1365 st->den_rate = ratio_den;
1366 /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
1367 for (fact = 2; fact <= IMIN (st->num_rate, st->den_rate); fact++) {
1368 while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) {
1369 st->num_rate /= fact;
1370 st->den_rate /= fact;
1375 for (i = 0; i < st->nb_channels; i++) {
1376 st->samp_frac_num[i] = st->samp_frac_num[i] * st->den_rate / old_den;
1378 if (st->samp_frac_num[i] >= st->den_rate)
1379 st->samp_frac_num[i] = st->den_rate - 1;
1383 if (st->initialised)
1385 return RESAMPLER_ERR_SUCCESS;
1389 speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num,
1390 spx_uint32_t * ratio_den)
1392 *ratio_num = st->num_rate;
1393 *ratio_den = st->den_rate;
1397 speex_resampler_set_quality (SpeexResamplerState * st, int quality)
1399 if (quality > 10 || quality < 0)
1400 return RESAMPLER_ERR_INVALID_ARG;
1401 if (st->quality == quality)
1402 return RESAMPLER_ERR_SUCCESS;
1403 st->quality = quality;
1404 if (st->initialised)
1406 return RESAMPLER_ERR_SUCCESS;
1410 speex_resampler_get_quality (SpeexResamplerState * st, int *quality)
1412 *quality = st->quality;
1416 speex_resampler_set_input_stride (SpeexResamplerState * st, spx_uint32_t stride)
1418 st->in_stride = stride;
1422 speex_resampler_get_input_stride (SpeexResamplerState * st,
1423 spx_uint32_t * stride)
1425 *stride = st->in_stride;
1429 speex_resampler_set_output_stride (SpeexResamplerState * st,
1430 spx_uint32_t stride)
1432 st->out_stride = stride;
1436 speex_resampler_get_output_stride (SpeexResamplerState * st,
1437 spx_uint32_t * stride)
1439 *stride = st->out_stride;
1443 speex_resampler_get_input_latency (SpeexResamplerState * st)
1445 return st->filt_len / 2;
1449 speex_resampler_get_output_latency (SpeexResamplerState * st)
1451 return ((st->filt_len / 2) * st->den_rate +
1452 (st->num_rate >> 1)) / st->num_rate;
1456 speex_resampler_get_filt_len (SpeexResamplerState * st)
1458 return st->filt_len;
1462 speex_resampler_get_sinc_filter_mode (SpeexResamplerState * st)
1464 return st->use_full_sinc_table;
1468 speex_resampler_skip_zeros (SpeexResamplerState * st)
1471 for (i = 0; i < st->nb_channels; i++)
1472 st->last_sample[i] = st->filt_len / 2;
1473 return RESAMPLER_ERR_SUCCESS;
1477 speex_resampler_reset_mem (SpeexResamplerState * st)
1480 for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++)
1482 return RESAMPLER_ERR_SUCCESS;
1486 speex_resampler_strerror (int err)
1489 case RESAMPLER_ERR_SUCCESS:
1491 case RESAMPLER_ERR_ALLOC_FAILED:
1492 return "Memory allocation failed.";
1493 case RESAMPLER_ERR_BAD_STATE:
1494 return "Bad resampler state.";
1495 case RESAMPLER_ERR_INVALID_ARG:
1496 return "Invalid argument.";
1497 case RESAMPLER_ERR_PTR_OVERLAP:
1498 return "Input and output buffers overlap.";
1500 return "Unknown error. Bad error code or strange version mismatch.";