SAF
Loading...
Searching...
No Matches
resample.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2008 Jean-Marc Valin
2 Copyright (C) 2008 Thorvald Natvig
3 */
9/*
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are
12 met:
13
14 1. Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16
17 2. Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20
21 3. The name of the author may not be used to endorse or promote products
22 derived from this software without specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35*/
36
37/*
38 The design goals of this code are:
39 - Very fast algorithm
40 - SIMD-friendly algorithm
41 - Low memory requirement
42 - Good *perceptual* quality (and not best SNR)
43
44 Warning: This resampler is relatively new. Although I think I got rid of
45 all the major bugs and I don't expect the API to change anymore, there
46 may be something I've missed. So use with caution.
47
48 This algorithm is based on this original resampling algorithm:
49 Smith, Julius O. Digital Audio Resampling Home Page
50 Center for Computer Research in Music and Acoustics (CCRMA),
51 Stanford University, 2007.
52 Web published at https://ccrma.stanford.edu/~jos/resample/.
53
54 There is one main difference, though. This resampler uses cubic
55 interpolation instead of linear interpolation in the above paper. This
56 makes the table much smaller and makes it possible to compute that table
57 on a per-stream basis. In turn, being able to tweak the table for each
58 stream makes it possible to both reduce complexity on simple ratios
59 (e.g. 2/3), and get rid of the rounding operations in the inner loop.
60 The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
61*/
62
63
64#define SPEEX_USE_CBLAS
65#ifdef SPEEX_USE_CBLAS
66# include "saf_externals.h"
67#endif
68
69#ifdef HAVE_CONFIG_H
70#include "config.h"
71#endif
72
73#ifdef OUTSIDE_SPEEX
74#include <stdlib.h>
75static void *speex_alloc(int size) {return calloc(size,1);}
76static void *speex_realloc(void *ptr, int size) {return realloc(ptr, size);}
77static void speex_free(void *ptr) {free(ptr);}
78#ifndef EXPORT
79#define EXPORT
80#endif
81#include "speex_resampler.h"
82#include "arch.h"
83#else /* OUTSIDE_SPEEX */
84
85#include "speex_resampler.h"
86#include "arch.h"
87#include "os_support.h"
88#endif /* OUTSIDE_SPEEX */
89
90#include <math.h>
91#include <limits.h>
92
93#define EXPORT
94
95#ifndef M_PI
96#define M_PI 3.14159265358979323846
97#endif
98
99#define IMAX(a,b) ((a) > (b) ? (a) : (b))
100#define IMIN(a,b) ((a) < (b) ? (a) : (b))
101
102#ifndef NULL
103#define NULL 0
104#endif
105
106#ifndef UINT32_MAX
107#define UINT32_MAX 4294967295U
108#endif
109
110#ifdef USE_SSE
111#include "resample_sse.h"
112#endif
113
114#ifdef USE_NEON
115#include "resample_neon.h"
116#endif
117
118/* Numer of elements to allocate on the stack */
119#ifdef VAR_ARRAYS
120#define FIXED_STACK_ALLOC 8192
121#else
122#define FIXED_STACK_ALLOC 1024
123#endif
124
125typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
126
128 spx_uint32_t in_rate;
129 spx_uint32_t out_rate;
130 spx_uint32_t num_rate;
131 spx_uint32_t den_rate;
132
133 int quality;
134 spx_uint32_t nb_channels;
135 spx_uint32_t filt_len;
136 spx_uint32_t mem_alloc_size;
137 spx_uint32_t buffer_size;
138 int int_advance;
139 int frac_advance;
140 float cutoff;
141 spx_uint32_t oversample;
142 int initialised;
143 int started;
144
145 /* These are per-channel */
146 spx_int32_t *last_sample;
147 spx_uint32_t *samp_frac_num;
148 spx_uint32_t *magic_samples;
149
150 spx_word16_t *mem;
151 spx_word16_t *sinc_table;
152 spx_uint32_t sinc_table_length;
153 resampler_basic_func resampler_ptr;
154
155 int in_stride;
156 int out_stride;
157} ;
158
159static const double kaiser12_table[68] = {
160 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
161 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
162 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
163 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
164 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
165 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
166 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
167 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
168 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
169 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
170 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
171 0.00001000, 0.00000000};
172/*
173static const double kaiser12_table[36] = {
174 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
175 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
176 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
177 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
178 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
179 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
180*/
181static const double kaiser10_table[36] = {
182 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
183 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
184 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
185 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
186 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
187 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
188
189static const double kaiser8_table[36] = {
190 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
191 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
192 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
193 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
194 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
195 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
196
197static const double kaiser6_table[36] = {
198 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
199 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
200 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
201 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
202 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
203 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
204
205struct FuncDef {
206 const double *table;
207 int oversample;
208};
209
210static const struct FuncDef kaiser12_funcdef = {kaiser12_table, 64};
211#define KAISER12 (&kaiser12_funcdef)
212static const struct FuncDef kaiser10_funcdef = {kaiser10_table, 32};
213#define KAISER10 (&kaiser10_funcdef)
214static const struct FuncDef kaiser8_funcdef = {kaiser8_table, 32};
215#define KAISER8 (&kaiser8_funcdef)
216static const struct FuncDef kaiser6_funcdef = {kaiser6_table, 32};
217#define KAISER6 (&kaiser6_funcdef)
218
220 int base_length;
221 int oversample;
222 float downsample_bandwidth;
223 float upsample_bandwidth;
224 const struct FuncDef *window_func;
225};
226
227
228/* This table maps conversion quality to internal parameters. There are two
229 reasons that explain why the up-sampling bandwidth is larger than the
230 down-sampling bandwidth:
231 1) When up-sampling, we can assume that the spectrum is already attenuated
232 close to the Nyquist rate (from an A/D or a previous resampling filter)
233 2) Any aliasing that occurs very close to the Nyquist rate will be masked
234 by the sinusoids/noise just below the Nyquist rate (guaranteed only for
235 up-sampling).
236*/
237static const struct QualityMapping quality_map[11] = {
238 { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */
239 { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */
240 { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */
241 { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */
242 { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */
243 { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */
244 { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */
245 {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */
246 {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */
247 {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */
248 {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
249};
250/*8,24,40,56,80,104,128,160,200,256,320*/
251static double compute_func(float x, const struct FuncDef *func)
252{
253 float y, frac;
254 double interp[4];
255 int ind;
256 y = x*func->oversample;
257 ind = (int)floor(y);
258 frac = (y-ind);
259 /* CSE with handle the repeated powers */
260 interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac);
261 interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac);
262 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
263 interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
264 /* Just to make sure we don't have rounding problems */
265 interp[1] = 1.f-interp[3]-interp[2]-interp[0];
266
267 /*sum = frac*accum[1] + (1-frac)*accum[2];*/
268 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
269}
270
271#if 0
272#include <stdio.h>
273int main(int argc, char **argv)
274{
275 int i;
276 for (i=0;i<256;i++)
277 {
278 printf ("%f\n", compute_func(i/256., KAISER12));
279 }
280 return 0;
281}
282#endif
283
284#ifdef FIXED_POINT
285/* The slow way of computing a sinc for the table. Should improve that some day */
286static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func)
287{
288 /*fprintf (stderr, "%f ", x);*/
289 float xx = x * cutoff;
290 if (fabs(x)<1e-6f)
291 return WORD2INT(32768.*cutoff);
292 else if (fabs(x) > .5f*N)
293 return 0;
294 /*FIXME: Can it really be any slower than this? */
295 return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
296}
297#else
298/* The slow way of computing a sinc for the table. Should improve that some day */
299static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func)
300{
301 /*fprintf (stderr, "%f ", x);*/
302 float xx = x * cutoff;
303 if (fabs(x)<1e-6)
304 return cutoff;
305 else if (fabs(x) > .5*N)
306 return 0;
307 /*FIXME: Can it really be any slower than this? */
308 return cutoff*sinf((float)M_PI*xx)/((float)M_PI*xx) * (float)compute_func(fabsf(2.0f*x/(float)N), window_func);
309}
310#endif
311
312#ifdef FIXED_POINT
313static void cubic_coef(spx_word16_t x, spx_word16_t interp[4])
314{
315 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
316 but I know it's MMSE-optimal on a sinc */
317 spx_word16_t x2, x3;
318 x2 = MULT16_16_P15(x, x);
319 x3 = MULT16_16_P15(x, x2);
320 interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
321 interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
322 interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15);
323 /* Just to make sure we don't have rounding problems */
324 interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3];
325 if (interp[2]<32767)
326 interp[2]+=1;
327}
328#else
329static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
330{
331 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
332 but I know it's MMSE-optimal on a sinc */
333 interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac;
334 interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac;
335 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
336 interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac;
337 /* Just to make sure we don't have rounding problems */
338 interp[2] = 1.f-interp[0]-interp[1]-interp[3];
339}
340#endif
341
342static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
343{
344 const int N = st->filt_len;
345 int out_sample = 0;
346 int last_sample = st->last_sample[channel_index];
347 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
348 const spx_word16_t *sinc_table = st->sinc_table;
349 const int out_stride = st->out_stride;
350 const int int_advance = st->int_advance;
351 const int frac_advance = st->frac_advance;
352 const spx_uint32_t den_rate = st->den_rate;
353 spx_word32_t sum;
354
355 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
356 {
357 const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];
358 const spx_word16_t *iptr = & in[last_sample];
359
360#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
361# ifdef SPEEX_USE_CBLAS
362 sum = cblas_sdot(N, sinct, 1, iptr, 1);
363# else
364 int j;
365 sum = 0;
366 for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]);
367# endif
368
369
370/* This code is slower on most DSPs which have only 2 accumulators.
371 Plus this this forces truncation to 32 bits and you lose the HW guard bits.
372 I think we can trust the compiler and let it vectorize and/or unroll itself.
373 spx_word32_t accum[4] = {0,0,0,0};
374 for(j=0;j<N;j+=4) {
375 accum[0] += MULT16_16(sinct[j], iptr[j]);
376 accum[1] += MULT16_16(sinct[j+1], iptr[j+1]);
377 accum[2] += MULT16_16(sinct[j+2], iptr[j+2]);
378 accum[3] += MULT16_16(sinct[j+3], iptr[j+3]);
379 }
380 sum = accum[0] + accum[1] + accum[2] + accum[3];
381*/
382 sum = SATURATE32PSHR(sum, 15, 32767);
383#else
384 sum = inner_product_single(sinct, iptr, N);
385#endif
386
387 out[out_stride * out_sample++] = sum;
388 last_sample += int_advance;
389 samp_frac_num += frac_advance;
390 if (samp_frac_num >= den_rate)
391 {
392 samp_frac_num -= den_rate;
393 last_sample++;
394 }
395 }
396
397 st->last_sample[channel_index] = last_sample;
398 st->samp_frac_num[channel_index] = samp_frac_num;
399 return out_sample;
400}
401
402#ifdef FIXED_POINT
403#else
404/* This is the same as the previous function, except with a double-precision accumulator */
405static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
406{
407 const int N = st->filt_len;
408 int out_sample = 0;
409 int last_sample = st->last_sample[channel_index];
410 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
411 const spx_word16_t *sinc_table = st->sinc_table;
412 const int out_stride = st->out_stride;
413 const int int_advance = st->int_advance;
414 const int frac_advance = st->frac_advance;
415 const spx_uint32_t den_rate = st->den_rate;
416 double sum;
417
418 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
419 {
420 const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];
421 const spx_word16_t *iptr = & in[last_sample];
422
423#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
424# ifdef SPEEX_USE_CBLAS
425 sum = (double)cblas_sdot(N, sinct, 1, iptr, 1);
426# else
427 int j;
428 double accum[4] = {0,0,0,0};
429
430 for(j=0;j<N;j+=4) {
431 accum[0] += sinct[j]*iptr[j];
432 accum[1] += sinct[j+1]*iptr[j+1];
433 accum[2] += sinct[j+2]*iptr[j+2];
434 accum[3] += sinct[j+3]*iptr[j+3];
435 }
436 sum = accum[0] + accum[1] + accum[2] + accum[3];
437# endif
438#else
439 sum = inner_product_double(sinct, iptr, N);
440#endif
441
442 out[out_stride * out_sample++] = (spx_word16_t)PSHR32(sum, 15);
443 last_sample += int_advance;
444 samp_frac_num += frac_advance;
445 if (samp_frac_num >= den_rate)
446 {
447 samp_frac_num -= den_rate;
448 last_sample++;
449 }
450 }
451
452 st->last_sample[channel_index] = last_sample;
453 st->samp_frac_num[channel_index] = samp_frac_num;
454 return out_sample;
455}
456#endif
457
458static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
459{
460 const int N = st->filt_len;
461 int out_sample = 0;
462 int last_sample = st->last_sample[channel_index];
463 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
464 const int out_stride = st->out_stride;
465 const int int_advance = st->int_advance;
466 const int frac_advance = st->frac_advance;
467 const spx_uint32_t den_rate = st->den_rate;
468 spx_word32_t sum;
469
470 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
471 {
472 const spx_word16_t *iptr = & in[last_sample];
473
474 const int offset = samp_frac_num*st->oversample/st->den_rate;
475#ifdef FIXED_POINT
476 const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
477#else
478 const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
479#endif
480 spx_word16_t interp[4];
481
482
483#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
484 int j;
485 spx_word32_t accum[4] = {0,0,0,0};
486
487 for(j=0;j<N;j++) {
488 const spx_word16_t curr_in=iptr[j];
489 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
490 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
491 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
492 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
493 }
494
495 cubic_coef(frac, interp);
496 sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
497 sum = SATURATE32PSHR(sum, 15, 32767);
498#else
499 cubic_coef(frac, interp);
500 sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
501#endif
502
503 out[out_stride * out_sample++] = sum;
504 last_sample += int_advance;
505 samp_frac_num += frac_advance;
506 if (samp_frac_num >= den_rate)
507 {
508 samp_frac_num -= den_rate;
509 last_sample++;
510 }
511 }
512
513 st->last_sample[channel_index] = last_sample;
514 st->samp_frac_num[channel_index] = samp_frac_num;
515 return out_sample;
516}
517
518#ifdef FIXED_POINT
519#else
520/* This is the same as the previous function, except with a double-precision accumulator */
521static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
522{
523 const int N = st->filt_len;
524 int out_sample = 0;
525 int last_sample = st->last_sample[channel_index];
526 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
527 const int out_stride = st->out_stride;
528 const int int_advance = st->int_advance;
529 const int frac_advance = st->frac_advance;
530 const spx_uint32_t den_rate = st->den_rate;
531 spx_word32_t sum;
532
533 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
534 {
535 const spx_word16_t *iptr = & in[last_sample];
536
537 const int offset = samp_frac_num*st->oversample/st->den_rate;
538#ifdef FIXED_POINT
539 const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
540#else
541 const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
542#endif
543 spx_word16_t interp[4];
544
545
546#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
547 int j;
548 double accum[4] = {0,0,0,0};
549
550 for(j=0;j<N;j++) {
551 const double curr_in=iptr[j];
552 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
553 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
554 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
555 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
556 }
557
558 cubic_coef(frac, interp);
559 sum = (spx_word32_t)(MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]));
560#else
561 cubic_coef(frac, interp);
562 sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
563#endif
564
565 out[out_stride * out_sample++] = PSHR32(sum,15);
566 last_sample += int_advance;
567 samp_frac_num += frac_advance;
568 if (samp_frac_num >= den_rate)
569 {
570 samp_frac_num -= den_rate;
571 last_sample++;
572 }
573 }
574
575 st->last_sample[channel_index] = last_sample;
576 st->samp_frac_num[channel_index] = samp_frac_num;
577 return out_sample;
578}
579#endif
580
581/* This resampler is used to produce zero output in situations where memory
582 for the filter could not be allocated. The expected numbers of input and
583 output samples are still processed so that callers failing to check error
584 codes are not surprised, possibly getting into infinite loops. */
585static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
586{
587 int out_sample = 0;
588 int last_sample = st->last_sample[channel_index];
589 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
590 const int out_stride = st->out_stride;
591 const int int_advance = st->int_advance;
592 const int frac_advance = st->frac_advance;
593 const spx_uint32_t den_rate = st->den_rate;
594
595 (void)in;
596 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
597 {
598 out[out_stride * out_sample++] = 0;
599 last_sample += int_advance;
600 samp_frac_num += frac_advance;
601 if (samp_frac_num >= den_rate)
602 {
603 samp_frac_num -= den_rate;
604 last_sample++;
605 }
606 }
607
608 st->last_sample[channel_index] = last_sample;
609 st->samp_frac_num[channel_index] = samp_frac_num;
610 return out_sample;
611}
612
613static int multiply_frac(spx_uint32_t *result, spx_uint32_t value, spx_uint32_t num, spx_uint32_t den)
614{
615 spx_uint32_t major = value / den;
616 spx_uint32_t remain = value % den;
617 /* TODO: Could use 64 bits operation to check for overflow. But only guaranteed in C99+ */
618 if (remain > UINT32_MAX / num || major > UINT32_MAX / num
619 || major * num > UINT32_MAX - remain * num / den)
620 return RESAMPLER_ERR_OVERFLOW;
621 *result = remain * num / den + major * num;
622 return RESAMPLER_ERR_SUCCESS;
623}
624
625static int update_filter(SpeexResamplerState *st)
626{
627 spx_uint32_t old_length = st->filt_len;
628 spx_uint32_t old_alloc_size = st->mem_alloc_size;
629 int use_direct;
630 spx_uint32_t min_sinc_table_length;
631 spx_uint32_t min_alloc_size;
632
633 st->int_advance = st->num_rate/st->den_rate;
634 st->frac_advance = st->num_rate%st->den_rate;
635 st->oversample = quality_map[st->quality].oversample;
636 st->filt_len = quality_map[st->quality].base_length;
637
638 if (st->num_rate > st->den_rate)
639 {
640 /* down-sampling */
641 st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
642 if (multiply_frac(&st->filt_len,st->filt_len,st->num_rate,st->den_rate) != RESAMPLER_ERR_SUCCESS)
643 goto fail;
644 /* Round up to make sure we have a multiple of 8 for SSE */
645 st->filt_len = ((st->filt_len-1)&(~0x7))+8;
646 if (2*st->den_rate < st->num_rate)
647 st->oversample >>= 1;
648 if (4*st->den_rate < st->num_rate)
649 st->oversample >>= 1;
650 if (8*st->den_rate < st->num_rate)
651 st->oversample >>= 1;
652 if (16*st->den_rate < st->num_rate)
653 st->oversample >>= 1;
654 if (st->oversample < 1)
655 st->oversample = 1;
656 } else {
657 /* up-sampling */
658 st->cutoff = quality_map[st->quality].upsample_bandwidth;
659 }
660
661#ifdef RESAMPLE_FULL_SINC_TABLE
662 use_direct = 1;
663 if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len)
664 goto fail;
665#else
666 /* Choose the resampling type that requires the least amount of memory */
667 use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8
668 && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len;
669#endif
670 if (use_direct)
671 {
672 min_sinc_table_length = st->filt_len*st->den_rate;
673 } else {
674 if ((INT_MAX/sizeof(spx_word16_t)-8)/st->oversample < st->filt_len)
675 goto fail;
676
677 min_sinc_table_length = st->filt_len*st->oversample+8;
678 }
679 if (st->sinc_table_length < min_sinc_table_length)
680 {
681 spx_word16_t *sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,min_sinc_table_length*sizeof(spx_word16_t));
682 if (!sinc_table)
683 goto fail;
684
685 st->sinc_table = sinc_table;
686 st->sinc_table_length = min_sinc_table_length;
687 }
688 if (use_direct)
689 {
690 spx_uint32_t i;
691 for (i=0;i<st->den_rate;i++)
692 {
693 spx_int32_t j;
694 for (j=0;j<(spx_int32_t)st->filt_len;j++)
695 {
696 st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func);
697 }
698 }
699#ifdef FIXED_POINT
700 st->resampler_ptr = resampler_basic_direct_single;
701#else
702 if (st->quality>8)
703 st->resampler_ptr = resampler_basic_direct_double;
704 else
705 st->resampler_ptr = resampler_basic_direct_single;
706#endif
707 /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/
708 } else {
709 spx_int32_t i;
710 for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)
711 st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func);
712#ifdef FIXED_POINT
713 st->resampler_ptr = resampler_basic_interpolate_single;
714#else
715 if (st->quality>8)
716 st->resampler_ptr = resampler_basic_interpolate_double;
717 else
718 st->resampler_ptr = resampler_basic_interpolate_single;
719#endif
720 /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/
721 }
722
723 /* Here's the place where we update the filter memory to take into account
724 the change in filter length. It's probably the messiest part of the code
725 due to handling of lots of corner cases. */
726
727 /* Adding buffer_size to filt_len won't overflow here because filt_len
728 could be multiplied by sizeof(spx_word16_t) above. */
729 min_alloc_size = st->filt_len-1 + st->buffer_size;
730 if (min_alloc_size > st->mem_alloc_size)
731 {
732 spx_word16_t *mem;
733 if (INT_MAX/sizeof(spx_word16_t)/st->nb_channels < min_alloc_size)
734 goto fail;
735 else if (!(mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*min_alloc_size * sizeof(*mem))))
736 goto fail;
737
738 st->mem = mem;
739 st->mem_alloc_size = min_alloc_size;
740 }
741 if (!st->started)
742 {
743 spx_uint32_t i;
744 for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
745 st->mem[i] = 0;
746 /*speex_warning("reinit filter");*/
747 } else if (st->filt_len > old_length)
748 {
749 spx_uint32_t i;
750 /* Increase the filter length */
751 /*speex_warning("increase filter size");*/
752 for (i=st->nb_channels;i--;)
753 {
754 spx_uint32_t j;
755 spx_uint32_t olen = old_length;
756 /*if (st->magic_samples[i])*/
757 {
758 /* Try and remove the magic samples as if nothing had happened */
759
760 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
761 olen = old_length + 2*st->magic_samples[i];
762 for (j=old_length-1+st->magic_samples[i];j--;)
763 st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
764 for (j=0;j<st->magic_samples[i];j++)
765 st->mem[i*st->mem_alloc_size+j] = 0;
766 st->magic_samples[i] = 0;
767 }
768 if (st->filt_len > olen)
769 {
770 /* If the new filter length is still bigger than the "augmented" length */
771 /* Copy data going backward */
772 for (j=0;j<olen-1;j++)
773 st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
774 /* Then put zeros for lack of anything better */
775 for (;j<st->filt_len-1;j++)
776 st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
777 /* Adjust last_sample */
778 st->last_sample[i] += (st->filt_len - olen)/2;
779 } else {
780 /* Put back some of the magic! */
781 st->magic_samples[i] = (olen - st->filt_len)/2;
782 for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
783 st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
784 }
785 }
786 } else if (st->filt_len < old_length)
787 {
788 spx_uint32_t i;
789 /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
790 samples so they can be used directly as input the next time(s) */
791 for (i=0;i<st->nb_channels;i++)
792 {
793 spx_uint32_t j;
794 spx_uint32_t old_magic = st->magic_samples[i];
795 st->magic_samples[i] = (old_length - st->filt_len)/2;
796 /* We must copy some of the memory that's no longer used */
797 /* Copy data going backward */
798 for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
799 st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
800 st->magic_samples[i] += old_magic;
801 }
802 }
803 return RESAMPLER_ERR_SUCCESS;
804
805fail:
806 st->resampler_ptr = resampler_basic_zero;
807 /* st->mem may still contain consumed input samples for the filter.
808 Restore filt_len so that filt_len - 1 still points to the position after
809 the last of these samples. */
810 st->filt_len = old_length;
811 return RESAMPLER_ERR_ALLOC_FAILED;
812}
813
814EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
815{
816 return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
817}
818
819EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
820{
821 SpeexResamplerState *st;
822 int filter_err;
823
824 if (nb_channels == 0 || ratio_num == 0 || ratio_den == 0 || quality > 10 || quality < 0)
825 {
826 if (err)
827 *err = RESAMPLER_ERR_INVALID_ARG;
828 return NULL;
829 }
830 st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
831 if (!st)
832 {
833 if (err)
834 *err = RESAMPLER_ERR_ALLOC_FAILED;
835 return NULL;
836 }
837 st->initialised = 0;
838 st->started = 0;
839 st->in_rate = 0;
840 st->out_rate = 0;
841 st->num_rate = 0;
842 st->den_rate = 0;
843 st->quality = -1;
844 st->sinc_table_length = 0;
845 st->mem_alloc_size = 0;
846 st->filt_len = 0;
847 st->mem = 0;
848 st->resampler_ptr = 0;
849
850 st->cutoff = 1.f;
851 st->nb_channels = nb_channels;
852 st->in_stride = 1;
853 st->out_stride = 1;
854
855 st->buffer_size = 160;
856
857 /* Per channel data */
858 if (!(st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t))))
859 goto fail;
860 if (!(st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t))))
861 goto fail;
862 if (!(st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t))))
863 goto fail;
864
865 speex_resampler_set_quality(st, quality);
866 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
867
868 filter_err = update_filter(st);
869 if (filter_err == RESAMPLER_ERR_SUCCESS)
870 {
871 st->initialised = 1;
872 } else {
873 speex_resampler_destroy(st);
874 st = NULL;
875 }
876 if (err)
877 *err = filter_err;
878
879 return st;
880
881fail:
882 if (err)
883 *err = RESAMPLER_ERR_ALLOC_FAILED;
884 speex_resampler_destroy(st);
885 return NULL;
886}
887
888EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
889{
890 speex_free(st->mem);
891 speex_free(st->sinc_table);
892 speex_free(st->last_sample);
893 speex_free(st->magic_samples);
894 speex_free(st->samp_frac_num);
895 speex_free(st);
896}
897
898static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
899{
900 int j=0;
901 const int N = st->filt_len;
902 int out_sample = 0;
903 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
904 spx_uint32_t ilen;
905
906 st->started = 1;
907
908 /* Call the right resampler through the function ptr */
909 out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len);
910
911 if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
912 *in_len = st->last_sample[channel_index];
913 *out_len = out_sample;
914 st->last_sample[channel_index] -= *in_len;
915
916 ilen = *in_len;
917
918 for(j=0;j<N-1;++j)
919 mem[j] = mem[j+ilen];
920
921 return RESAMPLER_ERR_SUCCESS;
922}
923
924static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) {
925 spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
926 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
927 const int N = st->filt_len;
928
929 speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len);
930
931 st->magic_samples[channel_index] -= tmp_in_len;
932
933 /* If we couldn't process all "magic" input samples, save the rest for next time */
934 if (st->magic_samples[channel_index])
935 {
936 spx_uint32_t i;
937 for (i=0;i<st->magic_samples[channel_index];i++)
938 mem[N-1+i]=mem[N-1+i+tmp_in_len];
939 }
940 *out += out_len*st->out_stride;
941 return out_len;
942}
943
944#ifdef FIXED_POINT
945EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
946#else
947EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
948#endif
949{
950 int j;
951 spx_uint32_t ilen = *in_len;
952 spx_uint32_t olen = *out_len;
953 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
954 const int filt_offs = st->filt_len - 1;
955 const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
956 const int istride = st->in_stride;
957
958 if (st->magic_samples[channel_index])
959 olen -= speex_resampler_magic(st, channel_index, &out, olen);
960 if (! st->magic_samples[channel_index]) {
961 while (ilen && olen) {
962 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
963 spx_uint32_t ochunk = olen;
964
965 if (in) {
966 for(j=0;j<(int)ichunk;++j)
967 x[j+filt_offs]=in[j*istride];
968 } else {
969 for(j=0;j<(int)ichunk;++j)
970 x[j+filt_offs]=0;
971 }
972 speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk);
973 ilen -= ichunk;
974 olen -= ochunk;
975 out += ochunk * st->out_stride;
976 if (in)
977 in += ichunk * istride;
978 }
979 }
980 *in_len -= ilen;
981 *out_len -= olen;
982 return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
983}
984
985#ifdef FIXED_POINT
986EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
987#else
988EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
989#endif
990{
991 int j;
992 const int istride_save = st->in_stride;
993 const int ostride_save = st->out_stride;
994 spx_uint32_t ilen = *in_len;
995 spx_uint32_t olen = *out_len;
996 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
997 const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
998#ifdef VAR_ARRAYS
999 const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
1000 spx_word16_t ystack[ylen];
1001#else
1002 const unsigned int ylen = FIXED_STACK_ALLOC;
1003 spx_word16_t ystack[FIXED_STACK_ALLOC];
1004#endif
1005
1006 st->out_stride = 1;
1007
1008 while (ilen && olen) {
1009 spx_word16_t *y = ystack;
1010 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
1011 spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
1012 spx_uint32_t omagic = 0;
1013
1014 if (st->magic_samples[channel_index]) {
1015 omagic = speex_resampler_magic(st, channel_index, &y, ochunk);
1016 ochunk -= omagic;
1017 olen -= omagic;
1018 }
1019 if (! st->magic_samples[channel_index]) {
1020 if (in) {
1021 for(j=0;j<(int)ichunk;++j)
1022#ifdef FIXED_POINT
1023 x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]);
1024#else
1025 x[j+st->filt_len-1]=in[j*istride_save];
1026#endif
1027 } else {
1028 for(j=0;j<(int)ichunk;++j)
1029 x[j+st->filt_len-1]=0;
1030 }
1031
1032 speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk);
1033 } else {
1034 ichunk = 0;
1035 ochunk = 0;
1036 }
1037
1038 for (j=0;j<(int)(ochunk+omagic);++j)
1039#ifdef FIXED_POINTf
1040 out[j*ostride_save] = ystack[j];
1041#else
1042 out[j*ostride_save] = WORD2INT(ystack[j]);
1043#endif
1044
1045 ilen -= ichunk;
1046 olen -= ochunk;
1047 out += (ochunk+omagic) * ostride_save;
1048 if (in)
1049 in += ichunk * istride_save;
1050 }
1051 st->out_stride = ostride_save;
1052 *in_len -= ilen;
1053 *out_len -= olen;
1054
1055 return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
1056}
1057
1058EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
1059{
1060 spx_uint32_t i;
1061 int istride_save, ostride_save;
1062 spx_uint32_t bak_out_len = *out_len;
1063 spx_uint32_t bak_in_len = *in_len;
1064 istride_save = st->in_stride;
1065 ostride_save = st->out_stride;
1066 st->in_stride = st->out_stride = st->nb_channels;
1067 for (i=0;i<st->nb_channels;i++)
1068 {
1069 *out_len = bak_out_len;
1070 *in_len = bak_in_len;
1071 if (in != NULL)
1072 speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
1073 else
1074 speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len);
1075 }
1076 st->in_stride = istride_save;
1077 st->out_stride = ostride_save;
1078 return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
1079}
1080
1081EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
1082{
1083 spx_uint32_t i;
1084 int istride_save, ostride_save;
1085 spx_uint32_t bak_out_len = *out_len;
1086 spx_uint32_t bak_in_len = *in_len;
1087 istride_save = st->in_stride;
1088 ostride_save = st->out_stride;
1089 st->in_stride = st->out_stride = st->nb_channels;
1090 for (i=0;i<st->nb_channels;i++)
1091 {
1092 *out_len = bak_out_len;
1093 *in_len = bak_in_len;
1094 if (in != NULL)
1095 speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
1096 else
1097 speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len);
1098 }
1099 st->in_stride = istride_save;
1100 st->out_stride = ostride_save;
1101 return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
1102}
1103
1104EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
1105{
1106 return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
1107}
1108
1109EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
1110{
1111 *in_rate = st->in_rate;
1112 *out_rate = st->out_rate;
1113}
1114
1115static inline spx_uint32_t compute_gcd(spx_uint32_t a, spx_uint32_t b)
1116{
1117 while (b != 0)
1118 {
1119 spx_uint32_t temp = a;
1120
1121 a = b;
1122 b = temp % b;
1123 }
1124 return a;
1125}
1126
1127EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
1128{
1129 spx_uint32_t fact;
1130 spx_uint32_t old_den;
1131 spx_uint32_t i;
1132
1133 if (ratio_num == 0 || ratio_den == 0)
1134 return RESAMPLER_ERR_INVALID_ARG;
1135
1136 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
1137 return RESAMPLER_ERR_SUCCESS;
1138
1139 old_den = st->den_rate;
1140 st->in_rate = in_rate;
1141 st->out_rate = out_rate;
1142 st->num_rate = ratio_num;
1143 st->den_rate = ratio_den;
1144
1145 fact = compute_gcd(st->num_rate, st->den_rate);
1146
1147 st->num_rate /= fact;
1148 st->den_rate /= fact;
1149
1150 if (old_den > 0)
1151 {
1152 for (i=0;i<st->nb_channels;i++)
1153 {
1154 if (multiply_frac(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS)
1155 return RESAMPLER_ERR_OVERFLOW;
1156 /* Safety net */
1157 if (st->samp_frac_num[i] >= st->den_rate)
1158 st->samp_frac_num[i] = st->den_rate-1;
1159 }
1160 }
1161
1162 if (st->initialised)
1163 return update_filter(st);
1164 return RESAMPLER_ERR_SUCCESS;
1165}
1166
1167EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
1168{
1169 *ratio_num = st->num_rate;
1170 *ratio_den = st->den_rate;
1171}
1172
1173EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
1174{
1175 if (quality > 10 || quality < 0)
1176 return RESAMPLER_ERR_INVALID_ARG;
1177 if (st->quality == quality)
1178 return RESAMPLER_ERR_SUCCESS;
1179 st->quality = quality;
1180 if (st->initialised)
1181 return update_filter(st);
1182 return RESAMPLER_ERR_SUCCESS;
1183}
1184
1185EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
1186{
1187 *quality = st->quality;
1188}
1189
1190EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
1191{
1192 st->in_stride = stride;
1193}
1194
1195EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1196{
1197 *stride = st->in_stride;
1198}
1199
1200EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
1201{
1202 st->out_stride = stride;
1203}
1204
1205EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1206{
1207 *stride = st->out_stride;
1208}
1209
1210EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st)
1211{
1212 return st->filt_len / 2;
1213}
1214
1215EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st)
1216{
1217 return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;
1218}
1219
1220EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st)
1221{
1222 spx_uint32_t i;
1223 for (i=0;i<st->nb_channels;i++)
1224 st->last_sample[i] = st->filt_len/2;
1225 return RESAMPLER_ERR_SUCCESS;
1226}
1227
1228EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)
1229{
1230 spx_uint32_t i;
1231 for (i=0;i<st->nb_channels;i++)
1232 {
1233 st->last_sample[i] = 0;
1234 st->magic_samples[i] = 0;
1235 st->samp_frac_num[i] = 0;
1236 }
1237 for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
1238 st->mem[i] = 0;
1239 return RESAMPLER_ERR_SUCCESS;
1240}
1241
1242EXPORT const char *speex_resampler_strerror(int err)
1243{
1244 switch (err)
1245 {
1246 case RESAMPLER_ERR_SUCCESS:
1247 return "Success.";
1248 case RESAMPLER_ERR_ALLOC_FAILED:
1249 return "Memory allocation failed.";
1250 case RESAMPLER_ERR_BAD_STATE:
1251 return "Bad resampler state.";
1252 case RESAMPLER_ERR_INVALID_ARG:
1253 return "Invalid argument.";
1254 case RESAMPLER_ERR_PTR_OVERLAP:
1255 return "Input and output buffers overlap.";
1256 default:
1257 return "Unknown error. Bad error code or strange version mismatch.";
1258 }
1259}
Various architecture definitions Speex.
Supported OSs for Speex resampler.
static void * speex_alloc(int size)
Speex wrapper for calloc.
Definition os_support.h:56
static void * speex_realloc(void *ptr, int size)
Speex wrapper for realloc.
Definition os_support.h:76
static void speex_free(void *ptr)
Speex wrapper for calloc.
Definition os_support.h:84
Resampler functions (NEON version)
Resampler functions (SSE version)
Include header for SAF externals.
Main header file for the Speex resampler.