media/libspeex_resampler/src/resample.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial