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