1 /* Copyright (C) 2007-2008 Jean-Marc Valin
2 Copyright (C) 2008 Thorvald Natvig
3
4 File: resample.c
5 Arbitrary resampling code
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are
9 met:
10
11 1. Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13
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.
17
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.
20
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.
32 */
33
34 /*
35 The design goals of this code are:
36 - Very fast algorithm
37 - SIMD-friendly algorithm
38 - Low memory requirement
39 - Good *perceptual* quality (and not best SNR)
40
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.
44
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/.
50
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.
58 */
59
60 #ifdef HAVE_CONFIG_H
61 #include "config.h"
62 #endif
63
64 #ifdef OUTSIDE_SPEEX
65 #include <stdlib.h>
speex_alloc(int size)66 static void *speex_alloc (int size) {return calloc(size,1);}
speex_realloc(void * ptr,int size)67 static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
speex_free(void * ptr)68 static void speex_free (void *ptr) {free(ptr);}
69 #include "speex_resampler.h"
70 #include "arch.h"
71 #else /* OUTSIDE_SPEEX */
72
73 #include "speex/speex_resampler.h"
74 #include "arch.h"
75 #include "os_support.h"
76 #endif /* OUTSIDE_SPEEX */
77
78 #include "stack_alloc.h"
79 #include <math.h>
80
81 #ifndef M_PI
82 #define M_PI 3.14159263
83 #endif
84
85 #ifdef FIXED_POINT
86 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
87 #else
88 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
89 #endif
90
91 #define IMAX(a,b) ((a) > (b) ? (a) : (b))
92 #define IMIN(a,b) ((a) < (b) ? (a) : (b))
93
94 #ifndef NULL
95 #define NULL 0
96 #endif
97
98 #ifdef _USE_SSE
99 #include "resample_sse.h"
100 #endif
101
102 #ifdef _USE_NEON
103 #include "resample_neon.h"
104 #endif
105
106 /* Numer of elements to allocate on the stack */
107 #ifdef VAR_ARRAYS
108 #define FIXED_STACK_ALLOC 8192
109 #else
110 #define FIXED_STACK_ALLOC 1024
111 #endif
112
113 typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
114
115 struct SpeexResamplerState_ {
116 spx_uint32_t in_rate;
117 spx_uint32_t out_rate;
118 spx_uint32_t num_rate;
119 spx_uint32_t den_rate;
120
121 int quality;
122 spx_uint32_t nb_channels;
123 spx_uint32_t filt_len;
124 spx_uint32_t mem_alloc_size;
125 spx_uint32_t buffer_size;
126 int int_advance;
127 int frac_advance;
128 float cutoff;
129 spx_uint32_t oversample;
130 int initialised;
131 int started;
132
133 /* These are per-channel */
134 spx_int32_t *last_sample;
135 spx_uint32_t *samp_frac_num;
136 spx_uint32_t *magic_samples;
137
138 spx_word16_t *mem;
139 spx_word16_t *sinc_table;
140 spx_uint32_t sinc_table_length;
141 resampler_basic_func resampler_ptr;
142
143 int in_stride;
144 int out_stride;
145 } ;
146
147 static double kaiser12_table[68] = {
148 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
149 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
150 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
151 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
152 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
153 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
154 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
155 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
156 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
157 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
158 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
159 0.00001000, 0.00000000};
160 /*
161 static double kaiser12_table[36] = {
162 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
163 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
164 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
165 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
166 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
167 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
168 */
169 static double kaiser10_table[36] = {
170 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
171 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
172 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
173 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
174 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
175 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
176
177 static double kaiser8_table[36] = {
178 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
179 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
180 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
181 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
182 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
183 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
184
185 static double kaiser6_table[36] = {
186 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
187 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
188 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
189 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
190 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
191 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
192
193 struct FuncDef {
194 double *table;
195 int oversample;
196 };
197
198 static struct FuncDef _KAISER12 = {kaiser12_table, 64};
199 #define KAISER12 (&_KAISER12)
200 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
201 #define KAISER12 (&_KAISER12)*/
202 static struct FuncDef _KAISER10 = {kaiser10_table, 32};
203 #define KAISER10 (&_KAISER10)
204 static struct FuncDef _KAISER8 = {kaiser8_table, 32};
205 #define KAISER8 (&_KAISER8)
206 static struct FuncDef _KAISER6 = {kaiser6_table, 32};
207 #define KAISER6 (&_KAISER6)
208
209 struct QualityMapping {
210 int base_length;
211 int oversample;
212 float downsample_bandwidth;
213 float upsample_bandwidth;
214 struct FuncDef *window_func;
215 };
216
217
218 /* This table maps conversion quality to internal parameters. There are two
219 reasons that explain why the up-sampling bandwidth is larger than the
220 down-sampling bandwidth:
221 1) When up-sampling, we can assume that the spectrum is already attenuated
222 close to the Nyquist rate (from an A/D or a previous resampling filter)
223 2) Any aliasing that occurs very close to the Nyquist rate will be masked
224 by the sinusoids/noise just below the Nyquist rate (guaranteed only for
225 up-sampling).
226 */
227 static const struct QualityMapping quality_map[11] = {
228 { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */
229 { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */
230 { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */
231 { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */
232 { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */
233 { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */
234 { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */
235 {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */
236 {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */
237 {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */
238 {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
239 };
240 /*8,24,40,56,80,104,128,160,200,256,320*/
compute_func(float x,struct FuncDef * func)241 static double compute_func(float x, struct FuncDef *func)
242 {
243 float y, frac;
244 double interp[4];
245 int ind;
246 y = x*func->oversample;
247 ind = (int)floor(y);
248 frac = (y-ind);
249 /* CSE with handle the repeated powers */
250 interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac);
251 interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac);
252 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
253 interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
254 /* Just to make sure we don't have rounding problems */
255 interp[1] = 1.f-interp[3]-interp[2]-interp[0];
256
257 /*sum = frac*accum[1] + (1-frac)*accum[2];*/
258 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
259 }
260
261 #if 0
262 #include <stdio.h>
263 int main(int argc, char **argv)
264 {
265 int i;
266 for (i=0;i<256;i++)
267 {
268 printf ("%f\n", compute_func(i/256., KAISER12));
269 }
270 return 0;
271 }
272 #endif
273
274 #ifdef FIXED_POINT
275 /* The slow way of computing a sinc for the table. Should improve that some day */
sinc(float cutoff,float x,int N,struct FuncDef * window_func)276 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
277 {
278 /*fprintf (stderr, "%f ", x);*/
279 float xx = x * cutoff;
280 if (fabs(x)<1e-6f)
281 return WORD2INT(32768.*cutoff);
282 else if (fabs(x) > .5f*N)
283 return 0;
284 /*FIXME: Can it really be any slower than this? */
285 return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
286 }
287 #else
288 /* The slow way of computing a sinc for the table. Should improve that some day */
sinc(float cutoff,float x,int N,struct FuncDef * window_func)289 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
290 {
291 /*fprintf (stderr, "%f ", x);*/
292 float xx = x * cutoff;
293 if (fabs(x)<1e-6)
294 return cutoff;
295 else if (fabs(x) > .5*N)
296 return 0;
297 /*FIXME: Can it really be any slower than this? */
298 return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func);
299 }
300 #endif
301
302 #ifdef FIXED_POINT
cubic_coef(spx_word16_t x,spx_word16_t interp[4])303 static void cubic_coef(spx_word16_t x, spx_word16_t interp[4])
304 {
305 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
306 but I know it's MMSE-optimal on a sinc */
307 spx_word16_t x2, x3;
308 x2 = MULT16_16_P15(x, x);
309 x3 = MULT16_16_P15(x, x2);
310 interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
311 interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
312 interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15);
313 /* Just to make sure we don't have rounding problems */
314 interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3];
315 if (interp[2]<32767)
316 interp[2]+=1;
317 }
318 #else
cubic_coef(spx_word16_t frac,spx_word16_t interp[4])319 static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
320 {
321 /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
322 but I know it's MMSE-optimal on a sinc */
323 interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac;
324 interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac;
325 /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
326 interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac;
327 /* Just to make sure we don't have rounding problems */
328 interp[2] = 1.-interp[0]-interp[1]-interp[3];
329 }
330 #endif
331
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)332 static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
333 {
334 const int N = st->filt_len;
335 int out_sample = 0;
336 int last_sample = st->last_sample[channel_index];
337 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
338 const spx_word16_t *sinc_table = st->sinc_table;
339 const int out_stride = st->out_stride;
340 const int int_advance = st->int_advance;
341 const int frac_advance = st->frac_advance;
342 const spx_uint32_t den_rate = st->den_rate;
343 spx_word32_t sum;
344 int j;
345
346 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
347 {
348 const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
349 const spx_word16_t *iptr = & in[last_sample];
350
351 #ifndef OVERRIDE_INNER_PRODUCT_SINGLE
352 float accum[4] = {0,0,0,0};
353
354 for(j=0;j<N;j+=4) {
355 accum[0] += sinc[j]*iptr[j];
356 accum[1] += sinc[j+1]*iptr[j+1];
357 accum[2] += sinc[j+2]*iptr[j+2];
358 accum[3] += sinc[j+3]*iptr[j+3];
359 }
360 sum = accum[0] + accum[1] + accum[2] + accum[3];
361 sum = SATURATE32PSHR(sum, 15, 32767);
362 #else
363 sum = inner_product_single(sinc, iptr, N);
364 #endif
365
366 out[out_stride * out_sample++] = sum;
367 last_sample += int_advance;
368 samp_frac_num += frac_advance;
369 if (samp_frac_num >= den_rate)
370 {
371 samp_frac_num -= den_rate;
372 last_sample++;
373 }
374 }
375
376 st->last_sample[channel_index] = last_sample;
377 st->samp_frac_num[channel_index] = samp_frac_num;
378 return out_sample;
379 }
380
381 #ifdef FIXED_POINT
382 #else
383 /* This is the same as the previous function, except with a double-precision accumulator */
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)384 static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
385 {
386 const int N = st->filt_len;
387 int out_sample = 0;
388 int last_sample = st->last_sample[channel_index];
389 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
390 const spx_word16_t *sinc_table = st->sinc_table;
391 const int out_stride = st->out_stride;
392 const int int_advance = st->int_advance;
393 const int frac_advance = st->frac_advance;
394 const spx_uint32_t den_rate = st->den_rate;
395 double sum;
396 int j;
397
398 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
399 {
400 const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
401 const spx_word16_t *iptr = & in[last_sample];
402
403 #ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
404 double accum[4] = {0,0,0,0};
405
406 for(j=0;j<N;j+=4) {
407 accum[0] += sinc[j]*iptr[j];
408 accum[1] += sinc[j+1]*iptr[j+1];
409 accum[2] += sinc[j+2]*iptr[j+2];
410 accum[3] += sinc[j+3]*iptr[j+3];
411 }
412 sum = accum[0] + accum[1] + accum[2] + accum[3];
413 #else
414 sum = inner_product_double(sinc, iptr, N);
415 #endif
416
417 out[out_stride * out_sample++] = PSHR32(sum, 15);
418 last_sample += int_advance;
419 samp_frac_num += frac_advance;
420 if (samp_frac_num >= den_rate)
421 {
422 samp_frac_num -= den_rate;
423 last_sample++;
424 }
425 }
426
427 st->last_sample[channel_index] = last_sample;
428 st->samp_frac_num[channel_index] = samp_frac_num;
429 return out_sample;
430 }
431 #endif
432
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)433 static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
434 {
435 const int N = st->filt_len;
436 int out_sample = 0;
437 int last_sample = st->last_sample[channel_index];
438 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
439 const int out_stride = st->out_stride;
440 const int int_advance = st->int_advance;
441 const int frac_advance = st->frac_advance;
442 const spx_uint32_t den_rate = st->den_rate;
443 int j;
444 spx_word32_t sum;
445
446 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
447 {
448 const spx_word16_t *iptr = & in[last_sample];
449
450 const int offset = samp_frac_num*st->oversample/st->den_rate;
451 #ifdef FIXED_POINT
452 const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
453 #else
454 const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
455 #endif
456 spx_word16_t interp[4];
457
458
459 #ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
460 spx_word32_t accum[4] = {0,0,0,0};
461
462 for(j=0;j<N;j++) {
463 const spx_word16_t curr_in=iptr[j];
464 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
465 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
466 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
467 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
468 }
469
470 cubic_coef(frac, interp);
471 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]);
472 sum = SATURATE32PSHR(sum, 15, 32767);
473 #else
474 cubic_coef(frac, interp);
475 sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
476 #endif
477
478 out[out_stride * out_sample++] = sum;
479 last_sample += int_advance;
480 samp_frac_num += frac_advance;
481 if (samp_frac_num >= den_rate)
482 {
483 samp_frac_num -= den_rate;
484 last_sample++;
485 }
486 }
487
488 st->last_sample[channel_index] = last_sample;
489 st->samp_frac_num[channel_index] = samp_frac_num;
490 return out_sample;
491 }
492
493 #ifdef FIXED_POINT
494 #else
495 /* This is the same as the previous function, except with a double-precision accumulator */
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)496 static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
497 {
498 const int N = st->filt_len;
499 int out_sample = 0;
500 int last_sample = st->last_sample[channel_index];
501 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
502 const int out_stride = st->out_stride;
503 const int int_advance = st->int_advance;
504 const int frac_advance = st->frac_advance;
505 const spx_uint32_t den_rate = st->den_rate;
506 int j;
507 spx_word32_t sum;
508
509 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
510 {
511 const spx_word16_t *iptr = & in[last_sample];
512
513 const int offset = samp_frac_num*st->oversample/st->den_rate;
514 #ifdef FIXED_POINT
515 const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
516 #else
517 const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
518 #endif
519 spx_word16_t interp[4];
520
521
522 #ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
523 double accum[4] = {0,0,0,0};
524
525 for(j=0;j<N;j++) {
526 const double curr_in=iptr[j];
527 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
528 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
529 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
530 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
531 }
532
533 cubic_coef(frac, interp);
534 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]);
535 #else
536 cubic_coef(frac, interp);
537 sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
538 #endif
539
540 out[out_stride * out_sample++] = PSHR32(sum,15);
541 last_sample += int_advance;
542 samp_frac_num += frac_advance;
543 if (samp_frac_num >= den_rate)
544 {
545 samp_frac_num -= den_rate;
546 last_sample++;
547 }
548 }
549
550 st->last_sample[channel_index] = last_sample;
551 st->samp_frac_num[channel_index] = samp_frac_num;
552 return out_sample;
553 }
554 #endif
555
update_filter(SpeexResamplerState * st)556 static void update_filter(SpeexResamplerState *st)
557 {
558 spx_uint32_t old_length;
559
560 old_length = st->filt_len;
561 st->oversample = quality_map[st->quality].oversample;
562 st->filt_len = quality_map[st->quality].base_length;
563
564 if (st->num_rate > st->den_rate)
565 {
566 /* down-sampling */
567 st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
568 /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
569 st->filt_len = st->filt_len*st->num_rate / st->den_rate;
570 /* Round down to make sure we have a multiple of 4 */
571 st->filt_len &= (~0x3);
572 if (2*st->den_rate < st->num_rate)
573 st->oversample >>= 1;
574 if (4*st->den_rate < st->num_rate)
575 st->oversample >>= 1;
576 if (8*st->den_rate < st->num_rate)
577 st->oversample >>= 1;
578 if (16*st->den_rate < st->num_rate)
579 st->oversample >>= 1;
580 if (st->oversample < 1)
581 st->oversample = 1;
582 } else {
583 /* up-sampling */
584 st->cutoff = quality_map[st->quality].upsample_bandwidth;
585 }
586
587 /* Choose the resampling type that requires the least amount of memory */
588 #ifdef RESAMPLE_FORCE_FULL_SINC_TABLE
589 if (1)
590 #else
591 if (st->den_rate <= st->oversample)
592 #endif
593 {
594 spx_uint32_t i;
595 if (!st->sinc_table)
596 st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));
597 else if (st->sinc_table_length < st->filt_len*st->den_rate)
598 {
599 st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));
600 st->sinc_table_length = st->filt_len*st->den_rate;
601 }
602 for (i=0;i<st->den_rate;i++)
603 {
604 spx_uint32_t j;
605 for (j=0;j<st->filt_len;j++)
606 {
607 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);
608 }
609 }
610 #ifdef FIXED_POINT
611 st->resampler_ptr = resampler_basic_direct_single;
612 #else
613 if (st->quality>8)
614 st->resampler_ptr = resampler_basic_direct_double;
615 else
616 st->resampler_ptr = resampler_basic_direct_single;
617 #endif
618 /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/
619 } else {
620 spx_int32_t i;
621 if (!st->sinc_table)
622 st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
623 else if (st->sinc_table_length < st->filt_len*st->oversample+8)
624 {
625 st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
626 st->sinc_table_length = st->filt_len*st->oversample+8;
627 }
628 for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)
629 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);
630 #ifdef FIXED_POINT
631 st->resampler_ptr = resampler_basic_interpolate_single;
632 #else
633 if (st->quality>8)
634 st->resampler_ptr = resampler_basic_interpolate_double;
635 else
636 st->resampler_ptr = resampler_basic_interpolate_single;
637 #endif
638 /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/
639 }
640 st->int_advance = st->num_rate/st->den_rate;
641 st->frac_advance = st->num_rate%st->den_rate;
642
643
644 /* Here's the place where we update the filter memory to take into account
645 the change in filter length. It's probably the messiest part of the code
646 due to handling of lots of corner cases. */
647 if (!st->mem)
648 {
649 spx_uint32_t i;
650 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
651 st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
652 for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
653 st->mem[i] = 0;
654 /*speex_warning("init filter");*/
655 } else if (!st->started)
656 {
657 spx_uint32_t i;
658 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
659 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
660 for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
661 st->mem[i] = 0;
662 /*speex_warning("reinit filter");*/
663 } else if (st->filt_len > old_length)
664 {
665 spx_int32_t i;
666 /* Increase the filter length */
667 /*speex_warning("increase filter size");*/
668 int old_alloc_size = st->mem_alloc_size;
669 if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size)
670 {
671 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
672 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
673 }
674 for (i=st->nb_channels-1;i>=0;i--)
675 {
676 spx_uint32_t j;
677 spx_uint32_t olen = old_length;
678 /*if (st->magic_samples[i])*/
679 {
680 /* Try and remove the magic samples as if nothing had happened */
681
682 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
683 olen = old_length + 2*st->magic_samples[i];
684 spx_int32_t k;
685 for (k=old_length-2+st->magic_samples[i];k>=0;k--)
686 st->mem[i*st->mem_alloc_size+k+st->magic_samples[i]] = st->mem[i*old_alloc_size+k];
687 for (j=0;j<st->magic_samples[i];j++)
688 st->mem[i*st->mem_alloc_size+j] = 0;
689 st->magic_samples[i] = 0;
690 }
691 if (st->filt_len > olen)
692 {
693 /* If the new filter length is still bigger than the "augmented" length */
694 /* Copy data going backward */
695 for (j=0;j<olen-1;j++)
696 st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
697 /* Then put zeros for lack of anything better */
698 for (;j<st->filt_len-1;j++)
699 st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
700 /* Adjust last_sample */
701 st->last_sample[i] += (st->filt_len - olen)/2;
702 } else {
703 /* Put back some of the magic! */
704 st->magic_samples[i] = (olen - st->filt_len)/2;
705 for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
706 st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
707 }
708 }
709 } else if (st->filt_len < old_length)
710 {
711 spx_uint32_t i;
712 /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
713 samples so they can be used directly as input the next time(s) */
714 for (i=0;i<st->nb_channels;i++)
715 {
716 spx_uint32_t j;
717 spx_uint32_t old_magic = st->magic_samples[i];
718 st->magic_samples[i] = (old_length - st->filt_len)/2;
719 /* We must copy some of the memory that's no longer used */
720 /* Copy data going backward */
721 for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
722 st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
723 st->magic_samples[i] += old_magic;
724 }
725 }
726
727 }
728
speex_resampler_init(spx_uint32_t nb_channels,spx_uint32_t in_rate,spx_uint32_t out_rate,int quality,int * err)729 EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
730 {
731 return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
732 }
733
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)734 EXPORT 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)
735 {
736 spx_uint32_t i;
737 SpeexResamplerState *st;
738 if (quality > 10 || quality < 0)
739 {
740 if (err)
741 *err = RESAMPLER_ERR_INVALID_ARG;
742 return NULL;
743 }
744 st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
745 st->initialised = 0;
746 st->started = 0;
747 st->in_rate = 0;
748 st->out_rate = 0;
749 st->num_rate = 0;
750 st->den_rate = 0;
751 st->quality = -1;
752 st->sinc_table_length = 0;
753 st->mem_alloc_size = 0;
754 st->filt_len = 0;
755 st->mem = 0;
756 st->resampler_ptr = 0;
757
758 st->cutoff = 1.f;
759 st->nb_channels = nb_channels;
760 st->in_stride = 1;
761 st->out_stride = 1;
762
763 #ifdef FIXED_POINT
764 st->buffer_size = 160;
765 #else
766 st->buffer_size = 160;
767 #endif
768
769 /* Per channel data */
770 st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
771 st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
772 st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
773 for (i=0;i<nb_channels;i++)
774 {
775 st->last_sample[i] = 0;
776 st->magic_samples[i] = 0;
777 st->samp_frac_num[i] = 0;
778 }
779
780 speex_resampler_set_quality(st, quality);
781 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
782
783
784 update_filter(st);
785
786 st->initialised = 1;
787 if (err)
788 *err = RESAMPLER_ERR_SUCCESS;
789
790 return st;
791 }
792
speex_resampler_destroy(SpeexResamplerState * st)793 EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
794 {
795 speex_free(st->mem);
796 speex_free(st->sinc_table);
797 speex_free(st->last_sample);
798 speex_free(st->magic_samples);
799 speex_free(st->samp_frac_num);
800 speex_free(st);
801 }
802
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)803 static 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)
804 {
805 int j=0;
806 const int N = st->filt_len;
807 int out_sample = 0;
808 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
809 spx_uint32_t ilen;
810
811 st->started = 1;
812
813 /* Call the right resampler through the function ptr */
814 out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len);
815
816 if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
817 *in_len = st->last_sample[channel_index];
818 *out_len = out_sample;
819 st->last_sample[channel_index] -= *in_len;
820
821 ilen = *in_len;
822
823 for(j=0;j<N-1;++j)
824 mem[j] = mem[j+ilen];
825
826 return RESAMPLER_ERR_SUCCESS;
827 }
828
speex_resampler_magic(SpeexResamplerState * st,spx_uint32_t channel_index,spx_word16_t ** out,spx_uint32_t out_len)829 static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) {
830 spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
831 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
832 const int N = st->filt_len;
833
834 speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len);
835
836 st->magic_samples[channel_index] -= tmp_in_len;
837
838 /* If we couldn't process all "magic" input samples, save the rest for next time */
839 if (st->magic_samples[channel_index])
840 {
841 spx_uint32_t i;
842 for (i=0;i<st->magic_samples[channel_index];i++)
843 mem[N-1+i]=mem[N-1+i+tmp_in_len];
844 }
845 *out += out_len*st->out_stride;
846 return out_len;
847 }
848
849 #ifdef FIXED_POINT
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)850 EXPORT 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)
851 #else
852 EXPORT 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)
853 #endif
854 {
855 spx_uint32_t j;
856 spx_uint32_t ilen = *in_len;
857 spx_uint32_t olen = *out_len;
858 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
859 const int filt_offs = st->filt_len - 1;
860 const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
861 const int istride = st->in_stride;
862
863 if (st->magic_samples[channel_index])
864 olen -= speex_resampler_magic(st, channel_index, &out, olen);
865 if (! st->magic_samples[channel_index]) {
866 while (ilen && olen) {
867 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
868 spx_uint32_t ochunk = olen;
869
870 if (in) {
871 for(j=0;j<ichunk;++j)
872 x[j+filt_offs]=in[j*istride];
873 } else {
874 for(j=0;j<ichunk;++j)
875 x[j+filt_offs]=0;
876 }
877 speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk);
878 ilen -= ichunk;
879 olen -= ochunk;
880 out += ochunk * st->out_stride;
881 if (in)
882 in += ichunk * istride;
883 }
884 }
885 *in_len -= ilen;
886 *out_len -= olen;
887 return RESAMPLER_ERR_SUCCESS;
888 }
889
890 #ifdef FIXED_POINT
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)891 EXPORT 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)
892 #else
893 EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
894 #endif
895 {
896 spx_uint32_t j;
897 const int istride_save = st->in_stride;
898 const int ostride_save = st->out_stride;
899 spx_uint32_t ilen = *in_len;
900 spx_uint32_t olen = *out_len;
901 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
902 const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
903 #ifdef VAR_ARRAYS
904 const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
905 VARDECL(spx_word16_t *ystack);
906 ALLOC(ystack, ylen, spx_word16_t);
907 #else
908 const unsigned int ylen = FIXED_STACK_ALLOC;
909 spx_word16_t ystack[FIXED_STACK_ALLOC];
910 #endif
911
912 st->out_stride = 1;
913
914 while (ilen && olen) {
915 spx_word16_t *y = ystack;
916 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
917 spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
918 spx_uint32_t omagic = 0;
919
920 if (st->magic_samples[channel_index]) {
921 omagic = speex_resampler_magic(st, channel_index, &y, ochunk);
922 ochunk -= omagic;
923 olen -= omagic;
924 }
925 if (! st->magic_samples[channel_index]) {
926 if (in) {
927 for(j=0;j<ichunk;++j)
928 #ifdef FIXED_POINT
929 x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]);
930 #else
931 x[j+st->filt_len-1]=in[j*istride_save];
932 #endif
933 } else {
934 for(j=0;j<ichunk;++j)
935 x[j+st->filt_len-1]=0;
936 }
937
938 speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk);
939 } else {
940 ichunk = 0;
941 ochunk = 0;
942 }
943
944 for (j=0;j<ochunk+omagic;++j)
945 #ifdef FIXED_POINT
946 out[j*ostride_save] = ystack[j];
947 #else
948 out[j*ostride_save] = WORD2INT(ystack[j]);
949 #endif
950
951 ilen -= ichunk;
952 olen -= ochunk;
953 out += (ochunk+omagic) * ostride_save;
954 if (in)
955 in += ichunk * istride_save;
956 }
957 st->out_stride = ostride_save;
958 *in_len -= ilen;
959 *out_len -= olen;
960
961 return RESAMPLER_ERR_SUCCESS;
962 }
963
speex_resampler_process_interleaved_float(SpeexResamplerState * st,const float * in,spx_uint32_t * in_len,float * out,spx_uint32_t * out_len)964 EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
965 {
966 spx_uint32_t i;
967 int istride_save, ostride_save;
968 spx_uint32_t bak_len = *out_len;
969 istride_save = st->in_stride;
970 ostride_save = st->out_stride;
971 st->in_stride = st->out_stride = st->nb_channels;
972 for (i=0;i<st->nb_channels;i++)
973 {
974 *out_len = bak_len;
975 if (in != NULL)
976 speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
977 else
978 speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len);
979 }
980 st->in_stride = istride_save;
981 st->out_stride = ostride_save;
982 return RESAMPLER_ERR_SUCCESS;
983 }
984
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)985 EXPORT 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)
986 {
987 spx_uint32_t i;
988 int istride_save, ostride_save;
989 spx_uint32_t bak_len = *out_len;
990 istride_save = st->in_stride;
991 ostride_save = st->out_stride;
992 st->in_stride = st->out_stride = st->nb_channels;
993 for (i=0;i<st->nb_channels;i++)
994 {
995 *out_len = bak_len;
996 if (in != NULL)
997 speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
998 else
999 speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len);
1000 }
1001 st->in_stride = istride_save;
1002 st->out_stride = ostride_save;
1003 return RESAMPLER_ERR_SUCCESS;
1004 }
1005
speex_resampler_set_rate(SpeexResamplerState * st,spx_uint32_t in_rate,spx_uint32_t out_rate)1006 EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
1007 {
1008 return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
1009 }
1010
speex_resampler_get_rate(SpeexResamplerState * st,spx_uint32_t * in_rate,spx_uint32_t * out_rate)1011 EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
1012 {
1013 *in_rate = st->in_rate;
1014 *out_rate = st->out_rate;
1015 }
1016
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)1017 EXPORT 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)
1018 {
1019 spx_uint32_t fact;
1020 spx_uint32_t old_den;
1021 spx_uint32_t i;
1022 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
1023 return RESAMPLER_ERR_SUCCESS;
1024
1025 old_den = st->den_rate;
1026 st->in_rate = in_rate;
1027 st->out_rate = out_rate;
1028 st->num_rate = ratio_num;
1029 st->den_rate = ratio_den;
1030 /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
1031 for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
1032 {
1033 while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
1034 {
1035 st->num_rate /= fact;
1036 st->den_rate /= fact;
1037 }
1038 }
1039
1040 if (old_den > 0)
1041 {
1042 for (i=0;i<st->nb_channels;i++)
1043 {
1044 st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
1045 /* Safety net */
1046 if (st->samp_frac_num[i] >= st->den_rate)
1047 st->samp_frac_num[i] = st->den_rate-1;
1048 }
1049 }
1050
1051 if (st->initialised)
1052 update_filter(st);
1053 return RESAMPLER_ERR_SUCCESS;
1054 }
1055
speex_resampler_get_ratio(SpeexResamplerState * st,spx_uint32_t * ratio_num,spx_uint32_t * ratio_den)1056 EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
1057 {
1058 *ratio_num = st->num_rate;
1059 *ratio_den = st->den_rate;
1060 }
1061
speex_resampler_set_quality(SpeexResamplerState * st,int quality)1062 EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
1063 {
1064 if (quality > 10 || quality < 0)
1065 return RESAMPLER_ERR_INVALID_ARG;
1066 if (st->quality == quality)
1067 return RESAMPLER_ERR_SUCCESS;
1068 st->quality = quality;
1069 if (st->initialised)
1070 update_filter(st);
1071 return RESAMPLER_ERR_SUCCESS;
1072 }
1073
speex_resampler_get_quality(SpeexResamplerState * st,int * quality)1074 EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
1075 {
1076 *quality = st->quality;
1077 }
1078
speex_resampler_set_input_stride(SpeexResamplerState * st,spx_uint32_t stride)1079 EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
1080 {
1081 st->in_stride = stride;
1082 }
1083
speex_resampler_get_input_stride(SpeexResamplerState * st,spx_uint32_t * stride)1084 EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1085 {
1086 *stride = st->in_stride;
1087 }
1088
speex_resampler_set_output_stride(SpeexResamplerState * st,spx_uint32_t stride)1089 EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
1090 {
1091 st->out_stride = stride;
1092 }
1093
speex_resampler_get_output_stride(SpeexResamplerState * st,spx_uint32_t * stride)1094 EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1095 {
1096 *stride = st->out_stride;
1097 }
1098
speex_resampler_get_input_latency(SpeexResamplerState * st)1099 EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st)
1100 {
1101 return st->filt_len / 2;
1102 }
1103
speex_resampler_get_output_latency(SpeexResamplerState * st)1104 EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st)
1105 {
1106 return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;
1107 }
1108
speex_resampler_skip_zeros(SpeexResamplerState * st)1109 EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st)
1110 {
1111 spx_uint32_t i;
1112 for (i=0;i<st->nb_channels;i++)
1113 st->last_sample[i] = st->filt_len/2;
1114 return RESAMPLER_ERR_SUCCESS;
1115 }
1116
speex_resampler_reset_mem(SpeexResamplerState * st)1117 EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)
1118 {
1119 spx_uint32_t i;
1120 for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
1121 st->mem[i] = 0;
1122 return RESAMPLER_ERR_SUCCESS;
1123 }
1124
speex_resampler_strerror(int err)1125 EXPORT const char *speex_resampler_strerror(int err)
1126 {
1127 switch (err)
1128 {
1129 case RESAMPLER_ERR_SUCCESS:
1130 return "Success.";
1131 case RESAMPLER_ERR_ALLOC_FAILED:
1132 return "Memory allocation failed.";
1133 case RESAMPLER_ERR_BAD_STATE:
1134 return "Bad resampler state.";
1135 case RESAMPLER_ERR_INVALID_ARG:
1136 return "Invalid argument.";
1137 case RESAMPLER_ERR_PTR_OVERLAP:
1138 return "Input and output buffers overlap.";
1139 default:
1140 return "Unknown error. Bad error code or strange version mismatch.";
1141 }
1142 }
1143