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 } 1132