1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libspeex_resampler/src/resample.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1233 @@ 1.4 +/* Copyright (C) 2007-2008 Jean-Marc Valin 1.5 + Copyright (C) 2008 Thorvald Natvig 1.6 + 1.7 + File: resample.c 1.8 + Arbitrary resampling code 1.9 + 1.10 + Redistribution and use in source and binary forms, with or without 1.11 + modification, are permitted provided that the following conditions are 1.12 + met: 1.13 + 1.14 + 1. Redistributions of source code must retain the above copyright notice, 1.15 + this list of conditions and the following disclaimer. 1.16 + 1.17 + 2. Redistributions in binary form must reproduce the above copyright 1.18 + notice, this list of conditions and the following disclaimer in the 1.19 + documentation and/or other materials provided with the distribution. 1.20 + 1.21 + 3. The name of the author may not be used to endorse or promote products 1.22 + derived from this software without specific prior written permission. 1.23 + 1.24 + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.25 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.26 + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1.27 + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 1.28 + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1.29 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 1.30 + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1.31 + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 1.32 + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 1.33 + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.34 + POSSIBILITY OF SUCH DAMAGE. 1.35 +*/ 1.36 + 1.37 +/* 1.38 + The design goals of this code are: 1.39 + - Very fast algorithm 1.40 + - SIMD-friendly algorithm 1.41 + - Low memory requirement 1.42 + - Good *perceptual* quality (and not best SNR) 1.43 + 1.44 + Warning: This resampler is relatively new. Although I think I got rid of 1.45 + all the major bugs and I don't expect the API to change anymore, there 1.46 + may be something I've missed. So use with caution. 1.47 + 1.48 + This algorithm is based on this original resampling algorithm: 1.49 + Smith, Julius O. Digital Audio Resampling Home Page 1.50 + Center for Computer Research in Music and Acoustics (CCRMA), 1.51 + Stanford University, 2007. 1.52 + Web published at http://www-ccrma.stanford.edu/~jos/resample/. 1.53 + 1.54 + There is one main difference, though. This resampler uses cubic 1.55 + interpolation instead of linear interpolation in the above paper. This 1.56 + makes the table much smaller and makes it possible to compute that table 1.57 + on a per-stream basis. In turn, being able to tweak the table for each 1.58 + stream makes it possible to both reduce complexity on simple ratios 1.59 + (e.g. 2/3), and get rid of the rounding operations in the inner loop. 1.60 + The latter both reduces CPU time and makes the algorithm more SIMD-friendly. 1.61 +*/ 1.62 + 1.63 +#ifdef HAVE_CONFIG_H 1.64 +# include "config.h" 1.65 +#endif 1.66 + 1.67 +#define RESAMPLE_HUGEMEM 1 1.68 + 1.69 +#ifdef OUTSIDE_SPEEX 1.70 +#include <stdlib.h> 1.71 +static void *speex_alloc (int size) {return calloc(size,1);} 1.72 +static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} 1.73 +static void speex_free (void *ptr) {free(ptr);} 1.74 +#include "speex_resampler.h" 1.75 +#include "arch.h" 1.76 +#else /* OUTSIDE_SPEEX */ 1.77 + 1.78 +#include "../include/speex/speex_resampler.h" 1.79 +#include "arch.h" 1.80 +#include "os_support.h" 1.81 +#endif /* OUTSIDE_SPEEX */ 1.82 + 1.83 +#include "stack_alloc.h" 1.84 +#include <math.h> 1.85 + 1.86 +#ifndef M_PI 1.87 +#define M_PI 3.14159263 1.88 +#endif 1.89 + 1.90 +#ifdef FIXED_POINT 1.91 +#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 1.92 +#else 1.93 +#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) 1.94 +#endif 1.95 + 1.96 +#define IMAX(a,b) ((a) > (b) ? (a) : (b)) 1.97 +#define IMIN(a,b) ((a) < (b) ? (a) : (b)) 1.98 + 1.99 +#ifndef NULL 1.100 +#define NULL 0 1.101 +#endif 1.102 + 1.103 +#include "sse_detect.h" 1.104 + 1.105 +/* We compile SSE code on x86 all the time, but we only use it if we find at 1.106 + * runtime that the CPU supports it. */ 1.107 +#if defined(FLOATING_POINT) && defined(__SSE__) 1.108 +#if defined(_MSC_VER) 1.109 +#define inline __inline 1.110 +#endif 1.111 +# include "resample_sse.h" 1.112 +#ifdef _MSC_VER 1.113 +#undef inline 1.114 +#endif 1.115 +#endif 1.116 + 1.117 +/* Numer of elements to allocate on the stack */ 1.118 +#ifdef VAR_ARRAYS 1.119 +#define FIXED_STACK_ALLOC 8192 1.120 +#else 1.121 +#define FIXED_STACK_ALLOC 1024 1.122 +#endif 1.123 + 1.124 +typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); 1.125 + 1.126 +struct SpeexResamplerState_ { 1.127 + spx_uint32_t in_rate; 1.128 + spx_uint32_t out_rate; 1.129 + spx_uint32_t num_rate; 1.130 + spx_uint32_t den_rate; 1.131 + 1.132 + int quality; 1.133 + spx_uint32_t nb_channels; 1.134 + spx_uint32_t filt_len; 1.135 + spx_uint32_t mem_alloc_size; 1.136 + spx_uint32_t buffer_size; 1.137 + int int_advance; 1.138 + int frac_advance; 1.139 + float cutoff; 1.140 + spx_uint32_t oversample; 1.141 + int initialised; 1.142 + int started; 1.143 + 1.144 + /* These are per-channel */ 1.145 + spx_int32_t *last_sample; 1.146 + spx_uint32_t *samp_frac_num; 1.147 + spx_uint32_t *magic_samples; 1.148 + 1.149 + spx_word16_t *mem; 1.150 + spx_word16_t *sinc_table; 1.151 + spx_uint32_t sinc_table_length; 1.152 + resampler_basic_func resampler_ptr; 1.153 + 1.154 + int in_stride; 1.155 + int out_stride; 1.156 +} ; 1.157 + 1.158 +static double kaiser12_table[68] = { 1.159 + 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, 1.160 + 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, 1.161 + 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601, 1.162 + 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014, 1.163 + 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490, 1.164 + 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546, 1.165 + 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178, 1.166 + 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947, 1.167 + 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058, 1.168 + 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438, 1.169 + 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734, 1.170 + 0.00001000, 0.00000000}; 1.171 +/* 1.172 +static double kaiser12_table[36] = { 1.173 + 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, 1.174 + 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, 1.175 + 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274, 1.176 + 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466, 1.177 + 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291, 1.178 + 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; 1.179 +*/ 1.180 +static double kaiser10_table[36] = { 1.181 + 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, 1.182 + 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, 1.183 + 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962, 1.184 + 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451, 1.185 + 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739, 1.186 + 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000}; 1.187 + 1.188 +static double kaiser8_table[36] = { 1.189 + 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, 1.190 + 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, 1.191 + 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272, 1.192 + 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, 1.193 + 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, 1.194 + 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; 1.195 + 1.196 +static double kaiser6_table[36] = { 1.197 + 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, 1.198 + 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, 1.199 + 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561, 1.200 + 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058, 1.201 + 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600, 1.202 + 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000}; 1.203 + 1.204 +struct FuncDef { 1.205 + double *table; 1.206 + int oversample; 1.207 +}; 1.208 + 1.209 +static struct FuncDef _KAISER12 = {kaiser12_table, 64}; 1.210 +#define KAISER12 (&_KAISER12) 1.211 +/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; 1.212 +#define KAISER12 (&_KAISER12)*/ 1.213 +static struct FuncDef _KAISER10 = {kaiser10_table, 32}; 1.214 +#define KAISER10 (&_KAISER10) 1.215 +static struct FuncDef _KAISER8 = {kaiser8_table, 32}; 1.216 +#define KAISER8 (&_KAISER8) 1.217 +static struct FuncDef _KAISER6 = {kaiser6_table, 32}; 1.218 +#define KAISER6 (&_KAISER6) 1.219 + 1.220 +struct QualityMapping { 1.221 + int base_length; 1.222 + int oversample; 1.223 + float downsample_bandwidth; 1.224 + float upsample_bandwidth; 1.225 + struct FuncDef *window_func; 1.226 +}; 1.227 + 1.228 + 1.229 +/* This table maps conversion quality to internal parameters. There are two 1.230 + reasons that explain why the up-sampling bandwidth is larger than the 1.231 + down-sampling bandwidth: 1.232 + 1) When up-sampling, we can assume that the spectrum is already attenuated 1.233 + close to the Nyquist rate (from an A/D or a previous resampling filter) 1.234 + 2) Any aliasing that occurs very close to the Nyquist rate will be masked 1.235 + by the sinusoids/noise just below the Nyquist rate (guaranteed only for 1.236 + up-sampling). 1.237 +*/ 1.238 +static const struct QualityMapping quality_map[11] = { 1.239 + { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */ 1.240 + { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */ 1.241 + { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ 1.242 + { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ 1.243 + { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ 1.244 + { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ 1.245 + { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ 1.246 + {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ 1.247 + {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ 1.248 + {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ 1.249 + {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ 1.250 +}; 1.251 +/*8,24,40,56,80,104,128,160,200,256,320*/ 1.252 +static double compute_func(float x, struct FuncDef *func) 1.253 +{ 1.254 + float y, frac; 1.255 + double interp[4]; 1.256 + int ind; 1.257 + y = x*func->oversample; 1.258 + ind = (int)floor(y); 1.259 + frac = (y-ind); 1.260 + /* CSE with handle the repeated powers */ 1.261 + interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac); 1.262 + interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac); 1.263 + /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ 1.264 + interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); 1.265 + /* Just to make sure we don't have rounding problems */ 1.266 + interp[1] = 1.f-interp[3]-interp[2]-interp[0]; 1.267 + 1.268 + /*sum = frac*accum[1] + (1-frac)*accum[2];*/ 1.269 + return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; 1.270 +} 1.271 + 1.272 +#if 0 1.273 +#include <stdio.h> 1.274 +int main(int argc, char **argv) 1.275 +{ 1.276 + int i; 1.277 + for (i=0;i<256;i++) 1.278 + { 1.279 + printf ("%f\n", compute_func(i/256., KAISER12)); 1.280 + } 1.281 + return 0; 1.282 +} 1.283 +#endif 1.284 + 1.285 +#ifdef FIXED_POINT 1.286 +/* The slow way of computing a sinc for the table. Should improve that some day */ 1.287 +static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) 1.288 +{ 1.289 + /*fprintf (stderr, "%f ", x);*/ 1.290 + float xx = x * cutoff; 1.291 + if (fabs(x)<1e-6f) 1.292 + return WORD2INT(32768.*cutoff); 1.293 + else if (fabs(x) > .5f*N) 1.294 + return 0; 1.295 + /*FIXME: Can it really be any slower than this? */ 1.296 + return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func)); 1.297 +} 1.298 +#else 1.299 +/* The slow way of computing a sinc for the table. Should improve that some day */ 1.300 +static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) 1.301 +{ 1.302 + /*fprintf (stderr, "%f ", x);*/ 1.303 + float xx = x * cutoff; 1.304 + if (fabs(x)<1e-6) 1.305 + return cutoff; 1.306 + else if (fabs(x) > .5*N) 1.307 + return 0; 1.308 + /*FIXME: Can it really be any slower than this? */ 1.309 + return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func); 1.310 +} 1.311 +#endif 1.312 + 1.313 +#ifdef FIXED_POINT 1.314 +static void cubic_coef(spx_word16_t x, spx_word16_t interp[4]) 1.315 +{ 1.316 + /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation 1.317 + but I know it's MMSE-optimal on a sinc */ 1.318 + spx_word16_t x2, x3; 1.319 + x2 = MULT16_16_P15(x, x); 1.320 + x3 = MULT16_16_P15(x, x2); 1.321 + interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15); 1.322 + interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1)); 1.323 + interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15); 1.324 + /* Just to make sure we don't have rounding problems */ 1.325 + interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3]; 1.326 + if (interp[2]<32767) 1.327 + interp[2]+=1; 1.328 +} 1.329 +#else 1.330 +static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4]) 1.331 +{ 1.332 + /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation 1.333 + but I know it's MMSE-optimal on a sinc */ 1.334 + interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac; 1.335 + interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac; 1.336 + /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ 1.337 + interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac; 1.338 + /* Just to make sure we don't have rounding problems */ 1.339 + interp[2] = 1.-interp[0]-interp[1]-interp[3]; 1.340 +} 1.341 +#endif 1.342 + 1.343 +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) 1.344 +{ 1.345 + const int N = st->filt_len; 1.346 + int out_sample = 0; 1.347 + int last_sample = st->last_sample[channel_index]; 1.348 + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 1.349 + const spx_word16_t *sinc_table = st->sinc_table; 1.350 + const int out_stride = st->out_stride; 1.351 + const int int_advance = st->int_advance; 1.352 + const int frac_advance = st->frac_advance; 1.353 + const spx_uint32_t den_rate = st->den_rate; 1.354 + spx_word32_t sum; 1.355 + 1.356 + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 1.357 + { 1.358 + const spx_word16_t *sinct = & sinc_table[samp_frac_num*N]; 1.359 + const spx_word16_t *iptr = & in[last_sample]; 1.360 + 1.361 +#ifdef OVERRIDE_INNER_PRODUCT_SINGLE 1.362 + if (moz_has_sse()) { 1.363 + sum = inner_product_single(sinct, iptr, N); 1.364 + } else { 1.365 +#endif 1.366 + int j; 1.367 + sum = 0; 1.368 + for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]); 1.369 + 1.370 +/* This code is slower on most DSPs which have only 2 accumulators. 1.371 + Plus this this forces truncation to 32 bits and you lose the HW guard bits. 1.372 + I think we can trust the compiler and let it vectorize and/or unroll itself. 1.373 + spx_word32_t accum[4] = {0,0,0,0}; 1.374 + for(j=0;j<N;j+=4) { 1.375 + accum[0] += MULT16_16(sinct[j], iptr[j]); 1.376 + accum[1] += MULT16_16(sinct[j+1], iptr[j+1]); 1.377 + accum[2] += MULT16_16(sinct[j+2], iptr[j+2]); 1.378 + accum[3] += MULT16_16(sinct[j+3], iptr[j+3]); 1.379 + } 1.380 + sum = accum[0] + accum[1] + accum[2] + accum[3]; 1.381 +*/ 1.382 +#ifdef OVERRIDE_INNER_PRODUCT_SINGLE 1.383 + } 1.384 +#endif 1.385 + 1.386 + out[out_stride * out_sample++] = SATURATE32(PSHR32(sum, 15), 32767); 1.387 + last_sample += int_advance; 1.388 + samp_frac_num += frac_advance; 1.389 + if (samp_frac_num >= den_rate) 1.390 + { 1.391 + samp_frac_num -= den_rate; 1.392 + last_sample++; 1.393 + } 1.394 + } 1.395 + 1.396 + st->last_sample[channel_index] = last_sample; 1.397 + st->samp_frac_num[channel_index] = samp_frac_num; 1.398 + return out_sample; 1.399 +} 1.400 + 1.401 +#ifdef FIXED_POINT 1.402 +#else 1.403 +/* This is the same as the previous function, except with a double-precision accumulator */ 1.404 +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) 1.405 +{ 1.406 + const int N = st->filt_len; 1.407 + int out_sample = 0; 1.408 + int last_sample = st->last_sample[channel_index]; 1.409 + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 1.410 + const spx_word16_t *sinc_table = st->sinc_table; 1.411 + const int out_stride = st->out_stride; 1.412 + const int int_advance = st->int_advance; 1.413 + const int frac_advance = st->frac_advance; 1.414 + const spx_uint32_t den_rate = st->den_rate; 1.415 + double sum; 1.416 + 1.417 + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 1.418 + { 1.419 + const spx_word16_t *sinct = & sinc_table[samp_frac_num*N]; 1.420 + const spx_word16_t *iptr = & in[last_sample]; 1.421 + 1.422 +#ifdef OVERRIDE_INNER_PRODUCT_DOUBLE 1.423 + if(moz_has_sse2()) { 1.424 + sum = inner_product_double(sinct, iptr, N); 1.425 + } else { 1.426 +#endif 1.427 + int j; 1.428 + double accum[4] = {0,0,0,0}; 1.429 + 1.430 + for(j=0;j<N;j+=4) { 1.431 + accum[0] += sinct[j]*iptr[j]; 1.432 + accum[1] += sinct[j+1]*iptr[j+1]; 1.433 + accum[2] += sinct[j+2]*iptr[j+2]; 1.434 + accum[3] += sinct[j+3]*iptr[j+3]; 1.435 + } 1.436 + sum = accum[0] + accum[1] + accum[2] + accum[3]; 1.437 +#ifdef OVERRIDE_INNER_PRODUCT_DOUBLE 1.438 + } 1.439 +#endif 1.440 + 1.441 + out[out_stride * out_sample++] = PSHR32(sum, 15); 1.442 + last_sample += int_advance; 1.443 + samp_frac_num += frac_advance; 1.444 + if (samp_frac_num >= den_rate) 1.445 + { 1.446 + samp_frac_num -= den_rate; 1.447 + last_sample++; 1.448 + } 1.449 + } 1.450 + 1.451 + st->last_sample[channel_index] = last_sample; 1.452 + st->samp_frac_num[channel_index] = samp_frac_num; 1.453 + return out_sample; 1.454 +} 1.455 +#endif 1.456 + 1.457 +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) 1.458 +{ 1.459 + const int N = st->filt_len; 1.460 + int out_sample = 0; 1.461 + int last_sample = st->last_sample[channel_index]; 1.462 + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 1.463 + const int out_stride = st->out_stride; 1.464 + const int int_advance = st->int_advance; 1.465 + const int frac_advance = st->frac_advance; 1.466 + const spx_uint32_t den_rate = st->den_rate; 1.467 + spx_word32_t sum; 1.468 + 1.469 + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 1.470 + { 1.471 + const spx_word16_t *iptr = & in[last_sample]; 1.472 + 1.473 + const int offset = samp_frac_num*st->oversample/st->den_rate; 1.474 +#ifdef FIXED_POINT 1.475 + const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 1.476 +#else 1.477 + const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 1.478 +#endif 1.479 + spx_word16_t interp[4]; 1.480 + 1.481 + 1.482 +#ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE 1.483 + if (moz_has_sse()) { 1.484 + cubic_coef(frac, interp); 1.485 + sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 1.486 + } else { 1.487 +#endif 1.488 + int j; 1.489 + spx_word32_t accum[4] = {0,0,0,0}; 1.490 + 1.491 + for(j=0;j<N;j++) { 1.492 + const spx_word16_t curr_in=iptr[j]; 1.493 + accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 1.494 + accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 1.495 + accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); 1.496 + accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 1.497 + } 1.498 + cubic_coef(frac, interp); 1.499 + sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1)); 1.500 +#ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE 1.501 + } 1.502 +#endif 1.503 + 1.504 + out[out_stride * out_sample++] = SATURATE32(PSHR32(sum, 14), 32767); 1.505 + last_sample += int_advance; 1.506 + samp_frac_num += frac_advance; 1.507 + if (samp_frac_num >= den_rate) 1.508 + { 1.509 + samp_frac_num -= den_rate; 1.510 + last_sample++; 1.511 + } 1.512 + } 1.513 + 1.514 + st->last_sample[channel_index] = last_sample; 1.515 + st->samp_frac_num[channel_index] = samp_frac_num; 1.516 + return out_sample; 1.517 +} 1.518 + 1.519 +#ifdef FIXED_POINT 1.520 +#else 1.521 +/* This is the same as the previous function, except with a double-precision accumulator */ 1.522 +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) 1.523 +{ 1.524 + const int N = st->filt_len; 1.525 + int out_sample = 0; 1.526 + int last_sample = st->last_sample[channel_index]; 1.527 + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 1.528 + const int out_stride = st->out_stride; 1.529 + const int int_advance = st->int_advance; 1.530 + const int frac_advance = st->frac_advance; 1.531 + const spx_uint32_t den_rate = st->den_rate; 1.532 + spx_word32_t sum; 1.533 + 1.534 + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 1.535 + { 1.536 + const spx_word16_t *iptr = & in[last_sample]; 1.537 + 1.538 + const int offset = samp_frac_num*st->oversample/st->den_rate; 1.539 +#ifdef FIXED_POINT 1.540 + const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 1.541 +#else 1.542 + const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 1.543 +#endif 1.544 + spx_word16_t interp[4]; 1.545 + 1.546 + 1.547 +#ifdef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE 1.548 + if (moz_has_sse2()) { 1.549 + cubic_coef(frac, interp); 1.550 + sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 1.551 + } else { 1.552 +#endif 1.553 + int j; 1.554 + double accum[4] = {0,0,0,0}; 1.555 + 1.556 + for(j=0;j<N;j++) { 1.557 + const double curr_in=iptr[j]; 1.558 + accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 1.559 + accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 1.560 + accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); 1.561 + accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 1.562 + } 1.563 + 1.564 + cubic_coef(frac, interp); 1.565 + 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]); 1.566 +#ifdef OVERRIDE_INNER_PRODUCT_DOUBLE 1.567 + } 1.568 +#endif 1.569 + out[out_stride * out_sample++] = PSHR32(sum,15); 1.570 + last_sample += int_advance; 1.571 + samp_frac_num += frac_advance; 1.572 + if (samp_frac_num >= den_rate) 1.573 + { 1.574 + samp_frac_num -= den_rate; 1.575 + last_sample++; 1.576 + } 1.577 + } 1.578 + 1.579 + st->last_sample[channel_index] = last_sample; 1.580 + st->samp_frac_num[channel_index] = samp_frac_num; 1.581 + return out_sample; 1.582 +} 1.583 +#endif 1.584 + 1.585 +/* This resampler is used to produce zero output in situations where memory 1.586 + for the filter could not be allocated. The expected numbers of input and 1.587 + output samples are still processed so that callers failing to check error 1.588 + codes are not surprised, possibly getting into infinite loops. */ 1.589 +static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 1.590 +{ 1.591 + int out_sample = 0; 1.592 + int last_sample = st->last_sample[channel_index]; 1.593 + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 1.594 + const int out_stride = st->out_stride; 1.595 + const int int_advance = st->int_advance; 1.596 + const int frac_advance = st->frac_advance; 1.597 + const spx_uint32_t den_rate = st->den_rate; 1.598 + 1.599 + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 1.600 + { 1.601 + out[out_stride * out_sample++] = 0; 1.602 + last_sample += int_advance; 1.603 + samp_frac_num += frac_advance; 1.604 + if (samp_frac_num >= den_rate) 1.605 + { 1.606 + samp_frac_num -= den_rate; 1.607 + last_sample++; 1.608 + } 1.609 + } 1.610 + 1.611 + st->last_sample[channel_index] = last_sample; 1.612 + st->samp_frac_num[channel_index] = samp_frac_num; 1.613 + return out_sample; 1.614 +} 1.615 + 1.616 +static int update_filter(SpeexResamplerState *st) 1.617 +{ 1.618 + spx_uint32_t old_length = st->filt_len; 1.619 + spx_uint32_t old_alloc_size = st->mem_alloc_size; 1.620 + int use_direct; 1.621 + spx_uint32_t min_sinc_table_length; 1.622 + spx_uint32_t min_alloc_size; 1.623 + 1.624 + st->int_advance = st->num_rate/st->den_rate; 1.625 + st->frac_advance = st->num_rate%st->den_rate; 1.626 + st->oversample = quality_map[st->quality].oversample; 1.627 + st->filt_len = quality_map[st->quality].base_length; 1.628 + 1.629 + if (st->num_rate > st->den_rate) 1.630 + { 1.631 + /* down-sampling */ 1.632 + st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; 1.633 + /* FIXME: divide the numerator and denominator by a certain amount if they're too large */ 1.634 + st->filt_len = st->filt_len*st->num_rate / st->den_rate; 1.635 + /* Round up to make sure we have a multiple of 8 */ 1.636 + st->filt_len = ((st->filt_len-1)&(~0x7))+8; 1.637 + if (2*st->den_rate < st->num_rate) 1.638 + st->oversample >>= 1; 1.639 + if (4*st->den_rate < st->num_rate) 1.640 + st->oversample >>= 1; 1.641 + if (8*st->den_rate < st->num_rate) 1.642 + st->oversample >>= 1; 1.643 + if (16*st->den_rate < st->num_rate) 1.644 + st->oversample >>= 1; 1.645 + if (st->oversample < 1) 1.646 + st->oversample = 1; 1.647 + } else { 1.648 + /* up-sampling */ 1.649 + st->cutoff = quality_map[st->quality].upsample_bandwidth; 1.650 + } 1.651 + 1.652 +#ifdef RESAMPLE_HUGEMEM 1.653 + use_direct = st->den_rate <= 16*(st->oversample+8); 1.654 +#else 1.655 + /* Choose the resampling type that requires the least amount of memory */ 1.656 + use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8; 1.657 +#endif 1.658 + if (use_direct) 1.659 + { 1.660 + min_sinc_table_length = st->filt_len*st->den_rate; 1.661 + } else { 1.662 + min_sinc_table_length = st->filt_len*st->oversample+8; 1.663 + } 1.664 + if (st->sinc_table_length < min_sinc_table_length) 1.665 + { 1.666 + spx_word16_t *sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,min_sinc_table_length*sizeof(spx_word16_t)); 1.667 + if (!sinc_table) 1.668 + goto fail; 1.669 + 1.670 + st->sinc_table = sinc_table; 1.671 + st->sinc_table_length = min_sinc_table_length; 1.672 + } 1.673 + if (use_direct) 1.674 + { 1.675 + spx_uint32_t i; 1.676 + for (i=0;i<st->den_rate;i++) 1.677 + { 1.678 + spx_int32_t j; 1.679 + for (j=0;j<st->filt_len;j++) 1.680 + { 1.681 + 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); 1.682 + } 1.683 + } 1.684 +#ifdef FIXED_POINT 1.685 + st->resampler_ptr = resampler_basic_direct_single; 1.686 +#else 1.687 + if (st->quality>8) 1.688 + st->resampler_ptr = resampler_basic_direct_double; 1.689 + else 1.690 + st->resampler_ptr = resampler_basic_direct_single; 1.691 +#endif 1.692 + /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ 1.693 + } else { 1.694 + spx_int32_t i; 1.695 + for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) 1.696 + 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); 1.697 +#ifdef FIXED_POINT 1.698 + st->resampler_ptr = resampler_basic_interpolate_single; 1.699 +#else 1.700 + if (st->quality>8) 1.701 + st->resampler_ptr = resampler_basic_interpolate_double; 1.702 + else 1.703 + st->resampler_ptr = resampler_basic_interpolate_single; 1.704 +#endif 1.705 + /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ 1.706 + } 1.707 + 1.708 + 1.709 + /* Here's the place where we update the filter memory to take into account 1.710 + the change in filter length. It's probably the messiest part of the code 1.711 + due to handling of lots of corner cases. */ 1.712 + min_alloc_size = st->filt_len-1 + st->buffer_size; 1.713 + if (min_alloc_size > st->mem_alloc_size) 1.714 + { 1.715 + spx_word16_t *mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*min_alloc_size * sizeof(spx_word16_t)); 1.716 + if (!mem) 1.717 + goto fail; 1.718 + 1.719 + st->mem = mem; 1.720 + st->mem_alloc_size = min_alloc_size; 1.721 + } 1.722 + if (!st->started) 1.723 + { 1.724 + spx_uint32_t i; 1.725 + for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) 1.726 + st->mem[i] = 0; 1.727 + /*speex_warning("reinit filter");*/ 1.728 + } else if (st->filt_len > old_length) 1.729 + { 1.730 + spx_uint32_t i; 1.731 + /* Increase the filter length */ 1.732 + /*speex_warning("increase filter size");*/ 1.733 + for (i=st->nb_channels;i--;) 1.734 + { 1.735 + spx_uint32_t j; 1.736 + spx_uint32_t olen = old_length; 1.737 + /*if (st->magic_samples[i])*/ 1.738 + { 1.739 + /* Try and remove the magic samples as if nothing had happened */ 1.740 + 1.741 + /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ 1.742 + olen = old_length + 2*st->magic_samples[i]; 1.743 + for (j=old_length-1+st->magic_samples[i];j--;) 1.744 + st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; 1.745 + for (j=0;j<st->magic_samples[i];j++) 1.746 + st->mem[i*st->mem_alloc_size+j] = 0; 1.747 + st->magic_samples[i] = 0; 1.748 + } 1.749 + if (st->filt_len > olen) 1.750 + { 1.751 + /* If the new filter length is still bigger than the "augmented" length */ 1.752 + /* Copy data going backward */ 1.753 + for (j=0;j<olen-1;j++) 1.754 + st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)]; 1.755 + /* Then put zeros for lack of anything better */ 1.756 + for (;j<st->filt_len-1;j++) 1.757 + st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; 1.758 + /* Adjust last_sample */ 1.759 + st->last_sample[i] += (st->filt_len - olen)/2; 1.760 + } else { 1.761 + /* Put back some of the magic! */ 1.762 + st->magic_samples[i] = (olen - st->filt_len)/2; 1.763 + for (j=0;j<st->filt_len-1+st->magic_samples[i];j++) 1.764 + st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; 1.765 + } 1.766 + } 1.767 + } else if (st->filt_len < old_length) 1.768 + { 1.769 + spx_uint32_t i; 1.770 + /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" 1.771 + samples so they can be used directly as input the next time(s) */ 1.772 + for (i=0;i<st->nb_channels;i++) 1.773 + { 1.774 + spx_uint32_t j; 1.775 + spx_uint32_t old_magic = st->magic_samples[i]; 1.776 + st->magic_samples[i] = (old_length - st->filt_len)/2; 1.777 + /* We must copy some of the memory that's no longer used */ 1.778 + /* Copy data going backward */ 1.779 + for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++) 1.780 + st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; 1.781 + st->magic_samples[i] += old_magic; 1.782 + } 1.783 + } 1.784 + return RESAMPLER_ERR_SUCCESS; 1.785 + 1.786 +fail: 1.787 + st->resampler_ptr = resampler_basic_zero; 1.788 + /* st->mem may still contain consumed input samples for the filter. 1.789 + Restore filt_len so that filt_len - 1 still points to the position after 1.790 + the last of these samples. */ 1.791 + st->filt_len = old_length; 1.792 + return RESAMPLER_ERR_ALLOC_FAILED; 1.793 +} 1.794 + 1.795 +SPX_RESAMPLE_EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 1.796 +{ 1.797 + return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); 1.798 +} 1.799 + 1.800 +SPX_RESAMPLE_EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 1.801 +{ 1.802 + spx_uint32_t i; 1.803 + SpeexResamplerState *st; 1.804 + int filter_err; 1.805 + 1.806 + if (quality > 10 || quality < 0) 1.807 + { 1.808 + if (err) 1.809 + *err = RESAMPLER_ERR_INVALID_ARG; 1.810 + return NULL; 1.811 + } 1.812 + st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); 1.813 + st->initialised = 0; 1.814 + st->started = 0; 1.815 + st->in_rate = 0; 1.816 + st->out_rate = 0; 1.817 + st->num_rate = 0; 1.818 + st->den_rate = 0; 1.819 + st->quality = -1; 1.820 + st->sinc_table_length = 0; 1.821 + st->mem_alloc_size = 0; 1.822 + st->filt_len = 0; 1.823 + st->mem = 0; 1.824 + st->resampler_ptr = 0; 1.825 + 1.826 + st->cutoff = 1.f; 1.827 + st->nb_channels = nb_channels; 1.828 + st->in_stride = 1; 1.829 + st->out_stride = 1; 1.830 + 1.831 +#ifdef FIXED_POINT 1.832 + st->buffer_size = 160; 1.833 +#else 1.834 + st->buffer_size = 160; 1.835 +#endif 1.836 + 1.837 + /* Per channel data */ 1.838 + st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t)); 1.839 + st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)); 1.840 + st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)); 1.841 + for (i=0;i<nb_channels;i++) 1.842 + { 1.843 + st->last_sample[i] = 0; 1.844 + st->magic_samples[i] = 0; 1.845 + st->samp_frac_num[i] = 0; 1.846 + } 1.847 + 1.848 + speex_resampler_set_quality(st, quality); 1.849 + speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); 1.850 + 1.851 + filter_err = update_filter(st); 1.852 + if (filter_err == RESAMPLER_ERR_SUCCESS) 1.853 + { 1.854 + st->initialised = 1; 1.855 + } else { 1.856 + speex_resampler_destroy(st); 1.857 + st = NULL; 1.858 + } 1.859 + if (err) 1.860 + *err = filter_err; 1.861 + 1.862 + return st; 1.863 +} 1.864 + 1.865 +SPX_RESAMPLE_EXPORT void speex_resampler_destroy(SpeexResamplerState *st) 1.866 +{ 1.867 + speex_free(st->mem); 1.868 + speex_free(st->sinc_table); 1.869 + speex_free(st->last_sample); 1.870 + speex_free(st->magic_samples); 1.871 + speex_free(st->samp_frac_num); 1.872 + speex_free(st); 1.873 +} 1.874 + 1.875 +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) 1.876 +{ 1.877 + int j=0; 1.878 + const int N = st->filt_len; 1.879 + int out_sample = 0; 1.880 + spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 1.881 + spx_uint32_t ilen; 1.882 + 1.883 + st->started = 1; 1.884 + 1.885 + /* Call the right resampler through the function ptr */ 1.886 + out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len); 1.887 + 1.888 + if (st->last_sample[channel_index] < (spx_int32_t)*in_len) 1.889 + *in_len = st->last_sample[channel_index]; 1.890 + *out_len = out_sample; 1.891 + st->last_sample[channel_index] -= *in_len; 1.892 + 1.893 + ilen = *in_len; 1.894 + 1.895 + for(j=0;j<N-1;++j) 1.896 + mem[j] = mem[j+ilen]; 1.897 + 1.898 + return RESAMPLER_ERR_SUCCESS; 1.899 +} 1.900 + 1.901 +static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) { 1.902 + spx_uint32_t tmp_in_len = st->magic_samples[channel_index]; 1.903 + spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 1.904 + const int N = st->filt_len; 1.905 + 1.906 + speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len); 1.907 + 1.908 + st->magic_samples[channel_index] -= tmp_in_len; 1.909 + 1.910 + /* If we couldn't process all "magic" input samples, save the rest for next time */ 1.911 + if (st->magic_samples[channel_index]) 1.912 + { 1.913 + spx_uint32_t i; 1.914 + for (i=0;i<st->magic_samples[channel_index];i++) 1.915 + mem[N-1+i]=mem[N-1+i+tmp_in_len]; 1.916 + } 1.917 + *out += out_len*st->out_stride; 1.918 + return out_len; 1.919 +} 1.920 + 1.921 +#ifdef FIXED_POINT 1.922 +SPX_RESAMPLE_EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) 1.923 +#else 1.924 +SPX_RESAMPLE_EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 1.925 +#endif 1.926 +{ 1.927 + int j; 1.928 + spx_uint32_t ilen = *in_len; 1.929 + spx_uint32_t olen = *out_len; 1.930 + spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; 1.931 + const int filt_offs = st->filt_len - 1; 1.932 + const spx_uint32_t xlen = st->mem_alloc_size - filt_offs; 1.933 + const int istride = st->in_stride; 1.934 + 1.935 + if (st->magic_samples[channel_index]) 1.936 + olen -= speex_resampler_magic(st, channel_index, &out, olen); 1.937 + if (! st->magic_samples[channel_index]) { 1.938 + while (ilen && olen) { 1.939 + spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; 1.940 + spx_uint32_t ochunk = olen; 1.941 + 1.942 + if (in) { 1.943 + for(j=0;j<ichunk;++j) 1.944 + x[j+filt_offs]=in[j*istride]; 1.945 + } else { 1.946 + for(j=0;j<ichunk;++j) 1.947 + x[j+filt_offs]=0; 1.948 + } 1.949 + speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk); 1.950 + ilen -= ichunk; 1.951 + olen -= ochunk; 1.952 + out += ochunk * st->out_stride; 1.953 + if (in) 1.954 + in += ichunk * istride; 1.955 + } 1.956 + } 1.957 + *in_len -= ilen; 1.958 + *out_len -= olen; 1.959 + return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 1.960 +} 1.961 + 1.962 +#ifdef FIXED_POINT 1.963 +SPX_RESAMPLE_EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 1.964 +#else 1.965 +SPX_RESAMPLE_EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) 1.966 +#endif 1.967 +{ 1.968 + int j; 1.969 + const int istride_save = st->in_stride; 1.970 + const int ostride_save = st->out_stride; 1.971 + spx_uint32_t ilen = *in_len; 1.972 + spx_uint32_t olen = *out_len; 1.973 + spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; 1.974 + const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1); 1.975 +#ifdef VAR_ARRAYS 1.976 + const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; 1.977 + VARDECL(spx_word16_t *ystack); 1.978 + ALLOC(ystack, ylen, spx_word16_t); 1.979 +#else 1.980 + const unsigned int ylen = FIXED_STACK_ALLOC; 1.981 + spx_word16_t ystack[FIXED_STACK_ALLOC]; 1.982 +#endif 1.983 + 1.984 + st->out_stride = 1; 1.985 + 1.986 + while (ilen && olen) { 1.987 + spx_word16_t *y = ystack; 1.988 + spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; 1.989 + spx_uint32_t ochunk = (olen > ylen) ? ylen : olen; 1.990 + spx_uint32_t omagic = 0; 1.991 + 1.992 + if (st->magic_samples[channel_index]) { 1.993 + omagic = speex_resampler_magic(st, channel_index, &y, ochunk); 1.994 + ochunk -= omagic; 1.995 + olen -= omagic; 1.996 + } 1.997 + if (! st->magic_samples[channel_index]) { 1.998 + if (in) { 1.999 + for(j=0;j<ichunk;++j) 1.1000 +#ifdef FIXED_POINT 1.1001 + x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]); 1.1002 +#else 1.1003 + x[j+st->filt_len-1]=in[j*istride_save]; 1.1004 +#endif 1.1005 + } else { 1.1006 + for(j=0;j<ichunk;++j) 1.1007 + x[j+st->filt_len-1]=0; 1.1008 + } 1.1009 + 1.1010 + speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk); 1.1011 + } else { 1.1012 + ichunk = 0; 1.1013 + ochunk = 0; 1.1014 + } 1.1015 + 1.1016 + for (j=0;j<ochunk+omagic;++j) 1.1017 +#ifdef FIXED_POINT 1.1018 + out[j*ostride_save] = ystack[j]; 1.1019 +#else 1.1020 + out[j*ostride_save] = WORD2INT(ystack[j]); 1.1021 +#endif 1.1022 + 1.1023 + ilen -= ichunk; 1.1024 + olen -= ochunk; 1.1025 + out += (ochunk+omagic) * ostride_save; 1.1026 + if (in) 1.1027 + in += ichunk * istride_save; 1.1028 + } 1.1029 + st->out_stride = ostride_save; 1.1030 + *in_len -= ilen; 1.1031 + *out_len -= olen; 1.1032 + 1.1033 + return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 1.1034 +} 1.1035 + 1.1036 +SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 1.1037 +{ 1.1038 + spx_uint32_t i; 1.1039 + int istride_save, ostride_save; 1.1040 + spx_uint32_t bak_out_len = *out_len; 1.1041 + spx_uint32_t bak_in_len = *in_len; 1.1042 + istride_save = st->in_stride; 1.1043 + ostride_save = st->out_stride; 1.1044 + st->in_stride = st->out_stride = st->nb_channels; 1.1045 + for (i=0;i<st->nb_channels;i++) 1.1046 + { 1.1047 + *out_len = bak_out_len; 1.1048 + *in_len = bak_in_len; 1.1049 + if (in != NULL) 1.1050 + speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); 1.1051 + else 1.1052 + speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len); 1.1053 + } 1.1054 + st->in_stride = istride_save; 1.1055 + st->out_stride = ostride_save; 1.1056 + return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 1.1057 +} 1.1058 + 1.1059 +SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) 1.1060 +{ 1.1061 + spx_uint32_t i; 1.1062 + int istride_save, ostride_save; 1.1063 + spx_uint32_t bak_out_len = *out_len; 1.1064 + spx_uint32_t bak_in_len = *in_len; 1.1065 + istride_save = st->in_stride; 1.1066 + ostride_save = st->out_stride; 1.1067 + st->in_stride = st->out_stride = st->nb_channels; 1.1068 + for (i=0;i<st->nb_channels;i++) 1.1069 + { 1.1070 + *out_len = bak_out_len; 1.1071 + *in_len = bak_in_len; 1.1072 + if (in != NULL) 1.1073 + speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); 1.1074 + else 1.1075 + speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len); 1.1076 + } 1.1077 + st->in_stride = istride_save; 1.1078 + st->out_stride = ostride_save; 1.1079 + return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 1.1080 +} 1.1081 + 1.1082 +SPX_RESAMPLE_EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) 1.1083 +{ 1.1084 + return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); 1.1085 +} 1.1086 + 1.1087 +SPX_RESAMPLE_EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) 1.1088 +{ 1.1089 + *in_rate = st->in_rate; 1.1090 + *out_rate = st->out_rate; 1.1091 +} 1.1092 + 1.1093 +SPX_RESAMPLE_EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) 1.1094 +{ 1.1095 + spx_uint32_t fact; 1.1096 + spx_uint32_t old_den; 1.1097 + spx_uint32_t i; 1.1098 + if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) 1.1099 + return RESAMPLER_ERR_SUCCESS; 1.1100 + 1.1101 + old_den = st->den_rate; 1.1102 + st->in_rate = in_rate; 1.1103 + st->out_rate = out_rate; 1.1104 + st->num_rate = ratio_num; 1.1105 + st->den_rate = ratio_den; 1.1106 + /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ 1.1107 + for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) 1.1108 + { 1.1109 + while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) 1.1110 + { 1.1111 + st->num_rate /= fact; 1.1112 + st->den_rate /= fact; 1.1113 + } 1.1114 + } 1.1115 + 1.1116 + if (old_den > 0) 1.1117 + { 1.1118 + for (i=0;i<st->nb_channels;i++) 1.1119 + { 1.1120 + st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; 1.1121 + /* Safety net */ 1.1122 + if (st->samp_frac_num[i] >= st->den_rate) 1.1123 + st->samp_frac_num[i] = st->den_rate-1; 1.1124 + } 1.1125 + } 1.1126 + 1.1127 + if (st->initialised) 1.1128 + return update_filter(st); 1.1129 + return RESAMPLER_ERR_SUCCESS; 1.1130 +} 1.1131 + 1.1132 +SPX_RESAMPLE_EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) 1.1133 +{ 1.1134 + *ratio_num = st->num_rate; 1.1135 + *ratio_den = st->den_rate; 1.1136 +} 1.1137 + 1.1138 +SPX_RESAMPLE_EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality) 1.1139 +{ 1.1140 + if (quality > 10 || quality < 0) 1.1141 + return RESAMPLER_ERR_INVALID_ARG; 1.1142 + if (st->quality == quality) 1.1143 + return RESAMPLER_ERR_SUCCESS; 1.1144 + st->quality = quality; 1.1145 + if (st->initialised) 1.1146 + return update_filter(st); 1.1147 + return RESAMPLER_ERR_SUCCESS; 1.1148 +} 1.1149 + 1.1150 +SPX_RESAMPLE_EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) 1.1151 +{ 1.1152 + *quality = st->quality; 1.1153 +} 1.1154 + 1.1155 +SPX_RESAMPLE_EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) 1.1156 +{ 1.1157 + st->in_stride = stride; 1.1158 +} 1.1159 + 1.1160 +SPX_RESAMPLE_EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1.1161 +{ 1.1162 + *stride = st->in_stride; 1.1163 +} 1.1164 + 1.1165 +SPX_RESAMPLE_EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) 1.1166 +{ 1.1167 + st->out_stride = stride; 1.1168 +} 1.1169 + 1.1170 +SPX_RESAMPLE_EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1.1171 +{ 1.1172 + *stride = st->out_stride; 1.1173 +} 1.1174 + 1.1175 +SPX_RESAMPLE_EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st) 1.1176 +{ 1.1177 + return st->filt_len / 2; 1.1178 +} 1.1179 + 1.1180 +SPX_RESAMPLE_EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st) 1.1181 +{ 1.1182 + return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate; 1.1183 +} 1.1184 + 1.1185 +SPX_RESAMPLE_EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st) 1.1186 +{ 1.1187 + spx_uint32_t i; 1.1188 + for (i=0;i<st->nb_channels;i++) 1.1189 + st->last_sample[i] = st->filt_len/2; 1.1190 + return RESAMPLER_ERR_SUCCESS; 1.1191 +} 1.1192 + 1.1193 +SPX_RESAMPLE_EXPORT int speex_resampler_set_skip_frac_num(SpeexResamplerState *st, spx_uint32_t skip_frac_num) 1.1194 +{ 1.1195 + spx_uint32_t i; 1.1196 + spx_uint32_t last_sample = skip_frac_num / st->den_rate; 1.1197 + spx_uint32_t samp_frac_num = skip_frac_num % st->den_rate; 1.1198 + for (i=0;i<st->nb_channels;i++) { 1.1199 + st->last_sample[i] = last_sample; 1.1200 + st->samp_frac_num[i] = samp_frac_num; 1.1201 + } 1.1202 + return RESAMPLER_ERR_SUCCESS; 1.1203 +} 1.1204 + 1.1205 +SPX_RESAMPLE_EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st) 1.1206 +{ 1.1207 + spx_uint32_t i; 1.1208 + for (i=0;i<st->nb_channels;i++) 1.1209 + { 1.1210 + st->last_sample[i] = 0; 1.1211 + st->magic_samples[i] = 0; 1.1212 + st->samp_frac_num[i] = 0; 1.1213 + } 1.1214 + for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 1.1215 + st->mem[i] = 0; 1.1216 + return RESAMPLER_ERR_SUCCESS; 1.1217 +} 1.1218 + 1.1219 +SPX_RESAMPLE_EXPORT const char *speex_resampler_strerror(int err) 1.1220 +{ 1.1221 + switch (err) 1.1222 + { 1.1223 + case RESAMPLER_ERR_SUCCESS: 1.1224 + return "Success."; 1.1225 + case RESAMPLER_ERR_ALLOC_FAILED: 1.1226 + return "Memory allocation failed."; 1.1227 + case RESAMPLER_ERR_BAD_STATE: 1.1228 + return "Bad resampler state."; 1.1229 + case RESAMPLER_ERR_INVALID_ARG: 1.1230 + return "Invalid argument."; 1.1231 + case RESAMPLER_ERR_PTR_OVERLAP: 1.1232 + return "Input and output buffers overlap."; 1.1233 + default: 1.1234 + return "Unknown error. Bad error code or strange version mismatch."; 1.1235 + } 1.1236 +}