Blame pph/resample.c

Packit Service cd2a00
/* Copyright (C) 2007 Jean-Marc Valin
Packit Service cd2a00
      
Packit Service cd2a00
   File: resample.c
Packit Service cd2a00
   Arbitrary resampling code
Packit Service cd2a00
Packit Service cd2a00
   Redistribution and use in source and binary forms, with or without
Packit Service cd2a00
   modification, are permitted provided that the following conditions are
Packit Service cd2a00
   met:
Packit Service cd2a00
Packit Service cd2a00
   1. Redistributions of source code must retain the above copyright notice,
Packit Service cd2a00
   this list of conditions and the following disclaimer.
Packit Service cd2a00
Packit Service cd2a00
   2. Redistributions in binary form must reproduce the above copyright
Packit Service cd2a00
   notice, this list of conditions and the following disclaimer in the
Packit Service cd2a00
   documentation and/or other materials provided with the distribution.
Packit Service cd2a00
Packit Service cd2a00
   3. The name of the author may not be used to endorse or promote products
Packit Service cd2a00
   derived from this software without specific prior written permission.
Packit Service cd2a00
Packit Service cd2a00
   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Packit Service cd2a00
   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit Service cd2a00
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit Service cd2a00
   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
Packit Service cd2a00
   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Packit Service cd2a00
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit Service cd2a00
   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit Service cd2a00
   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
Packit Service cd2a00
   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
Packit Service cd2a00
   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit Service cd2a00
   POSSIBILITY OF SUCH DAMAGE.
Packit Service cd2a00
*/
Packit Service cd2a00
Packit Service cd2a00
/*
Packit Service cd2a00
   The design goals of this code are:
Packit Service cd2a00
      - Very fast algorithm
Packit Service cd2a00
      - SIMD-friendly algorithm
Packit Service cd2a00
      - Low memory requirement
Packit Service cd2a00
      - Good *perceptual* quality (and not best SNR)
Packit Service cd2a00
Packit Service cd2a00
   The code is working, but it's in a very early stage, so it may have
Packit Service cd2a00
   artifacts, noise or subliminal messages from satan. Also, the API 
Packit Service cd2a00
   isn't stable and I can actually promise that I *will* change the API
Packit Service cd2a00
   some time in the future.
Packit Service cd2a00
Packit Service cd2a00
TODO list:
Packit Service cd2a00
      - Variable calculation resolution depending on quality setting
Packit Service cd2a00
         - Single vs double in float mode
Packit Service cd2a00
         - 16-bit vs 32-bit (sinc only) in fixed-point mode
Packit Service cd2a00
      - Make sure the filter update works even when changing params 
Packit Service cd2a00
             after only a few samples procesed
Packit Service cd2a00
*/
Packit Service cd2a00
Packit Service cd2a00
#ifdef HAVE_CONFIG_H
Packit Service cd2a00
#include "config.h"
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
#ifdef OUTSIDE_SPEEX
Packit Service cd2a00
#include <stdlib.h>
Packit Service cd2a00
static void *speex_alloc (int size) {return calloc(size,1);}
Packit Service cd2a00
static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
Packit Service cd2a00
static void speex_free (void *ptr) {free(ptr);}
Packit Service cd2a00
#include "speex_resampler.h"
Packit Service cd2a00
#include "arch.h"
Packit Service cd2a00
#else /* OUTSIDE_SPEEX */
Packit Service cd2a00
               
Packit Service cd2a00
#include "speex/speex_resampler.h"
Packit Service cd2a00
#include "misc.h"
Packit Service cd2a00
#endif /* OUTSIDE_SPEEX */
Packit Service cd2a00
Packit Service cd2a00
#include <math.h>
Packit Service cd2a00
Packit Service cd2a00
#ifndef M_PI
Packit Service cd2a00
#define M_PI 3.14159263
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))  
Packit Service cd2a00
#else
Packit Service cd2a00
#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))  
Packit Service cd2a00
#endif
Packit Service cd2a00
               
Packit Service cd2a00
/*#define float double*/
Packit Service cd2a00
#define FILTER_SIZE 64
Packit Service cd2a00
#define OVERSAMPLE 8
Packit Service cd2a00
Packit Service cd2a00
#define IMAX(a,b) ((a) > (b) ? (a) : (b))
Packit Service cd2a00
#define IMIN(a,b) ((a) < (b) ? (a) : (b))
Packit Service cd2a00
Packit Service cd2a00
#ifndef NULL
Packit Service cd2a00
#define NULL 0
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
Packit Service cd2a00
Packit Service cd2a00
struct SpeexResamplerState_ {
Packit Service cd2a00
   spx_uint32_t in_rate;
Packit Service cd2a00
   spx_uint32_t out_rate;
Packit Service cd2a00
   spx_uint32_t num_rate;
Packit Service cd2a00
   spx_uint32_t den_rate;
Packit Service cd2a00
   
Packit Service cd2a00
   int    quality;
Packit Service cd2a00
   spx_uint32_t nb_channels;
Packit Service cd2a00
   spx_uint32_t filt_len;
Packit Service cd2a00
   spx_uint32_t mem_alloc_size;
Packit Service cd2a00
   int          int_advance;
Packit Service cd2a00
   int          frac_advance;
Packit Service cd2a00
   float  cutoff;
Packit Service cd2a00
   spx_uint32_t oversample;
Packit Service cd2a00
   int          initialised;
Packit Service cd2a00
   int          started;
Packit Service cd2a00
   
Packit Service cd2a00
   /* These are per-channel */
Packit Service cd2a00
   spx_int32_t  *last_sample;
Packit Service cd2a00
   spx_uint32_t *samp_frac_num;
Packit Service cd2a00
   spx_uint32_t *magic_samples;
Packit Service cd2a00
   
Packit Service cd2a00
   spx_word16_t *mem;
Packit Service cd2a00
   spx_word16_t *sinc_table;
Packit Service cd2a00
   spx_uint32_t sinc_table_length;
Packit Service cd2a00
   resampler_basic_func resampler_ptr;
Packit Service cd2a00
         
Packit Service cd2a00
   int    in_stride;
Packit Service cd2a00
   int    out_stride;
Packit Service cd2a00
} ;
Packit Service cd2a00
Packit Service cd2a00
static double kaiser12_table[68] = {
Packit Service cd2a00
   0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
Packit Service cd2a00
   0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
Packit Service cd2a00
   0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
Packit Service cd2a00
   0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
Packit Service cd2a00
   0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
Packit Service cd2a00
   0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
Packit Service cd2a00
   0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
Packit Service cd2a00
   0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
Packit Service cd2a00
   0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
Packit Service cd2a00
   0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
Packit Service cd2a00
   0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
Packit Service cd2a00
   0.00001000, 0.00000000};
