resample.c

Go to the documentation of this file.
00001 /* Copyright (C) 2007-2008 Jean-Marc Valin
00002    Copyright (C) 2008      Thorvald Natvig
00003       
00004    File: resample.c
00005    Arbitrary resampling code
00006 
00007    Redistribution and use in source and binary forms, with or without
00008    modification, are permitted provided that the following conditions are
00009    met:
00010 
00011    1. Redistributions of source code must retain the above copyright notice,
00012    this list of conditions and the following disclaimer.
00013 
00014    2. Redistributions in binary form must reproduce the above copyright
00015    notice, this list of conditions and the following disclaimer in the
00016    documentation and/or other materials provided with the distribution.
00017 
00018    3. The name of the author may not be used to endorse or promote products
00019    derived from this software without specific prior written permission.
00020 
00021    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00022    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00023    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00024    DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
00025    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00027    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00029    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031    POSSIBILITY OF SUCH DAMAGE.
00032 */
00033 
00034 /*
00035    The design goals of this code are:
00036       - Very fast algorithm
00037       - SIMD-friendly algorithm
00038       - Low memory requirement
00039       - Good *perceptual* quality (and not best SNR)
00040 
00041    Warning: This resampler is relatively new. Although I think I got rid of 
00042    all the major bugs and I don't expect the API to change anymore, there
00043    may be something I've missed. So use with caution.
00044 
00045    This algorithm is based on this original resampling algorithm:
00046    Smith, Julius O. Digital Audio Resampling Home Page
00047    Center for Computer Research in Music and Acoustics (CCRMA), 
00048    Stanford University, 2007.
00049    Web published at http://www-ccrma.stanford.edu/~jos/resample/.
00050 
00051    There is one main difference, though. This resampler uses cubic 
00052    interpolation instead of linear interpolation in the above paper. This
00053    makes the table much smaller and makes it possible to compute that table
00054    on a per-stream basis. In turn, being able to tweak the table for each 
00055    stream makes it possible to both reduce complexity on simple ratios 
00056    (e.g. 2/3), and get rid of the rounding operations in the inner loop. 
00057    The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
00058 */
00059 
00060 #ifdef HAVE_CONFIG_H
00061 #include "config.h"
00062 #endif
00063 
00064 #include <stdlib.h>
00065 static void *speex_alloc (int size) {return calloc(size,1);}
00066 static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
00067 static void speex_free (void *ptr) {free(ptr);}
00068 #include "speex_resampler.h"
00069 #include "arch.h"
00070 
00071 #include "stack_alloc.h"
00072 #include <math.h>
00073 
00074 #ifndef M_PI
00075 #define M_PI 3.14159263
00076 #endif
00077 
00078 #ifdef FIXED_POINT
00079 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
00080 #else
00081 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
00082 #endif
00083 
00084 #define IMAX(a,b) ((a) > (b) ? (a) : (b))
00085 #define IMIN(a,b) ((a) < (b) ? (a) : (b))
00086 
00087 #ifndef NULL
00088 #define NULL 0
00089 #endif
00090 
00091 #ifdef _USE_SSE
00092 #include "resample_sse.h"
00093 #endif
00094 
00095 /* Numer of elements to allocate on the stack */
00096 #ifdef VAR_ARRAYS
00097 #define FIXED_STACK_ALLOC 8192
00098 #else
00099 #define FIXED_STACK_ALLOC 1024
00100 #endif
00101 
00102 typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
00103 
00104 struct SpeexResamplerState_ {
00105    spx_uint32_t in_rate;
00106    spx_uint32_t out_rate;
00107    spx_uint32_t num_rate;
00108    spx_uint32_t den_rate;
00109    
00110    int    quality;
00111    spx_uint32_t nb_channels;
00112    spx_uint32_t filt_len;
00113    spx_uint32_t mem_alloc_size;
00114    spx_uint32_t buffer_size;
00115    int          int_advance;
00116    int          frac_advance;
00117    float  cutoff;
00118    spx_uint32_t oversample;
00119    int          initialised;
00120    int          started;
00121    
00122    /* These are per-channel */
00123    spx_int32_t  *last_sample;
00124    spx_uint32_t *samp_frac_num;
00125    spx_uint32_t *magic_samples;
00126    
00127    spx_word16_t *mem;
00128    spx_word16_t *sinc_table;
00129    spx_uint32_t sinc_table_length;
00130    resampler_basic_func resampler_ptr;
00131          
00132    int    in_stride;
00133    int    out_stride;
00134 } ;
00135 
00136 static double kaiser12_table[68] = {
00137    0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
00138    0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
00139    0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
00140    0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
00141    0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
00142    0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
00143    0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
00144    0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
00145    0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
00146    0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
00147    0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
00148    0.00001000, 0.00000000};
00149 /*
00150 static double kaiser12_table[36] = {
00151    0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
00152    0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
00153    0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
00154    0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
00155    0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
00156    0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
00157 */
00158 static double kaiser10_table[36] = {
00159    0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
00160    0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
00161    0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
00162    0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
00163    0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
00164    0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
00165 
00166 static double kaiser8_table[36] = {
00167    0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
00168    0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
00169    0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
00170    0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
00171    0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
00172    0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
00173    
00174 static double kaiser6_table[36] = {
00175    0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
00176    0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
00177    0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
00178    0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
00179    0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
00180    0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
00181 
00182 struct FuncDef {
00183    double *table;
00184    int oversample;
00185 };
00186       
00187 static struct FuncDef _KAISER12 = {kaiser12_table, 64};
00188 #define KAISER12 (&_KAISER12)
00189 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
00190 #define KAISER12 (&_KAISER12)*/
00191 static struct FuncDef _KAISER10 = {kaiser10_table, 32};
00192 #define KAISER10 (&_KAISER10)
00193 static struct FuncDef _KAISER8 = {kaiser8_table, 32};
00194 #define KAISER8 (&_KAISER8)
00195 static struct FuncDef _KAISER6 = {kaiser6_table, 32};
00196 #define KAISER6 (&_KAISER6)
00197 
00198 struct QualityMapping {
00199    int base_length;
00200    int oversample;
00201    float downsample_bandwidth;
00202    float upsample_bandwidth;
00203    struct FuncDef *window_func;
00204 };
00205 
00206 
00207 /* This table maps conversion quality to internal parameters. There are two
00208    reasons that explain why the up-sampling bandwidth is larger than the 
00209    down-sampling bandwidth:
00210    1) When up-sampling, we can assume that the spectrum is already attenuated
00211       close to the Nyquist rate (from an A/D or a previous resampling filter)
00212    2) Any aliasing that occurs very close to the Nyquist rate will be masked
00213       by the sinusoids/noise just below the Nyquist rate (guaranteed only for
00214       up-sampling).
00215 */
00216 static const struct QualityMapping quality_map[11] = {
00217    {  8,  4, 0.830f, 0.860f, KAISER6 }, /* Q0 */
00218    { 16,  4, 0.850f, 0.880f, KAISER6 }, /* Q1 */
00219    { 32,  4, 0.882f, 0.910f, KAISER6 }, /* Q2 */  /* 82.3% cutoff ( ~60 dB stop) 6  */
00220    { 48,  8, 0.895f, 0.917f, KAISER8 }, /* Q3 */  /* 84.9% cutoff ( ~80 dB stop) 8  */
00221    { 64,  8, 0.921f, 0.940f, KAISER8 }, /* Q4 */  /* 88.7% cutoff ( ~80 dB stop) 8  */
00222    { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */  /* 89.1% cutoff (~100 dB stop) 10 */
00223    { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */  /* 91.5% cutoff (~100 dB stop) 10 */
00224    {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */  /* 93.1% cutoff (~100 dB stop) 10 */
00225    {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */  /* 94.5% cutoff (~100 dB stop) 10 */
00226    {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */  /* 95.5% cutoff (~100 dB stop) 10 */
00227    {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
00228 };
00229 /*8,24,40,56,80,104,128,160,200,256,320*/
00230 static double compute_func(float x, struct FuncDef *func)
00231 {
00232    float y, frac;
00233    double interp[4];
00234    int ind; 
00235    y = x*func->oversample;
00236    ind = (int)floor(y);
00237    frac = (y-ind);
00238    /* CSE with handle the repeated powers */
00239    interp[3] =  -0.1666666667*frac + 0.1666666667*(frac*frac*frac);
00240    interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac);
00241    /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
00242    interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
00243    /* Just to make sure we don't have rounding problems */
00244    interp[1] = 1.f-interp[3]-interp[2]-interp[0];
00245    
00246    /*sum = frac*accum[1] + (1-frac)*accum[2];*/
00247    return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
00248 }
00249 
00250 #if 0
00251 #include <stdio.h>
00252 int main(int argc, char **argv)
00253 {
00254    int i;
00255    for (i=0;i<256;i++)
00256    {
00257       printf ("%f\n", compute_func(i/256., KAISER12));
00258    }
00259    return 0;
00260 }
00261 #endif
00262 
00263 #ifdef FIXED_POINT
00264 /* The slow way of computing a sinc for the table. Should improve that some day */
00265 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
00266 {
00267    /*fprintf (stderr, "%f ", x);*/
00268    float xx = x * cutoff;
00269    if (fabs(x)<1e-6f)
00270       return WORD2INT(32768.*cutoff);
00271    else if (fabs(x) > .5f*N)
00272       return 0;
00273    /*FIXME: Can it really be any slower than this? */
00274    return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
00275 }
00276 #else
00277 /* The slow way of computing a sinc for the table. Should improve that some day */
00278 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
00279 {
00280    /*fprintf (stderr, "%f ", x);*/
00281    float xx = x * cutoff;
00282    if (fabs(x)<1e-6)
00283       return cutoff;
00284    else if (fabs(x) > .5*N)
00285       return 0;
00286    /*FIXME: Can it really be any slower than this? */
00287    return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func);
00288 }
00289 #endif
00290 
00291 #ifdef FIXED_POINT
00292 static void cubic_coef(spx_word16_t x, spx_word16_t interp[4])
00293 {
00294    /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
00295    but I know it's MMSE-optimal on a sinc */
00296    spx_word16_t x2, x3;
00297    x2 = MULT16_16_P15(x, x);
00298    x3 = MULT16_16_P15(x, x2);
00299    interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
00300    interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
00301    interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15);
00302    /* Just to make sure we don't have rounding problems */
00303    interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3];
00304    if (interp[2]<32767)
00305       interp[2]+=1;
00306 }
00307 #else
00308 static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
00309 {
00310    /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
00311    but I know it's MMSE-optimal on a sinc */
00312    interp[0] =  -0.16667f*frac + 0.16667f*frac*frac*frac;
00313    interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac;
00314    /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
00315    interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac;
00316    /* Just to make sure we don't have rounding problems */
00317    interp[2] = 1.-interp[0]-interp[1]-interp[3];
00318 }
00319 #endif
00320 
00321 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)
00322 {
00323    const int N = st->filt_len;
00324    int out_sample = 0;
00325    int last_sample = st->last_sample[channel_index];
00326    spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
00327    const spx_word16_t *sinc_table = st->sinc_table;
00328    const int out_stride = st->out_stride;
00329    const int int_advance = st->int_advance;
00330    const int frac_advance = st->frac_advance;
00331    const spx_uint32_t den_rate = st->den_rate;
00332    spx_word32_t sum;
00333    int j;
00334 
00335    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
00336    {
00337       const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
00338       const spx_word16_t *iptr = & in[last_sample];
00339 
00340 #ifndef OVERRIDE_INNER_PRODUCT_SINGLE
00341       float accum[4] = {0,0,0,0};
00342 
00343       for(j=0;j<N;j+=4) {
00344         accum[0] += sinc[j]*iptr[j];
00345         accum[1] += sinc[j+1]*iptr[j+1];
00346         accum[2] += sinc[j+2]*iptr[j+2];
00347         accum[3] += sinc[j+3]*iptr[j+3];
00348       }
00349       sum = accum[0] + accum[1] + accum[2] + accum[3];
00350 #else
00351       sum = inner_product_single(sinc, iptr, N);
00352 #endif
00353 
00354       out[out_stride * out_sample++] = PSHR32(sum, 15);
00355       last_sample += int_advance;
00356       samp_frac_num += frac_advance;
00357       if (samp_frac_num >= den_rate)
00358       {
00359          samp_frac_num -= den_rate;
00360          last_sample++;
00361       }
00362    }
00363 
00364    st->last_sample[channel_index] = last_sample;
00365    st->samp_frac_num[channel_index] = samp_frac_num;
00366    return out_sample;
00367 }
00368 
00369 #ifdef FIXED_POINT
00370 #else
00371 /* This is the same as the previous function, except with a double-precision accumulator */
00372 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)
00373 {
00374    const int N = st->filt_len;
00375    int out_sample = 0;
00376    int last_sample = st->last_sample[channel_index];
00377    spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
00378    const spx_word16_t *sinc_table = st->sinc_table;
00379    const int out_stride = st->out_stride;
00380    const int int_advance = st->int_advance;
00381    const int frac_advance = st->frac_advance;
00382    const spx_uint32_t den_rate = st->den_rate;
00383    double sum;
00384    int j;
00385 
00386    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
00387    {
00388       const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
00389       const spx_word16_t *iptr = & in[last_sample];
00390 
00391 #ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
00392       double accum[4] = {0,0,0,0};
00393 
00394       for(j=0;j<N;j+=4) {
00395         accum[0] += sinc[j]*iptr[j];
00396         accum[1] += sinc[j+1]*iptr[j+1];
00397         accum[2] += sinc[j+2]*iptr[j+2];
00398         accum[3] += sinc[j+3]*iptr[j+3];
00399       }
00400       sum = accum[0] + accum[1] + accum[2] + accum[3];
00401 #else
00402       sum = inner_product_double(sinc, iptr, N);
00403 #endif
00404 
00405       out[out_stride * out_sample++] = PSHR32(sum, 15);
00406       last_sample += int_advance;
00407       samp_frac_num += frac_advance;
00408       if (samp_frac_num >= den_rate)
00409       {
00410          samp_frac_num -= den_rate;
00411          last_sample++;
00412       }
00413    }
00414 
00415    st->last_sample[channel_index] = last_sample;
00416    st->samp_frac_num[channel_index] = samp_frac_num;
00417    return out_sample;
00418 }
00419 #endif
00420 
00421 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)
00422 {
00423    const int N = st->filt_len;
00424    int out_sample = 0;
00425    int last_sample = st->last_sample[channel_index];
00426    spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
00427    const int out_stride = st->out_stride;
00428    const int int_advance = st->int_advance;
00429    const int frac_advance = st->frac_advance;
00430    const spx_uint32_t den_rate = st->den_rate;
00431    int j;
00432    spx_word32_t sum;
00433 
00434    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
00435    {
00436       const spx_word16_t *iptr = & in[last_sample];
00437 
00438       const int offset = samp_frac_num*st->oversample/st->den_rate;
00439 #ifdef FIXED_POINT
00440       const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
00441 #else
00442       const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
00443 #endif
00444       spx_word16_t interp[4];
00445 
00446 
00447 #ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
00448       spx_word32_t accum[4] = {0,0,0,0};
00449 
00450       for(j=0;j<N;j++) {
00451         const spx_word16_t curr_in=iptr[j];
00452         accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
00453         accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
00454         accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
00455         accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
00456       }
00457 
00458       cubic_coef(frac, interp);
00459       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]);
00460 #else
00461       cubic_coef(frac, interp);
00462       sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
00463 #endif
00464       
00465       out[out_stride * out_sample++] = PSHR32(sum,15);
00466       last_sample += int_advance;
00467       samp_frac_num += frac_advance;
00468       if (samp_frac_num >= den_rate)
00469       {
00470          samp_frac_num -= den_rate;
00471          last_sample++;
00472       }
00473    }
00474 
00475    st->last_sample[channel_index] = last_sample;
00476    st->samp_frac_num[channel_index] = samp_frac_num;
00477    return out_sample;
00478 }
00479 
00480 #ifdef FIXED_POINT
00481 #else
00482 /* This is the same as the previous function, except with a double-precision accumulator */
00483 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)
00484 {
00485    const int N = st->filt_len;
00486    int out_sample = 0;
00487    int last_sample = st->last_sample[channel_index];
00488    spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
00489    const int out_stride = st->out_stride;
00490    const int int_advance = st->int_advance;
00491    const int frac_advance = st->frac_advance;
00492    const spx_uint32_t den_rate = st->den_rate;
00493    int j;
00494    spx_word32_t sum;
00495 
00496    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
00497    {
00498       const spx_word16_t *iptr = & in[last_sample];
00499 
00500       const int offset = samp_frac_num*st->oversample/st->den_rate;
00501 #ifdef FIXED_POINT
00502       const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
00503 #else
00504       const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
00505 #endif
00506       spx_word16_t interp[4];
00507 
00508 
00509 #ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
00510       double accum[4] = {0,0,0,0};
00511 
00512       for(j=0;j<N;j++) {
00513         const double curr_in=iptr[j];
00514         accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
00515         accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
00516         accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
00517         accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
00518       }
00519 
00520       cubic_coef(frac, interp);
00521       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]);
00522 #else
00523       cubic_coef(frac, interp);
00524       sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
00525 #endif
00526       
00527       out[out_stride * out_sample++] = PSHR32(sum,15);
00528       last_sample += int_advance;
00529       samp_frac_num += frac_advance;
00530       if (samp_frac_num >= den_rate)
00531       {
00532          samp_frac_num -= den_rate;
00533          last_sample++;
00534       }
00535    }
00536 
00537    st->last_sample[channel_index] = last_sample;
00538    st->samp_frac_num[channel_index] = samp_frac_num;
00539    return out_sample;
00540 }
00541 #endif
00542 
00543 static void update_filter(SpeexResamplerState *st)
00544 {
00545    spx_uint32_t old_length;
00546    
00547    old_length = st->filt_len;
00548    st->oversample = quality_map[st->quality].oversample;
00549    st->filt_len = quality_map[st->quality].base_length;
00550    
00551    if (st->num_rate > st->den_rate)
00552    {
00553       /* down-sampling */
00554       st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
00555       /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
00556       st->filt_len = st->filt_len*st->num_rate / st->den_rate;
00557       /* Round down to make sure we have a multiple of 4 */
00558       st->filt_len &= (~0x3);
00559       if (2*st->den_rate < st->num_rate)
00560          st->oversample >>= 1;
00561       if (4*st->den_rate < st->num_rate)
00562          st->oversample >>= 1;
00563       if (8*st->den_rate < st->num_rate)
00564          st->oversample >>= 1;
00565       if (16*st->den_rate < st->num_rate)
00566          st->oversample >>= 1;
00567       if (st->oversample < 1)
00568          st->oversample = 1;
00569    } else {
00570       /* up-sampling */
00571       st->cutoff = quality_map[st->quality].upsample_bandwidth;
00572    }
00573    
00574    /* Choose the resampling type that requires the least amount of memory */
00575    if (st->den_rate <= st->oversample)
00576    {
00577       spx_uint32_t i;
00578       if (!st->sinc_table)
00579          st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));
00580       else if (st->sinc_table_length < st->filt_len*st->den_rate)
00581       {
00582          st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));
00583          st->sinc_table_length = st->filt_len*st->den_rate;
00584       }
00585       for (i=0;i<st->den_rate;i++)
00586       {
00587          spx_int32_t j;
00588          for (j=0;j<st->filt_len;j++)
00589          {
00590             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);
00591          }
00592       }
00593 #ifdef FIXED_POINT
00594       st->resampler_ptr = resampler_basic_direct_single;
00595 #else
00596       if (st->quality>8)
00597          st->resampler_ptr = resampler_basic_direct_double;
00598       else
00599          st->resampler_ptr = resampler_basic_direct_single;
00600 #endif
00601       /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/
00602    } else {
00603       spx_int32_t i;
00604       if (!st->sinc_table)
00605          st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
00606       else if (st->sinc_table_length < st->filt_len*st->oversample+8)
00607       {
00608          st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
00609          st->sinc_table_length = st->filt_len*st->oversample+8;
00610       }
00611       for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)
00612          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);
00613 #ifdef FIXED_POINT
00614       st->resampler_ptr = resampler_basic_interpolate_single;
00615 #else
00616       if (st->quality>8)
00617          st->resampler_ptr = resampler_basic_interpolate_double;
00618       else
00619          st->resampler_ptr = resampler_basic_interpolate_single;
00620 #endif
00621       /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/
00622    }
00623    st->int_advance = st->num_rate/st->den_rate;
00624    st->frac_advance = st->num_rate%st->den_rate;
00625 
00626    
00627    /* Here's the place where we update the filter memory to take into account
00628       the change in filter length. It's probably the messiest part of the code
00629       due to handling of lots of corner cases. */
00630    if (!st->mem)
00631    {
00632       spx_uint32_t i;
00633       st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
00634       st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
00635       for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
00636          st->mem[i] = 0;
00637       /*speex_warning("init filter");*/
00638    } else if (!st->started)
00639    {
00640       spx_uint32_t i;
00641       st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
00642       st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
00643       for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
00644          st->mem[i] = 0;
00645       /*speex_warning("reinit filter");*/
00646    } else if (st->filt_len > old_length)
00647    {
00648       spx_int32_t i;
00649       /* Increase the filter length */
00650       /*speex_warning("increase filter size");*/
00651       int old_alloc_size = st->mem_alloc_size;
00652       if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size)
00653       {
00654          st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
00655          st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
00656       }
00657       for (i=st->nb_channels-1;i>=0;i--)
00658       {
00659          spx_int32_t j;
00660          spx_uint32_t olen = old_length;
00661          /*if (st->magic_samples[i])*/
00662          {
00663             /* Try and remove the magic samples as if nothing had happened */
00664             
00665             /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
00666             olen = old_length + 2*st->magic_samples[i];
00667             for (j=old_length-2+st->magic_samples[i];j>=0;j--)
00668                st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
00669             for (j=0;j<st->magic_samples[i];j++)
00670                st->mem[i*st->mem_alloc_size+j] = 0;
00671             st->magic_samples[i] = 0;
00672          }
00673          if (st->filt_len > olen)
00674          {
00675             /* If the new filter length is still bigger than the "augmented" length */
00676             /* Copy data going backward */
00677             for (j=0;j<olen-1;j++)
00678                st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
00679             /* Then put zeros for lack of anything better */
00680             for (;j<st->filt_len-1;j++)
00681                st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
00682             /* Adjust last_sample */
00683             st->last_sample[i] += (st->filt_len - olen)/2;
00684          } else {
00685             /* Put back some of the magic! */
00686             st->magic_samples[i] = (olen - st->filt_len)/2;
00687             for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
00688                st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
00689          }
00690       }
00691    } else if (st->filt_len < old_length)
00692    {
00693       spx_uint32_t i;
00694       /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
00695          samples so they can be used directly as input the next time(s) */
00696       for (i=0;i<st->nb_channels;i++)
00697       {
00698          spx_uint32_t j;
00699          spx_uint32_t old_magic = st->magic_samples[i];
00700          st->magic_samples[i] = (old_length - st->filt_len)/2;
00701          /* We must copy some of the memory that's no longer used */
00702          /* Copy data going backward */
00703          for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
00704             st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
00705          st->magic_samples[i] += old_magic;
00706       }
00707    }
00708 
00709 }
00710 
00711  SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
00712 {
00713    return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
00714 }
00715 
00716  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)
00717 {
00718    spx_uint32_t i;
00719    SpeexResamplerState *st;
00720    if (quality > 10 || quality < 0)
00721    {
00722       if (err)
00723          *err = RESAMPLER_ERR_INVALID_ARG;
00724       return NULL;
00725    }
00726    st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
00727    st->initialised = 0;
00728    st->started = 0;
00729    st->in_rate = 0;
00730    st->out_rate = 0;
00731    st->num_rate = 0;
00732    st->den_rate = 0;
00733    st->quality = -1;
00734    st->sinc_table_length = 0;
00735    st->mem_alloc_size = 0;
00736    st->filt_len = 0;
00737    st->mem = 0;
00738    st->resampler_ptr = 0;
00739          
00740    st->cutoff = 1.f;
00741    st->nb_channels = nb_channels;
00742    st->in_stride = 1;
00743    st->out_stride = 1;
00744    
00745 #ifdef FIXED_POINT
00746    st->buffer_size = 160;
00747 #else
00748    st->buffer_size = 160;
00749 #endif
00750    
00751    /* Per channel data */
00752    st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
00753    st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
00754    st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
00755    for (i=0;i<nb_channels;i++)
00756    {
00757       st->last_sample[i] = 0;
00758       st->magic_samples[i] = 0;
00759       st->samp_frac_num[i] = 0;
00760    }
00761 
00762    speex_resampler_set_quality(st, quality);
00763    speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
00764 
00765    
00766    update_filter(st);
00767    
00768    st->initialised = 1;
00769    if (err)
00770       *err = RESAMPLER_ERR_SUCCESS;
00771 
00772    return st;
00773 }
00774 
00775  void speex_resampler_destroy(SpeexResamplerState *st)
00776 {
00777    speex_free(st->mem);
00778    speex_free(st->sinc_table);
00779    speex_free(st->last_sample);
00780    speex_free(st->magic_samples);
00781    speex_free(st->samp_frac_num);
00782    speex_free(st);
00783 }
00784 
00785 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)
00786 {
00787    int j=0;
00788    const int N = st->filt_len;
00789    int out_sample = 0;
00790    spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
00791    spx_uint32_t ilen;
00792    
00793    st->started = 1;
00794    
00795    /* Call the right resampler through the function ptr */
00796    out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len);
00797    
00798    if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
00799       *in_len = st->last_sample[channel_index];
00800    *out_len = out_sample;
00801    st->last_sample[channel_index] -= *in_len;
00802    
00803    ilen = *in_len;
00804 
00805    for(j=0;j<N-1;++j)
00806      mem[j] = mem[j+ilen];
00807 
00808    return RESAMPLER_ERR_SUCCESS;
00809 }
00810 
00811 static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) {
00812    spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
00813    spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
00814    const int N = st->filt_len;
00815    
00816    speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len);
00817 
00818    st->magic_samples[channel_index] -= tmp_in_len;
00819    
00820    /* If we couldn't process all "magic" input samples, save the rest for next time */
00821    if (st->magic_samples[channel_index])
00822    {
00823       spx_uint32_t i;
00824       for (i=0;i<st->magic_samples[channel_index];i++)
00825          mem[N-1+i]=mem[N-1+i+tmp_in_len];
00826    }
00827    *out += out_len*st->out_stride;
00828    return out_len;
00829 }
00830 
00831 #ifdef FIXED_POINT
00832  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)
00833 #else
00834  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)
00835 #endif
00836 {
00837    int j;
00838    spx_uint32_t ilen = *in_len;
00839    spx_uint32_t olen = *out_len;
00840    spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
00841    const int filt_offs = st->filt_len - 1;
00842    const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
00843    const int istride = st->in_stride;
00844 
00845    if (st->magic_samples[channel_index]) 
00846       olen -= speex_resampler_magic(st, channel_index, &out, olen);
00847    if (! st->magic_samples[channel_index]) {
00848       while (ilen && olen) {
00849         spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
00850         spx_uint32_t ochunk = olen;
00851  
00852         if (in) {
00853            for(j=0;j<ichunk;++j)
00854               x[j+filt_offs]=in[j*istride];
00855         } else {
00856           for(j=0;j<ichunk;++j)
00857             x[j+filt_offs]=0;
00858         }
00859         speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk);
00860         ilen -= ichunk;
00861         olen -= ochunk;
00862         out += ochunk * st->out_stride;
00863         if (in)
00864            in += ichunk * istride;
00865       }
00866    }
00867    *in_len -= ilen;
00868    *out_len -= olen;
00869    return RESAMPLER_ERR_SUCCESS;
00870 }
00871 
00872 #ifdef FIXED_POINT
00873  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)
00874 #else
00875  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)
00876 #endif
00877 {
00878    int j;
00879    const int istride_save = st->in_stride;
00880    const int ostride_save = st->out_stride;
00881    spx_uint32_t ilen = *in_len;
00882    spx_uint32_t olen = *out_len;
00883    spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
00884    const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
00885 #ifdef VAR_ARRAYS
00886    const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
00887    VARDECL(spx_word16_t *ystack);
00888    ALLOC(ystack, ylen, spx_word16_t);
00889 #else
00890    const unsigned int ylen = FIXED_STACK_ALLOC;
00891    spx_word16_t ystack[FIXED_STACK_ALLOC];
00892 #endif
00893 
00894    st->out_stride = 1;
00895    
00896    while (ilen && olen) {
00897      spx_word16_t *y = ystack;
00898      spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
00899      spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
00900      spx_uint32_t omagic = 0;
00901 
00902      if (st->magic_samples[channel_index]) {
00903        omagic = speex_resampler_magic(st, channel_index, &y, ochunk);
00904        ochunk -= omagic;
00905        olen -= omagic;
00906      }
00907      if (! st->magic_samples[channel_index]) {
00908        if (in) {
00909          for(j=0;j<ichunk;++j)
00910 #ifdef FIXED_POINT
00911            x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]);
00912 #else
00913            x[j+st->filt_len-1]=in[j*istride_save];
00914 #endif
00915        } else {
00916          for(j=0;j<ichunk;++j)
00917            x[j+st->filt_len-1]=0;
00918        }
00919 
00920        speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk);
00921      } else {
00922        ichunk = 0;
00923        ochunk = 0;
00924      }
00925 
00926      for (j=0;j<ochunk+omagic;++j)
00927 #ifdef FIXED_POINT
00928         out[j*ostride_save] = ystack[j];
00929 #else
00930         out[j*ostride_save] = WORD2INT(ystack[j]);
00931 #endif
00932      
00933      ilen -= ichunk;
00934      olen -= ochunk;
00935      out += (ochunk+omagic) * ostride_save;
00936      if (in)
00937        in += ichunk * istride_save;
00938    }
00939    st->out_stride = ostride_save;
00940    *in_len -= ilen;
00941    *out_len -= olen;
00942 
00943    return RESAMPLER_ERR_SUCCESS;
00944 }
00945 
00946  int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
00947 {
00948    spx_uint32_t i;
00949    int istride_save, ostride_save;
00950    spx_uint32_t bak_len = *out_len;
00951    istride_save = st->in_stride;
00952    ostride_save = st->out_stride;
00953    st->in_stride = st->out_stride = st->nb_channels;
00954    for (i=0;i<st->nb_channels;i++)
00955    {
00956       *out_len = bak_len;
00957       if (in != NULL)
00958          speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
00959       else
00960          speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len);
00961    }
00962    st->in_stride = istride_save;
00963    st->out_stride = ostride_save;
00964    return RESAMPLER_ERR_SUCCESS;
00965 }
00966                
00967  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)
00968 {
00969    spx_uint32_t i;
00970    int istride_save, ostride_save;
00971    spx_uint32_t bak_len = *out_len;
00972    istride_save = st->in_stride;
00973    ostride_save = st->out_stride;
00974    st->in_stride = st->out_stride = st->nb_channels;
00975    for (i=0;i<st->nb_channels;i++)
00976    {
00977       *out_len = bak_len;
00978       if (in != NULL)
00979          speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
00980       else
00981          speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len);
00982    }
00983    st->in_stride = istride_save;
00984    st->out_stride = ostride_save;
00985    return RESAMPLER_ERR_SUCCESS;
00986 }
00987 
00988  int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
00989 {
00990    return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
00991 }
00992 
00993  void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
00994 {
00995    *in_rate = st->in_rate;
00996    *out_rate = st->out_rate;
00997 }
00998 
00999  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)
01000 {
01001    spx_uint32_t fact;
01002    spx_uint32_t old_den;
01003    spx_uint32_t i;
01004    if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
01005       return RESAMPLER_ERR_SUCCESS;
01006    
01007    old_den = st->den_rate;
01008    st->in_rate = in_rate;
01009    st->out_rate = out_rate;
01010    st->num_rate = ratio_num;
01011    st->den_rate = ratio_den;
01012    /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
01013    for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
01014    {
01015       while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
01016       {
01017          st->num_rate /= fact;
01018          st->den_rate /= fact;
01019       }
01020    }
01021       
01022    if (old_den > 0)
01023    {
01024       for (i=0;i<st->nb_channels;i++)
01025       {
01026          st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
01027          /* Safety net */
01028          if (st->samp_frac_num[i] >= st->den_rate)
01029             st->samp_frac_num[i] = st->den_rate-1;
01030       }
01031    }
01032    
01033    if (st->initialised)
01034       update_filter(st);
01035    return RESAMPLER_ERR_SUCCESS;
01036 }
01037 
01038  void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
01039 {
01040    *ratio_num = st->num_rate;
01041    *ratio_den = st->den_rate;
01042 }
01043 
01044  int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
01045 {
01046    if (quality > 10 || quality < 0)
01047       return RESAMPLER_ERR_INVALID_ARG;
01048    if (st->quality == quality)
01049       return RESAMPLER_ERR_SUCCESS;
01050    st->quality = quality;
01051    if (st->initialised)
01052       update_filter(st);
01053    return RESAMPLER_ERR_SUCCESS;
01054 }
01055 
01056  void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
01057 {
01058    *quality = st->quality;
01059 }
01060 
01061  void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
01062 {
01063    st->in_stride = stride;
01064 }
01065 
01066  void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
01067 {
01068    *stride = st->in_stride;
01069 }
01070 
01071  void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
01072 {
01073    st->out_stride = stride;
01074 }
01075 
01076  void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
01077 {
01078    *stride = st->out_stride;
01079 }
01080 
01081  int speex_resampler_get_input_latency(SpeexResamplerState *st)
01082 {
01083   return st->filt_len / 2;
01084 }
01085 
01086  int speex_resampler_get_output_latency(SpeexResamplerState *st)
01087 {
01088   return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;
01089 }
01090 
01091  int speex_resampler_skip_zeros(SpeexResamplerState *st)
01092 {
01093    spx_uint32_t i;
01094    for (i=0;i<st->nb_channels;i++)
01095       st->last_sample[i] = st->filt_len/2;
01096    return RESAMPLER_ERR_SUCCESS;
01097 }
01098 
01099  int speex_resampler_reset_mem(SpeexResamplerState *st)
01100 {
01101    spx_uint32_t i;
01102    for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
01103       st->mem[i] = 0;
01104    return RESAMPLER_ERR_SUCCESS;
01105 }
01106 
01107  const char *speex_resampler_strerror(int err)
01108 {
01109    switch (err)
01110    {
01111       case RESAMPLER_ERR_SUCCESS:
01112          return "Success.";
01113       case RESAMPLER_ERR_ALLOC_FAILED:
01114          return "Memory allocation failed.";
01115       case RESAMPLER_ERR_BAD_STATE:
01116          return "Bad resampler state.";
01117       case RESAMPLER_ERR_INVALID_ARG:
01118          return "Invalid argument.";
01119       case RESAMPLER_ERR_PTR_OVERLAP:
01120          return "Input and output buffers overlap.";
01121       default:
01122          return "Unknown error. Bad error code or strange version mismatch.";
01123    }
01124 }

Generated on Thu Apr 16 06:27:53 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6