~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/third_party/speex/libspeex/resample.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

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