Packit Service cd2a00
/*
Packit Service cd2a00
static double kaiser12_table[36] = {
Packit Service cd2a00
   0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
Packit Service cd2a00
   0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
Packit Service cd2a00
   0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
Packit Service cd2a00
   0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
Packit Service cd2a00
   0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
Packit Service cd2a00
   0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
Packit Service cd2a00
*/
Packit Service cd2a00
static double kaiser10_table[36] = {
Packit Service cd2a00
   0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
Packit Service cd2a00
   0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
Packit Service cd2a00
   0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
Packit Service cd2a00
   0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
Packit Service cd2a00
   0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
Packit Service cd2a00
   0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
Packit Service cd2a00
Packit Service cd2a00
static double kaiser8_table[36] = {
Packit Service cd2a00
   0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
Packit Service cd2a00
   0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
Packit Service cd2a00
   0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
Packit Service cd2a00
   0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
Packit Service cd2a00
   0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
Packit Service cd2a00
   0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
Packit Service cd2a00
   
Packit Service cd2a00
static double kaiser6_table[36] = {
Packit Service cd2a00
   0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
Packit Service cd2a00
   0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
Packit Service cd2a00
   0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
Packit Service cd2a00
   0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
Packit Service cd2a00
   0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
Packit Service cd2a00
   0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
Packit Service cd2a00
Packit Service cd2a00
struct FuncDef {
Packit Service cd2a00
   double *table;
Packit Service cd2a00
   int oversample;
Packit Service cd2a00
};
Packit Service cd2a00
      
Packit Service cd2a00
static struct FuncDef _KAISER12 = {kaiser12_table, 64};
Packit Service cd2a00
#define KAISER12 (&_KAISER12)
Packit Service cd2a00
/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
Packit Service cd2a00
#define KAISER12 (&_KAISER12)*/
Packit Service cd2a00
static struct FuncDef _KAISER10 = {kaiser10_table, 32};
Packit Service cd2a00
#define KAISER10 (&_KAISER10)
Packit Service cd2a00
static struct FuncDef _KAISER8 = {kaiser8_table, 32};
Packit Service cd2a00
#define KAISER8 (&_KAISER8)
Packit Service cd2a00
static struct FuncDef _KAISER6 = {kaiser6_table, 32};
Packit Service cd2a00
#define KAISER6 (&_KAISER6)
Packit Service cd2a00
Packit Service cd2a00
struct QualityMapping {
Packit Service cd2a00
   int base_length;
Packit Service cd2a00
   int oversample;
Packit Service cd2a00
   float downsample_bandwidth;
Packit Service cd2a00
   float upsample_bandwidth;
Packit Service cd2a00
   struct FuncDef *window_func;
Packit Service cd2a00
};
Packit Service cd2a00
Packit Service cd2a00
Packit Service cd2a00
/* This table maps conversion quality to internal parameters. There are two
Packit Service cd2a00
   reasons that explain why the up-sampling bandwidth is larger than the 
Packit Service cd2a00
   down-sampling bandwidth:
Packit Service cd2a00
   1) When up-sampling, we can assume that the spectrum is already attenuated
Packit Service cd2a00
      close to the Nyquist rate (from an A/D or a previous resampling filter)
Packit Service cd2a00
   2) Any aliasing that occurs very close to the Nyquist rate will be masked
Packit Service cd2a00
      by the sinusoids/noise just below the Nyquist rate (guaranteed only for
Packit Service cd2a00
      up-sampling).
Packit Service cd2a00
*/
Packit Service cd2a00
static const struct QualityMapping quality_map[11] = {
Packit Service cd2a00
   {  8,  4, 0.830f, 0.860f, KAISER6 }, /* Q0 */
Packit Service cd2a00
   { 16,  4, 0.850f, 0.880f, KAISER6 }, /* Q1 */
Packit Service cd2a00
   { 32,  4, 0.882f, 0.910f, KAISER6 }, /* Q2 */  /* 82.3% cutoff ( ~60 dB stop) 6  */
Packit Service cd2a00
   { 48,  8, 0.895f, 0.917f, KAISER8 }, /* Q3 */  /* 84.9% cutoff ( ~80 dB stop) 8  */
Packit Service cd2a00
   { 64,  8, 0.921f, 0.940f, KAISER8 }, /* Q4 */  /* 88.7% cutoff ( ~80 dB stop) 8  */
Packit Service cd2a00
   { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */  /* 89.1% cutoff (~100 dB stop) 10 */
Packit Service cd2a00
   { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */  /* 91.5% cutoff (~100 dB stop) 10 */
Packit Service cd2a00
   {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */  /* 93.1% cutoff (~100 dB stop) 10 */
Packit Service cd2a00
   {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */  /* 94.5% cutoff (~100 dB stop) 10 */
Packit Service cd2a00
   {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */  /* 95.5% cutoff (~100 dB stop) 10 */
Packit Service cd2a00
   {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
Packit Service cd2a00
};
Packit Service cd2a00
/*8,24,40,56,80,104,128,160,200,256,320*/
Packit Service cd2a00
static double compute_func(float x, struct FuncDef *func)
Packit Service cd2a00
{
Packit Service cd2a00
   float y, frac;
Packit Service cd2a00
   double interp[4];
Packit Service cd2a00
   int ind; 
Packit Service cd2a00
   y = x*func->oversample;
Packit Service cd2a00
   ind = (int)floor(y);
Packit Service cd2a00
   frac = (y-ind);
Packit Service cd2a00
   /* CSE with handle the repeated powers */
Packit Service cd2a00
   interp[3] =  -0.1666666667*frac + 0.1666666667*(frac*frac*frac);
Packit Service cd2a00
   interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac);
Packit Service cd2a00
   /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
Packit Service cd2a00
   interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
Packit Service cd2a00
   /* Just to make sure we don't have rounding problems */
Packit Service cd2a00
   interp[1] = 1.f-interp[3]-interp[2]-interp[0];
Packit Service cd2a00
   
Packit Service cd2a00
   /*sum = frac*accum[1] + (1-frac)*accum[2];*/
Packit Service cd2a00
   return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
#if 0
Packit Service cd2a00
#include <stdio.h>
Packit Service cd2a00
int main(int argc, char **argv)
Packit Service cd2a00
{
Packit Service cd2a00
   int i;
Packit Service cd2a00
   for (i=0;i<256;i++)
Packit Service cd2a00
   {
Packit Service cd2a00
      printf ("%f\n", compute_func(i/256., KAISER12));
Packit Service cd2a00
   }
Packit Service cd2a00
   return 0;
Packit Service cd2a00
}
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
/* The slow way of computing a sinc for the table. Should improve that some day */
Packit Service cd2a00
static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
Packit Service cd2a00
{
Packit Service cd2a00
   /*fprintf (stderr, "%f ", x);*/
Packit Service cd2a00
   float xx = x * cutoff;
Packit Service cd2a00
   if (fabs(x)<1e-6f)
Packit Service cd2a00
      return WORD2INT(32768.*cutoff);
Packit Service cd2a00
   else if (fabs(x) > .5f*N)
Packit Service cd2a00
      return 0;
Packit Service cd2a00
   /*FIXME: Can it really be any slower than this? */
Packit Service cd2a00
   return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
Packit Service cd2a00
}
Packit Service cd2a00
#else
Packit Service cd2a00
/* The slow way of computing a sinc for the table. Should improve that some day */
Packit Service cd2a00
static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
Packit Service cd2a00
{
Packit Service cd2a00
   /*fprintf (stderr, "%f ", x);*/
Packit Service cd2a00
   float xx = x * cutoff;
Packit Service cd2a00
   if (fabs(x)<1e-6)
Packit Service cd2a00
      return cutoff;
Packit Service cd2a00
   else if (fabs(x) > .5*N)
Packit Service cd2a00
      return 0;
Packit Service cd2a00
   /*FIXME: Can it really be any slower than this? */
Packit Service cd2a00
   return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func);
Packit Service cd2a00
}
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
static void cubic_coef(spx_word16_t x, spx_word16_t interp[4])
Packit Service cd2a00
{
Packit Service cd2a00
   /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
Packit Service cd2a00
   but I know it's MMSE-optimal on a sinc */
Packit Service cd2a00
   spx_word16_t x2, x3;
Packit Service cd2a00
   x2 = MULT16_16_P15(x, x);
Packit Service cd2a00
   x3 = MULT16_16_P15(x, x2);
Packit Service cd2a00
   interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
Packit Service cd2a00
   interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
Packit Service cd2a00
   interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15);
Packit Service cd2a00
   /* Just to make sure we don't have rounding problems */
Packit Service cd2a00
   interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3];
Packit Service cd2a00
   if (interp[2]<32767)
Packit Service cd2a00
      interp[2]+=1;
Packit Service cd2a00
}
Packit Service cd2a00
#else
Packit Service cd2a00
static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
Packit Service cd2a00
{
Packit Service cd2a00
   /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
Packit Service cd2a00
   but I know it's MMSE-optimal on a sinc */
Packit Service cd2a00
   interp[0] =  -0.16667f*frac + 0.16667f*frac*frac*frac;
Packit Service cd2a00
   interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac;
Packit Service cd2a00
   /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
Packit Service cd2a00
   interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac;
Packit Service cd2a00
   /* Just to make sure we don't have rounding problems */
Packit Service cd2a00
   interp[2] = 1.-interp[0]-interp[1]-interp[3];
Packit Service cd2a00
}
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   int N = st->filt_len;
Packit Service cd2a00
   int out_sample = 0;
Packit Service cd2a00
   spx_word16_t *mem;
Packit Service cd2a00
   int last_sample = st->last_sample[channel_index];
Packit Service cd2a00
   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
Packit Service cd2a00
   mem = st->mem + channel_index * st->mem_alloc_size;
Packit Service cd2a00
   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
Packit Service cd2a00
   {
Packit Service cd2a00
      int j;
Packit Service cd2a00
      spx_word32_t sum=0;
Packit Service cd2a00
      
Packit Service cd2a00
      /* We already have all the filter coefficients pre-computed in the table */
Packit Service cd2a00
      const spx_word16_t *ptr;
Packit Service cd2a00
      /* Do the memory part */
Packit Service cd2a00
      for (j=0;last_sample-N+1+j < 0;j++)
Packit Service cd2a00
      {
Packit Service cd2a00
         sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]);
Packit Service cd2a00
      }
Packit Service cd2a00
      
Packit Service cd2a00
      /* Do the new part */
Packit Service cd2a00
      ptr = in+st->in_stride*(last_sample-N+1+j);
Packit Service cd2a00
      for (;j
Packit Service cd2a00
      {
Packit Service cd2a00
         sum += MULT16_16(*ptr,st->sinc_table[samp_frac_num*st->filt_len+j]);
Packit Service cd2a00
         ptr += st->in_stride;
Packit Service cd2a00
      }
Packit Service cd2a00
   
Packit Service cd2a00
      *out = PSHR32(sum,15);
Packit Service cd2a00
      out += st->out_stride;
Packit Service cd2a00
      out_sample++;
Packit Service cd2a00
      last_sample += st->int_advance;
Packit Service cd2a00
      samp_frac_num += st->frac_advance;
Packit Service cd2a00
      if (samp_frac_num >= st->den_rate)
Packit Service cd2a00
      {
Packit Service cd2a00
         samp_frac_num -= st->den_rate;
Packit Service cd2a00
         last_sample++;
Packit Service cd2a00
      }
Packit Service cd2a00
   }
Packit Service cd2a00
   st->last_sample[channel_index] = last_sample;
Packit Service cd2a00
   st->samp_frac_num[channel_index] = samp_frac_num;
Packit Service cd2a00
   return out_sample;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
#else
Packit Service cd2a00
/* This is the same as the previous function, except with a double-precision accumulator */
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   int N = st->filt_len;
Packit Service cd2a00
   int out_sample = 0;
Packit Service cd2a00
   spx_word16_t *mem;
Packit Service cd2a00
   int last_sample = st->last_sample[channel_index];
Packit Service cd2a00
   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
Packit Service cd2a00
   mem = st->mem + channel_index * st->mem_alloc_size;
Packit Service cd2a00
   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
Packit Service cd2a00
   {
Packit Service cd2a00
      int j;
Packit Service cd2a00
      double sum=0;
Packit Service cd2a00
      
Packit Service cd2a00
      /* We already have all the filter coefficients pre-computed in the table */
Packit Service cd2a00
      const spx_word16_t *ptr;
Packit Service cd2a00
      /* Do the memory part */
Packit Service cd2a00
      for (j=0;last_sample-N+1+j < 0;j++)
Packit Service cd2a00
      {
Packit Service cd2a00
         sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
Packit Service cd2a00
      }
Packit Service cd2a00
      
Packit Service cd2a00
      /* Do the new part */
Packit Service cd2a00
      ptr = in+st->in_stride*(last_sample-N+1+j);
Packit Service cd2a00
      for (;j
Packit Service cd2a00
      {
Packit Service cd2a00
         sum += MULT16_16(*ptr,(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
Packit Service cd2a00
         ptr += st->in_stride;
Packit Service cd2a00
      }
Packit Service cd2a00
   
Packit Service cd2a00
      *out = sum;
Packit Service cd2a00
      out += st->out_stride;
Packit Service cd2a00
      out_sample++;
Packit Service cd2a00
      last_sample += st->int_advance;
Packit Service cd2a00
      samp_frac_num += st->frac_advance;
Packit Service cd2a00
      if (samp_frac_num >= st->den_rate)
Packit Service cd2a00
      {
Packit Service cd2a00
         samp_frac_num -= st->den_rate;
Packit Service cd2a00
         last_sample++;
Packit Service cd2a00
      }
Packit Service cd2a00
   }
Packit Service cd2a00
   st->last_sample[channel_index] = last_sample;
Packit Service cd2a00
   st->samp_frac_num[channel_index] = samp_frac_num;
Packit Service cd2a00
   return out_sample;
Packit Service cd2a00
}
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   int N = st->filt_len;
Packit Service cd2a00
   int out_sample = 0;
Packit Service cd2a00
   spx_word16_t *mem;
Packit Service cd2a00
   int last_sample = st->last_sample[channel_index];
Packit Service cd2a00
   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
Packit Service cd2a00
   mem = st->mem + channel_index * st->mem_alloc_size;
Packit Service cd2a00
   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
Packit Service cd2a00
   {
Packit Service cd2a00
      int j;
Packit Service cd2a00
      spx_word32_t sum=0;
Packit Service cd2a00
      
Packit Service cd2a00
      /* We need to interpolate the sinc filter */
Packit Service cd2a00
      spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f};
Packit Service cd2a00
      spx_word16_t interp[4];
Packit Service cd2a00
      const spx_word16_t *ptr;
Packit Service cd2a00
      int offset;
Packit Service cd2a00
      spx_word16_t frac;
Packit Service cd2a00
      offset = samp_frac_num*st->oversample/st->den_rate;
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
      frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
Packit Service cd2a00
#else
Packit Service cd2a00
      frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
Packit Service cd2a00
#endif
Packit Service cd2a00
         /* This code is written like this to make it easy to optimise with SIMD.
Packit Service cd2a00
      For most DSPs, it would be best to split the loops in two because most DSPs 
Packit Service cd2a00
      have only two accumulators */
Packit Service cd2a00
      for (j=0;last_sample-N+1+j < 0;j++)
Packit Service cd2a00
      {
Packit Service cd2a00
         spx_word16_t curr_mem = mem[last_sample+j];
Packit Service cd2a00
         accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
Packit Service cd2a00
         accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
Packit Service cd2a00
         accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
Packit Service cd2a00
         accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
Packit Service cd2a00
      }
Packit Service cd2a00
      ptr = in+st->in_stride*(last_sample-N+1+j);
Packit Service cd2a00
      /* Do the new part */
Packit Service cd2a00
      for (;j
Packit Service cd2a00
      {
Packit Service cd2a00
         spx_word16_t curr_in = *ptr;
Packit Service cd2a00
         ptr += st->in_stride;
Packit Service cd2a00
         accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
Packit Service cd2a00
         accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
Packit Service cd2a00
         accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
Packit Service cd2a00
         accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
Packit Service cd2a00
      }
Packit Service cd2a00
      cubic_coef(frac, interp);
Packit Service cd2a00
      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]);
Packit Service cd2a00
   
Packit Service cd2a00
      *out = PSHR32(sum,15);
Packit Service cd2a00
      out += st->out_stride;
Packit Service cd2a00
      out_sample++;
Packit Service cd2a00
      last_sample += st->int_advance;
Packit Service cd2a00
      samp_frac_num += st->frac_advance;
Packit Service cd2a00
      if (samp_frac_num >= st->den_rate)
Packit Service cd2a00
      {
Packit Service cd2a00
         samp_frac_num -= st->den_rate;
Packit Service cd2a00
         last_sample++;
Packit Service cd2a00
      }
Packit Service cd2a00
   }
Packit Service cd2a00
   st->last_sample[channel_index] = last_sample;
Packit Service cd2a00
   st->samp_frac_num[channel_index] = samp_frac_num;
Packit Service cd2a00
   return out_sample;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
#else
Packit Service cd2a00
/* This is the same as the previous function, except with a double-precision accumulator */
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   int N = st->filt_len;
Packit Service cd2a00
   int out_sample = 0;
Packit Service cd2a00
   spx_word16_t *mem;
Packit Service cd2a00
   int last_sample = st->last_sample[channel_index];
Packit Service cd2a00
   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
Packit Service cd2a00
   mem = st->mem + channel_index * st->mem_alloc_size;
Packit Service cd2a00
   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
Packit Service cd2a00
   {
Packit Service cd2a00
      int j;
Packit Service cd2a00
      spx_word32_t sum=0;
Packit Service cd2a00
      
Packit Service cd2a00
      /* We need to interpolate the sinc filter */
Packit Service cd2a00
      double accum[4] = {0.f,0.f, 0.f, 0.f};
Packit Service cd2a00
      float interp[4];
Packit Service cd2a00
      const spx_word16_t *ptr;
Packit Service cd2a00
      float alpha = ((float)samp_frac_num)/st->den_rate;
Packit Service cd2a00
      int offset = samp_frac_num*st->oversample/st->den_rate;
Packit Service cd2a00
      float frac = alpha*st->oversample - offset;
Packit Service cd2a00
         /* This code is written like this to make it easy to optimise with SIMD.
Packit Service cd2a00
      For most DSPs, it would be best to split the loops in two because most DSPs 
Packit Service cd2a00
      have only two accumulators */
Packit Service cd2a00
      for (j=0;last_sample-N+1+j < 0;j++)
Packit Service cd2a00
      {
Packit Service cd2a00
         double curr_mem = mem[last_sample+j];
Packit Service cd2a00
         accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
Packit Service cd2a00
         accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
Packit Service cd2a00
         accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
Packit Service cd2a00
         accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
Packit Service cd2a00
      }
Packit Service cd2a00
      ptr = in+st->in_stride*(last_sample-N+1+j);
Packit Service cd2a00
      /* Do the new part */
Packit Service cd2a00
      for (;j
Packit Service cd2a00
      {
Packit Service cd2a00
         double curr_in = *ptr;
Packit Service cd2a00
         ptr += st->in_stride;
Packit Service cd2a00
         accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
Packit Service cd2a00
         accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
Packit Service cd2a00
         accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
Packit Service cd2a00
         accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
Packit Service cd2a00
      }
Packit Service cd2a00
      cubic_coef(frac, interp);
Packit Service cd2a00
      sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3];
Packit Service cd2a00
   
Packit Service cd2a00
      *out = PSHR32(sum,15);
Packit Service cd2a00
      out += st->out_stride;
Packit Service cd2a00
      out_sample++;
Packit Service cd2a00
      last_sample += st->int_advance;
Packit Service cd2a00
      samp_frac_num += st->frac_advance;
Packit Service cd2a00
      if (samp_frac_num >= st->den_rate)
Packit Service cd2a00
      {
Packit Service cd2a00
         samp_frac_num -= st->den_rate;
Packit Service cd2a00
         last_sample++;
Packit Service cd2a00
      }
Packit Service cd2a00
   }
Packit Service cd2a00
   st->last_sample[channel_index] = last_sample;
Packit Service cd2a00
   st->samp_frac_num[channel_index] = samp_frac_num;
Packit Service cd2a00
   return out_sample;
Packit Service cd2a00
}
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
static void update_filter(SpeexResamplerState *st)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t old_length;
Packit Service cd2a00
   
Packit Service cd2a00
   old_length = st->filt_len;
Packit Service cd2a00
   st->oversample = quality_map[st->quality].oversample;
Packit Service cd2a00
   st->filt_len = quality_map[st->quality].base_length;
Packit Service cd2a00
   
Packit Service cd2a00
   if (st->num_rate > st->den_rate)
Packit Service cd2a00
   {
Packit Service cd2a00
      /* down-sampling */
Packit Service cd2a00
      st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
Packit Service cd2a00
      /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
Packit Service cd2a00
      st->filt_len = st->filt_len*st->num_rate / st->den_rate;
Packit Service cd2a00
      /* Round down to make sure we have a multiple of 4 */
Packit Service cd2a00
      st->filt_len &= (~0x3);
Packit Service cd2a00
      if (2*st->den_rate < st->num_rate)
Packit Service cd2a00
         st->oversample >>= 1;
Packit Service cd2a00
      if (4*st->den_rate < st->num_rate)
Packit Service cd2a00
         st->oversample >>= 1;
Packit Service cd2a00
      if (8*st->den_rate < st->num_rate)
Packit Service cd2a00
         st->oversample >>= 1;
Packit Service cd2a00
      if (16*st->den_rate < st->num_rate)
Packit Service cd2a00
         st->oversample >>= 1;
Packit Service cd2a00
      if (st->oversample < 1)
Packit Service cd2a00
         st->oversample = 1;
Packit Service cd2a00
   } else {
Packit Service cd2a00
      /* up-sampling */
Packit Service cd2a00
      st->cutoff = quality_map[st->quality].upsample_bandwidth;
Packit Service cd2a00
   }
Packit Service cd2a00
Packit Service cd2a00
   /* Choose the resampling type that requires the least amount of memory */
Packit Service cd2a00
   if (st->den_rate <= st->oversample)
Packit Service cd2a00
   {
Packit Service cd2a00
      spx_uint32_t i;
Packit Service cd2a00
      if (!st->sinc_table)
Packit Service cd2a00
         st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));
Packit Service cd2a00
      else if (st->sinc_table_length < st->filt_len*st->den_rate)
Packit Service cd2a00
      {
Packit Service cd2a00
         st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));
Packit Service cd2a00
         st->sinc_table_length = st->filt_len*st->den_rate;
Packit Service cd2a00
      }
Packit Service cd2a00
      for (i=0;i<st->den_rate;i++)
Packit Service cd2a00
      {
Packit Service cd2a00
         spx_int32_t j;
Packit Service cd2a00
         for (j=0;j<st->filt_len;j++)
Packit Service cd2a00
         {
Packit Service cd2a00
            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);
Packit Service cd2a00
         }
Packit Service cd2a00
      }
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
      st->resampler_ptr = resampler_basic_direct_single;
