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