198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* Copyright (C) 2007-2008 Jean-Marc Valin 298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Copyright (C) 2008 Thorvald Natvig 398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project File: resample.c 598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Arbitrary resampling code 698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Redistribution and use in source and binary forms, with or without 898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project modification, are permitted provided that the following conditions are 998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project met: 1098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1. Redistributions of source code must retain the above copyright notice, 1298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project this list of conditions and the following disclaimer. 1398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 2. Redistributions in binary form must reproduce the above copyright 1598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project notice, this list of conditions and the following disclaimer in the 1698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project documentation and/or other materials provided with the distribution. 1798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3. The name of the author may not be used to endorse or promote products 1998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project derived from this software without specific prior written permission. 2098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 2198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project POSSIBILITY OF SUCH DAMAGE. 3298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/ 3398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* 3598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project The design goals of this code are: 3698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project - Very fast algorithm 3798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project - SIMD-friendly algorithm 3898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project - Low memory requirement 3998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project - Good *perceptual* quality (and not best SNR) 4098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 4198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Warning: This resampler is relatively new. Although I think I got rid of 4298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project all the major bugs and I don't expect the API to change anymore, there 4398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project may be something I've missed. So use with caution. 4498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 4598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project This algorithm is based on this original resampling algorithm: 4698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Smith, Julius O. Digital Audio Resampling Home Page 4798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Center for Computer Research in Music and Acoustics (CCRMA), 4898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Stanford University, 2007. 4998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Web published at http://www-ccrma.stanford.edu/~jos/resample/. 5098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 5198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project There is one main difference, though. This resampler uses cubic 5298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interpolation instead of linear interpolation in the above paper. This 5398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project makes the table much smaller and makes it possible to compute that table 5498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project on a per-stream basis. In turn, being able to tweak the table for each 5598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project stream makes it possible to both reduce complexity on simple ratios 5698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project (e.g. 2/3), and get rid of the rounding operations in the inner loop. 5798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project The latter both reduces CPU time and makes the algorithm more SIMD-friendly. 5898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/ 5998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 6098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef HAVE_CONFIG_H 6198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "config.h" 6298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 6398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 6498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef OUTSIDE_SPEEX 6598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <stdlib.h> 6698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void *speex_alloc (int size) {return calloc(size,1);} 6798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} 6898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void speex_free (void *ptr) {free(ptr);} 6998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "speex_resampler.h" 7098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "arch.h" 7198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else /* OUTSIDE_SPEEX */ 7298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 7398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "speex/speex_resampler.h" 7498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "arch.h" 7598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "os_support.h" 7698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif /* OUTSIDE_SPEEX */ 7798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 7898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "stack_alloc.h" 7998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <math.h> 8098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 8198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef M_PI 8298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define M_PI 3.14159263 8398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 8498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 8598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 8698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 8798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 8898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) 8998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 9098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 9198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define IMAX(a,b) ((a) > (b) ? (a) : (b)) 9298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define IMIN(a,b) ((a) < (b) ? (a) : (b)) 9398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 9498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef NULL 9598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define NULL 0 9698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 9798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 9898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef _USE_SSE 9998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "resample_sse.h" 10098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 10198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1026adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha#ifdef _USE_NEON 1036adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha#include "resample_neon.h" 1046adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha#endif 1056adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha 10698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* Numer of elements to allocate on the stack */ 10798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef VAR_ARRAYS 10898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define FIXED_STACK_ALLOC 8192 10998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 11098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define FIXED_STACK_ALLOC 1024 11198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 11298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 11398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projecttypedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); 11498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 11598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstruct SpeexResamplerState_ { 11698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t in_rate; 11798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t out_rate; 11898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t num_rate; 11998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t den_rate; 12098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 12198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int quality; 12298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t nb_channels; 12398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t filt_len; 12498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t mem_alloc_size; 12598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t buffer_size; 12698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int int_advance; 12798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int frac_advance; 12898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project float cutoff; 12998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t oversample; 13098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int initialised; 13198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int started; 13298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 13398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* These are per-channel */ 13498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_int32_t *last_sample; 13598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t *samp_frac_num; 13698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t *magic_samples; 13798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 13898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t *mem; 13998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t *sinc_table; 14098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t sinc_table_length; 14198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project resampler_basic_func resampler_ptr; 14298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 14398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int in_stride; 14498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int out_stride; 14598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} ; 14698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 14798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic double kaiser12_table[68] = { 14898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, 14998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, 15098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601, 15198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014, 15298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490, 15398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546, 15498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178, 15598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947, 15698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058, 15798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438, 15898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734, 15998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.00001000, 0.00000000}; 16098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* 16198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic double kaiser12_table[36] = { 16298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, 16398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, 16498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274, 16598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466, 16698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291, 16798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; 16898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/ 16998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic double kaiser10_table[36] = { 17098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, 17198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, 17298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962, 17398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451, 17498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739, 17598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000}; 17698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 17798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic double kaiser8_table[36] = { 17898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, 17998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, 18098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272, 18198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, 18298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, 18398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; 18498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 18598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic double kaiser6_table[36] = { 18698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, 18798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, 18898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561, 18998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058, 19098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600, 19198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000}; 19298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 19398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstruct FuncDef { 19498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project double *table; 19598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int oversample; 19698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}; 19798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 19898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic struct FuncDef _KAISER12 = {kaiser12_table, 64}; 19998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define KAISER12 (&_KAISER12) 20098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; 20198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define KAISER12 (&_KAISER12)*/ 20298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic struct FuncDef _KAISER10 = {kaiser10_table, 32}; 20398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define KAISER10 (&_KAISER10) 20498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic struct FuncDef _KAISER8 = {kaiser8_table, 32}; 20598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define KAISER8 (&_KAISER8) 20698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic struct FuncDef _KAISER6 = {kaiser6_table, 32}; 20798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define KAISER6 (&_KAISER6) 20898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 20998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstruct QualityMapping { 21098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int base_length; 21198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int oversample; 21298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project float downsample_bandwidth; 21398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project float upsample_bandwidth; 21498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project struct FuncDef *window_func; 21598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}; 21698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 21798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 21898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* This table maps conversion quality to internal parameters. There are two 21998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project reasons that explain why the up-sampling bandwidth is larger than the 22098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project down-sampling bandwidth: 22198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1) When up-sampling, we can assume that the spectrum is already attenuated 22298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project close to the Nyquist rate (from an A/D or a previous resampling filter) 22398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 2) Any aliasing that occurs very close to the Nyquist rate will be masked 22498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project by the sinusoids/noise just below the Nyquist rate (guaranteed only for 22598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project up-sampling). 22698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/ 22798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic const struct QualityMapping quality_map[11] = { 22898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */ 22998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */ 23098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ 23198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ 23298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ 23398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ 23498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ 23598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ 23698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ 23798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ 23898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ 23998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}; 24098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/*8,24,40,56,80,104,128,160,200,256,320*/ 24198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic double compute_func(float x, struct FuncDef *func) 24298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 24398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project float y, frac; 24498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project double interp[4]; 24598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int ind; 24698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project y = x*func->oversample; 24798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ind = (int)floor(y); 24898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project frac = (y-ind); 24998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* CSE with handle the repeated powers */ 25098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac); 25198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac); 25298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ 25398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); 25498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Just to make sure we don't have rounding problems */ 25598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[1] = 1.f-interp[3]-interp[2]-interp[0]; 25698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 25798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*sum = frac*accum[1] + (1-frac)*accum[2];*/ 25898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; 25998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 26098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 26198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#if 0 26298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <stdio.h> 26398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint main(int argc, char **argv) 26498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 26598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int i; 26698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<256;i++) 26798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 26898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project printf ("%f\n", compute_func(i/256., KAISER12)); 26998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 27098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return 0; 27198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 27298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 27398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 27498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 27598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* The slow way of computing a sinc for the table. Should improve that some day */ 27698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) 27798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 27898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*fprintf (stderr, "%f ", x);*/ 27998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project float xx = x * cutoff; 28098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (fabs(x)<1e-6f) 28198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return WORD2INT(32768.*cutoff); 28298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project else if (fabs(x) > .5f*N) 28398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return 0; 28498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*FIXME: Can it really be any slower than this? */ 28598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func)); 28698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 28798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 28898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* The slow way of computing a sinc for the table. Should improve that some day */ 28998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) 29098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 29198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*fprintf (stderr, "%f ", x);*/ 29298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project float xx = x * cutoff; 29398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (fabs(x)<1e-6) 29498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return cutoff; 29598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project else if (fabs(x) > .5*N) 29698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return 0; 29798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*FIXME: Can it really be any slower than this? */ 29898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func); 29998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 30098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 30198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 30298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 30398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void cubic_coef(spx_word16_t x, spx_word16_t interp[4]) 30498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 30598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation 30698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project but I know it's MMSE-optimal on a sinc */ 30798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t x2, x3; 30898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project x2 = MULT16_16_P15(x, x); 30998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project x3 = MULT16_16_P15(x, x2); 31098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15); 31198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1)); 31298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15); 31398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Just to make sure we don't have rounding problems */ 31498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3]; 31598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (interp[2]<32767) 31698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[2]+=1; 31798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 31898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 31998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void cubic_coef(spx_word16_t frac, spx_word16_t interp[4]) 32098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 32198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation 32298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project but I know it's MMSE-optimal on a sinc */ 32398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac; 32498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac; 32598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ 32698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac; 32798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Just to make sure we don't have rounding problems */ 32898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project interp[2] = 1.-interp[0]-interp[1]-interp[3]; 32998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 33098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 33198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 33298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic 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) 33398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 33498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int N = st->filt_len; 33598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int out_sample = 0; 33698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int last_sample = st->last_sample[channel_index]; 33798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 33898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t *sinc_table = st->sinc_table; 33998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int out_stride = st->out_stride; 34098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int int_advance = st->int_advance; 34198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int frac_advance = st->frac_advance; 34298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_uint32_t den_rate = st->den_rate; 34398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word32_t sum; 34498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int j; 34598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 34698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 34798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 34898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; 34998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t *iptr = & in[last_sample]; 35098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 35198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_INNER_PRODUCT_SINGLE 35298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project float accum[4] = {0,0,0,0}; 35398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 35498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<N;j+=4) { 35598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[0] += sinc[j]*iptr[j]; 35698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[1] += sinc[j+1]*iptr[j+1]; 35798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[2] += sinc[j+2]*iptr[j+2]; 35898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[3] += sinc[j+3]*iptr[j+3]; 35998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 36098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project sum = accum[0] + accum[1] + accum[2] + accum[3]; 3616adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha sum = SATURATE32PSHR(sum, 15, 32767); 36298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 36398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project sum = inner_product_single(sinc, iptr, N); 36498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 36598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3666adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha out[out_stride * out_sample++] = sum; 36798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project last_sample += int_advance; 36898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samp_frac_num += frac_advance; 36998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (samp_frac_num >= den_rate) 37098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 37198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samp_frac_num -= den_rate; 37298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project last_sample++; 37398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 37498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 37598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 37698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample[channel_index] = last_sample; 37798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->samp_frac_num[channel_index] = samp_frac_num; 37898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return out_sample; 37998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 38098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 38198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 38298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 38398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* This is the same as the previous function, except with a double-precision accumulator */ 38498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic 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) 38598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 38698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int N = st->filt_len; 38798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int out_sample = 0; 38898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int last_sample = st->last_sample[channel_index]; 38998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 39098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t *sinc_table = st->sinc_table; 39198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int out_stride = st->out_stride; 39298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int int_advance = st->int_advance; 39398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int frac_advance = st->frac_advance; 39498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_uint32_t den_rate = st->den_rate; 39598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project double sum; 39698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int j; 39798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 39898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 39998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 40098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; 40198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t *iptr = & in[last_sample]; 40298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 40398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE 40498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project double accum[4] = {0,0,0,0}; 40598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 40698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<N;j+=4) { 40798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[0] += sinc[j]*iptr[j]; 40898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[1] += sinc[j+1]*iptr[j+1]; 40998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[2] += sinc[j+2]*iptr[j+2]; 41098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[3] += sinc[j+3]*iptr[j+3]; 41198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 41298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project sum = accum[0] + accum[1] + accum[2] + accum[3]; 41398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 41498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project sum = inner_product_double(sinc, iptr, N); 41598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 41698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 41798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project out[out_stride * out_sample++] = PSHR32(sum, 15); 41898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project last_sample += int_advance; 41998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samp_frac_num += frac_advance; 42098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (samp_frac_num >= den_rate) 42198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 42298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samp_frac_num -= den_rate; 42398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project last_sample++; 42498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 42598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 42698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 42798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample[channel_index] = last_sample; 42898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->samp_frac_num[channel_index] = samp_frac_num; 42998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return out_sample; 43098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 43198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 43298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 43398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic 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) 43498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 43598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int N = st->filt_len; 43698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int out_sample = 0; 43798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int last_sample = st->last_sample[channel_index]; 43898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 43998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int out_stride = st->out_stride; 44098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int int_advance = st->int_advance; 44198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int frac_advance = st->frac_advance; 44298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_uint32_t den_rate = st->den_rate; 44398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int j; 44498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word32_t sum; 44598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 44698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 44798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 44898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t *iptr = & in[last_sample]; 44998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 45098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int offset = samp_frac_num*st->oversample/st->den_rate; 45198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 45298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 45398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 45498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 45598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 45698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t interp[4]; 45798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 45898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 45998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE 46098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word32_t accum[4] = {0,0,0,0}; 46198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 46298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<N;j++) { 46398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t curr_in=iptr[j]; 46498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 46598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 46698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); 46798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 46898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 46998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 47098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project cubic_coef(frac, interp); 47198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 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]); 4726adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha sum = SATURATE32PSHR(sum, 15, 32767); 47398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 47498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project cubic_coef(frac, interp); 47598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 47698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 47798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 4786adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha out[out_stride * out_sample++] = sum; 47998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project last_sample += int_advance; 48098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samp_frac_num += frac_advance; 48198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (samp_frac_num >= den_rate) 48298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 48398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samp_frac_num -= den_rate; 48498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project last_sample++; 48598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 48698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 48798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 48898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample[channel_index] = last_sample; 48998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->samp_frac_num[channel_index] = samp_frac_num; 49098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return out_sample; 49198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 49298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 49398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 49498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 49598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* This is the same as the previous function, except with a double-precision accumulator */ 49698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic 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) 49798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 49898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int N = st->filt_len; 49998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int out_sample = 0; 50098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int last_sample = st->last_sample[channel_index]; 50198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 50298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int out_stride = st->out_stride; 50398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int int_advance = st->int_advance; 50498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int frac_advance = st->frac_advance; 50598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_uint32_t den_rate = st->den_rate; 50698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int j; 50798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word32_t sum; 50898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 50998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 51098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 51198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t *iptr = & in[last_sample]; 51298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 51398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int offset = samp_frac_num*st->oversample/st->den_rate; 51498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 51598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 51698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 51798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 51898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 51998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t interp[4]; 52098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 52198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 52298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE 52398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project double accum[4] = {0,0,0,0}; 52498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 52598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<N;j++) { 52698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const double curr_in=iptr[j]; 52798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 52898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 52998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); 53098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 53198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 53298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 53398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project cubic_coef(frac, interp); 53498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 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]); 53598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 53698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project cubic_coef(frac, interp); 53798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 53898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 53998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 54098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project out[out_stride * out_sample++] = PSHR32(sum,15); 54198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project last_sample += int_advance; 54298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samp_frac_num += frac_advance; 54398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (samp_frac_num >= den_rate) 54498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 54598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samp_frac_num -= den_rate; 54698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project last_sample++; 54798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 54898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 54998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 55098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample[channel_index] = last_sample; 55198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->samp_frac_num[channel_index] = samp_frac_num; 55298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return out_sample; 55398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 55498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 55598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 55698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void update_filter(SpeexResamplerState *st) 55798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 55898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t old_length; 55998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 56098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project old_length = st->filt_len; 56198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->oversample = quality_map[st->quality].oversample; 56298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->filt_len = quality_map[st->quality].base_length; 56398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 56498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->num_rate > st->den_rate) 56598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 56698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* down-sampling */ 56798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; 56898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* FIXME: divide the numerator and denominator by a certain amount if they're too large */ 56998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->filt_len = st->filt_len*st->num_rate / st->den_rate; 57098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Round down to make sure we have a multiple of 4 */ 57198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->filt_len &= (~0x3); 57298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (2*st->den_rate < st->num_rate) 57398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->oversample >>= 1; 57498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (4*st->den_rate < st->num_rate) 57598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->oversample >>= 1; 57698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (8*st->den_rate < st->num_rate) 57798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->oversample >>= 1; 57898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (16*st->den_rate < st->num_rate) 57998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->oversample >>= 1; 58098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->oversample < 1) 58198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->oversample = 1; 58298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else { 58398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* up-sampling */ 58498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->cutoff = quality_map[st->quality].upsample_bandwidth; 58598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 58698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 58798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Choose the resampling type that requires the least amount of memory */ 5886adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha#ifdef RESAMPLE_FORCE_FULL_SINC_TABLE 5896adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha if (1) 5906adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha#else 59198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->den_rate <= st->oversample) 5926adacb80950e35de9df0a1d7a060aba795712494Jyri Sarha#endif 59398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 59498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 59598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (!st->sinc_table) 59698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t)); 59798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project else if (st->sinc_table_length < st->filt_len*st->den_rate) 59898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 59998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t)); 60098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->sinc_table_length = st->filt_len*st->den_rate; 60198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 60298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->den_rate;i++) 60398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 60498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_int32_t j; 60598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (j=0;j<st->filt_len;j++) 60698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 60798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 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); 60898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 60998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 61098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 61198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->resampler_ptr = resampler_basic_direct_single; 61298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 61398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->quality>8) 61498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->resampler_ptr = resampler_basic_direct_double; 61598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project else 61698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->resampler_ptr = resampler_basic_direct_single; 61798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 61898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ 61998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else { 62098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_int32_t i; 62198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (!st->sinc_table) 62298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); 62398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project else if (st->sinc_table_length < st->filt_len*st->oversample+8) 62498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 62598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); 62698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->sinc_table_length = st->filt_len*st->oversample+8; 62798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 62898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) 62998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 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); 63098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 63198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->resampler_ptr = resampler_basic_interpolate_single; 63298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 63398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->quality>8) 63498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->resampler_ptr = resampler_basic_interpolate_double; 63598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project else 63698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->resampler_ptr = resampler_basic_interpolate_single; 63798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 63898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ 63998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 64098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->int_advance = st->num_rate/st->den_rate; 64198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->frac_advance = st->num_rate%st->den_rate; 64298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 64398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 64498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Here's the place where we update the filter memory to take into account 64598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project the change in filter length. It's probably the messiest part of the code 64698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project due to handling of lots of corner cases. */ 64798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (!st->mem) 64898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 64998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 65098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 65198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 65298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) 65398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i] = 0; 65498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*speex_warning("init filter");*/ 65598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else if (!st->started) 65698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 65798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 65898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 65998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 66098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) 66198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i] = 0; 66298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*speex_warning("reinit filter");*/ 66398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else if (st->filt_len > old_length) 66498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 66598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_int32_t i; 66698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Increase the filter length */ 66798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*speex_warning("increase filter size");*/ 66898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int old_alloc_size = st->mem_alloc_size; 66998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size) 67098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 67198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 67298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 67398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 67498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=st->nb_channels-1;i>=0;i--) 67598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 67698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_int32_t j; 67798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t olen = old_length; 67898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /*if (st->magic_samples[i])*/ 67998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 68098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Try and remove the magic samples as if nothing had happened */ 68198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 68298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ 68398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project olen = old_length + 2*st->magic_samples[i]; 68498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (j=old_length-2+st->magic_samples[i];j>=0;j--) 68598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; 68698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (j=0;j<st->magic_samples[i];j++) 68798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i*st->mem_alloc_size+j] = 0; 68898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->magic_samples[i] = 0; 68998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 69098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->filt_len > olen) 69198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 69298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* If the new filter length is still bigger than the "augmented" length */ 69398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Copy data going backward */ 69498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (j=0;j<olen-1;j++) 69598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)]; 69698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Then put zeros for lack of anything better */ 69798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (;j<st->filt_len-1;j++) 69898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; 69998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Adjust last_sample */ 70098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample[i] += (st->filt_len - olen)/2; 70198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else { 70298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Put back some of the magic! */ 70398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->magic_samples[i] = (olen - st->filt_len)/2; 70498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (j=0;j<st->filt_len-1+st->magic_samples[i];j++) 70598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; 70698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 70798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 70898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else if (st->filt_len < old_length) 70998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 71098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 71198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" 71298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project samples so they can be used directly as input the next time(s) */ 71398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->nb_channels;i++) 71498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 71598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t j; 71698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t old_magic = st->magic_samples[i]; 71798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->magic_samples[i] = (old_length - st->filt_len)/2; 71898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* We must copy some of the memory that's no longer used */ 71998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Copy data going backward */ 72098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++) 72198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; 72298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->magic_samples[i] += old_magic; 72398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 72498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 72598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 72698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 72798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 72898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 72998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 73098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); 73198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 73298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 73398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT 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) 73498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 73598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 73698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SpeexResamplerState *st; 73798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (quality > 10 || quality < 0) 73898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 73998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (err) 74098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *err = RESAMPLER_ERR_INVALID_ARG; 74198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return NULL; 74298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 74398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); 74498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->initialised = 0; 74598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->started = 0; 74698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->in_rate = 0; 74798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->out_rate = 0; 74898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->num_rate = 0; 74998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->den_rate = 0; 75098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->quality = -1; 75198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->sinc_table_length = 0; 75298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem_alloc_size = 0; 75398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->filt_len = 0; 75498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem = 0; 75598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->resampler_ptr = 0; 75698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 75798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->cutoff = 1.f; 75898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->nb_channels = nb_channels; 75998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->in_stride = 1; 76098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->out_stride = 1; 76198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 76298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 76398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->buffer_size = 160; 76498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 76598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->buffer_size = 160; 76698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 76798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 76898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Per channel data */ 76998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); 77098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); 77198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); 77298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<nb_channels;i++) 77398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 77498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample[i] = 0; 77598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->magic_samples[i] = 0; 77698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->samp_frac_num[i] = 0; 77798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 77898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 77998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_set_quality(st, quality); 78098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); 78198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 78298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 78398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project update_filter(st); 78498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 78598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->initialised = 1; 78698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (err) 78798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *err = RESAMPLER_ERR_SUCCESS; 78898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 78998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return st; 79098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 79198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 79298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_resampler_destroy(SpeexResamplerState *st) 79398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 79498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_free(st->mem); 79598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_free(st->sinc_table); 79698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_free(st->last_sample); 79798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_free(st->magic_samples); 79898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_free(st->samp_frac_num); 79998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_free(st); 80098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 80198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 80298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic 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) 80398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 80498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int j=0; 80598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int N = st->filt_len; 80698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int out_sample = 0; 80798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 80898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t ilen; 80998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 81098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->started = 1; 81198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 81298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Call the right resampler through the function ptr */ 81398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len); 81498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 81598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->last_sample[channel_index] < (spx_int32_t)*in_len) 81698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *in_len = st->last_sample[channel_index]; 81798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len = out_sample; 81898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample[channel_index] -= *in_len; 81998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 82098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ilen = *in_len; 82198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 82298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<N-1;++j) 82398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project mem[j] = mem[j+ilen]; 82498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 82598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 82698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 82798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 82898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) { 82998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t tmp_in_len = st->magic_samples[channel_index]; 83098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 83198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int N = st->filt_len; 83298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 83398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len); 83498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 83598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->magic_samples[channel_index] -= tmp_in_len; 83698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 83798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* If we couldn't process all "magic" input samples, save the rest for next time */ 83898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->magic_samples[channel_index]) 83998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 84098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 84198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->magic_samples[channel_index];i++) 84298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project mem[N-1+i]=mem[N-1+i+tmp_in_len]; 84398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 84498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out += out_len*st->out_stride; 84598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return out_len; 84698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 84798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 84898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 84998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT 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) 85098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 85198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT 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) 85298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 85398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 85498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int j; 85598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t ilen = *in_len; 85698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t olen = *out_len; 85798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; 85898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int filt_offs = st->filt_len - 1; 85998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_uint32_t xlen = st->mem_alloc_size - filt_offs; 86098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int istride = st->in_stride; 86198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 86298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->magic_samples[channel_index]) 86398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project olen -= speex_resampler_magic(st, channel_index, &out, olen); 86498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (! st->magic_samples[channel_index]) { 86598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project while (ilen && olen) { 86698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; 86798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t ochunk = olen; 86898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 86998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (in) { 87098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<ichunk;++j) 87198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project x[j+filt_offs]=in[j*istride]; 87298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else { 87398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<ichunk;++j) 87498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project x[j+filt_offs]=0; 87598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 87698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk); 87798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ilen -= ichunk; 87898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project olen -= ochunk; 87998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project out += ochunk * st->out_stride; 88098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (in) 88198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project in += ichunk * istride; 88298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 88398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 88498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *in_len -= ilen; 88598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len -= olen; 88698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 88798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 88898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 88998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 89098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT 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) 89198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 89298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT 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) 89398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 89498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 89598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int j; 89698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int istride_save = st->in_stride; 89798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const int ostride_save = st->out_stride; 89898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t ilen = *in_len; 89998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t olen = *out_len; 90098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; 90198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1); 90298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef VAR_ARRAYS 90398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; 90498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project VARDECL(spx_word16_t *ystack); 90598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ALLOC(ystack, ylen, spx_word16_t); 90698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 90798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const unsigned int ylen = FIXED_STACK_ALLOC; 90898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t ystack[FIXED_STACK_ALLOC]; 90998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 91098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 91198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->out_stride = 1; 91298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 91398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project while (ilen && olen) { 91498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_word16_t *y = ystack; 91598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; 91698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t ochunk = (olen > ylen) ? ylen : olen; 91798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t omagic = 0; 91898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 91998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->magic_samples[channel_index]) { 92098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project omagic = speex_resampler_magic(st, channel_index, &y, ochunk); 92198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ochunk -= omagic; 92298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project olen -= omagic; 92398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 92498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (! st->magic_samples[channel_index]) { 92598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (in) { 92698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<ichunk;++j) 92798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 92898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]); 92998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 93098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project x[j+st->filt_len-1]=in[j*istride_save]; 93198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 93298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else { 93398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for(j=0;j<ichunk;++j) 93498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project x[j+st->filt_len-1]=0; 93598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 93698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 93798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk); 93898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else { 93998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ichunk = 0; 94098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ochunk = 0; 94198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 94298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 94398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (j=0;j<ochunk+omagic;++j) 94498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT 94598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project out[j*ostride_save] = ystack[j]; 94698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else 94798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project out[j*ostride_save] = WORD2INT(ystack[j]); 94898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 94998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 95098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ilen -= ichunk; 95198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project olen -= ochunk; 95298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project out += (ochunk+omagic) * ostride_save; 95398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (in) 95498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project in += ichunk * istride_save; 95598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 95698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->out_stride = ostride_save; 95798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *in_len -= ilen; 95898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len -= olen; 95998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 96098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 96198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 96298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 96398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 96498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 96598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 96698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int istride_save, ostride_save; 96798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t bak_len = *out_len; 96898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project istride_save = st->in_stride; 96998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ostride_save = st->out_stride; 97098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->in_stride = st->out_stride = st->nb_channels; 97198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->nb_channels;i++) 97298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 97398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len = bak_len; 97498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (in != NULL) 97598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); 97698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project else 97798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len); 97898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 97998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->in_stride = istride_save; 98098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->out_stride = ostride_save; 98198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 98298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 98398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 98498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT 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) 98598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 98698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 98798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int istride_save, ostride_save; 98898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t bak_len = *out_len; 98998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project istride_save = st->in_stride; 99098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ostride_save = st->out_stride; 99198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->in_stride = st->out_stride = st->nb_channels; 99298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->nb_channels;i++) 99398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 99498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len = bak_len; 99598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (in != NULL) 99698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); 99798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project else 99898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len); 99998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 100098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->in_stride = istride_save; 100198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->out_stride = ostride_save; 100298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 100398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 100498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 100598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) 100698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 100798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); 100898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 100998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 101098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) 101198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 101298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *in_rate = st->in_rate; 101398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_rate = st->out_rate; 101498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 101598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 101698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT 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) 101798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 101898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t fact; 101998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t old_den; 102098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 102198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) 102298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 102398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 102498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project old_den = st->den_rate; 102598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->in_rate = in_rate; 102698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->out_rate = out_rate; 102798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->num_rate = ratio_num; 102898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->den_rate = ratio_den; 102998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ 103098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) 103198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 103298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) 103398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 103498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->num_rate /= fact; 103598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->den_rate /= fact; 103698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 103798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 103898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 103998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (old_den > 0) 104098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 104198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->nb_channels;i++) 104298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 104398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; 104498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Safety net */ 104598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->samp_frac_num[i] >= st->den_rate) 104698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->samp_frac_num[i] = st->den_rate-1; 104798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 104898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 104998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 105098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->initialised) 105198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project update_filter(st); 105298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 105398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 105498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 105598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) 105698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 105798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *ratio_num = st->num_rate; 105898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *ratio_den = st->den_rate; 105998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 106098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 106198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality) 106298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 106398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (quality > 10 || quality < 0) 106498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_INVALID_ARG; 106598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->quality == quality) 106698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 106798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->quality = quality; 106898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->initialised) 106998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project update_filter(st); 107098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 107198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 107298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 107398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) 107498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 107598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *quality = st->quality; 107698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 107798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 107898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) 107998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 108098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->in_stride = stride; 108198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 108298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 108398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) 108498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 108598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *stride = st->in_stride; 108698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 108798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 108898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) 108998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 109098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->out_stride = stride; 109198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 109298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 109398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) 109498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 109598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *stride = st->out_stride; 109698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 109798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 109898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st) 109998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 110098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return st->filt_len / 2; 110198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 110298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 110398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st) 110498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 110598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate; 110698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 110798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 110898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st) 110998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 111098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 111198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->nb_channels;i++) 111298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->last_sample[i] = st->filt_len/2; 111398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 111498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 111598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 111698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_resampler_reset_mem(SpeexResamplerState *st) 111798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 111898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project spx_uint32_t i; 111998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 112098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->mem[i] = 0; 112198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return RESAMPLER_ERR_SUCCESS; 112298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 112398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 112498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT const char *speex_resampler_strerror(int err) 112598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 112698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project switch (err) 112798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 112898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project case RESAMPLER_ERR_SUCCESS: 112998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return "Success."; 113098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project case RESAMPLER_ERR_ALLOC_FAILED: 113198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return "Memory allocation failed."; 113298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project case RESAMPLER_ERR_BAD_STATE: 113398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return "Bad resampler state."; 113498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project case RESAMPLER_ERR_INVALID_ARG: 113598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return "Invalid argument."; 113698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project case RESAMPLER_ERR_PTR_OVERLAP: 113798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return "Input and output buffers overlap."; 113898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project default: 113998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return "Unknown error. Bad error code or strange version mismatch."; 114098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 114198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 1142