Packit Service cd2a00
#else
Packit Service cd2a00
      if (st->quality>8)
Packit Service cd2a00
         st->resampler_ptr = resampler_basic_direct_double;
Packit Service cd2a00
      else
Packit Service cd2a00
         st->resampler_ptr = resampler_basic_direct_single;
Packit Service cd2a00
#endif
Packit Service cd2a00
      /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/
Packit Service cd2a00
   } else {
Packit Service cd2a00
      spx_int32_t i;
Packit Service cd2a00
      if (!st->sinc_table)
Packit Service cd2a00
         st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
Packit Service cd2a00
      else if (st->sinc_table_length < st->filt_len*st->oversample+8)
Packit Service cd2a00
      {
Packit Service cd2a00
         st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
Packit Service cd2a00
         st->sinc_table_length = st->filt_len*st->oversample+8;
Packit Service cd2a00
      }
Packit Service cd2a00
      for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)
Packit Service cd2a00
         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);
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
      st->resampler_ptr = resampler_basic_interpolate_single;
Packit Service cd2a00
#else
Packit Service cd2a00
      if (st->quality>8)
Packit Service cd2a00
         st->resampler_ptr = resampler_basic_interpolate_double;
Packit Service cd2a00
      else
Packit Service cd2a00
         st->resampler_ptr = resampler_basic_interpolate_single;
