summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libspeex/resample.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libspeex/resample.c')
-rw-r--r--lib/rbcodec/codecs/libspeex/resample.c735
1 files changed, 363 insertions, 372 deletions
diff --git a/lib/rbcodec/codecs/libspeex/resample.c b/lib/rbcodec/codecs/libspeex/resample.c
index 65dfef28a3..5f5b9c6b4d 100644
--- a/lib/rbcodec/codecs/libspeex/resample.c
+++ b/lib/rbcodec/codecs/libspeex/resample.c
@@ -1,5 +1,6 @@
1/* Copyright (C) 2007 Jean-Marc Valin 1/* Copyright (C) 2007-2008 Jean-Marc Valin
2 2 Copyright (C) 2008 Thorvald Natvig
3
3 File: resample.c 4 File: resample.c
4 Arbitrary resampling code 5 Arbitrary resampling code
5 6
@@ -37,27 +38,27 @@
37 - Low memory requirement 38 - Low memory requirement
38 - Good *perceptual* quality (and not best SNR) 39 - Good *perceptual* quality (and not best SNR)
39 40
40 Warning: This resampler is relatively new. Although I think I got rid of 41 Warning: This resampler is relatively new. Although I think I got rid of
41 all the major bugs and I don't expect the API to change anymore, there 42 all the major bugs and I don't expect the API to change anymore, there
42 may be something I've missed. So use with caution. 43 may be something I've missed. So use with caution.
43 44
44 This algorithm is based on this original resampling algorithm: 45 This algorithm is based on this original resampling algorithm:
45 Smith, Julius O. Digital Audio Resampling Home Page 46 Smith, Julius O. Digital Audio Resampling Home Page
46 Center for Computer Research in Music and Acoustics (CCRMA), 47 Center for Computer Research in Music and Acoustics (CCRMA),
47 Stanford University, 2007. 48 Stanford University, 2007.
48 Web published at http://www-ccrma.stanford.edu/~jos/resample/. 49 Web published at http://www-ccrma.stanford.edu/~jos/resample/.
49 50
50 There is one main difference, though. This resampler uses cubic 51 There is one main difference, though. This resampler uses cubic
51 interpolation instead of linear interpolation in the above paper. This 52 interpolation instead of linear interpolation in the above paper. This
52 makes the table much smaller and makes it possible to compute that table 53 makes the table much smaller and makes it possible to compute that table
53 on a per-stream basis. In turn, being able to tweak the table for each 54 on a per-stream basis. In turn, being able to tweak the table for each
54 stream makes it possible to both reduce complexity on simple ratios 55 stream makes it possible to both reduce complexity on simple ratios
55 (e.g. 2/3), and get rid of the rounding operations in the inner loop. 56 (e.g. 2/3), and get rid of the rounding operations in the inner loop.
56 The latter both reduces CPU time and makes the algorithm more SIMD-friendly. 57 The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
57*/ 58*/
58 59
59#ifdef HAVE_CONFIG_H 60#ifdef HAVE_CONFIG_H
60#include "config-speex.h" 61#include "config.h"
61#endif 62#endif
62 63
63#ifdef OUTSIDE_SPEEX 64#ifdef OUTSIDE_SPEEX
@@ -68,12 +69,13 @@ static void speex_free (void *ptr) {free(ptr);}
68#include "speex_resampler.h" 69#include "speex_resampler.h"
69#include "arch.h" 70#include "arch.h"
70#else /* OUTSIDE_SPEEX */ 71#else /* OUTSIDE_SPEEX */
71 72
72#include "speex/speex_resampler.h" 73#include "speex/speex_resampler.h"
73#include "arch.h" 74#include "arch.h"
74#include "os_support.h" 75#include "os_support.h"
75#endif /* OUTSIDE_SPEEX */ 76#endif /* OUTSIDE_SPEEX */
76 77
78#include "stack_alloc.h"
77#include <math.h> 79#include <math.h>
78 80
79#ifndef M_PI 81#ifndef M_PI
@@ -81,14 +83,10 @@ static void speex_free (void *ptr) {free(ptr);}
81#endif 83#endif
82 84
83#ifdef FIXED_POINT 85#ifdef FIXED_POINT
84#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 86#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
85#else 87#else
86#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) 88#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
87#endif 89#endif
88
89/*#define float double*/
90#define FILTER_SIZE 64
91#define OVERSAMPLE 8
92 90
93#define IMAX(a,b) ((a) > (b) ? (a) : (b)) 91#define IMAX(a,b) ((a) > (b) ? (a) : (b))
94#define IMIN(a,b) ((a) < (b) ? (a) : (b)) 92#define IMIN(a,b) ((a) < (b) ? (a) : (b))
@@ -97,6 +95,17 @@ static void speex_free (void *ptr) {free(ptr);}
97#define NULL 0 95#define NULL 0
98#endif 96#endif
99 97
98#ifdef _USE_SSE
99#include "resample_sse.h"
100#endif
101
102/* Numer of elements to allocate on the stack */
103#ifdef VAR_ARRAYS
104#define FIXED_STACK_ALLOC 8192
105#else
106#define FIXED_STACK_ALLOC 1024
107#endif
108
100typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); 109typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
101 110
102struct SpeexResamplerState_ { 111struct SpeexResamplerState_ {
@@ -104,28 +113,29 @@ struct SpeexResamplerState_ {
104 spx_uint32_t out_rate; 113 spx_uint32_t out_rate;
105 spx_uint32_t num_rate; 114 spx_uint32_t num_rate;
106 spx_uint32_t den_rate; 115 spx_uint32_t den_rate;
107 116
108 int quality; 117 int quality;
109 spx_uint32_t nb_channels; 118 spx_uint32_t nb_channels;
110 spx_uint32_t filt_len; 119 spx_uint32_t filt_len;
111 spx_uint32_t mem_alloc_size; 120 spx_uint32_t mem_alloc_size;
121 spx_uint32_t buffer_size;
112 int int_advance; 122 int int_advance;
113 int frac_advance; 123 int frac_advance;
114 float cutoff; 124 float cutoff;
115 spx_uint32_t oversample; 125 spx_uint32_t oversample;
116 int initialised; 126 int initialised;
117 int started; 127 int started;
118 128
119 /* These are per-channel */ 129 /* These are per-channel */
120 spx_int32_t *last_sample; 130 spx_int32_t *last_sample;
121 spx_uint32_t *samp_frac_num; 131 spx_uint32_t *samp_frac_num;
122 spx_uint32_t *magic_samples; 132 spx_uint32_t *magic_samples;
123 133
124 spx_word16_t *mem; 134 spx_word16_t *mem;
125 spx_word16_t *sinc_table; 135 spx_word16_t *sinc_table;
126 spx_uint32_t sinc_table_length; 136 spx_uint32_t sinc_table_length;
127 resampler_basic_func resampler_ptr; 137 resampler_basic_func resampler_ptr;
128 138
129 int in_stride; 139 int in_stride;
130 int out_stride; 140 int out_stride;
131} ; 141} ;
@@ -167,7 +177,7 @@ static double kaiser8_table[36] = {
167 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, 177 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
168 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, 178 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
169 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; 179 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
170 180
171static double kaiser6_table[36] = { 181static double kaiser6_table[36] = {
172 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, 182 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
173 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, 183 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
@@ -180,7 +190,7 @@ struct FuncDef {
180 double *table; 190 double *table;
181 int oversample; 191 int oversample;
182}; 192};
183 193
184static struct FuncDef _KAISER12 = {kaiser12_table, 64}; 194static struct FuncDef _KAISER12 = {kaiser12_table, 64};
185#define KAISER12 (&_KAISER12) 195#define KAISER12 (&_KAISER12)
186/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; 196/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
@@ -202,7 +212,7 @@ struct QualityMapping {
202 212
203 213
204/* This table maps conversion quality to internal parameters. There are two 214/* This table maps conversion quality to internal parameters. There are two
205 reasons that explain why the up-sampling bandwidth is larger than the 215 reasons that explain why the up-sampling bandwidth is larger than the
206 down-sampling bandwidth: 216 down-sampling bandwidth:
207 1) When up-sampling, we can assume that the spectrum is already attenuated 217 1) When up-sampling, we can assume that the spectrum is already attenuated
208 close to the Nyquist rate (from an A/D or a previous resampling filter) 218 close to the Nyquist rate (from an A/D or a previous resampling filter)
@@ -228,7 +238,7 @@ static double compute_func(float x, struct FuncDef *func)
228{ 238{
229 float y, frac; 239 float y, frac;
230 double interp[4]; 240 double interp[4];
231 int ind; 241 int ind;
232 y = x*func->oversample; 242 y = x*func->oversample;
233 ind = (int)floor(y); 243 ind = (int)floor(y);
234 frac = (y-ind); 244 frac = (y-ind);
@@ -239,7 +249,7 @@ static double compute_func(float x, struct FuncDef *func)
239 interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); 249 interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
240 /* Just to make sure we don't have rounding problems */ 250 /* Just to make sure we don't have rounding problems */
241 interp[1] = 1.f-interp[3]-interp[2]-interp[0]; 251 interp[1] = 1.f-interp[3]-interp[2]-interp[0];
242 252
243 /*sum = frac*accum[1] + (1-frac)*accum[2];*/ 253 /*sum = frac*accum[1] + (1-frac)*accum[2];*/
244 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; 254 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
245} 255}
@@ -317,47 +327,47 @@ static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
317 327
318static 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) 328static 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)
319{ 329{
320 int N = st->filt_len; 330 const int N = st->filt_len;
321 int out_sample = 0; 331 int out_sample = 0;
322 spx_word16_t *mem;
323 int last_sample = st->last_sample[channel_index]; 332 int last_sample = st->last_sample[channel_index];
324 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 333 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
325 mem = st->mem + channel_index * st->mem_alloc_size; 334 const spx_word16_t *sinc_table = st->sinc_table;
335 const int out_stride = st->out_stride;
336 const int int_advance = st->int_advance;
337 const int frac_advance = st->frac_advance;
338 const spx_uint32_t den_rate = st->den_rate;
339 spx_word32_t sum;
340 int j;
341
326 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 342 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
327 { 343 {
328 int j; 344 const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
329 spx_word32_t sum=0; 345 const spx_word16_t *iptr = & in[last_sample];
330 346
331 /* We already have all the filter coefficients pre-computed in the table */ 347#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
332 const spx_word16_t *ptr; 348 float accum[4] = {0,0,0,0};
333 /* Do the memory part */ 349
334 for (j=0;last_sample-N+1+j < 0;j++) 350 for(j=0;j<N;j+=4) {
335 { 351 accum[0] += sinc[j]*iptr[j];
336 sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]); 352 accum[1] += sinc[j+1]*iptr[j+1];
337 } 353 accum[2] += sinc[j+2]*iptr[j+2];
338 354 accum[3] += sinc[j+3]*iptr[j+3];
339 /* Do the new part */
340 if (in != NULL)
341 {
342 ptr = in+st->in_stride*(last_sample-N+1+j);
343 for (;j<N;j++)
344 {
345 sum += MULT16_16(*ptr,st->sinc_table[samp_frac_num*st->filt_len+j]);
346 ptr += st->in_stride;
347 }
348 } 355 }
349 356 sum = accum[0] + accum[1] + accum[2] + accum[3];
350 *out = PSHR32(sum,15); 357#else
351 out += st->out_stride; 358 sum = inner_product_single(sinc, iptr, N);
352 out_sample++; 359#endif
353 last_sample += st->int_advance; 360
354 samp_frac_num += st->frac_advance; 361 out[out_stride * out_sample++] = PSHR32(sum, 15);
355 if (samp_frac_num >= st->den_rate) 362 last_sample += int_advance;
363 samp_frac_num += frac_advance;
364 if (samp_frac_num >= den_rate)
356 { 365 {
357 samp_frac_num -= st->den_rate; 366 samp_frac_num -= den_rate;
358 last_sample++; 367 last_sample++;
359 } 368 }
360 } 369 }
370
361 st->last_sample[channel_index] = last_sample; 371 st->last_sample[channel_index] = last_sample;
362 st->samp_frac_num[channel_index] = samp_frac_num; 372 st->samp_frac_num[channel_index] = samp_frac_num;
363 return out_sample; 373 return out_sample;
@@ -368,47 +378,47 @@ static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t c
368/* This is the same as the previous function, except with a double-precision accumulator */ 378/* This is the same as the previous function, except with a double-precision accumulator */
369static 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) 379static 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)
370{ 380{
371 int N = st->filt_len; 381 const int N = st->filt_len;
372 int out_sample = 0; 382 int out_sample = 0;
373 spx_word16_t *mem;
374 int last_sample = st->last_sample[channel_index]; 383 int last_sample = st->last_sample[channel_index];
375 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 384 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
376 mem = st->mem + channel_index * st->mem_alloc_size; 385 const spx_word16_t *sinc_table = st->sinc_table;
386 const int out_stride = st->out_stride;
387 const int int_advance = st->int_advance;
388 const int frac_advance = st->frac_advance;
389 const spx_uint32_t den_rate = st->den_rate;
390 double sum;
391 int j;
392
377 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 393 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
378 { 394 {
379 int j; 395 const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
380 double sum=0; 396 const spx_word16_t *iptr = & in[last_sample];
381 397
382 /* We already have all the filter coefficients pre-computed in the table */ 398#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
383 const spx_word16_t *ptr; 399 double accum[4] = {0,0,0,0};
384 /* Do the memory part */ 400
385 for (j=0;last_sample-N+1+j < 0;j++) 401 for(j=0;j<N;j+=4) {
386 { 402 accum[0] += sinc[j]*iptr[j];
387 sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]); 403 accum[1] += sinc[j+1]*iptr[j+1];
388 } 404 accum[2] += sinc[j+2]*iptr[j+2];
389 405 accum[3] += sinc[j+3]*iptr[j+3];
390 /* Do the new part */
391 if (in != NULL)
392 {
393 ptr = in+st->in_stride*(last_sample-N+1+j);
394 for (;j<N;j++)
395 {
396 sum += MULT16_16(*ptr,(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
397 ptr += st->in_stride;
398 }
399 } 406 }
400 407 sum = accum[0] + accum[1] + accum[2] + accum[3];
401 *out = sum; 408#else
402 out += st->out_stride; 409 sum = inner_product_double(sinc, iptr, N);
403 out_sample++; 410#endif
404 last_sample += st->int_advance; 411
405 samp_frac_num += st->frac_advance; 412 out[out_stride * out_sample++] = PSHR32(sum, 15);
406 if (samp_frac_num >= st->den_rate) 413 last_sample += int_advance;
414 samp_frac_num += frac_advance;
415 if (samp_frac_num >= den_rate)
407 { 416 {
408 samp_frac_num -= st->den_rate; 417 samp_frac_num -= den_rate;
409 last_sample++; 418 last_sample++;
410 } 419 }
411 } 420 }
421
412 st->last_sample[channel_index] = last_sample; 422 st->last_sample[channel_index] = last_sample;
413 st->samp_frac_num[channel_index] = samp_frac_num; 423 st->samp_frac_num[channel_index] = samp_frac_num;
414 return out_sample; 424 return out_sample;
@@ -417,69 +427,58 @@ static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t c
417 427
418static 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) 428static 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)
419{ 429{
420 int N = st->filt_len; 430 const int N = st->filt_len;
421 int out_sample = 0; 431 int out_sample = 0;
422 spx_word16_t *mem;
423 int last_sample = st->last_sample[channel_index]; 432 int last_sample = st->last_sample[channel_index];
424 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 433 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
425 mem = st->mem + channel_index * st->mem_alloc_size; 434 const int out_stride = st->out_stride;
435 const int int_advance = st->int_advance;
436 const int frac_advance = st->frac_advance;
437 const spx_uint32_t den_rate = st->den_rate;
438 int j;
439 spx_word32_t sum;
440
426 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 441 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
427 { 442 {
428 int j; 443 const spx_word16_t *iptr = & in[last_sample];
429 spx_word32_t sum=0; 444
430 445 const int offset = samp_frac_num*st->oversample/st->den_rate;
431 /* We need to interpolate the sinc filter */
432 spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f};
433 spx_word16_t interp[4];
434 const spx_word16_t *ptr;
435 int offset;
436 spx_word16_t frac;
437 offset = samp_frac_num*st->oversample/st->den_rate;
438#ifdef FIXED_POINT 446#ifdef FIXED_POINT
439 frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 447 const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
440#else 448#else
441 frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 449 const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
442#endif 450#endif
443 /* This code is written like this to make it easy to optimise with SIMD. 451 spx_word16_t interp[4];
444 For most DSPs, it would be best to split the loops in two because most DSPs 452
445 have only two accumulators */ 453
446 for (j=0;last_sample-N+1+j < 0;j++) 454#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
447 { 455 spx_word32_t accum[4] = {0,0,0,0};
448 spx_word16_t curr_mem = mem[last_sample+j]; 456
449 accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 457 for(j=0;j<N;j++) {
450 accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 458 const spx_word16_t curr_in=iptr[j];
451 accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); 459 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
452 accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 460 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
453 } 461 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
454 462 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
455 if (in != NULL)
456 {
457 ptr = in+st->in_stride*(last_sample-N+1+j);
458 /* Do the new part */
459 for (;j<N;j++)
460 {
461 spx_word16_t curr_in = *ptr;
462 ptr += st->in_stride;
463 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
464 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
465 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
466 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
467 }
468 } 463 }
464
469 cubic_coef(frac, interp); 465 cubic_coef(frac, interp);
470 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]); 466 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]);
471 467#else
472 *out = PSHR32(sum,15); 468 cubic_coef(frac, interp);
473 out += st->out_stride; 469 sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
474 out_sample++; 470#endif
475 last_sample += st->int_advance; 471
476 samp_frac_num += st->frac_advance; 472 out[out_stride * out_sample++] = PSHR32(sum,15);
477 if (samp_frac_num >= st->den_rate) 473 last_sample += int_advance;
474 samp_frac_num += frac_advance;
475 if (samp_frac_num >= den_rate)
478 { 476 {
479 samp_frac_num -= st->den_rate; 477 samp_frac_num -= den_rate;
480 last_sample++; 478 last_sample++;
481 } 479 }
482 } 480 }
481
483 st->last_sample[channel_index] = last_sample; 482 st->last_sample[channel_index] = last_sample;
484 st->samp_frac_num[channel_index] = samp_frac_num; 483 st->samp_frac_num[channel_index] = samp_frac_num;
485 return out_sample; 484 return out_sample;
@@ -490,63 +489,58 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
490/* This is the same as the previous function, except with a double-precision accumulator */ 489/* This is the same as the previous function, except with a double-precision accumulator */
491static 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) 490static 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)
492{ 491{
493 int N = st->filt_len; 492 const int N = st->filt_len;
494 int out_sample = 0; 493 int out_sample = 0;
495 spx_word16_t *mem;
496 int last_sample = st->last_sample[channel_index]; 494 int last_sample = st->last_sample[channel_index];
497 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 495 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
498 mem = st->mem + channel_index * st->mem_alloc_size; 496 const int out_stride = st->out_stride;
497 const int int_advance = st->int_advance;
498 const int frac_advance = st->frac_advance;
499 const spx_uint32_t den_rate = st->den_rate;
500 int j;
501 spx_word32_t sum;
502
499 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 503 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
500 { 504 {
501 int j; 505 const spx_word16_t *iptr = & in[last_sample];
502 spx_word32_t sum=0; 506
503 507 const int offset = samp_frac_num*st->oversample/st->den_rate;
504 /* We need to interpolate the sinc filter */ 508#ifdef FIXED_POINT
505 double accum[4] = {0.f,0.f, 0.f, 0.f}; 509 const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
506 float interp[4]; 510#else
507 const spx_word16_t *ptr; 511 const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
508 float alpha = ((float)samp_frac_num)/st->den_rate; 512#endif
509 int offset = samp_frac_num*st->oversample/st->den_rate; 513 spx_word16_t interp[4];
510 float frac = alpha*st->oversample - offset; 514
511 /* This code is written like this to make it easy to optimise with SIMD. 515
512 For most DSPs, it would be best to split the loops in two because most DSPs 516#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
513 have only two accumulators */ 517 double accum[4] = {0,0,0,0};
514 for (j=0;last_sample-N+1+j < 0;j++) 518
515 { 519 for(j=0;j<N;j++) {
516 double curr_mem = mem[last_sample+j]; 520 const double curr_in=iptr[j];
517 accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 521 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
518 accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 522 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
519 accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); 523 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
520 accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 524 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
521 }
522 if (in != NULL)
523 {
524 ptr = in+st->in_stride*(last_sample-N+1+j);
525 /* Do the new part */
526 for (;j<N;j++)
527 {
528 double curr_in = *ptr;
529 ptr += st->in_stride;
530 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
531 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
532 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
533 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
534 }
535 } 525 }
526
536 cubic_coef(frac, interp); 527 cubic_coef(frac, interp);
537 sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3]; 528 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]);
538 529#else
539 *out = PSHR32(sum,15); 530 cubic_coef(frac, interp);
540 out += st->out_stride; 531 sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
541 out_sample++; 532#endif
542 last_sample += st->int_advance; 533
543 samp_frac_num += st->frac_advance; 534 out[out_stride * out_sample++] = PSHR32(sum,15);
544 if (samp_frac_num >= st->den_rate) 535 last_sample += int_advance;
536 samp_frac_num += frac_advance;
537 if (samp_frac_num >= den_rate)
545 { 538 {
546 samp_frac_num -= st->den_rate; 539 samp_frac_num -= den_rate;
547 last_sample++; 540 last_sample++;
548 } 541 }
549 } 542 }
543
550 st->last_sample[channel_index] = last_sample; 544 st->last_sample[channel_index] = last_sample;
551 st->samp_frac_num[channel_index] = samp_frac_num; 545 st->samp_frac_num[channel_index] = samp_frac_num;
552 return out_sample; 546 return out_sample;
@@ -556,11 +550,11 @@ static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint3
556static void update_filter(SpeexResamplerState *st) 550static void update_filter(SpeexResamplerState *st)
557{ 551{
558 spx_uint32_t old_length; 552 spx_uint32_t old_length;
559 553
560 old_length = st->filt_len; 554 old_length = st->filt_len;
561 st->oversample = quality_map[st->quality].oversample; 555 st->oversample = quality_map[st->quality].oversample;
562 st->filt_len = quality_map[st->quality].base_length; 556 st->filt_len = quality_map[st->quality].base_length;
563 557
564 if (st->num_rate > st->den_rate) 558 if (st->num_rate > st->den_rate)
565 { 559 {
566 /* down-sampling */ 560 /* down-sampling */
@@ -636,25 +630,25 @@ static void update_filter(SpeexResamplerState *st)
636 st->int_advance = st->num_rate/st->den_rate; 630 st->int_advance = st->num_rate/st->den_rate;
637 st->frac_advance = st->num_rate%st->den_rate; 631 st->frac_advance = st->num_rate%st->den_rate;
638 632
639 633
640 /* Here's the place where we update the filter memory to take into account 634 /* Here's the place where we update the filter memory to take into account
641 the change in filter length. It's probably the messiest part of the code 635 the change in filter length. It's probably the messiest part of the code
642 due to handling of lots of corner cases. */ 636 due to handling of lots of corner cases. */
643 if (!st->mem) 637 if (!st->mem)
644 { 638 {
645 spx_uint32_t i; 639 spx_uint32_t i;
646 st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 640 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
647 for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 641 st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
642 for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
648 st->mem[i] = 0; 643 st->mem[i] = 0;
649 st->mem_alloc_size = st->filt_len-1;
650 /*speex_warning("init filter");*/ 644 /*speex_warning("init filter");*/
651 } else if (!st->started) 645 } else if (!st->started)
652 { 646 {
653 spx_uint32_t i; 647 spx_uint32_t i;
654 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 648 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
655 for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 649 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
650 for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
656 st->mem[i] = 0; 651 st->mem[i] = 0;
657 st->mem_alloc_size = st->filt_len-1;
658 /*speex_warning("reinit filter");*/ 652 /*speex_warning("reinit filter");*/
659 } else if (st->filt_len > old_length) 653 } else if (st->filt_len > old_length)
660 { 654 {
@@ -662,10 +656,10 @@ static void update_filter(SpeexResamplerState *st)
662 /* Increase the filter length */ 656 /* Increase the filter length */
663 /*speex_warning("increase filter size");*/ 657 /*speex_warning("increase filter size");*/
664 int old_alloc_size = st->mem_alloc_size; 658 int old_alloc_size = st->mem_alloc_size;
665 if (st->filt_len-1 > st->mem_alloc_size) 659 if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size)
666 { 660 {
667 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 661 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
668 st->mem_alloc_size = st->filt_len-1; 662 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
669 } 663 }
670 for (i=st->nb_channels-1;i>=0;i--) 664 for (i=st->nb_channels-1;i>=0;i--)
671 { 665 {
@@ -674,7 +668,7 @@ static void update_filter(SpeexResamplerState *st)
674 /*if (st->magic_samples[i])*/ 668 /*if (st->magic_samples[i])*/
675 { 669 {
676 /* Try and remove the magic samples as if nothing had happened */ 670 /* Try and remove the magic samples as if nothing had happened */
677 671
678 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ 672 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
679 olen = old_length + 2*st->magic_samples[i]; 673 olen = old_length + 2*st->magic_samples[i];
680 for (j=old_length-2+st->magic_samples[i];j>=0;j--) 674 for (j=old_length-2+st->magic_samples[i];j>=0;j--)
@@ -721,12 +715,12 @@ static void update_filter(SpeexResamplerState *st)
721 715
722} 716}
723 717
724SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 718EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
725{ 719{
726 return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); 720 return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
727} 721}
728 722
729SpeexResamplerState *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) 723EXPORT 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)
730{ 724{
731 spx_uint32_t i; 725 spx_uint32_t i;
732 SpeexResamplerState *st; 726 SpeexResamplerState *st;
@@ -749,12 +743,18 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
749 st->filt_len = 0; 743 st->filt_len = 0;
750 st->mem = 0; 744 st->mem = 0;
751 st->resampler_ptr = 0; 745 st->resampler_ptr = 0;
752 746
753 st->cutoff = 1.f; 747 st->cutoff = 1.f;
754 st->nb_channels = nb_channels; 748 st->nb_channels = nb_channels;
755 st->in_stride = 1; 749 st->in_stride = 1;
756 st->out_stride = 1; 750 st->out_stride = 1;
757 751
752#ifdef FIXED_POINT
753 st->buffer_size = 160;
754#else
755 st->buffer_size = 160;
756#endif
757
758 /* Per channel data */ 758 /* Per channel data */
759 st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); 759 st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
760 st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); 760 st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
@@ -769,9 +769,9 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
769 speex_resampler_set_quality(st, quality); 769 speex_resampler_set_quality(st, quality);
770 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); 770 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
771 771
772 772
773 update_filter(st); 773 update_filter(st);
774 774
775 st->initialised = 1; 775 st->initialised = 1;
776 if (err) 776 if (err)
777 *err = RESAMPLER_ERR_SUCCESS; 777 *err = RESAMPLER_ERR_SUCCESS;
@@ -779,7 +779,7 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
779 return st; 779 return st;
780} 780}
781 781
782void speex_resampler_destroy(SpeexResamplerState *st) 782EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
783{ 783{
784 speex_free(st->mem); 784 speex_free(st->mem);
785 speex_free(st->sinc_table); 785 speex_free(st->sinc_table);
@@ -789,186 +789,168 @@ void speex_resampler_destroy(SpeexResamplerState *st)
789 speex_free(st); 789 speex_free(st);
790} 790}
791 791
792 792static 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)
793
794static int speex_resampler_process_native(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)
795{ 793{
796 int j=0; 794 int j=0;
797 int N = st->filt_len; 795 const int N = st->filt_len;
798 int out_sample = 0; 796 int out_sample = 0;
799 spx_word16_t *mem; 797 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
800 spx_uint32_t tmp_out_len = 0; 798 spx_uint32_t ilen;
801 mem = st->mem + channel_index * st->mem_alloc_size; 799
802 st->started = 1; 800 st->started = 1;
803 801
804 /* Handle the case where we have samples left from a reduction in filter length */
805 if (st->magic_samples[channel_index])
806 {
807 int istride_save;
808 spx_uint32_t tmp_in_len;
809 spx_uint32_t tmp_magic;
810
811 istride_save = st->in_stride;
812 tmp_in_len = st->magic_samples[channel_index];
813 tmp_out_len = *out_len;
814 /* magic_samples needs to be set to zero to avoid infinite recursion */
815 tmp_magic = st->magic_samples[channel_index];
816 st->magic_samples[channel_index] = 0;
817 st->in_stride = 1;
818 speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len);
819 st->in_stride = istride_save;
820 /*speex_warning_int("extra samples:", tmp_out_len);*/
821 /* If we couldn't process all "magic" input samples, save the rest for next time */
822 if (tmp_in_len < tmp_magic)
823 {
824 spx_uint32_t i;
825 st->magic_samples[channel_index] = tmp_magic-tmp_in_len;
826 for (i=0;i<st->magic_samples[channel_index];i++)
827 mem[N-1+i]=mem[N-1+i+tmp_in_len];
828 }
829 out += tmp_out_len*st->out_stride;
830 *out_len -= tmp_out_len;
831 }
832
833 /* Call the right resampler through the function ptr */ 802 /* Call the right resampler through the function ptr */
834 out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len); 803 out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len);
835 804
836 if (st->last_sample[channel_index] < (spx_int32_t)*in_len) 805 if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
837 *in_len = st->last_sample[channel_index]; 806 *in_len = st->last_sample[channel_index];
838 *out_len = out_sample+tmp_out_len; 807 *out_len = out_sample;
839 st->last_sample[channel_index] -= *in_len; 808 st->last_sample[channel_index] -= *in_len;
840 809
841 for (j=0;j<N-1-(spx_int32_t)*in_len;j++) 810 ilen = *in_len;
842 mem[j] = mem[j+*in_len]; 811
843 for (;j<N-1;j++) 812 for(j=0;j<N-1;++j)
844 mem[j] = in[st->in_stride*(j+*in_len-N+1)]; 813 mem[j] = mem[j+ilen];
845 814
846 return RESAMPLER_ERR_SUCCESS; 815 return RESAMPLER_ERR_SUCCESS;
847} 816}
848 817
849#define FIXED_STACK_ALLOC 1024 818static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) {
819 spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
820 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
821 const int N = st->filt_len;
822
823 speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len);
824
825 st->magic_samples[channel_index] -= tmp_in_len;
826
827 /* If we couldn't process all "magic" input samples, save the rest for next time */
828 if (st->magic_samples[channel_index])
829 {
830 spx_uint32_t i;
831 for (i=0;i<st->magic_samples[channel_index];i++)
832 mem[N-1+i]=mem[N-1+i+tmp_in_len];
833 }
834 *out += out_len*st->out_stride;
835 return out_len;
836}
850 837
851#ifdef FIXED_POINT 838#ifdef FIXED_POINT
852int 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) 839EXPORT 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)
853{
854 spx_uint32_t i;
855 int istride_save, ostride_save;
856#ifdef VAR_ARRAYS
857 spx_word16_t x[*in_len];
858 spx_word16_t y[*out_len];
859 /*VARDECL(spx_word16_t *x);
860 VARDECL(spx_word16_t *y);
861 ALLOC(x, *in_len, spx_word16_t);
862 ALLOC(y, *out_len, spx_word16_t);*/
863 istride_save = st->in_stride;
864 ostride_save = st->out_stride;
865 for (i=0;i<*in_len;i++)
866 x[i] = WORD2INT(in[i*st->in_stride]);
867 st->in_stride = st->out_stride = 1;
868 speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
869 st->in_stride = istride_save;
870 st->out_stride = ostride_save;
871 for (i=0;i<*out_len;i++)
872 out[i*st->out_stride] = y[i];
873#else 840#else
874 spx_word16_t x[FIXED_STACK_ALLOC]; 841EXPORT 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)
875 spx_word16_t y[FIXED_STACK_ALLOC]; 842#endif
876 spx_uint32_t ilen=*in_len, olen=*out_len; 843{
877 istride_save = st->in_stride; 844 int j;
878 ostride_save = st->out_stride; 845 spx_uint32_t ilen = *in_len;
879 while (ilen && olen) 846 spx_uint32_t olen = *out_len;
880 { 847 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
881 spx_uint32_t ichunk, ochunk; 848 const int filt_offs = st->filt_len - 1;
882 ichunk = ilen; 849 const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
883 ochunk = olen; 850 const int istride = st->in_stride;
884 if (ichunk>FIXED_STACK_ALLOC) 851
885 ichunk=FIXED_STACK_ALLOC; 852 if (st->magic_samples[channel_index])
886 if (ochunk>FIXED_STACK_ALLOC) 853 olen -= speex_resampler_magic(st, channel_index, &out, olen);
887 ochunk=FIXED_STACK_ALLOC; 854 if (! st->magic_samples[channel_index]) {
888 for (i=0;i<ichunk;i++) 855 while (ilen && olen) {
889 x[i] = WORD2INT(in[i*st->in_stride]); 856 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
890 st->in_stride = st->out_stride = 1; 857 spx_uint32_t ochunk = olen;
891 speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); 858
892 st->in_stride = istride_save; 859 if (in) {
893 st->out_stride = ostride_save; 860 for(j=0;j<ichunk;++j)
894 for (i=0;i<ochunk;i++) 861 x[j+filt_offs]=in[j*istride];
895 out[i*st->out_stride] = y[i]; 862 } else {
896 out += ochunk; 863 for(j=0;j<ichunk;++j)
897 in += ichunk; 864 x[j+filt_offs]=0;
898 ilen -= ichunk; 865 }
899 olen -= ochunk; 866 speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk);
867 ilen -= ichunk;
868 olen -= ochunk;
869 out += ochunk * st->out_stride;
870 if (in)
871 in += ichunk * istride;
872 }
900 } 873 }
901 *in_len -= ilen; 874 *in_len -= ilen;
902 *out_len -= olen; 875 *out_len -= olen;
903#endif
904 return RESAMPLER_ERR_SUCCESS; 876 return RESAMPLER_ERR_SUCCESS;
905} 877}
906int 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) 878
907{ 879#ifdef FIXED_POINT
908 return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); 880EXPORT 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)
909}
910#else 881#else
911int 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) 882EXPORT 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)
912{ 883#endif
913 return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
914}
915int 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)
916{ 884{
917 spx_uint32_t i; 885 int j;
918 int istride_save, ostride_save; 886 const int istride_save = st->in_stride;
887 const int ostride_save = st->out_stride;
888 spx_uint32_t ilen = *in_len;
889 spx_uint32_t olen = *out_len;
890 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
891 const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
919#ifdef VAR_ARRAYS 892#ifdef VAR_ARRAYS
920 spx_word16_t x[*in_len]; 893 const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
921 spx_word16_t y[*out_len]; 894 VARDECL(spx_word16_t *ystack);
922 /*VARDECL(spx_word16_t *x); 895 ALLOC(ystack, ylen, spx_word16_t);
923 VARDECL(spx_word16_t *y);
924 ALLOC(x, *in_len, spx_word16_t);
925 ALLOC(y, *out_len, spx_word16_t);*/
926 istride_save = st->in_stride;
927 ostride_save = st->out_stride;
928 for (i=0;i<*in_len;i++)
929 x[i] = in[i*st->in_stride];
930 st->in_stride = st->out_stride = 1;
931 speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
932 st->in_stride = istride_save;
933 st->out_stride = ostride_save;
934 for (i=0;i<*out_len;i++)
935 out[i*st->out_stride] = WORD2INT(y[i]);
936#else 896#else
937 spx_word16_t x[FIXED_STACK_ALLOC]; 897 const unsigned int ylen = FIXED_STACK_ALLOC;
938 spx_word16_t y[FIXED_STACK_ALLOC]; 898 spx_word16_t ystack[FIXED_STACK_ALLOC];
939 spx_uint32_t ilen=*in_len, olen=*out_len; 899#endif
940 istride_save = st->in_stride; 900
941 ostride_save = st->out_stride; 901 st->out_stride = 1;
942 while (ilen && olen) 902
943 { 903 while (ilen && olen) {
944 spx_uint32_t ichunk, ochunk; 904 spx_word16_t *y = ystack;
945 ichunk = ilen; 905 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
946 ochunk = olen; 906 spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
947 if (ichunk>FIXED_STACK_ALLOC) 907 spx_uint32_t omagic = 0;
948 ichunk=FIXED_STACK_ALLOC; 908
949 if (ochunk>FIXED_STACK_ALLOC) 909 if (st->magic_samples[channel_index]) {
950 ochunk=FIXED_STACK_ALLOC; 910 omagic = speex_resampler_magic(st, channel_index, &y, ochunk);
951 for (i=0;i<ichunk;i++) 911 ochunk -= omagic;
952 x[i] = in[i*st->in_stride]; 912 olen -= omagic;
953 st->in_stride = st->out_stride = 1; 913 }
954 speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); 914 if (! st->magic_samples[channel_index]) {
955 st->in_stride = istride_save; 915 if (in) {
956 st->out_stride = ostride_save; 916 for(j=0;j<ichunk;++j)
957 for (i=0;i<ochunk;i++) 917#ifdef FIXED_POINT
958 out[i*st->out_stride] = WORD2INT(y[i]); 918 x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]);
959 out += ochunk; 919#else
960 in += ichunk; 920 x[j+st->filt_len-1]=in[j*istride_save];
961 ilen -= ichunk; 921#endif
962 olen -= ochunk; 922 } else {
923 for(j=0;j<ichunk;++j)
924 x[j+st->filt_len-1]=0;
925 }
926
927 speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk);
928 } else {
929 ichunk = 0;
930 ochunk = 0;
931 }
932
933 for (j=0;j<ochunk+omagic;++j)
934#ifdef FIXED_POINT
935 out[j*ostride_save] = ystack[j];
936#else
937 out[j*ostride_save] = WORD2INT(ystack[j]);
938#endif
939
940 ilen -= ichunk;
941 olen -= ochunk;
942 out += (ochunk+omagic) * ostride_save;
943 if (in)
944 in += ichunk * istride_save;
963 } 945 }
946 st->out_stride = ostride_save;
964 *in_len -= ilen; 947 *in_len -= ilen;
965 *out_len -= olen; 948 *out_len -= olen;
966#endif 949
967 return RESAMPLER_ERR_SUCCESS; 950 return RESAMPLER_ERR_SUCCESS;
968} 951}
969#endif
970 952
971int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 953EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
972{ 954{
973 spx_uint32_t i; 955 spx_uint32_t i;
974 int istride_save, ostride_save; 956 int istride_save, ostride_save;
@@ -989,8 +971,7 @@ int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const flo
989 return RESAMPLER_ERR_SUCCESS; 971 return RESAMPLER_ERR_SUCCESS;
990} 972}
991 973
992 974EXPORT 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)
993int 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)
994{ 975{
995 spx_uint32_t i; 976 spx_uint32_t i;
996 int istride_save, ostride_save; 977 int istride_save, ostride_save;
@@ -1011,25 +992,25 @@ int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_i
1011 return RESAMPLER_ERR_SUCCESS; 992 return RESAMPLER_ERR_SUCCESS;
1012} 993}
1013 994
1014int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) 995EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
1015{ 996{
1016 return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); 997 return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
1017} 998}
1018 999
1019void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) 1000EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
1020{ 1001{
1021 *in_rate = st->in_rate; 1002 *in_rate = st->in_rate;
1022 *out_rate = st->out_rate; 1003 *out_rate = st->out_rate;
1023} 1004}
1024 1005
1025int 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) 1006EXPORT 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)
1026{ 1007{
1027 spx_uint32_t fact; 1008 spx_uint32_t fact;
1028 spx_uint32_t old_den; 1009 spx_uint32_t old_den;
1029 spx_uint32_t i; 1010 spx_uint32_t i;
1030 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) 1011 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
1031 return RESAMPLER_ERR_SUCCESS; 1012 return RESAMPLER_ERR_SUCCESS;
1032 1013
1033 old_den = st->den_rate; 1014 old_den = st->den_rate;
1034 st->in_rate = in_rate; 1015 st->in_rate = in_rate;
1035 st->out_rate = out_rate; 1016 st->out_rate = out_rate;
@@ -1044,7 +1025,7 @@ int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_nu
1044 st->den_rate /= fact; 1025 st->den_rate /= fact;
1045 } 1026 }
1046 } 1027 }
1047 1028
1048 if (old_den > 0) 1029 if (old_den > 0)
1049 { 1030 {
1050 for (i=0;i<st->nb_channels;i++) 1031 for (i=0;i<st->nb_channels;i++)
@@ -1055,19 +1036,19 @@ int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_nu
1055 st->samp_frac_num[i] = st->den_rate-1; 1036 st->samp_frac_num[i] = st->den_rate-1;
1056 } 1037 }
1057 } 1038 }
1058 1039
1059 if (st->initialised) 1040 if (st->initialised)
1060 update_filter(st); 1041 update_filter(st);
1061 return RESAMPLER_ERR_SUCCESS; 1042 return RESAMPLER_ERR_SUCCESS;
1062} 1043}
1063 1044
1064void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) 1045EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
1065{ 1046{
1066 *ratio_num = st->num_rate; 1047 *ratio_num = st->num_rate;
1067 *ratio_den = st->den_rate; 1048 *ratio_den = st->den_rate;
1068} 1049}
1069 1050
1070int speex_resampler_set_quality(SpeexResamplerState *st, int quality) 1051EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
1071{ 1052{
1072 if (quality > 10 || quality < 0) 1053 if (quality > 10 || quality < 0)
1073 return RESAMPLER_ERR_INVALID_ARG; 1054 return RESAMPLER_ERR_INVALID_ARG;
@@ -1079,32 +1060,42 @@ int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
1079 return RESAMPLER_ERR_SUCCESS; 1060 return RESAMPLER_ERR_SUCCESS;
1080} 1061}
1081 1062
1082void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) 1063EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
1083{ 1064{
1084 *quality = st->quality; 1065 *quality = st->quality;
1085} 1066}
1086 1067
1087void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) 1068EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
1088{ 1069{
1089 st->in_stride = stride; 1070 st->in_stride = stride;
1090} 1071}
1091 1072
1092void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1073EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1093{ 1074{
1094 *stride = st->in_stride; 1075 *stride = st->in_stride;
1095} 1076}
1096 1077
1097void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) 1078EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
1098{ 1079{
1099 st->out_stride = stride; 1080 st->out_stride = stride;
1100} 1081}
1101 1082
1102void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1083EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1103{ 1084{
1104 *stride = st->out_stride; 1085 *stride = st->out_stride;
1105} 1086}
1106 1087
1107int speex_resampler_skip_zeros(SpeexResamplerState *st) 1088EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st)
1089{
1090 return st->filt_len / 2;
1091}
1092
1093EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st)
1094{
1095 return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;
1096}
1097
1098EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st)
1108{ 1099{
1109 spx_uint32_t i; 1100 spx_uint32_t i;
1110 for (i=0;i<st->nb_channels;i++) 1101 for (i=0;i<st->nb_channels;i++)
@@ -1112,7 +1103,7 @@ int speex_resampler_skip_zeros(SpeexResamplerState *st)
1112 return RESAMPLER_ERR_SUCCESS; 1103 return RESAMPLER_ERR_SUCCESS;
1113} 1104}
1114 1105
1115int speex_resampler_reset_mem(SpeexResamplerState *st) 1106EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)
1116{ 1107{
1117 spx_uint32_t i; 1108 spx_uint32_t i;
1118 for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 1109 for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
@@ -1120,7 +1111,7 @@ int speex_resampler_reset_mem(SpeexResamplerState *st)
1120 return RESAMPLER_ERR_SUCCESS; 1111 return RESAMPLER_ERR_SUCCESS;
1121} 1112}
1122 1113
1123const char *speex_resampler_strerror(int err) 1114EXPORT const char *speex_resampler_strerror(int err)
1124{ 1115{
1125 switch (err) 1116 switch (err)
1126 { 1117 {