Packit Service cd2a00
#endif
Packit Service cd2a00
      /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/
Packit Service cd2a00
   }
Packit Service cd2a00
   st->int_advance = st->num_rate/st->den_rate;
Packit Service cd2a00
   st->frac_advance = st->num_rate%st->den_rate;
Packit Service cd2a00
Packit Service cd2a00
   
Packit Service cd2a00
   /* Here's the place where we update the filter memory to take into account
Packit Service cd2a00
      the change in filter length. It's probably the messiest part of the code
Packit Service cd2a00
      due to handling of lots of corner cases. */
Packit Service cd2a00
   if (!st->mem)
Packit Service cd2a00
   {
Packit Service cd2a00
      spx_uint32_t i;
Packit Service cd2a00
      st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
Packit Service cd2a00
      for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
Packit Service cd2a00
         st->mem[i] = 0;
Packit Service cd2a00
      st->mem_alloc_size = st->filt_len-1;
Packit Service cd2a00
      /*speex_warning("init filter");*/
Packit Service cd2a00
   } else if (!st->started)
Packit Service cd2a00
   {
Packit Service cd2a00
      spx_uint32_t i;
Packit Service cd2a00
      st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
Packit Service cd2a00
      for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
Packit Service cd2a00
         st->mem[i] = 0;
Packit Service cd2a00
      st->mem_alloc_size = st->filt_len-1;
Packit Service cd2a00
      /*speex_warning("reinit filter");*/
Packit Service cd2a00
   } else if (st->filt_len > old_length)
Packit Service cd2a00
   {
Packit Service cd2a00
      spx_int32_t i;
Packit Service cd2a00
      /* Increase the filter length */
Packit Service cd2a00
      /*speex_warning("increase filter size");*/
Packit Service cd2a00
      int old_alloc_size = st->mem_alloc_size;
Packit Service cd2a00
      if (st->filt_len-1 > st->mem_alloc_size)
Packit Service cd2a00
      {
Packit Service cd2a00
         st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
Packit Service cd2a00
         st->mem_alloc_size = st->filt_len-1;
Packit Service cd2a00
      }
Packit Service cd2a00
      for (i=st->nb_channels-1;i>=0;i--)
Packit Service cd2a00
      {
Packit Service cd2a00
         spx_int32_t j;
Packit Service cd2a00
         spx_uint32_t olen = old_length;
Packit Service cd2a00
         /*if (st->magic_samples[i])*/
Packit Service cd2a00
         {
Packit Service cd2a00
            /* Try and remove the magic samples as if nothing had happened */
Packit Service cd2a00
            
Packit Service cd2a00
            /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
Packit Service cd2a00
            olen = old_length + 2*st->magic_samples[i];
Packit Service cd2a00
            for (j=old_length-2+st->magic_samples[i];j>=0;j--)
Packit Service cd2a00
               st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
Packit Service cd2a00
            for (j=0;j<st->magic_samples[i];j++)
Packit Service cd2a00
               st->mem[i*st->mem_alloc_size+j] = 0;
Packit Service cd2a00
            st->magic_samples[i] = 0;
Packit Service cd2a00
         }
Packit Service cd2a00
         if (st->filt_len > olen)
Packit Service cd2a00
         {
Packit Service cd2a00
            /* If the new filter length is still bigger than the "augmented" length */
Packit Service cd2a00
            /* Copy data going backward */
Packit Service cd2a00
            for (j=0;j
Packit Service cd2a00
               st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
Packit Service cd2a00
            /* Then put zeros for lack of anything better */
Packit Service cd2a00
            for (;j<st->filt_len-1;j++)
Packit Service cd2a00
               st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
Packit Service cd2a00
            /* Adjust last_sample */
Packit Service cd2a00
            st->last_sample[i] += (st->filt_len - olen)/2;
Packit Service cd2a00
         } else {
Packit Service cd2a00
            /* Put back some of the magic! */
Packit Service cd2a00
            st->magic_samples[i] = (olen - st->filt_len)/2;
Packit Service cd2a00
            for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
Packit Service cd2a00
               st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
Packit Service cd2a00
         }
Packit Service cd2a00
      }
Packit Service cd2a00
   } else if (st->filt_len < old_length)
Packit Service cd2a00
   {
Packit Service cd2a00
      spx_uint32_t i;
Packit Service cd2a00
      /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
Packit Service cd2a00
         samples so they can be used directly as input the next time(s) */
Packit Service cd2a00
      for (i=0;i<st->nb_channels;i++)
Packit Service cd2a00
      {
Packit Service cd2a00
         spx_uint32_t j;
Packit Service cd2a00
         spx_uint32_t old_magic = st->magic_samples[i];
Packit Service cd2a00
         st->magic_samples[i] = (old_length - st->filt_len)/2;
Packit Service cd2a00
         /* We must copy some of the memory that's no longer used */
Packit Service cd2a00
         /* Copy data going backward */
Packit Service cd2a00
         for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
Packit Service cd2a00
            st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
Packit Service cd2a00
         st->magic_samples[i] += old_magic;
Packit Service cd2a00
      }
Packit Service cd2a00
   }
Packit Service cd2a00
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
Packit Service cd2a00
{
Packit Service cd2a00
   return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t i;
Packit Service cd2a00
   SpeexResamplerState *st;
Packit Service cd2a00
   if (quality > 10 || quality < 0)
Packit Service cd2a00
   {
Packit Service cd2a00
      if (err)
Packit Service cd2a00
         *err = RESAMPLER_ERR_INVALID_ARG;
Packit Service cd2a00
      return NULL;
Packit Service cd2a00
   }
Packit Service cd2a00
   st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
Packit Service cd2a00
   st->initialised = 0;
Packit Service cd2a00
   st->started = 0;
Packit Service cd2a00
   st->in_rate = 0;
Packit Service cd2a00
   st->out_rate = 0;
Packit Service cd2a00
   st->num_rate = 0;
Packit Service cd2a00
   st->den_rate = 0;
Packit Service cd2a00
   st->quality = -1;
Packit Service cd2a00
   st->sinc_table_length = 0;
Packit Service cd2a00
   st->mem_alloc_size = 0;
Packit Service cd2a00
   st->filt_len = 0;
Packit Service cd2a00
   st->mem = 0;
Packit Service cd2a00
   st->resampler_ptr = 0;
Packit Service cd2a00
         
Packit Service cd2a00
   st->cutoff = 1.f;
Packit Service cd2a00
   st->nb_channels = nb_channels;
Packit Service cd2a00
   st->in_stride = 1;
Packit Service cd2a00
   st->out_stride = 1;
Packit Service cd2a00
   
Packit Service cd2a00
   /* Per channel data */
Packit Service cd2a00
   st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
Packit Service cd2a00
   st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
Packit Service cd2a00
   st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
Packit Service cd2a00
   for (i=0;i
Packit Service cd2a00
   {
Packit Service cd2a00
      st->last_sample[i] = 0;
Packit Service cd2a00
      st->magic_samples[i] = 0;
Packit Service cd2a00
      st->samp_frac_num[i] = 0;
Packit Service cd2a00
   }
Packit Service cd2a00
Packit Service cd2a00
   speex_resampler_set_quality(st, quality);
Packit Service cd2a00
   speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
Packit Service cd2a00
Packit Service cd2a00
   
Packit Service cd2a00
   update_filter(st);
Packit Service cd2a00
   
Packit Service cd2a00
   st->initialised = 1;
Packit Service cd2a00
   if (err)
Packit Service cd2a00
      *err = RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
Packit Service cd2a00
   return st;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
void speex_resampler_destroy(SpeexResamplerState *st)
Packit Service cd2a00
{
Packit Service cd2a00
   speex_free(st->mem);
Packit Service cd2a00
   speex_free(st->sinc_table);
Packit Service cd2a00
   speex_free(st->last_sample);
Packit Service cd2a00
   speex_free(st->magic_samples);
Packit Service cd2a00
   speex_free(st->samp_frac_num);
Packit Service cd2a00
   speex_free(st);
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
Packit Service cd2a00
Packit Service cd2a00
static int speex_resampler_process_native(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)
Packit Service cd2a00
{
Packit Service cd2a00
   int j=0;
Packit Service cd2a00
   int N = st->filt_len;
Packit Service cd2a00
   int out_sample = 0;
Packit Service cd2a00
   spx_word16_t *mem;
Packit Service cd2a00
   spx_uint32_t tmp_out_len = 0;
Packit Service cd2a00
   mem = st->mem + channel_index * st->mem_alloc_size;
Packit Service cd2a00
   st->started = 1;
Packit Service cd2a00
   
Packit Service cd2a00
   /* Handle the case where we have samples left from a reduction in filter length */
Packit Service cd2a00
   if (st->magic_samples[channel_index])
Packit Service cd2a00
   {
Packit Service cd2a00
      int istride_save;
Packit Service cd2a00
      spx_uint32_t tmp_in_len;
Packit Service cd2a00
      spx_uint32_t tmp_magic;
Packit Service cd2a00
      
Packit Service cd2a00
      istride_save = st->in_stride;
Packit Service cd2a00
      tmp_in_len = st->magic_samples[channel_index];
Packit Service cd2a00
      tmp_out_len = *out_len;
Packit Service cd2a00
      /* magic_samples needs to be set to zero to avoid infinite recursion */
Packit Service cd2a00
      tmp_magic = st->magic_samples[channel_index];
Packit Service cd2a00
      st->magic_samples[channel_index] = 0;
Packit Service cd2a00
      st->in_stride = 1;
Packit Service cd2a00
      speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len);
Packit Service cd2a00
      st->in_stride = istride_save;
Packit Service cd2a00
      /*speex_warning_int("extra samples:", tmp_out_len);*/
Packit Service cd2a00
      /* If we couldn't process all "magic" input samples, save the rest for next time */
Packit Service cd2a00
      if (tmp_in_len < tmp_magic)
Packit Service cd2a00
      {
Packit Service cd2a00
         spx_uint32_t i;
Packit Service cd2a00
         st->magic_samples[channel_index] = tmp_magic-tmp_in_len;
Packit Service cd2a00
         for (i=0;i<st->magic_samples[channel_index];i++)
Packit Service cd2a00
            mem[N-1+i]=mem[N-1+i+tmp_in_len];
Packit Service cd2a00
      }
Packit Service cd2a00
      out += tmp_out_len*st->out_stride;
Packit Service cd2a00
      *out_len -= tmp_out_len;
Packit Service cd2a00
   }
Packit Service cd2a00
   
Packit Service cd2a00
   /* Call the right resampler through the function ptr */
Packit Service cd2a00
   out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len);
Packit Service cd2a00
   
Packit Service cd2a00
   if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
Packit Service cd2a00
      *in_len = st->last_sample[channel_index];
Packit Service cd2a00
   *out_len = out_sample+tmp_out_len;
Packit Service cd2a00
   st->last_sample[channel_index] -= *in_len;
Packit Service cd2a00
   
Packit Service cd2a00
   for (j=0;j
Packit Service cd2a00
      mem[j] = mem[j+*in_len];
Packit Service cd2a00
   for (;j
Packit Service cd2a00
      mem[j] = in[st->in_stride*(j+*in_len-N+1)];
Packit Service cd2a00
   
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
#define FIXED_STACK_ALLOC 1024
Packit Service cd2a00
Packit Service cd2a00
#ifdef FIXED_POINT
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t i;
Packit Service cd2a00
   int istride_save, ostride_save;
Packit Service cd2a00
#ifdef VAR_ARRAYS
Packit Service cd2a00
   spx_word16_t x[*in_len];
Packit Service cd2a00
   spx_word16_t y[*out_len];
Packit Service cd2a00
   /*VARDECL(spx_word16_t *x);
Packit Service cd2a00
   VARDECL(spx_word16_t *y);
Packit Service cd2a00
   ALLOC(x, *in_len, spx_word16_t);
Packit Service cd2a00
   ALLOC(y, *out_len, spx_word16_t);*/
Packit Service cd2a00
   istride_save = st->in_stride;
Packit Service cd2a00
   ostride_save = st->out_stride;
Packit Service cd2a00
   for (i=0;i<*in_len;i++)
Packit Service cd2a00
      x[i] = WORD2INT(in[i*st->in_stride]);
Packit Service cd2a00
   st->in_stride = st->out_stride = 1;
Packit Service cd2a00
   speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
Packit Service cd2a00
   st->in_stride = istride_save;
Packit Service cd2a00
   st->out_stride = ostride_save;
Packit Service cd2a00
   for (i=0;i<*out_len;i++)
Packit Service cd2a00
      out[i*st->out_stride] = y[i];
Packit Service cd2a00
#else
Packit Service cd2a00
   spx_word16_t x[FIXED_STACK_ALLOC];
Packit Service cd2a00
   spx_word16_t y[FIXED_STACK_ALLOC];
Packit Service cd2a00
   spx_uint32_t ilen=*in_len, olen=*out_len;
Packit Service cd2a00
   istride_save = st->in_stride;
Packit Service cd2a00
   ostride_save = st->out_stride;
Packit Service cd2a00
   while (ilen && olen)
Packit Service cd2a00
   {
Packit Service cd2a00
      spx_uint32_t ichunk, ochunk;
Packit Service cd2a00
      ichunk = ilen;
Packit Service cd2a00
      ochunk = olen;
Packit Service cd2a00
      if (ichunk>FIXED_STACK_ALLOC)
Packit Service cd2a00
         ichunk=FIXED_STACK_ALLOC;
Packit Service cd2a00
      if (ochunk>FIXED_STACK_ALLOC)
Packit Service cd2a00
         ochunk=FIXED_STACK_ALLOC;
Packit Service cd2a00
      for (i=0;i
Packit Service cd2a00
         x[i] = WORD2INT(in[i*st->in_stride]);
Packit Service cd2a00
      st->in_stride = st->out_stride = 1;
Packit Service cd2a00
      speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
Packit Service cd2a00
      st->in_stride = istride_save;
Packit Service cd2a00
      st->out_stride = ostride_save;
Packit Service cd2a00
      for (i=0;i
Packit Service cd2a00
         out[i*st->out_stride] = y[i];
Packit Service cd2a00
      out += ochunk;
Packit Service cd2a00
      in += ichunk;
Packit Service cd2a00
      ilen -= ichunk;
Packit Service cd2a00
      olen -= ochunk;
Packit Service cd2a00
   }
Packit Service cd2a00
   *in_len -= ilen;
Packit Service cd2a00
   *out_len -= olen;   
Packit Service cd2a00
#endif
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
Packit Service cd2a00
}
Packit Service cd2a00
#else
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
Packit Service cd2a00
}
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t i;
Packit Service cd2a00
   int istride_save, ostride_save;
Packit Service cd2a00
#ifdef VAR_ARRAYS
Packit Service cd2a00
   spx_word16_t x[*in_len];
Packit Service cd2a00
   spx_word16_t y[*out_len];
Packit Service cd2a00
   /*VARDECL(spx_word16_t *x);
Packit Service cd2a00
   VARDECL(spx_word16_t *y);
Packit Service cd2a00
   ALLOC(x, *in_len, spx_word16_t);
Packit Service cd2a00
   ALLOC(y, *out_len, spx_word16_t);*/
Packit Service cd2a00
   istride_save = st->in_stride;
Packit Service cd2a00
   ostride_save = st->out_stride;
Packit Service cd2a00
   for (i=0;i<*in_len;i++)
Packit Service cd2a00
      x[i] = in[i*st->in_stride];
Packit Service cd2a00
   st->in_stride = st->out_stride = 1;
Packit Service cd2a00
   speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
Packit Service cd2a00
   st->in_stride = istride_save;
Packit Service cd2a00
   st->out_stride = ostride_save;
Packit Service cd2a00
   for (i=0;i<*out_len;i++)
Packit Service cd2a00
      out[i*st->out_stride] = WORD2INT(y[i]);
Packit Service cd2a00
#else
Packit Service cd2a00
   spx_word16_t x[FIXED_STACK_ALLOC];
Packit Service cd2a00
   spx_word16_t y[FIXED_STACK_ALLOC];
Packit Service cd2a00
   spx_uint32_t ilen=*in_len, olen=*out_len;
Packit Service cd2a00
   istride_save = st->in_stride;
Packit Service cd2a00
   ostride_save = st->out_stride;
Packit Service cd2a00
   while (ilen && olen)
Packit Service cd2a00
   {
Packit Service cd2a00
      spx_uint32_t ichunk, ochunk;
Packit Service cd2a00
      ichunk = ilen;
Packit Service cd2a00
      ochunk = olen;
Packit Service cd2a00
      if (ichunk>FIXED_STACK_ALLOC)
Packit Service cd2a00
         ichunk=FIXED_STACK_ALLOC;
Packit Service cd2a00
      if (ochunk>FIXED_STACK_ALLOC)
Packit Service cd2a00
         ochunk=FIXED_STACK_ALLOC;
Packit Service cd2a00
      for (i=0;i
Packit Service cd2a00
         x[i] = in[i*st->in_stride];
Packit Service cd2a00
      st->in_stride = st->out_stride = 1;
Packit Service cd2a00
      speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
Packit Service cd2a00
      st->in_stride = istride_save;
Packit Service cd2a00
      st->out_stride = ostride_save;
Packit Service cd2a00
      for (i=0;i
Packit Service cd2a00
         out[i*st->out_stride] = WORD2INT(y[i]);
Packit Service cd2a00
      out += ochunk;
Packit Service cd2a00
      in += ichunk;
Packit Service cd2a00
      ilen -= ichunk;
Packit Service cd2a00
      olen -= ochunk;
Packit Service cd2a00
   }
Packit Service cd2a00
   *in_len -= ilen;
Packit Service cd2a00
   *out_len -= olen;   
Packit Service cd2a00
#endif
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
#endif
Packit Service cd2a00
Packit Service cd2a00
int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t i;
Packit Service cd2a00
   int istride_save, ostride_save;
Packit Service cd2a00
   spx_uint32_t bak_len = *out_len;
Packit Service cd2a00
   istride_save = st->in_stride;
Packit Service cd2a00
   ostride_save = st->out_stride;
Packit Service cd2a00
   st->in_stride = st->out_stride = st->nb_channels;
Packit Service cd2a00
   for (i=0;i<st->nb_channels;i++)
Packit Service cd2a00
   {
Packit Service cd2a00
      *out_len = bak_len;
Packit Service cd2a00
      speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
Packit Service cd2a00
   }
Packit Service cd2a00
   st->in_stride = istride_save;
Packit Service cd2a00
   st->out_stride = ostride_save;
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
               
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t i;
Packit Service cd2a00
   int istride_save, ostride_save;
Packit Service cd2a00
   spx_uint32_t bak_len = *out_len;
Packit Service cd2a00
   istride_save = st->in_stride;
Packit Service cd2a00
   ostride_save = st->out_stride;
Packit Service cd2a00
   st->in_stride = st->out_stride = st->nb_channels;
Packit Service cd2a00
   for (i=0;i<st->nb_channels;i++)
Packit Service cd2a00
   {
Packit Service cd2a00
      *out_len = bak_len;
Packit Service cd2a00
      speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
Packit Service cd2a00
   }
Packit Service cd2a00
   st->in_stride = istride_save;
Packit Service cd2a00
   st->out_stride = ostride_save;
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
Packit Service cd2a00
{
Packit Service cd2a00
   return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
Packit Service cd2a00
{
Packit Service cd2a00
   *in_rate = st->in_rate;
Packit Service cd2a00
   *out_rate = st->out_rate;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
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)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t fact;
Packit Service cd2a00
   spx_uint32_t old_den;
Packit Service cd2a00
   spx_uint32_t i;
Packit Service cd2a00
   if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
Packit Service cd2a00
      return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
   
Packit Service cd2a00
   old_den = st->den_rate;
Packit Service cd2a00
   st->in_rate = in_rate;
Packit Service cd2a00
   st->out_rate = out_rate;
Packit Service cd2a00
   st->num_rate = ratio_num;
Packit Service cd2a00
   st->den_rate = ratio_den;
Packit Service cd2a00
   /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
Packit Service cd2a00
   for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
Packit Service cd2a00
   {
Packit Service cd2a00
      while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
Packit Service cd2a00
      {
Packit Service cd2a00
         st->num_rate /= fact;
Packit Service cd2a00
         st->den_rate /= fact;
Packit Service cd2a00
      }
Packit Service cd2a00
   }
Packit Service cd2a00
      
Packit Service cd2a00
   if (old_den > 0)
Packit Service cd2a00
   {
Packit Service cd2a00
      for (i=0;i<st->nb_channels;i++)
Packit Service cd2a00
      {
Packit Service cd2a00
         st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
Packit Service cd2a00
         /* Safety net */
Packit Service cd2a00
         if (st->samp_frac_num[i] >= st->den_rate)
Packit Service cd2a00
            st->samp_frac_num[i] = st->den_rate-1;
Packit Service cd2a00
      }
Packit Service cd2a00
   }
Packit Service cd2a00
   
Packit Service cd2a00
   if (st->initialised)
Packit Service cd2a00
      update_filter(st);
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
Packit Service cd2a00
{
Packit Service cd2a00
   *ratio_num = st->num_rate;
Packit Service cd2a00
   *ratio_den = st->den_rate;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
Packit Service cd2a00
{
Packit Service cd2a00
   if (quality > 10 || quality < 0)
Packit Service cd2a00
      return RESAMPLER_ERR_INVALID_ARG;
Packit Service cd2a00
   if (st->quality == quality)
Packit Service cd2a00
      return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
   st->quality = quality;
Packit Service cd2a00
   if (st->initialised)
Packit Service cd2a00
      update_filter(st);
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
Packit Service cd2a00
{
Packit Service cd2a00
   *quality = st->quality;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
Packit Service cd2a00
{
Packit Service cd2a00
   st->in_stride = stride;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
Packit Service cd2a00
{
Packit Service cd2a00
   *stride = st->in_stride;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
Packit Service cd2a00
{
Packit Service cd2a00
   st->out_stride = stride;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
Packit Service cd2a00
{
Packit Service cd2a00
   *stride = st->out_stride;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
int speex_resampler_skip_zeros(SpeexResamplerState *st)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t i;
Packit Service cd2a00
   for (i=0;i<st->nb_channels;i++)
Packit Service cd2a00
      st->last_sample[i] = st->filt_len/2;
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
int speex_resampler_reset_mem(SpeexResamplerState *st)
Packit Service cd2a00
{
Packit Service cd2a00
   spx_uint32_t i;
Packit Service cd2a00
   for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
Packit Service cd2a00
      st->mem[i] = 0;
Packit Service cd2a00
   return RESAMPLER_ERR_SUCCESS;
Packit Service cd2a00
}
Packit Service cd2a00
Packit Service cd2a00
const char *speex_resampler_strerror(int err)
Packit Service cd2a00
{
Packit Service cd2a00
   switch (err)
Packit Service cd2a00
   {
Packit Service cd2a00
      case RESAMPLER_ERR_SUCCESS:
Packit Service cd2a00
         return "Success.";
Packit Service cd2a00
      case RESAMPLER_ERR_ALLOC_FAILED:
Packit Service cd2a00
         return "Memory allocation failed.";
Packit Service cd2a00
      case RESAMPLER_ERR_BAD_STATE:
Packit Service cd2a00
         return "Bad resampler state.";
Packit Service cd2a00
      case RESAMPLER_ERR_INVALID_ARG:
Packit Service cd2a00
         return "Invalid argument.";
Packit Service cd2a00
      case RESAMPLER_ERR_PTR_OVERLAP:
Packit Service cd2a00
         return "Input and output buffers overlap.";
Packit Service cd2a00
      default:
Packit Service cd2a00
         return "Unknown error. Bad error code or strange version mismatch.";
Packit Service cd2a00
   }
Packit Service cd2a00
}