Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

codecs: Update libspeex from 1.2beta3 to 1.2rc1

This is a relatively minor bump, but it's the first step towards
bringing this current.

Change-Id: Iab6c9b0c77f0ba705280434ea74b513364719499

+1397 -992
+8 -7
lib/rbcodec/codecs/libspeex/COPYING
··· 1 - Copyright 2002-2006 2 - Xiph.org Foundation 3 - Jean-Marc Valin 4 - David Rowe 5 - EpicGames 6 - Analog Devices 7 - Commonwealth Scientific and Industrial Research Organisation (CSIRO) 1 + Copyright 2002-2008 Xiph.org Foundation 2 + Copyright 2002-2008 Jean-Marc Valin 3 + Copyright 2005-2007 Analog Devices Inc. 4 + Copyright 2005-2008 Commonwealth Scientific and Industrial Research 5 + Organisation (CSIRO) 6 + Copyright 1993, 2002, 2006 David Rowe 7 + Copyright 2003 EpicGames 8 + Copyright 1992-1994 Jutta Degener, Carsten Bormann 8 9 9 10 Redistribution and use in source and binary forms, with or without 10 11 modification, are permitted provided that the following conditions
+3 -3
lib/rbcodec/codecs/libspeex/README.rockbox
··· 1 - Library: libspeex-1.2beta3 (SVN version 14054) 2 - Imported: 2007-03-12 by Dan Everton 3 - 1 + Library: libspeex-1.2rc1 2 + Imported 1.2beta3: 2007-03-12 by Dan Everton 3 + Updated 1.2rc1: 2024-05-08 by Solomon Peachy 4 4 5 5 This directory contains a local version of libspeex for decoding Ogg/Speex 6 6 audio streams.
+1 -1
lib/rbcodec/codecs/libspeex/arch.h
··· 235 235 236 236 237 237 #ifdef FIXED_DEBUG 238 - long long spx_mips=0; 238 + extern long long spx_mips=0; 239 239 #endif 240 240 241 241
+26 -25
lib/rbcodec/codecs/libspeex/bits.c
··· 1 - /* Copyright (C) 2002 Jean-Marc Valin 1 + /* Copyright (C) 2002 Jean-Marc Valin 2 2 File: speex_bits.c 3 3 4 4 Handles bit packing/unpacking ··· 6 6 Redistribution and use in source and binary forms, with or without 7 7 modification, are permitted provided that the following conditions 8 8 are met: 9 - 9 + 10 10 - Redistributions of source code must retain the above copyright 11 11 notice, this list of conditions and the following disclaimer. 12 - 12 + 13 13 - Redistributions in binary form must reproduce the above copyright 14 14 notice, this list of conditions and the following disclaimer in the 15 15 documentation and/or other materials provided with the distribution. 16 - 16 + 17 17 - Neither the name of the Xiph.org Foundation nor the names of its 18 18 contributors may be used to endorse or promote products derived from 19 19 this software without specific prior written permission. 20 - 20 + 21 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ··· 46 46 #endif 47 47 48 48 #ifdef ROCKBOX_VOICE_ENCODER 49 - void speex_bits_init(SpeexBits *bits) 49 + EXPORT void speex_bits_init(SpeexBits *bits) 50 50 { 51 51 bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME); 52 52 if (!bits->chars) ··· 62 62 63 63 #if 0 64 64 /* Rockbox: unused */ 65 - void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size) 65 + EXPORT void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size) 66 66 { 67 67 bits->chars = (char*)buff; 68 68 bits->buf_size = buf_size; ··· 73 73 } 74 74 #endif 75 75 76 - void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size) 76 + EXPORT void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size) 77 77 { 78 78 bits->chars = (char*)buff; 79 79 bits->buf_size = buf_size; ··· 84 84 bits->charPtr=0; 85 85 bits->bitPtr=0; 86 86 bits->overflow=0; 87 - 87 + 88 88 } 89 89 90 90 #ifndef ROCKBOX_VOICE_CODEC 91 - void speex_bits_destroy(SpeexBits *bits) 91 + EXPORT void speex_bits_destroy(SpeexBits *bits) 92 92 { 93 93 if (bits->owner) 94 94 speex_free(bits->chars); ··· 97 97 #endif 98 98 99 99 #ifdef ROCKBOX_VOICE_ENCODER 100 - void speex_bits_reset(SpeexBits *bits) 100 + EXPORT void speex_bits_reset(SpeexBits *bits) 101 101 { 102 102 /* We only need to clear the first byte now */ 103 103 bits->chars[0]=0; ··· 110 110 111 111 #if 0 112 112 /* Rockbox: unused */ 113 - void speex_bits_rewind(SpeexBits *bits) 113 + EXPORT void speex_bits_rewind(SpeexBits *bits) 114 114 { 115 115 bits->charPtr=0; 116 116 bits->bitPtr=0; ··· 119 119 #endif 120 120 121 121 #if !defined(SPEEX_VOICE_ENCODER) && !defined(ROCKBOX_VOICE_CODEC) 122 - void speex_bits_read_from(SpeexBits *bits, char *chars, int len) 122 + EXPORT void speex_bits_read_from(SpeexBits *bits, char *chars, int len) 123 123 { 124 124 int i; 125 125 int nchars = len / BYTES_PER_CHAR; ··· 166 166 bits->charPtr=0; 167 167 } 168 168 169 - void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes) 169 + EXPORT void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes) 170 170 { 171 171 int i,pos; 172 + 172 173 int nchars = nbytes/BYTES_PER_CHAR; 173 174 174 175 if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size) ··· 200 201 #endif 201 202 202 203 #ifndef SPEEX_DISABLE_ENCODER 203 - int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes) 204 + EXPORT int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes) 204 205 { 205 206 int i; 206 207 int max_nchars = max_nbytes/BYTES_PER_CHAR; ··· 223 224 return max_nchars*BYTES_PER_CHAR; 224 225 } 225 226 226 - int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes) 227 + EXPORT int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes) 227 228 { 228 229 int max_nchars = max_nbytes/BYTES_PER_CHAR; 229 230 int i; ··· 241 242 return max_nchars*BYTES_PER_CHAR; 242 243 } 243 244 244 - void speex_bits_pack(SpeexBits *bits, int data, int nbBits) 245 + EXPORT void speex_bits_pack(SpeexBits *bits, int data, int nbBits) 245 246 { 246 247 unsigned int d=data; 247 248 ··· 287 288 288 289 #if 0 289 290 /* Rockbox: unused */ 290 - int speex_bits_unpack_signed(SpeexBits *bits, int nbBits) 291 + EXPORT int speex_bits_unpack_signed(SpeexBits *bits, int nbBits) 291 292 { 292 293 unsigned int d=speex_bits_unpack_unsigned(bits,nbBits); 293 294 /* If number is negative */ ··· 299 300 } 300 301 #endif 301 302 302 - unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits) 303 + EXPORT unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits) 303 304 { 304 305 unsigned int d=0; 305 306 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits) ··· 323 324 324 325 #if 0 325 326 /* Rockbox: unused */ 326 - unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits) 327 + EXPORT unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits) 327 328 { 328 329 unsigned int d=0; 329 330 int bitPtr, charPtr; ··· 353 354 } 354 355 #endif 355 356 356 - int speex_bits_peek(SpeexBits *bits) 357 + EXPORT int speex_bits_peek(SpeexBits *bits) 357 358 { 358 359 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits) 359 360 bits->overflow=1; ··· 362 363 return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1; 363 364 } 364 365 365 - void speex_bits_advance(SpeexBits *bits, int n) 366 + EXPORT void speex_bits_advance(SpeexBits *bits, int n) 366 367 { 367 368 if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){ 368 369 bits->overflow=1; ··· 372 373 bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */ 373 374 } 374 375 375 - int speex_bits_remaining(SpeexBits *bits) 376 + EXPORT int speex_bits_remaining(SpeexBits *bits) 376 377 { 377 378 if (bits->overflow) 378 379 return -1; ··· 382 383 383 384 #if 0 384 385 /* Rockbox: unused */ 385 - int speex_bits_nbytes(SpeexBits *bits) 386 + EXPORT int speex_bits_nbytes(SpeexBits *bits) 386 387 { 387 388 return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR); 388 389 } 389 390 #endif 390 391 391 392 #ifndef SPEEX_DISABLE_ENCODER 392 - void speex_bits_insert_terminator(SpeexBits *bits) 393 + EXPORT void speex_bits_insert_terminator(SpeexBits *bits) 393 394 { 394 395 if (bits->bitPtr) 395 396 speex_bits_pack(bits, 0, 1);
+14 -6
lib/rbcodec/codecs/libspeex/config-speex.h
··· 1 1 #ifndef ROCKBOX_VOICE_ENCODER 2 - #include "codeclib.h" 2 + #include "codeclib.h" 3 3 #include "autoconf.h" 4 4 #else 5 5 #define ICODE_ATTR ··· 17 17 18 18 /* Make use of ARM4E assembly optimizations */ 19 19 #if defined(CPU_ARM) 20 + #if (ARM_ARCH < 5) 20 21 #define ARM4_ASM 22 + #else 23 + #define ARM5E_ASM 24 + #endif 21 25 #endif 22 26 23 27 /* Make use of Coldfire assembly optimizations */ ··· 40 44 41 45 #ifndef ROCKBOX_VOICE_ENCODER 42 46 /* Compile target codec as fixed point */ 43 - #define FIXED_POINT 47 + #define FIXED_POINT 44 48 #else 45 49 /* Compile voice clip encoder as floating point */ 46 - #define FLOATING_POINT 50 + #define FLOATING_POINT 47 51 #endif 48 52 49 53 #ifndef ROCKBOX_VOICE_CODEC ··· 137 141 #define SPEEX_MAJOR_VERSION 1 138 142 139 143 /* Version micro */ 140 - #define SPEEX_MICRO_VERSION 15 144 + #define SPEEX_MICRO_VERSION 16 141 145 142 146 /* Version minor */ 143 147 #define SPEEX_MINOR_VERSION 1 144 148 145 149 /* Complete version string */ 146 - #define SPEEX_VERSION "1.2beta3" 150 + #define SPEEX_VERSION "1.2rc1" 147 151 148 152 /* Define to 1 if you have the ANSI C header files. */ 149 153 #define STDC_HEADERS 1 ··· 155 159 /* #undef USE_ALLOCA */ 156 160 157 161 /* Use C99 variable-size arrays */ 158 - #define VAR_ARRAYS 162 + #define VAR_ARRAYS 159 163 160 164 /* Enable Vorbis-style psychoacoustics (EXPERIMENTAL) */ 161 165 /* #undef VORBIS_PSYCHO */ ··· 184 188 185 189 #define RELEASE 1 186 190 191 + /* We don't care */ 192 + #define EXPORT 193 + 194 + #define USE_KISS_FFT
+120 -11
lib/rbcodec/codecs/libspeex/fftwrap.c
··· 1 - /* Copyright (C) 2005-2006 Jean-Marc Valin 1 + /* Copyright (C) 2005-2006 Jean-Marc Valin 2 2 File: fftwrap.c 3 3 4 - Wrapper for various FFTs 4 + Wrapper for various FFTs 5 5 6 6 Redistribution and use in source and binary forms, with or without 7 7 modification, are permitted provided that the following conditions 8 8 are met: 9 - 9 + 10 10 - Redistributions of source code must retain the above copyright 11 11 notice, this list of conditions and the following disclaimer. 12 - 12 + 13 13 - Redistributions in binary form must reproduce the above copyright 14 14 notice, this list of conditions and the following disclaimer in the 15 15 documentation and/or other materials provided with the distribution. 16 - 16 + 17 17 - Neither the name of the Xiph.org Foundation nor the names of its 18 18 contributors may be used to endorse or promote products derived from 19 19 this software without specific prior written permission. 20 - 20 + 21 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ··· 35 35 #ifdef HAVE_CONFIG_H 36 36 #include "config-speex.h" 37 37 #endif 38 - 39 - /*#define USE_SMALLFT*/ 40 - #define USE_KISS_FFT 41 - 42 38 43 39 #include "arch.h" 44 40 #include "os_support.h" ··· 66 62 for (i=0;i<len;i++) 67 63 { 68 64 out[i] = SHL16(in[i], shift); 69 - } 65 + } 70 66 return shift; 71 67 } 72 68 ··· 128 124 out[i] = in[i]; 129 125 } 130 126 spx_drft_backward((struct drft_lookup *)table, out); 127 + } 128 + 129 + #elif defined(USE_INTEL_MKL) 130 + #include <mkl.h> 131 + 132 + struct mkl_config { 133 + DFTI_DESCRIPTOR_HANDLE desc; 134 + int N; 135 + }; 136 + 137 + void *spx_fft_init(int size) 138 + { 139 + struct mkl_config *table = (struct mkl_config *) speex_alloc(sizeof(struct mkl_config)); 140 + table->N = size; 141 + DftiCreateDescriptor(&table->desc, DFTI_SINGLE, DFTI_REAL, 1, size); 142 + DftiSetValue(table->desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT); 143 + DftiSetValue(table->desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE); 144 + DftiSetValue(table->desc, DFTI_FORWARD_SCALE, 1.0f / size); 145 + DftiCommitDescriptor(table->desc); 146 + return table; 147 + } 148 + 149 + void spx_fft_destroy(void *table) 150 + { 151 + struct mkl_config *t = (struct mkl_config *) table; 152 + DftiFreeDescriptor(t->desc); 153 + speex_free(table); 154 + } 155 + 156 + void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) 157 + { 158 + struct mkl_config *t = (struct mkl_config *) table; 159 + DftiComputeForward(t->desc, in, out); 160 + } 161 + 162 + void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) 163 + { 164 + struct mkl_config *t = (struct mkl_config *) table; 165 + DftiComputeBackward(t->desc, in, out); 166 + } 167 + 168 + #elif defined(USE_GPL_FFTW3) 169 + 170 + #include <fftw3.h> 171 + 172 + struct fftw_config { 173 + float *in; 174 + float *out; 175 + fftwf_plan fft; 176 + fftwf_plan ifft; 177 + int N; 178 + }; 179 + 180 + void *spx_fft_init(int size) 181 + { 182 + struct fftw_config *table = (struct fftw_config *) speex_alloc(sizeof(struct fftw_config)); 183 + table->in = fftwf_malloc(sizeof(float) * (size+2)); 184 + table->out = fftwf_malloc(sizeof(float) * (size+2)); 185 + 186 + table->fft = fftwf_plan_dft_r2c_1d(size, table->in, (fftwf_complex *) table->out, FFTW_PATIENT); 187 + table->ifft = fftwf_plan_dft_c2r_1d(size, (fftwf_complex *) table->in, table->out, FFTW_PATIENT); 188 + 189 + table->N = size; 190 + return table; 191 + } 192 + 193 + void spx_fft_destroy(void *table) 194 + { 195 + struct fftw_config *t = (struct fftw_config *) table; 196 + fftwf_destroy_plan(t->fft); 197 + fftwf_destroy_plan(t->ifft); 198 + fftwf_free(t->in); 199 + fftwf_free(t->out); 200 + speex_free(table); 201 + } 202 + 203 + 204 + void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) 205 + { 206 + int i; 207 + struct fftw_config *t = (struct fftw_config *) table; 208 + const int N = t->N; 209 + float *iptr = t->in; 210 + float *optr = t->out; 211 + const float m = 1.0 / N; 212 + for(i=0;i<N;++i) 213 + iptr[i]=in[i] * m; 214 + 215 + fftwf_execute(t->fft); 216 + 217 + out[0] = optr[0]; 218 + for(i=1;i<N;++i) 219 + out[i] = optr[i+1]; 220 + } 221 + 222 + void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) 223 + { 224 + int i; 225 + struct fftw_config *t = (struct fftw_config *) table; 226 + const int N = t->N; 227 + float *iptr = t->in; 228 + float *optr = t->out; 229 + 230 + iptr[0] = in[0]; 231 + iptr[1] = 0.0f; 232 + for(i=1;i<N;++i) 233 + iptr[i+1] = in[i]; 234 + iptr[N+1] = 0.0f; 235 + 236 + fftwf_execute(t->ifft); 237 + 238 + for(i=0;i<N;++i) 239 + out[i] = optr[i]; 131 240 } 132 241 133 242 #elif defined(USE_KISS_FFT)
+1 -1
lib/rbcodec/codecs/libspeex/filters_arm4.h
··· 86 86 "\tmov %5, %5, asr %3 \n" 87 87 "\tstrh %5, [%1], #2 \n" 88 88 89 - "\tbge .normalize16loop%=\n" 89 + "\tbgt .normalize16loop%=\n" 90 90 : "=r" (dead1), "=r" (dead2), "=r" (dead3), "=r" (dead4), 91 91 "=r" (dead5), "=r" (dead6) 92 92 : "0" (x), "1" (y), "2" (len>>2), "3" (sig_shift)
+29 -29
lib/rbcodec/codecs/libspeex/fixed_debug.h
··· 7 7 Redistribution and use in source and binary forms, with or without 8 8 modification, are permitted provided that the following conditions 9 9 are met: 10 - 10 + 11 11 - Redistributions of source code must retain the above copyright 12 12 notice, this list of conditions and the following disclaimer. 13 - 13 + 14 14 - Redistributions in binary form must reproduce the above copyright 15 15 notice, this list of conditions and the following disclaimer in the 16 16 documentation and/or other materials provided with the distribution. 17 - 17 + 18 18 - Neither the name of the Xiph.org Foundation nor the names of its 19 19 contributors may be used to endorse or promote products derived from 20 20 this software without specific prior written permission. 21 - 21 + 22 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 23 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ··· 101 101 } 102 102 103 103 #define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__) 104 - static inline short _SHR16(int a, int shift, char *file, int line) 104 + static inline short _SHR16(int a, int shift, char *file, int line) 105 105 { 106 106 int res; 107 107 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) ··· 115 115 return res; 116 116 } 117 117 #define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__) 118 - static inline short _SHL16(int a, int shift, char *file, int line) 118 + static inline short _SHL16(int a, int shift, char *file, int line) 119 119 { 120 120 int res; 121 121 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) ··· 129 129 return res; 130 130 } 131 131 132 - static inline int SHR32(long long a, int shift) 132 + static inline int SHR32(long long a, int shift) 133 133 { 134 134 long long res; 135 135 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) ··· 144 144 spx_mips++; 145 145 return res; 146 146 } 147 - static inline int SHL32(long long a, int shift) 147 + static inline int SHL32(long long a, int shift) 148 148 { 149 149 long long res; 150 150 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) ··· 161 161 } 162 162 163 163 #define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift)) 164 - #define PSHR32(a,shift) (SHR32(ADD32((a),((1<<((shift))>>1))),shift)) 164 + #define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift)) 165 165 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) 166 166 167 167 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) ··· 171 171 //#define SHL(a,shift) ((a) << (shift)) 172 172 173 173 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__) 174 - static inline short _ADD16(int a, int b, char *file, int line) 174 + static inline short _ADD16(int a, int b, char *file, int line) 175 175 { 176 176 int res; 177 177 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 188 188 } 189 189 190 190 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__) 191 - static inline short _SUB16(int a, int b, char *file, int line) 191 + static inline short _SUB16(int a, int b, char *file, int line) 192 192 { 193 193 int res; 194 194 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 203 203 } 204 204 205 205 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__) 206 - static inline int _ADD32(long long a, long long b, char *file, int line) 206 + static inline int _ADD32(long long a, long long b, char *file, int line) 207 207 { 208 208 long long res; 209 209 if (!VERIFY_INT(a) || !VERIFY_INT(b)) ··· 219 219 return res; 220 220 } 221 221 222 - static inline int SUB32(long long a, long long b) 222 + static inline int SUB32(long long a, long long b) 223 223 { 224 224 long long res; 225 225 if (!VERIFY_INT(a) || !VERIFY_INT(b)) ··· 236 236 #define ADD64(a,b) (MIPS_INC(a)+(b)) 237 237 238 238 /* result fits in 16 bits */ 239 - static inline short MULT16_16_16(int a, int b) 239 + static inline short MULT16_16_16(int a, int b) 240 240 { 241 241 int res; 242 242 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 251 251 } 252 252 253 253 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__) 254 - static inline int _MULT16_16(int a, int b, char *file, int line) 254 + static inline int _MULT16_16(int a, int b, char *file, int line) 255 255 { 256 256 long long res; 257 257 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 279 279 { 280 280 fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); 281 281 } 282 - if (ABS32(b)>=(1<<(15+Q))) 283 - fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); 282 + if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) 283 + fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); 284 284 res = (((long long)a)*(long long)b) >> Q; 285 285 if (!VERIFY_INT(res)) 286 286 fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line); ··· 295 295 { 296 296 fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b); 297 297 } 298 - if (ABS32(b)>=(1<<(15+Q))) 299 - fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b); 300 - res = ((((long long)a)*(long long)b) + ((1<<Q)>>1))>> Q; 298 + if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) 299 + fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b); 300 + res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<<Q)>>1))>> Q; 301 301 if (!VERIFY_INT(res)) 302 302 fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res); 303 303 spx_mips+=5; ··· 323 323 return a; 324 324 } 325 325 326 - static inline int MULT16_16_Q11_32(int a, int b) 326 + static inline int MULT16_16_Q11_32(int a, int b) 327 327 { 328 328 long long res; 329 329 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 337 337 spx_mips+=3; 338 338 return res; 339 339 } 340 - static inline short MULT16_16_Q13(int a, int b) 340 + static inline short MULT16_16_Q13(int a, int b) 341 341 { 342 342 long long res; 343 343 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 351 351 spx_mips+=3; 352 352 return res; 353 353 } 354 - static inline short MULT16_16_Q14(int a, int b) 354 + static inline short MULT16_16_Q14(int a, int b) 355 355 { 356 356 long long res; 357 357 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 365 365 spx_mips+=3; 366 366 return res; 367 367 } 368 - static inline short MULT16_16_Q15(int a, int b) 368 + static inline short MULT16_16_Q15(int a, int b) 369 369 { 370 370 long long res; 371 371 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 382 382 return res; 383 383 } 384 384 385 - static inline short MULT16_16_P13(int a, int b) 385 + static inline short MULT16_16_P13(int a, int b) 386 386 { 387 387 long long res; 388 388 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 399 399 spx_mips+=4; 400 400 return res; 401 401 } 402 - static inline short MULT16_16_P14(int a, int b) 402 + static inline short MULT16_16_P14(int a, int b) 403 403 { 404 404 long long res; 405 405 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 416 416 spx_mips+=4; 417 417 return res; 418 418 } 419 - static inline short MULT16_16_P15(int a, int b) 419 + static inline short MULT16_16_P15(int a, int b) 420 420 { 421 421 long long res; 422 422 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) ··· 436 436 437 437 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__) 438 438 439 - static inline int _DIV32_16(long long a, long long b, char *file, int line) 439 + static inline int _DIV32_16(long long a, long long b, char *file, int line) 440 440 { 441 441 long long res; 442 442 if (b==0) ··· 462 462 } 463 463 464 464 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__) 465 - static inline int _DIV32(long long a, long long b, char *file, int line) 465 + static inline int _DIV32(long long a, long long b, char *file, int line) 466 466 { 467 467 long long res; 468 468 if (b==0)
+2 -2
lib/rbcodec/codecs/libspeex/fixed_generic.h
··· 47 47 #define SHR32(a,shift) ((a) >> (shift)) 48 48 #define SHL32(a,shift) ((a) << (shift)) 49 49 #define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) 50 - #define PSHR32(a,shift) (SHR32((a)+((1<<((shift))>>1)),shift)) 50 + #define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift)) 51 51 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) 52 52 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 53 53 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 54 54 55 55 #define SHR(a,shift) ((a) >> (shift)) 56 56 #define SHL(a,shift) ((spx_word32_t)(a) << (shift)) 57 - #define PSHR(a,shift) (SHR((a)+((1<<((shift))>>1)),shift)) 57 + #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) 58 58 #define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 59 59 60 60
+97 -95
lib/rbcodec/codecs/libspeex/jitter.c
··· 1 - /* Copyright (C) 2002 Jean-Marc Valin 1 + /* Copyright (C) 2002 Jean-Marc Valin 2 2 File: speex_jitter.h 3 3 4 4 Adaptive jitter buffer for Speex ··· 6 6 Redistribution and use in source and binary forms, with or without 7 7 modification, are permitted provided that the following conditions 8 8 are met: 9 - 9 + 10 10 - Redistributions of source code must retain the above copyright 11 11 notice, this list of conditions and the following disclaimer. 12 - 12 + 13 13 - Redistributions in binary form must reproduce the above copyright 14 14 notice, this list of conditions and the following disclaimer in the 15 15 documentation and/or other materials provided with the distribution. 16 - 16 + 17 17 - Neither the name of the Xiph.org Foundation nor the names of its 18 18 contributors may be used to endorse or promote products derived from 19 19 this software without specific prior written permission. 20 - 20 + 21 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ··· 73 73 #define LT32(a,b) (((spx_int32_t)((a)-(b)))<0) 74 74 #define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0) 75 75 76 - #define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step)) 76 + #define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step)) 77 77 78 - #define MAX_TIMINGS 20 78 + #define MAX_TIMINGS 40 79 79 #define MAX_BUFFERS 3 80 - #define TOP_DELAY 20 80 + #define TOP_DELAY 40 81 81 82 82 /** Buffer that keeps the time of arrival of the latest packets */ 83 83 struct TimingBuffer { 84 84 int filled; /**< Number of entries occupied in "timing" and "counts"*/ 85 85 int curr_count; /**< Number of packet timings we got (including those we discarded) */ 86 - spx_int16_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */ 86 + spx_int32_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */ 87 87 spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */ 88 88 }; 89 89 ··· 103 103 tb->curr_count++; 104 104 return; 105 105 } 106 - 106 + 107 107 /* Find where the timing info goes in the sorted list */ 108 108 pos = 0; 109 109 /* FIXME: Do bisection instead of linear search */ ··· 111 111 { 112 112 pos++; 113 113 } 114 - 114 + 115 115 speex_assert(pos <= tb->filled && pos < MAX_TIMINGS); 116 - 116 + 117 117 /* Shift everything so we can perform the insertion */ 118 118 if (pos < tb->filled) 119 119 { ··· 126 126 /* Insert */ 127 127 tb->timing[pos] = timing; 128 128 tb->counts[pos] = tb->curr_count; 129 - 129 + 130 130 tb->curr_count++; 131 131 if (tb->filled<MAX_TIMINGS) 132 132 tb->filled++; ··· 139 139 spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */ 140 140 spx_uint32_t last_returned_timestamp; /**< Useful for getting the next packet with the same timestamp (for fragmented media) */ 141 141 spx_uint32_t next_stop; /**< Estimated time the next get() will be called */ 142 - 142 + 143 143 spx_int32_t buffered; /**< Amount of data we think is still buffered by the application (timestamp units)*/ 144 - 144 + 145 145 JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */ 146 146 spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */ 147 - 147 + 148 148 void (*destroy) (void *); /**< Callback for destroying a packet */ 149 149 150 150 spx_int32_t delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */ ··· 154 154 int late_cutoff; /**< How late must a packet be for it not to be considered at all */ 155 155 int interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */ 156 156 int auto_adjust; /**< Whether to automatically adjust the delay at any time */ 157 - 157 + 158 158 struct TimingBuffer _tb[MAX_BUFFERS]; /**< Don't use those directly */ 159 159 struct TimingBuffer *timeBuffers[MAX_BUFFERS]; /**< Storing arrival time of latest frames so we can compute some stats */ 160 160 int window_size; /**< Total window over which the late frames are counted */ ··· 162 162 int max_late_rate; /**< Absolute maximum amount of late packets tolerable (in percent) */ 163 163 int latency_tradeoff; /**< Latency equivalent of losing one percent of packets */ 164 164 int auto_tradeoff; /**< Latency equivalent of losing one percent of packets (automatic default) */ 165 - 165 + 166 166 int lost_count; /**< Number of consecutive lost packets */ 167 167 }; 168 168 169 - /** Based on available data, this computes the optimal delay for the jitter buffer. 169 + /** Based on available data, this computes the optimal delay for the jitter buffer. 170 170 The optimised function is in timestamp units and is: 171 171 cost = delay + late_factor*[number of frames that would be late if we used that delay] 172 172 @param tb Array of buffers 173 - @param late_factor Equivalent cost of a late frame (in timestamp units) 173 + @param late_factor Equivalent cost of a late frame (in timestamp units) 174 174 */ 175 175 static spx_int16_t compute_opt_delay(JitterBuffer *jitter) 176 176 { ··· 186 186 int worst = 0; 187 187 spx_int32_t deltaT; 188 188 struct TimingBuffer *tb; 189 - 189 + 190 190 tb = jitter->_tb; 191 - 191 + 192 192 /* Number of packet timings we have received (including those we didn't keep) */ 193 193 tot_count = 0; 194 194 for (i=0;i<MAX_BUFFERS;i++) 195 195 tot_count += tb[i].curr_count; 196 196 if (tot_count==0) 197 197 return 0; 198 - 198 + 199 199 /* Compute cost for one lost packet */ 200 200 if (jitter->latency_tradeoff != 0) 201 201 late_factor = jitter->latency_tradeoff * 100.0f / tot_count; 202 202 else 203 203 late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count; 204 - 204 + 205 205 /*fprintf(stderr, "late_factor = %f\n", late_factor);*/ 206 206 for (i=0;i<MAX_BUFFERS;i++) 207 207 pos[i] = 0; 208 - 209 - /* Pick the TOP_DELAY "latest" packets (doesn't need to actually be late 208 + 209 + /* Pick the TOP_DELAY "latest" packets (doesn't need to actually be late 210 210 for the current settings) */ 211 211 for (i=0;i<TOP_DELAY;i++) 212 212 { ··· 225 225 if (next != -1) 226 226 { 227 227 spx_int32_t cost; 228 - 228 + 229 229 if (i==0) 230 230 worst = latest; 231 231 best = latest; 232 232 latest = ROUND_DOWN(latest, jitter->delay_step); 233 233 pos[next]++; 234 - 234 + 235 235 /* Actual cost function that tells us how bad using this delay would be */ 236 236 cost = -latest + late_factor*late; 237 237 /*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/ ··· 243 243 } else { 244 244 break; 245 245 } 246 - 246 + 247 247 /* For the next timing we will consider, there will be one more late packet to count */ 248 248 late++; 249 249 /* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */ 250 250 if (latest >= 0 && !penalty_taken) 251 251 { 252 252 penalty_taken = 1; 253 - late+=2; 253 + late+=4; 254 254 } 255 255 } 256 - 256 + 257 257 deltaT = best-worst; 258 258 /* This is a default "automatic latency tradeoff" when none is provided */ 259 259 jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY; 260 260 /*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/ 261 - 261 + 262 262 /* FIXME: Compute a short-term estimate too and combine with the long-term one */ 263 - 263 + 264 264 /* Prevents reducing the buffer size when we haven't really had much data */ 265 265 if (tot_count < TOP_DELAY && opt > 0) 266 266 return 0; ··· 269 269 270 270 271 271 /** Initialise jitter buffer */ 272 - JitterBuffer *jitter_buffer_init(int step_size) 272 + EXPORT JitterBuffer *jitter_buffer_init(int step_size) 273 273 { 274 274 JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer)); 275 275 if (jitter) ··· 294 294 } 295 295 296 296 /** Reset jitter buffer */ 297 - void jitter_buffer_reset(JitterBuffer *jitter) 297 + EXPORT void jitter_buffer_reset(JitterBuffer *jitter) 298 298 { 299 299 int i; 300 300 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) ··· 315 315 jitter->lost_count = 0; 316 316 jitter->buffered = 0; 317 317 jitter->auto_tradeoff = 32000; 318 - 318 + 319 319 for (i=0;i<MAX_BUFFERS;i++) 320 320 { 321 321 tb_init(&jitter->_tb[i]); ··· 325 325 } 326 326 327 327 /** Destroy jitter buffer */ 328 - void jitter_buffer_destroy(JitterBuffer *jitter) 328 + EXPORT void jitter_buffer_destroy(JitterBuffer *jitter) 329 329 { 330 330 jitter_buffer_reset(jitter); 331 331 speex_free(jitter); ··· 365 365 366 366 367 367 /** Put one packet into the jitter buffer */ 368 - void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) 368 + EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) 369 369 { 370 370 int i,j; 371 371 int late; 372 372 /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/ 373 - 373 + 374 374 /* Cleanup buffer (remove old packets that weren't played) */ 375 375 if (!jitter->reset_state) 376 376 { ··· 388 388 } 389 389 } 390 390 } 391 - 391 + 392 392 /*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/ 393 393 /* Check if packet is late (could still be useful though) */ 394 394 if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop)) ··· 398 398 } else { 399 399 late = 0; 400 400 } 401 - 401 + 402 + /* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is 403 + * used to resync. */ 404 + if (jitter->lost_count>20) 405 + { 406 + jitter_buffer_reset(jitter); 407 + } 408 + 402 409 /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */ 403 410 if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp)) 404 411 { ··· 409 416 if (jitter->packets[i].data==NULL) 410 417 break; 411 418 } 412 - 419 + 413 420 /*No place left in the buffer, need to make room for it by discarding the oldest packet */ 414 421 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) 415 422 { ··· 428 435 else 429 436 speex_free(jitter->packets[i].data); 430 437 jitter->packets[i].data=NULL; 431 - if (jitter->lost_count>20) 432 - { 433 - jitter_buffer_reset(jitter); 434 - } 435 - /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/ 438 + /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/ 436 439 } 437 - 440 + 438 441 /* Copy packet in buffer */ 439 442 if (jitter->destroy) 440 443 { ··· 454 457 else 455 458 jitter->arrival[i] = jitter->next_stop; 456 459 } 457 - 458 - 460 + 461 + 459 462 } 460 463 461 464 /** Get one packet from the jitter buffer */ 462 - int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset) 465 + EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset) 463 466 { 464 467 int i; 465 468 unsigned int j; 466 469 int incomplete = 0; 467 470 spx_int16_t opt; 468 - 471 + 469 472 if (start_offset != NULL) 470 473 *start_offset = 0; 471 474 ··· 485 488 } 486 489 if (found) 487 490 { 488 - jitter->reset_state=0; 491 + jitter->reset_state=0; 489 492 jitter->pointer_timestamp = oldest; 490 493 jitter->next_stop = oldest; 491 494 } else { ··· 494 497 return JITTER_BUFFER_MISSING; 495 498 } 496 499 } 497 - 500 + 498 501 499 502 jitter->last_returned_timestamp = jitter->pointer_timestamp; 500 - 503 + 501 504 if (jitter->interp_requested != 0) 502 505 { 503 506 packet->timestamp = jitter->pointer_timestamp; 504 507 packet->span = jitter->interp_requested; 505 - 508 + 506 509 /* Increment the pointer because it got decremented in the delay update */ 507 510 jitter->pointer_timestamp += jitter->interp_requested; 508 511 packet->len = 0; 509 512 /*fprintf (stderr, "Deferred interpolate\n");*/ 510 - 513 + 511 514 jitter->interp_requested = 0; 512 - 515 + 513 516 jitter->buffered = packet->span - desired_span; 514 517 515 518 return JITTER_BUFFER_INSERTION; 516 519 } 517 - 520 + 518 521 /* Searching for the packet that fits best */ 519 - 522 + 520 523 /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */ 521 524 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) 522 525 { 523 526 if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span)) 524 527 break; 525 528 } 526 - 529 + 527 530 /* If no match, try for an "older" packet that still spans (fully) the current chunk */ 528 531 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) 529 532 { ··· 533 536 break; 534 537 } 535 538 } 536 - 539 + 537 540 /* If still no match, try for an "older" packet that spans part of the current chunk */ 538 541 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) 539 542 { ··· 543 546 break; 544 547 } 545 548 } 546 - 549 + 547 550 /* If still no match, try for earliest packet possible */ 548 551 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) 549 552 { ··· 577 580 if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) 578 581 { 579 582 spx_int32_t offset; 580 - 583 + 581 584 /* We (obviously) haven't lost this packet */ 582 585 jitter->lost_count = 0; 583 - 586 + 584 587 /* In this case, 0 isn't as a valid timestamp */ 585 588 if (jitter->arrival[i] != 0) 586 589 { 587 590 update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin); 588 591 } 589 - 590 - 592 + 593 + 591 594 if (jitter->packets[i].len > packet->len) 592 595 { 593 596 speex_warning_int("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len); ··· 611 614 *start_offset = offset; 612 615 else if (offset != 0) 613 616 speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset); 614 - 617 + 615 618 packet->timestamp = jitter->packets[i].timestamp; 616 619 jitter->last_returned_timestamp = packet->timestamp; 617 - 620 + 618 621 packet->span = jitter->packets[i].span; 619 622 packet->sequence = jitter->packets[i].sequence; 620 623 packet->user_data = jitter->packets[i].user_data; ··· 622 625 jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span; 623 626 624 627 jitter->buffered = packet->span - desired_span; 625 - 628 + 626 629 if (start_offset != NULL) 627 630 jitter->buffered += *start_offset; 628 - 631 + 629 632 return JITTER_BUFFER_OK; 630 633 } 631 - 632 - 634 + 635 + 633 636 /* If we haven't found anything worth returning */ 634 - 637 + 635 638 /*fprintf (stderr, "not found\n");*/ 636 639 jitter->lost_count++; 637 640 /*fprintf (stderr, "m");*/ 638 641 /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/ 639 - 642 + 640 643 opt = compute_opt_delay(jitter); 641 - 642 - /* Should we force an increase in the buffer or just do normal interpolation? */ 644 + 645 + /* Should we force an increase in the buffer or just do normal interpolation? */ 643 646 if (opt < 0) 644 647 { 645 648 /* Need to increase buffering */ 646 - 649 + 647 650 /* Shift histogram to compensate */ 648 651 shift_timings(jitter, -opt); 649 - 652 + 650 653 packet->timestamp = jitter->pointer_timestamp; 651 654 packet->span = -opt; 652 655 /* Don't move the pointer_timestamp forward */ 653 656 packet->len = 0; 654 - 657 + 655 658 jitter->buffered = packet->span - desired_span; 656 659 return JITTER_BUFFER_INSERTION; 657 660 /*jitter->pointer_timestamp -= jitter->delay_step;*/ ··· 659 662 } else { 660 663 /* Normal packet loss */ 661 664 packet->timestamp = jitter->pointer_timestamp; 662 - 665 + 663 666 desired_span = ROUND_DOWN(desired_span, jitter->concealment_size); 664 667 packet->span = desired_span; 665 668 jitter->pointer_timestamp += desired_span; 666 669 packet->len = 0; 667 - 670 + 668 671 jitter->buffered = packet->span - desired_span; 669 672 return JITTER_BUFFER_MISSING; 670 673 /*fprintf (stderr, "Normal loss\n");*/ ··· 673 676 674 677 } 675 678 676 - int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet) 679 + EXPORT int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet) 677 680 { 678 681 int i, j; 679 682 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) ··· 713 716 { 714 717 spx_int16_t opt = compute_opt_delay(jitter); 715 718 /*fprintf(stderr, "opt adjustment is %d ", opt);*/ 716 - 719 + 717 720 if (opt < 0) 718 721 { 719 722 shift_timings(jitter, -opt); 720 - 723 + 721 724 jitter->pointer_timestamp += opt; 722 725 jitter->interp_requested = -opt; 723 726 /*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/ ··· 727 730 jitter->pointer_timestamp += opt; 728 731 /*fprintf (stderr, "Decision to drop %d samples\n", opt);*/ 729 732 } 730 - 733 + 731 734 return opt; 732 735 } 733 736 734 737 /* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ 735 - int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) 738 + EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) 736 739 { 737 - /* If the programmer calls jitter_buffer_update_delay() directly, 740 + /* If the programmer calls jitter_buffer_update_delay() directly, 738 741 automatically disable auto-adjustment */ 739 742 jitter->auto_adjust = 0; 740 743 ··· 742 745 } 743 746 744 747 /** Get pointer timestamp of jitter buffer */ 745 - int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter) 748 + EXPORT int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter) 746 749 { 747 750 return jitter->pointer_timestamp; 748 751 } 749 752 750 - void jitter_buffer_tick(JitterBuffer *jitter) 753 + EXPORT void jitter_buffer_tick(JitterBuffer *jitter) 751 754 { 752 755 /* Automatically-adjust the buffering delay if requested */ 753 756 if (jitter->auto_adjust) 754 757 _jitter_buffer_update_delay(jitter, NULL, NULL); 755 - 758 + 756 759 if (jitter->buffered >= 0) 757 760 { 758 761 jitter->next_stop = jitter->pointer_timestamp - jitter->buffered; ··· 763 766 jitter->buffered = 0; 764 767 } 765 768 766 - void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem) 769 + EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem) 767 770 { 768 771 /* Automatically-adjust the buffering delay if requested */ 769 772 if (jitter->auto_adjust) 770 773 _jitter_buffer_update_delay(jitter, NULL, NULL); 771 - 774 + 772 775 if (jitter->buffered < 0) 773 776 speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered); 774 777 jitter->next_stop = jitter->pointer_timestamp - rem; ··· 776 779 777 780 778 781 /* Used like the ioctl function to control the jitter buffer parameters */ 779 - int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) 782 + EXPORT int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) 780 783 { 781 784 int count, i; 782 785 switch(request) ··· 836 839 } 837 840 return 0; 838 841 } 839 -
+342 -234
lib/rbcodec/codecs/libspeex/mdf.c
··· 1 - /* Copyright (C) 2003-2006 Jean-Marc Valin 1 + /* Copyright (C) 2003-2008 Jean-Marc Valin 2 2 3 3 File: mdf.c 4 4 Echo canceller based on the MDF algorithm (see below) ··· 33 33 /* 34 34 The echo canceller is based on the MDF algorithm described in: 35 35 36 - J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter, 37 - IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2, 36 + J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter, 37 + IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2, 38 38 February 1990. 39 - 40 - We use the Alternatively Updated MDF (AUMDF) variant. Robustness to 39 + 40 + We use the Alternatively Updated MDF (AUMDF) variant. Robustness to 41 41 double-talk is achieved using a variable learning rate as described in: 42 - 43 - Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo 42 + 43 + Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo 44 44 Cancellation With Double-Talk. IEEE Transactions on Audio, 45 45 Speech and Language Processing, Vol. 15, No. 3, pp. 1030-1034, 2007. 46 46 http://people.xiph.org/~jm/papers/valin_taslp2006.pdf 47 - 47 + 48 48 There is no explicit double-talk detection, but a continuous variation 49 49 in the learning rate based on residual echo, double-talk and background 50 50 noise. 51 - 51 + 52 52 About the fixed-point version: 53 - All the signals are represented with 16-bit words. The filter weights 53 + All the signals are represented with 16-bit words. The filter weights 54 54 are represented with 32-bit words, but only the top 16 bits are used 55 55 in most cases. The lower 16 bits are completely unreliable (due to the 56 56 fact that the update is done only on the top bits), but help in the 57 57 adaptation -- probably by removing a "threshold effect" due to 58 58 quantization (rounding going to zero) when the gradient is small. 59 - 59 + 60 60 Another kludge that seems to work good: when performing the weight 61 61 update, we only move half the way toward the "goal" this seems to 62 62 reduce the effect of quantization noise in the update phase. This 63 63 can be seen as applying a gradient descent on a "soft constraint" 64 64 instead of having a hard constraint. 65 - 65 + 66 66 */ 67 67 68 68 #ifdef HAVE_CONFIG_H ··· 88 88 #define WEIGHT_SHIFT 0 89 89 #endif 90 90 91 + #ifdef FIXED_POINT 92 + #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 93 + #else 94 + #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) 95 + #endif 96 + 91 97 /* If enabled, the AEC will use a foreground filter and a background filter to be more robust to double-talk 92 98 and difficult signals in general. The cost is an extra FFT and a matrix-vector multiply */ 93 99 #define TWO_PATH ··· 131 137 int adapted; 132 138 int saturated; 133 139 int screwed_up; 140 + int C; /** Number of input channels (microphones) */ 141 + int K; /** Number of output channels (loudspeakers) */ 134 142 spx_int32_t sampling_rate; 135 143 spx_word16_t spec_average; 136 144 spx_word16_t beta0; 137 145 spx_word16_t beta_max; 138 146 spx_word32_t sum_adapt; 139 147 spx_word16_t leak_estimate; 140 - 148 + 141 149 spx_word16_t *e; /* scratch */ 142 150 spx_word16_t *x; /* Far-end input buffer (2N) */ 143 151 spx_word16_t *X; /* Far-end buffer (M+1 frames) in frequency domain */ ··· 171 179 spx_word16_t *window; 172 180 spx_word16_t *prop; 173 181 void *fft_table; 174 - spx_word16_t memX, memD, memE; 182 + spx_word16_t *memX, *memD, *memE; 175 183 spx_word16_t preemph; 176 184 spx_word16_t notch_radius; 177 - spx_mem_t notch_mem[2]; 185 + spx_mem_t *notch_mem; 178 186 179 187 /* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */ 180 188 spx_int16_t *play_buf; ··· 182 190 int play_buf_started; 183 191 }; 184 192 185 - static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem) 193 + static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem, int stride) 186 194 { 187 195 int i; 188 196 spx_word16_t den2; ··· 190 198 den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius)); 191 199 #else 192 200 den2 = radius*radius + .7*(1-radius)*(1-radius); 193 - #endif 201 + #endif 194 202 /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/ 195 203 for (i=0;i<len;i++) 196 204 { 197 - spx_word16_t vin = in[i]; 205 + spx_word16_t vin = in[i*stride]; 198 206 spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15); 199 207 #ifdef FIXED_POINT 200 208 mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1); ··· 234 242 ps[j]=MULT16_16(X[i],X[i]); 235 243 } 236 244 245 + /** Compute power spectrum of a half-complex (packed) vector and accumulate */ 246 + static inline void power_spectrum_accum(const spx_word16_t *X, spx_word32_t *ps, int N) 247 + { 248 + int i, j; 249 + ps[0]+=MULT16_16(X[0],X[0]); 250 + for (i=1,j=1;i<N-1;i+=2,j++) 251 + { 252 + ps[j] += MULT16_16(X[i],X[i]) + MULT16_16(X[i+1],X[i+1]); 253 + } 254 + ps[j]+=MULT16_16(X[i],X[i]); 255 + } 256 + 237 257 /** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */ 238 258 #ifdef FIXED_POINT 239 259 static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M) ··· 330 350 prod[i] = FLOAT_MUL32(W,MULT16_16(X[i],Y[i])); 331 351 } 332 352 333 - static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, spx_word16_t *prop) 353 + static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, int P, spx_word16_t *prop) 334 354 { 335 - int i, j; 355 + int i, j, p; 336 356 spx_word16_t max_sum = 1; 337 357 spx_word32_t prop_sum = 1; 338 358 for (i=0;i<M;i++) 339 359 { 340 360 spx_word32_t tmp = 1; 341 - for (j=0;j<N;j++) 342 - tmp += MULT16_16(EXTRACT16(SHR32(W[i*N+j],18)), EXTRACT16(SHR32(W[i*N+j],18))); 361 + for (p=0;p<P;p++) 362 + for (j=0;j<N;j++) 363 + tmp += MULT16_16(EXTRACT16(SHR32(W[p*N*M + i*N+j],18)), EXTRACT16(SHR32(W[p*N*M + i*N+j],18))); 343 364 #ifdef FIXED_POINT 344 365 /* Just a security in case an overflow were to occur */ 345 366 tmp = MIN32(ABS32(tmp), 536870912); ··· 378 399 #endif 379 400 380 401 /** Creates a new echo canceller state */ 381 - SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) 402 + EXPORT SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) 382 403 { 383 - int i,N,M; 404 + return speex_echo_state_init_mc(frame_size, filter_length, 1, 1); 405 + } 406 + 407 + EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers) 408 + { 409 + int i,N,M, C, K; 384 410 SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState)); 385 411 412 + st->K = nb_speakers; 413 + st->C = nb_mic; 414 + C=st->C; 415 + K=st->K; 386 416 #ifdef DUMP_ECHO_CANCEL_DATA 387 417 if (rFile || pFile || oFile) 388 418 speex_fatal("Opening dump files twice"); ··· 390 420 pFile = fopen("aec_play.sw", "wb"); 391 421 oFile = fopen("aec_out.sw", "wb"); 392 422 #endif 393 - 423 + 394 424 st->frame_size = frame_size; 395 425 st->window_size = 2*frame_size; 396 426 N = st->window_size; ··· 412 442 st->leak_estimate = 0; 413 443 414 444 st->fft_table = spx_fft_init(N); 415 - 416 - st->e = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 417 - st->x = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 418 - st->input = (spx_word16_t*)speex_alloc(st->frame_size*sizeof(spx_word16_t)); 419 - st->y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 420 - st->last_y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 445 + 446 + st->e = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 447 + st->x = (spx_word16_t*)speex_alloc(K*N*sizeof(spx_word16_t)); 448 + st->input = (spx_word16_t*)speex_alloc(C*st->frame_size*sizeof(spx_word16_t)); 449 + st->y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 450 + st->last_y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 421 451 st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 422 452 st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 423 453 st->Xf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 424 454 st->Yh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 425 455 st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 426 456 427 - st->X = (spx_word16_t*)speex_alloc((M+1)*N*sizeof(spx_word16_t)); 428 - st->Y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 429 - st->E = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 430 - st->W = (spx_word32_t*)speex_alloc(M*N*sizeof(spx_word32_t)); 457 + st->X = (spx_word16_t*)speex_alloc(K*(M+1)*N*sizeof(spx_word16_t)); 458 + st->Y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 459 + st->E = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 460 + st->W = (spx_word32_t*)speex_alloc(C*K*M*N*sizeof(spx_word32_t)); 431 461 #ifdef TWO_PATH 432 - st->foreground = (spx_word16_t*)speex_alloc(M*N*sizeof(spx_word16_t)); 462 + st->foreground = (spx_word16_t*)speex_alloc(M*N*C*K*sizeof(spx_word16_t)); 433 463 #endif 434 464 st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 435 465 st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t)); ··· 450 480 #endif 451 481 for (i=0;i<=st->frame_size;i++) 452 482 st->power_1[i] = FLOAT_ONE; 453 - for (i=0;i<N*M;i++) 483 + for (i=0;i<N*M*K*C;i++) 454 484 st->W[i] = 0; 455 485 { 456 486 spx_word32_t sum = 0; ··· 465 495 } 466 496 for (i=M-1;i>=0;i--) 467 497 { 468 - st->prop[i] = DIV32(MULT16_16(QCONST16(.8,15), st->prop[i]),sum); 498 + st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum); 469 499 } 470 500 } 471 - 472 - st->memX=st->memD=st->memE=0; 501 + 502 + st->memX = (spx_word16_t*)speex_alloc(K*sizeof(spx_word16_t)); 503 + st->memD = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); 504 + st->memE = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); 473 505 st->preemph = QCONST16(.9,15); 474 506 if (st->sampling_rate<12000) 475 507 st->notch_radius = QCONST16(.9, 15); ··· 478 510 else 479 511 st->notch_radius = QCONST16(.992, 15); 480 512 481 - st->notch_mem[0] = st->notch_mem[1] = 0; 513 + st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t)); 482 514 st->adapted = 0; 483 515 st->Pey = st->Pyy = FLOAT_ONE; 484 - 516 + 485 517 #ifdef TWO_PATH 486 518 st->Davg1 = st->Davg2 = 0; 487 519 st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 488 520 #endif 489 - 490 - st->play_buf = (spx_int16_t*)speex_alloc((PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); 521 + 522 + st->play_buf = (spx_int16_t*)speex_alloc(K*(PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); 491 523 st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; 492 524 st->play_buf_started = 0; 493 - 525 + 494 526 return st; 495 527 } 496 528 497 529 /** Resets echo canceller state */ 498 - void speex_echo_state_reset(SpeexEchoState *st) 530 + EXPORT void speex_echo_state_reset(SpeexEchoState *st) 499 531 { 500 - int i, M, N; 532 + int i, M, N, C, K; 501 533 st->cancel_count=0; 502 534 st->screwed_up = 0; 503 535 N = st->window_size; 504 536 M = st->M; 537 + C=st->C; 538 + K=st->K; 505 539 for (i=0;i<N*M;i++) 506 540 st->W[i] = 0; 507 541 #ifdef TWO_PATH ··· 521 555 { 522 556 st->last_y[i] = 0; 523 557 } 524 - for (i=0;i<N;i++) 558 + for (i=0;i<N*C;i++) 525 559 { 526 560 st->E[i] = 0; 561 + } 562 + for (i=0;i<N*K;i++) 563 + { 527 564 st->x[i] = 0; 528 565 } 529 - st->notch_mem[0] = st->notch_mem[1] = 0; 530 - st->memX=st->memD=st->memE=0; 566 + for (i=0;i<2*C;i++) 567 + st->notch_mem[i] = 0; 568 + for (i=0;i<C;i++) 569 + st->memD[i]=st->memE[i]=0; 570 + for (i=0;i<K;i++) 571 + st->memX[i]=0; 531 572 532 573 st->saturated = 0; 533 574 st->adapted = 0; ··· 545 586 } 546 587 547 588 /** Destroys an echo canceller state */ 548 - void speex_echo_state_destroy(SpeexEchoState *st) 589 + EXPORT void speex_echo_state_destroy(SpeexEchoState *st) 549 590 { 550 591 spx_fft_destroy(st->fft_table); 551 592 ··· 576 617 #ifdef FIXED_POINT 577 618 speex_free(st->wtmp2); 578 619 #endif 620 + speex_free(st->memX); 621 + speex_free(st->memD); 622 + speex_free(st->memE); 623 + speex_free(st->notch_mem); 624 + 579 625 speex_free(st->play_buf); 580 626 speex_free(st); 581 - 627 + 582 628 #ifdef DUMP_ECHO_CANCEL_DATA 583 629 fclose(rFile); 584 630 fclose(pFile); ··· 587 633 #endif 588 634 } 589 635 590 - void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out) 636 + EXPORT void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out) 591 637 { 592 638 int i; 593 639 /*speex_warning_int("capture with fill level ", st->play_buf_pos/st->frame_size);*/ ··· 610 656 } 611 657 } 612 658 613 - void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) 659 + EXPORT void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) 614 660 { 615 661 /*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/ 616 662 if (!st->play_buf_started) ··· 637 683 } 638 684 639 685 /** Performs echo cancellation on a frame (deprecated, last arg now ignored) */ 640 - void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout) 686 + EXPORT void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout) 641 687 { 642 688 speex_echo_cancellation(st, in, far_end, out); 643 689 } 644 690 645 691 /** Performs echo cancellation on a frame */ 646 - void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out) 692 + EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out) 647 693 { 648 - int i,j; 649 - int N,M; 694 + int i,j, chan, speak; 695 + int N,M, C, K; 650 696 spx_word32_t Syy,See,Sxx,Sdd, Sff; 651 697 #ifdef TWO_PATH 652 698 spx_word32_t Dbf; ··· 658 704 spx_float_t alpha, alpha_1; 659 705 spx_word16_t RER; 660 706 spx_word32_t tmp32; 661 - 707 + 662 708 N = st->window_size; 663 709 M = st->M; 710 + C = st->C; 711 + K = st->K; 712 + 664 713 st->cancel_count++; 665 714 #ifdef FIXED_POINT 666 715 ss=DIV32_16(11469,M); ··· 670 719 ss_1 = 1-ss; 671 720 #endif 672 721 673 - /* Apply a notch filter to make sure DC doesn't end up causing problems */ 674 - filter_dc_notch16(in, st->notch_radius, st->input, st->frame_size, st->notch_mem); 675 - /* Copy input data to buffer and apply pre-emphasis */ 676 - for (i=0;i<st->frame_size;i++) 722 + for (chan = 0; chan < C; chan++) 677 723 { 678 - spx_word32_t tmp32; 679 - tmp32 = SUB32(EXTEND32(far_end[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memX))); 680 - #ifdef FIXED_POINT 681 - /* If saturation occurs here, we need to freeze adaptation for M+1 frames (not just one) */ 682 - if (tmp32 > 32767) 724 + /* Apply a notch filter to make sure DC doesn't end up causing problems */ 725 + filter_dc_notch16(in+chan, st->notch_radius, st->input+chan*st->frame_size, st->frame_size, st->notch_mem+2*chan, C); 726 + /* Copy input data to buffer and apply pre-emphasis */ 727 + /* Copy input data to buffer */ 728 + for (i=0;i<st->frame_size;i++) 683 729 { 684 - tmp32 = 32767; 685 - st->saturated = M+1; 730 + spx_word32_t tmp32; 731 + /* FIXME: This core has changed a bit, need to merge properly */ 732 + tmp32 = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD[chan]))); 733 + #ifdef FIXED_POINT 734 + if (tmp32 > 32767) 735 + { 736 + tmp32 = 32767; 737 + if (st->saturated == 0) 738 + st->saturated = 1; 739 + } 740 + if (tmp32 < -32767) 741 + { 742 + tmp32 = -32767; 743 + if (st->saturated == 0) 744 + st->saturated = 1; 745 + } 746 + #endif 747 + st->memD[chan] = st->input[chan*st->frame_size+i]; 748 + st->input[chan*st->frame_size+i] = EXTRACT16(tmp32); 686 749 } 687 - if (tmp32 < -32767) 750 + } 751 + 752 + for (speak = 0; speak < K; speak++) 753 + { 754 + for (i=0;i<st->frame_size;i++) 688 755 { 689 - tmp32 = -32767; 690 - st->saturated = M+1; 691 - } 692 - #endif 693 - st->x[i+st->frame_size] = EXTRACT16(tmp32); 694 - st->memX = far_end[i]; 695 - 696 - tmp32 = SUB32(EXTEND32(st->input[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD))); 756 + spx_word32_t tmp32; 757 + st->x[speak*N+i] = st->x[speak*N+i+st->frame_size]; 758 + tmp32 = SUB32(EXTEND32(far_end[i*K+speak]), EXTEND32(MULT16_16_P15(st->preemph, st->memX[speak]))); 697 759 #ifdef FIXED_POINT 698 - if (tmp32 > 32767) 699 - { 700 - tmp32 = 32767; 701 - if (st->saturated == 0) 702 - st->saturated = 1; 703 - } 704 - if (tmp32 < -32767) 760 + /*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */ 761 + if (tmp32 > 32767) 762 + { 763 + tmp32 = 32767; 764 + st->saturated = M+1; 765 + } 766 + if (tmp32 < -32767) 767 + { 768 + tmp32 = -32767; 769 + st->saturated = M+1; 770 + } 771 + #endif 772 + st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32); 773 + st->memX[speak] = far_end[i*K+speak]; 774 + } 775 + } 776 + 777 + for (speak = 0; speak < K; speak++) 778 + { 779 + /* Shift memory: this could be optimized eventually*/ 780 + for (j=M-1;j>=0;j--) 705 781 { 706 - tmp32 = -32767; 707 - if (st->saturated == 0) 708 - st->saturated = 1; 782 + for (i=0;i<N;i++) 783 + st->X[(j+1)*N*K+speak*N+i] = st->X[j*N*K+speak*N+i]; 709 784 } 710 - #endif 711 - st->memD = st->input[i]; 712 - st->input[i] = tmp32; 785 + /* Convert x (echo input) to frequency domain */ 786 + spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]); 713 787 } 714 788 715 - /* Shift memory: this could be optimized eventually*/ 716 - for (j=M-1;j>=0;j--) 789 + Sxx = 0; 790 + for (speak = 0; speak < K; speak++) 717 791 { 718 - for (i=0;i<N;i++) 719 - st->X[(j+1)*N+i] = st->X[j*N+i]; 792 + Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); 793 + power_spectrum_accum(st->X+speak*N, st->Xf, N); 720 794 } 721 795 722 - /* Convert x (far end) to frequency domain */ 723 - spx_fft(st->fft_table, st->x, &st->X[0]); 724 - for (i=0;i<N;i++) 725 - st->last_y[i] = st->x[i]; 726 - Sxx = mdf_inner_prod(st->x+st->frame_size, st->x+st->frame_size, st->frame_size); 727 - for (i=0;i<st->frame_size;i++) 728 - st->x[i] = st->x[i+st->frame_size]; 729 - /* From here on, the top part of x is used as scratch space */ 730 - 796 + Sff = 0; 797 + for (chan = 0; chan < C; chan++) 798 + { 731 799 #ifdef TWO_PATH 732 - /* Compute foreground filter */ 733 - spectral_mul_accum16(st->X, st->foreground, st->Y, N, M); 734 - spx_ifft(st->fft_table, st->Y, st->e); 735 - for (i=0;i<st->frame_size;i++) 736 - st->e[i] = SUB16(st->input[i], st->e[i+st->frame_size]); 737 - Sff = mdf_inner_prod(st->e, st->e, st->frame_size); 800 + /* Compute foreground filter */ 801 + spectral_mul_accum16(st->X, st->foreground+chan*N*K*M, st->Y+chan*N, N, M*K); 802 + spx_ifft(st->fft_table, st->Y+chan*N, st->e+chan*N); 803 + for (i=0;i<st->frame_size;i++) 804 + st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->e[chan*N+i+st->frame_size]); 805 + Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 738 806 #endif 739 - 807 + } 808 + 740 809 /* Adjust proportional adaption rate */ 741 - mdf_adjust_prop (st->W, N, M, st->prop); 810 + /* FIXME: Adjust that for C, K*/ 811 + if (st->adapted) 812 + mdf_adjust_prop (st->W, N, M, C*K, st->prop); 742 813 /* Compute weight gradient */ 743 814 if (st->saturated == 0) 744 815 { 745 - for (j=M-1;j>=0;j--) 816 + for (chan = 0; chan < C; chan++) 746 817 { 747 - weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N], st->E, st->PHI, N); 748 - for (i=0;i<N;i++) 749 - st->W[j*N+i] = ADD32(st->W[j*N+i], st->PHI[i]); 750 - 818 + for (speak = 0; speak < K; speak++) 819 + { 820 + for (j=M-1;j>=0;j--) 821 + { 822 + weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N*K+speak*N], st->E+chan*N, st->PHI, N); 823 + for (i=0;i<N;i++) 824 + st->W[chan*N*K*M + j*N*K + speak*N + i] += st->PHI[i]; 825 + } 826 + } 751 827 } 752 828 } else { 753 829 st->saturated--; 754 830 } 755 - 831 + 832 + /* FIXME: MC conversion required */ 756 833 /* Update weight to prevent circular convolution (MDF / AUMDF) */ 757 - for (j=0;j<M;j++) 834 + for (chan = 0; chan < C; chan++) 758 835 { 759 - /* This is a variant of the Alternatively Updated MDF (AUMDF) */ 760 - /* Remove the "if" to make this an MDF filter */ 761 - if (j==0 || st->cancel_count%(M-1) == j-1) 836 + for (speak = 0; speak < K; speak++) 762 837 { 763 - #ifdef FIXED_POINT 764 - for (i=0;i<N;i++) 765 - st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],NORMALIZE_SCALEDOWN+16)); 766 - spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 767 - for (i=0;i<st->frame_size;i++) 838 + for (j=0;j<M;j++) 768 839 { 769 - st->wtmp[i]=0; 770 - } 771 - for (i=st->frame_size;i<N;i++) 772 - { 773 - st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); 774 - } 775 - spx_fft(st->fft_table, st->wtmp, st->wtmp2); 776 - /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ 777 - for (i=0;i<N;i++) 778 - st->W[j*N+i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); 840 + /* This is a variant of the Alternatively Updated MDF (AUMDF) */ 841 + /* Remove the "if" to make this an MDF filter */ 842 + if (j==0 || st->cancel_count%(M-1) == j-1) 843 + { 844 + #ifdef FIXED_POINT 845 + for (i=0;i<N;i++) 846 + st->wtmp2[i] = EXTRACT16(PSHR32(st->W[chan*N*K*M + j*N*K + speak*N + i],NORMALIZE_SCALEDOWN+16)); 847 + spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 848 + for (i=0;i<st->frame_size;i++) 849 + { 850 + st->wtmp[i]=0; 851 + } 852 + for (i=st->frame_size;i<N;i++) 853 + { 854 + st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); 855 + } 856 + spx_fft(st->fft_table, st->wtmp, st->wtmp2); 857 + /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ 858 + for (i=0;i<N;i++) 859 + st->W[chan*N*K*M + j*N*K + speak*N + i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); 779 860 #else 780 - spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); 781 - for (i=st->frame_size;i<N;i++) 782 - { 783 - st->wtmp[i]=0; 784 - } 785 - spx_fft(st->fft_table, st->wtmp, &st->W[j*N]); 861 + spx_ifft(st->fft_table, &st->W[chan*N*K*M + j*N*K + speak*N], st->wtmp); 862 + for (i=st->frame_size;i<N;i++) 863 + { 864 + st->wtmp[i]=0; 865 + } 866 + spx_fft(st->fft_table, st->wtmp, &st->W[chan*N*K*M + j*N*K + speak*N]); 786 867 #endif 868 + } 869 + } 787 870 } 788 871 } 789 872 790 - /* Compute filter response Y */ 791 - spectral_mul_accum(st->X, st->W, st->Y, N, M); 792 - spx_ifft(st->fft_table, st->Y, st->y); 873 + /* So we can use power_spectrum_accum */ 874 + for (i=0;i<=st->frame_size;i++) 875 + st->Rf[i] = st->Yf[i] = st->Xf[i] = 0; 793 876 877 + Dbf = 0; 878 + See = 0; 794 879 #ifdef TWO_PATH 795 880 /* Difference in response, this is used to estimate the variance of our residual power estimate */ 796 - for (i=0;i<st->frame_size;i++) 797 - st->e[i] = SUB16(st->e[i+st->frame_size], st->y[i+st->frame_size]); 798 - Dbf = 10+mdf_inner_prod(st->e, st->e, st->frame_size); 881 + for (chan = 0; chan < C; chan++) 882 + { 883 + spectral_mul_accum(st->X, st->W+chan*N*K*M, st->Y+chan*N, N, M*K); 884 + spx_ifft(st->fft_table, st->Y+chan*N, st->y+chan*N); 885 + for (i=0;i<st->frame_size;i++) 886 + st->e[chan*N+i] = SUB16(st->e[chan*N+i+st->frame_size], st->y[chan*N+i+st->frame_size]); 887 + Dbf += 10+mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 888 + for (i=0;i<st->frame_size;i++) 889 + st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); 890 + See += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 891 + } 799 892 #endif 800 893 801 - for (i=0;i<st->frame_size;i++) 802 - st->e[i] = SUB16(st->input[i], st->y[i+st->frame_size]); 803 - See = mdf_inner_prod(st->e, st->e, st->frame_size); 804 894 #ifndef TWO_PATH 805 895 Sff = See; 806 896 #endif 807 897 808 898 #ifdef TWO_PATH 809 899 /* Logic for updating the foreground filter */ 810 - 900 + 811 901 /* For two time windows, compute the mean of the energy difference, as well as the variance */ 812 902 st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See))); 813 903 st->Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),st->Davg2), MULT16_32_Q15(QCONST16(.15f,15),SUB32(Sff,See))); 814 904 st->Dvar1 = FLOAT_ADD(FLOAT_MULT(VAR1_SMOOTH, st->Dvar1), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.4f,15),Sff), MULT16_32_Q15(QCONST16(.4f,15),Dbf))); 815 905 st->Dvar2 = FLOAT_ADD(FLOAT_MULT(VAR2_SMOOTH, st->Dvar2), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.15f,15),Sff), MULT16_32_Q15(QCONST16(.15f,15),Dbf))); 816 - 906 + 817 907 /* Equivalent float code: 818 908 st->Davg1 = .6*st->Davg1 + .4*(Sff-See); 819 909 st->Davg2 = .85*st->Davg2 + .15*(Sff-See); 820 910 st->Dvar1 = .36*st->Dvar1 + .16*Sff*Dbf; 821 911 st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf; 822 912 */ 823 - 913 + 824 914 update_foreground = 0; 825 915 /* Check if we have a statistically significant reduction in the residual echo */ 826 916 /* Note that this is *not* Gaussian, so we need to be careful about the longer tail */ ··· 830 920 update_foreground = 1; 831 921 else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2)))) 832 922 update_foreground = 1; 833 - 923 + 834 924 /* Do we update? */ 835 925 if (update_foreground) 836 926 { 837 927 st->Davg1 = st->Davg2 = 0; 838 928 st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 839 929 /* Copy background filter to foreground filter */ 840 - for (i=0;i<N*M;i++) 930 + for (i=0;i<N*M*C*K;i++) 841 931 st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16)); 842 932 /* Apply a smooth transition so as to not introduce blocking artifacts */ 843 - for (i=0;i<st->frame_size;i++) 844 - st->e[i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[i+st->frame_size]); 933 + for (chan = 0; chan < C; chan++) 934 + for (i=0;i<st->frame_size;i++) 935 + st->e[chan*N+i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[chan*N+i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[chan*N+i+st->frame_size]); 845 936 } else { 846 937 int reset_background=0; 847 938 /* Otherwise, check if the background filter is significantly worse */ ··· 854 945 if (reset_background) 855 946 { 856 947 /* Copy foreground filter to background filter */ 857 - for (i=0;i<N*M;i++) 948 + for (i=0;i<N*M*C*K;i++) 858 949 st->W[i] = SHL32(EXTEND32(st->foreground[i]),16); 859 950 /* We also need to copy the output so as to get correct adaptation */ 860 - for (i=0;i<st->frame_size;i++) 861 - st->y[i+st->frame_size] = st->e[i+st->frame_size]; 862 - for (i=0;i<st->frame_size;i++) 863 - st->e[i] = SUB16(st->input[i], st->y[i+st->frame_size]); 951 + for (chan = 0; chan < C; chan++) 952 + { 953 + for (i=0;i<st->frame_size;i++) 954 + st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size]; 955 + for (i=0;i<st->frame_size;i++) 956 + st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); 957 + } 864 958 See = Sff; 865 959 st->Davg1 = st->Davg2 = 0; 866 960 st->Dvar1 = st->Dvar2 = FLOAT_ZERO; ··· 868 962 } 869 963 #endif 870 964 871 - /* Compute error signal (for the output with de-emphasis) */ 872 - for (i=0;i<st->frame_size;i++) 965 + Sey = Syy = Sdd = 0; 966 + for (chan = 0; chan < C; chan++) 873 967 { 874 - spx_word32_t tmp_out; 968 + /* Compute error signal (for the output with de-emphasis) */ 969 + for (i=0;i<st->frame_size;i++) 970 + { 971 + spx_word32_t tmp_out; 875 972 #ifdef TWO_PATH 876 - tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->e[i+st->frame_size])); 973 + tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->e[chan*N+i+st->frame_size])); 877 974 #else 878 - tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->y[i+st->frame_size])); 975 + tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->y[chan*N+i+st->frame_size])); 879 976 #endif 880 - /* Saturation */ 881 - if (tmp_out>32767) 882 - tmp_out = 32767; 883 - else if (tmp_out<-32768) 884 - tmp_out = -32768; 885 - tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE))); 977 + tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE[chan]))); 886 978 /* This is an arbitrary test for saturation in the microphone signal */ 887 - if (in[i] <= -32000 || in[i] >= 32000) 888 - { 889 - tmp_out = 0; 979 + if (in[i*C+chan] <= -32000 || in[i*C+chan] >= 32000) 980 + { 890 981 if (st->saturated == 0) 891 982 st->saturated = 1; 983 + } 984 + out[i*C+chan] = WORD2INT(tmp_out); 985 + st->memE[chan] = tmp_out; 892 986 } 893 - out[i] = (spx_int16_t)tmp_out; 894 - st->memE = tmp_out; 895 - } 896 - 987 + 897 988 #ifdef DUMP_ECHO_CANCEL_DATA 898 - dump_audio(in, far_end, out, st->frame_size); 989 + dump_audio(in, far_end, out, st->frame_size); 899 990 #endif 900 - 901 - /* Compute error signal (filter update version) */ 902 - for (i=0;i<st->frame_size;i++) 903 - { 904 - st->e[i+st->frame_size] = st->e[i]; 905 - st->e[i] = 0; 991 + 992 + /* Compute error signal (filter update version) */ 993 + for (i=0;i<st->frame_size;i++) 994 + { 995 + st->e[chan*N+i+st->frame_size] = st->e[chan*N+i]; 996 + st->e[chan*N+i] = 0; 997 + } 998 + 999 + /* Compute a bunch of correlations */ 1000 + /* FIXME: bad merge */ 1001 + Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); 1002 + Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); 1003 + Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size); 1004 + 1005 + /* Convert error to frequency domain */ 1006 + spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N); 1007 + for (i=0;i<st->frame_size;i++) 1008 + st->y[i+chan*N] = 0; 1009 + spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N); 1010 + 1011 + /* Compute power spectrum of echo (X), error (E) and filter response (Y) */ 1012 + power_spectrum_accum(st->E+chan*N, st->Rf, N); 1013 + power_spectrum_accum(st->Y+chan*N, st->Yf, N); 1014 + 906 1015 } 907 1016 908 - /* Compute a bunch of correlations */ 909 - Sey = mdf_inner_prod(st->e+st->frame_size, st->y+st->frame_size, st->frame_size); 910 - Syy = mdf_inner_prod(st->y+st->frame_size, st->y+st->frame_size, st->frame_size); 911 - Sdd = mdf_inner_prod(st->input, st->input, st->frame_size); 912 - 913 1017 /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/ 914 - 1018 + 915 1019 /* Do some sanity check */ 916 1020 if (!(Syy>=0 && Sxx>=0 && See >= 0) 917 1021 #ifndef FIXED_POINT ··· 921 1025 { 922 1026 /* Things have gone really bad */ 923 1027 st->screwed_up += 50; 924 - for (i=0;i<st->frame_size;i++) 1028 + for (i=0;i<st->frame_size*C;i++) 925 1029 out[i] = 0; 926 1030 } else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6))) 927 1031 { ··· 941 1045 /* Add a small noise floor to make sure not to have problems when dividing */ 942 1046 See = MAX32(See, SHR32(MULT16_16(N, 100),6)); 943 1047 944 - /* Convert error to frequency domain */ 945 - spx_fft(st->fft_table, st->e, st->E); 946 - for (i=0;i<st->frame_size;i++) 947 - st->y[i] = 0; 948 - spx_fft(st->fft_table, st->y, st->Y); 1048 + for (speak = 0; speak < K; speak++) 1049 + { 1050 + Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); 1051 + power_spectrum_accum(st->X+speak*N, st->Xf, N); 1052 + } 949 1053 950 - /* Compute power spectrum of far end (X), error (E) and filter response (Y) */ 951 - power_spectrum(st->E, st->Rf, N); 952 - power_spectrum(st->Y, st->Yf, N); 953 - power_spectrum(st->X, st->Xf, N); 954 - 1054 + 955 1055 /* Smooth far end energy estimate over time */ 956 1056 for (j=0;j<=st->frame_size;j++) 957 1057 st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]); 958 - 959 - /* Enable this to compute the power based only on the tail (would need to compute more 960 - efficiently to make this really useful */ 961 - if (0) 962 - { 963 - float scale2 = .5f/M; 964 - for (j=0;j<=st->frame_size;j++) 965 - st->power[j] = 100; 966 - for (i=0;i<M;i++) 967 - { 968 - power_spectrum(&st->X[i*N], st->Xf, N); 969 - for (j=0;j<=st->frame_size;j++) 970 - st->power[j] += scale2*st->Xf[j]; 971 - } 972 - } 973 1058 974 1059 /* Compute filtered spectra and (cross-)correlations */ 975 1060 for (j=st->frame_size;j>=0;j--) ··· 987 1072 st->Yh[j] = (1-st->spec_average)*st->Yh[j] + st->spec_average*st->Yf[j]; 988 1073 #endif 989 1074 } 990 - 1075 + 991 1076 Pyy = FLOAT_SQRT(Pyy); 992 1077 Pey = FLOAT_DIVU(Pey,Pyy); 993 1078 ··· 1015 1100 else 1016 1101 st->leak_estimate = SHL16(st->leak_estimate,1); 1017 1102 /*printf ("%f\n", st->leak_estimate);*/ 1018 - 1103 + 1019 1104 /* Compute Residual to Error Ratio */ 1020 1105 #ifdef FIXED_POINT 1021 1106 tmp32 = MULT16_32_Q15(st->leak_estimate,Syy); ··· 1071 1156 /* Temporary adaption rate if filter is not yet adapted enough */ 1072 1157 spx_word16_t adapt_rate=0; 1073 1158 1074 - if (Sxx > SHR32(MULT16_16(N, 1000),6)) 1159 + if (Sxx > SHR32(MULT16_16(N, 1000),6)) 1075 1160 { 1076 1161 tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx); 1077 1162 #ifdef FIXED_POINT ··· 1091 1176 st->sum_adapt = ADD32(st->sum_adapt,adapt_rate); 1092 1177 } 1093 1178 1094 - /* Save residual echo so it can be used by the nonlinear processor */ 1179 + /* FIXME: MC conversion required */ 1180 + for (i=0;i<st->frame_size;i++) 1181 + st->last_y[i] = st->last_y[st->frame_size+i]; 1095 1182 if (st->adapted) 1096 1183 { 1097 1184 /* If the filter is adapted, take the filtered echo */ 1098 1185 for (i=0;i<st->frame_size;i++) 1099 - st->last_y[i] = st->last_y[st->frame_size+i]; 1100 - for (i=0;i<st->frame_size;i++) 1101 1186 st->last_y[st->frame_size+i] = in[i]-out[i]; 1102 1187 } else { 1103 1188 /* If filter isn't adapted yet, all we can do is take the far end signal directly */ ··· 1113 1198 int i; 1114 1199 spx_word16_t leak2; 1115 1200 int N; 1116 - 1201 + 1117 1202 N = st->window_size; 1118 1203 1119 1204 /* Apply hanning window (should pre-compute it)*/ 1120 1205 for (i=0;i<N;i++) 1121 1206 st->y[i] = MULT16_16_Q15(st->window[i],st->last_y[i]); 1122 - 1207 + 1123 1208 /* Compute power spectrum of the echo */ 1124 1209 spx_fft(st->fft_table, st->y, st->Y); 1125 1210 power_spectrum(st->Y, residual_echo, N); 1126 - 1211 + 1127 1212 #ifdef FIXED_POINT 1128 1213 if (st->leak_estimate > 16383) 1129 1214 leak2 = 32767; ··· 1138 1223 /* Estimate residual echo */ 1139 1224 for (i=0;i<=st->frame_size;i++) 1140 1225 residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]); 1141 - 1226 + 1142 1227 } 1143 1228 1144 - int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) 1229 + EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) 1145 1230 { 1146 1231 switch(request) 1147 1232 { 1148 - 1233 + 1149 1234 case SPEEX_ECHO_GET_FRAME_SIZE: 1150 1235 (*(int*)ptr) = st->frame_size; 1151 1236 break; ··· 1168 1253 break; 1169 1254 case SPEEX_ECHO_GET_SAMPLING_RATE: 1170 1255 (*(int*)ptr) = st->sampling_rate; 1256 + break; 1257 + case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE: 1258 + /*FIXME: Implement this for multiple channels */ 1259 + *((spx_int32_t *)ptr) = st->M * st->frame_size; 1260 + break; 1261 + case SPEEX_ECHO_GET_IMPULSE_RESPONSE: 1262 + { 1263 + int M = st->M, N = st->window_size, n = st->frame_size, i, j; 1264 + spx_int32_t *filt = (spx_int32_t *) ptr; 1265 + for(j=0;j<M;j++) 1266 + { 1267 + /*FIXME: Implement this for multiple channels */ 1268 + #ifdef FIXED_POINT 1269 + for (i=0;i<N;i++) 1270 + st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN)); 1271 + spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 1272 + #else 1273 + spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); 1274 + #endif 1275 + for(i=0;i<n;i++) 1276 + filt[j*n+i] = PSHR32(MULT16_16(32767,st->wtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN); 1277 + } 1278 + } 1171 1279 break; 1172 1280 default: 1173 1281 speex_warning_int("Unknown speex_echo_ctl request: ", request);
+6 -2
lib/rbcodec/codecs/libspeex/modes.c
··· 450 450 451 451 452 452 /* Default mode for narrowband */ 453 - const SpeexMode speex_nb_mode = { 453 + EXPORT const SpeexMode speex_nb_mode = { 454 454 &nb_mode, 455 455 nb_mode_query, 456 456 "narrowband", ··· 479 479 480 480 481 481 482 - int speex_mode_query(const SpeexMode *mode, int request, void *ptr) 482 + EXPORT int speex_mode_query(const SpeexMode *mode, int request, void *ptr) 483 483 { 484 484 return mode->query(mode->mode, request, ptr); 485 485 } 486 486 487 + #ifdef FIXED_DEBUG 488 + long long spx_mips=0; 489 + #endif 490 +
+5 -5
lib/rbcodec/codecs/libspeex/modes_wb.c
··· 55 55 #endif 56 56 57 57 #ifndef ROCKBOX_VOICE_CODEC 58 - const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode}; 58 + EXPORT const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode}; 59 59 #else 60 - const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, NULL}; 60 + EXPORT const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, NULL}; 61 61 #endif 62 62 63 63 extern const signed char hexc_table[]; ··· 250 250 }; 251 251 252 252 253 - const SpeexMode speex_wb_mode = { 253 + EXPORT const SpeexMode speex_wb_mode = { 254 254 &sb_wb_mode, 255 255 wb_mode_query, 256 256 "wideband (sub-band CELP)", ··· 285 285 286 286 #ifndef ROCKBOX_VOICE_CODEC 287 287 /* Split-band "ultra-wideband" (32 kbps) CELP mode*/ 288 - static const SpeexSBMode sb_uwb_mode = { 288 + EXPORT static const SpeexSBMode sb_uwb_mode = { 289 289 &speex_wb_mode, 290 290 320, /*frameSize*/ 291 291 80, /*subframeSize*/ ··· 365 365 /* We have defined speex_lib_get_mode() as a macro in speex.h */ 366 366 #undef speex_lib_get_mode 367 367 368 - const SpeexMode * speex_lib_get_mode (int mode) 368 + EXPORT const SpeexMode * speex_lib_get_mode (int mode) 369 369 { 370 370 if (mode < 0 || mode >= SPEEX_NB_MODES) return NULL; 371 371
+118 -84
lib/rbcodec/codecs/libspeex/preprocess.c
··· 1 1 /* Copyright (C) 2003 Epic Games (written by Jean-Marc Valin) 2 - Copyright (C) 2004-2006 Epic Games 3 - 2 + Copyright (C) 2004-2006 Epic Games 3 + 4 4 File: preprocess.c 5 5 Preprocessor with denoising based on the algorithm by Ephraim and Malah 6 6 ··· 34 34 35 35 /* 36 36 Recommended papers: 37 - 37 + 38 38 Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error 39 - short-time spectral amplitude estimator". IEEE Transactions on Acoustics, 39 + short-time spectral amplitude estimator". IEEE Transactions on Acoustics, 40 40 Speech and Signal Processing, vol. ASSP-32, no. 6, pp. 1109-1121, 1984. 41 - 41 + 42 42 Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error 43 - log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and 43 + log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and 44 44 Signal Processing, vol. ASSP-33, no. 2, pp. 443-445, 1985. 45 - 45 + 46 46 I. Cohen and B. Berdugo, "Speech enhancement for non-stationary noise environments". 47 47 Signal Processing, vol. 81, no. 2, pp. 2403-2418, 2001. 48 48 49 - Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic 50 - approach to combined acoustic echo cancellation and noise reduction". IEEE 49 + Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic 50 + approach to combined acoustic echo cancellation and noise reduction". IEEE 51 51 Transactions on Speech and Audio Processing, 2002. 52 - 52 + 53 53 J.-M. Valin, J. Rouat, and F. Michaud, "Microphone array post-filter for separation 54 - of simultaneous non-stationary sources". In Proceedings IEEE International 54 + of simultaneous non-stationary sources". In Proceedings IEEE International 55 55 Conference on Acoustics, Speech, and Signal Processing, 2004. 56 56 */ 57 57 ··· 75 75 #define LOUDNESS_EXP 5.f 76 76 #define AMP_SCALE .001f 77 77 #define AMP_SCALE_1 1000.f 78 - 78 + 79 79 #define NB_BANDS 24 80 80 81 81 #define SPEECH_PROB_START_DEFAULT QCONST16(0.35f,15) ··· 117 117 a = SHL32(a,8); 118 118 return PDIV32_16(a,b); 119 119 } 120 - 120 + 121 121 } 122 122 static inline spx_word16_t DIV32_16_Q15(spx_word32_t a, spx_word32_t b) 123 123 { ··· 185 185 int sampling_rate; /**< Sampling rate of the input/output */ 186 186 int nbands; 187 187 FilterBank *bank; 188 - 188 + 189 189 /* Parameters */ 190 190 int denoise_enabled; 191 191 int vad_enabled; ··· 198 198 int echo_suppress; 199 199 int echo_suppress_active; 200 200 SpeexEchoState *echo_state; 201 - 201 + 202 + spx_word16_t speech_prob; /**< Probability last frame was speech */ 203 + 202 204 /* DSP-related arrays */ 203 205 spx_word16_t *frame; /**< Processing frame (2*ps_size) */ 204 206 spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */ ··· 234 236 float *loudness_weight; /**< Perceptual loudness curve */ 235 237 float loudness; /**< Loudness estimate */ 236 238 float agc_gain; /**< Current AGC gain */ 237 - int nb_loudness_adapt; /**< Number of frames used for loudness adaptation so far */ 238 239 float max_gain; /**< Maximum gain allowed */ 239 240 float max_increase_step; /**< Maximum increase in gain from one frame to another */ 240 241 float max_decrease_step; /**< Maximum decrease in gain from one frame to another */ ··· 259 260 spx_word16_t tmp; 260 261 #ifdef FIXED_POINT 261 262 spx_word16_t x = DIV32_16(MULT16_16(32767,i),len); 262 - #else 263 + #else 263 264 spx_word16_t x = DIV32_16(MULT16_16(QCONST16(4.f,13),i),len); 264 265 #endif 265 266 int inv=0; ··· 284 285 } 285 286 } 286 287 287 - 288 + 288 289 #ifdef FIXED_POINT 289 - /* This function approximates the gain function 290 - y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x) 290 + /* This function approximates the gain function 291 + y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x) 291 292 which multiplied by xi/(1+xi) is the optimal gain 292 293 in the loudness domain ( sqrt[amplitude] ) 293 294 Input in Q11 format, output in Q15 ··· 320 321 static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len) 321 322 { 322 323 int i; 323 - 324 + 324 325 if (noise_suppress > effective_echo_suppress) 325 326 { 326 327 spx_word16_t noise_gain, gain_ratio; ··· 346 347 } 347 348 348 349 #else 349 - /* This function approximates the gain function 350 - y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x) 350 + /* This function approximates the gain function 351 + y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x) 351 352 which multiplied by xi/(1+xi) is the optimal gain 352 353 in the loudness domain ( sqrt[amplitude] ) 353 354 */ ··· 391 392 } 392 393 393 394 #endif 394 - SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate) 395 + EXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate) 395 396 { 396 397 int i; 397 398 int N, N3, N4, M; ··· 413 414 break; 414 415 } 415 416 } 416 - 417 - 417 + 418 + 418 419 if (st->ps_size < 3*st->frame_size/4) 419 420 st->ps_size = st->ps_size * 3 / 2; 420 421 #else ··· 424 425 N = st->ps_size; 425 426 N3 = 2*N - st->frame_size; 426 427 N4 = st->frame_size - N3; 427 - 428 + 428 429 st->sampling_rate = sampling_rate; 429 430 st->denoise_enabled = 1; 430 431 st->vad_enabled = 0; ··· 439 440 st->speech_prob_continue = SPEECH_PROB_CONTINUE_DEFAULT; 440 441 441 442 st->echo_state = NULL; 442 - 443 + 443 444 st->nbands = NB_BANDS; 444 445 M = st->nbands; 445 446 st->bank = filterbank_new(M, sampling_rate, N, 1); 446 - 447 + 447 448 st->frame = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); 448 449 st->window = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); 449 450 st->ft = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); 450 - 451 + 451 452 st->ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); 452 453 st->noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); 453 454 st->echo_noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); ··· 460 461 st->gain2 = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); 461 462 st->gain_floor = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); 462 463 st->zeta = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); 463 - 464 + 464 465 st->S = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 465 466 st->Smin = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 466 467 st->Stmp = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 467 468 st->update_prob = (int*)speex_alloc(N*sizeof(int)); 468 - 469 + 469 470 st->inbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t)); 470 471 st->outbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t)); 471 472 472 473 conj_window(st->window, 2*N3); 473 474 for (i=2*N3;i<2*st->ps_size;i++) 474 475 st->window[i]=Q15_ONE; 475 - 476 + 476 477 if (N4>0) 477 478 { 478 479 for (i=N3-1;i>=0;i--) ··· 514 515 /*st->loudness = pow(AMP_SCALE*st->agc_level,LOUDNESS_EXP);*/ 515 516 st->loudness = 1e-15; 516 517 st->agc_gain = 1; 517 - st->nb_loudness_adapt = 0; 518 518 st->max_gain = 30; 519 519 st->max_increase_step = exp(0.11513f * 12.*st->frame_size / st->sampling_rate); 520 520 st->max_decrease_step = exp(-0.11513f * 40.*st->frame_size / st->sampling_rate); ··· 530 530 return st; 531 531 } 532 532 533 - void speex_preprocess_state_destroy(SpeexPreprocessState *st) 533 + EXPORT void speex_preprocess_state_destroy(SpeexPreprocessState *st) 534 534 { 535 535 speex_free(st->frame); 536 536 speex_free(st->ft); ··· 573 573 float target_gain; 574 574 float loudness=1.f; 575 575 float rate; 576 - 576 + 577 577 for (i=2;i<N;i++) 578 578 { 579 579 loudness += 2.f*N*st->ps[i]* st->loudness_weight[i]; ··· 583 583 loudness*2 > pow(st->loudness, 1.0/LOUDNESS_EXP))*/ 584 584 if (Pframe>.3f) 585 585 { 586 - st->nb_loudness_adapt++; 587 586 /*rate=2.0f*Pframe*Pframe/(1+st->nb_loudness_adapt);*/ 588 587 rate = .03*Pframe*Pframe; 589 588 st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP); ··· 592 591 st->init_max *= 1.f + .1f*Pframe*Pframe; 593 592 } 594 593 /*printf ("%f %f %f %f\n", Pframe, loudness, pow(st->loudness, 1.0f/LOUDNESS_EXP), st->loudness2);*/ 595 - 594 + 596 595 target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP); 597 596 598 597 if ((Pframe>.5 && st->nb_adapt > 20) || target_gain < st->agc_gain) ··· 605 604 target_gain = st->max_gain; 606 605 if (target_gain > st->init_max) 607 606 target_gain = st->init_max; 608 - 607 + 609 608 st->agc_gain = target_gain; 610 609 } 611 610 /*fprintf (stderr, "%f %f %f\n", loudness, (float)AMP_SCALE_1*pow(st->loudness, 1.0f/LOUDNESS_EXP), st->agc_gain);*/ 612 - 611 + 613 612 for (i=0;i<2*N;i++) 614 613 ft[i] *= st->agc_gain; 615 614 st->prev_loudness = loudness; ··· 629 628 st->frame[i]=st->inbuf[i]; 630 629 for (i=0;i<st->frame_size;i++) 631 630 st->frame[N3+i]=x[i]; 632 - 631 + 633 632 /* Update inbuf */ 634 633 for (i=0;i<N3;i++) 635 634 st->inbuf[i]=x[N4+i]; ··· 648 647 st->frame[i] = SHL16(st->frame[i], st->frame_shift); 649 648 } 650 649 #endif 651 - 650 + 652 651 /* Perform FFT */ 653 652 spx_fft(st->fft_lookup, st->frame, st->ft); 654 - 653 + 655 654 /* Power spectrum */ 656 655 ps[0]=MULT16_16(st->ft[0],st->ft[0]); 657 656 for (i=1;i<N;i++) ··· 669 668 int N = st->ps_size; 670 669 671 670 for (i=1;i<N-1;i++) 672 - st->S[i] = MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1]) 671 + st->S[i] = MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1]) 673 672 + MULT16_32_Q15(QCONST16(.1f,15),st->ps[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i+1]); 674 673 st->S[0] = MULT16_32_Q15(QCONST16(.8f,15),st->S[0]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[0]); 675 674 st->S[N-1] = MULT16_32_Q15(QCONST16(.8f,15),st->S[N-1]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[N-1]); 676 - 675 + 677 676 if (st->nb_adapt==1) 678 677 { 679 678 for (i=0;i<N;i++) ··· 700 699 for (i=0;i<N;i++) 701 700 { 702 701 st->Smin[i] = MIN32(st->Smin[i], st->S[i]); 703 - st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]); 702 + st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]); 704 703 } 705 704 } 706 705 for (i=0;i<N;i++) 707 706 { 708 - if (MULT16_32_Q15(QCONST16(.4f,15),st->S[i]) > ADD32(st->Smin[i],EXTEND32(20))) 707 + if (MULT16_32_Q15(QCONST16(.4f,15),st->S[i]) > st->Smin[i]) 709 708 st->update_prob[i] = 1; 710 709 else 711 710 st->update_prob[i] = 0; ··· 719 718 720 719 void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len); 721 720 722 - int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo) 721 + EXPORT int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo) 723 722 { 724 723 return speex_preprocess_run(st, x); 725 724 } 726 725 727 - int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x) 726 + EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x) 728 727 { 729 728 int i; 730 729 int M; ··· 736 735 spx_word16_t Pframe; 737 736 spx_word16_t beta, beta_1; 738 737 spx_word16_t effective_echo_suppress; 739 - 738 + 740 739 st->nb_adapt++; 741 740 if (st->nb_adapt>20000) 742 741 st->nb_adapt = 20000; 743 742 st->min_count++; 744 - 743 + 745 744 beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt)); 746 745 beta_1 = Q15_ONE-beta; 747 746 M = st->nbands; ··· 775 774 st->update_prob[i] = 0; 776 775 } 777 776 */ 778 - 777 + 779 778 /* Update the noise estimate for the frequencies where it can be */ 780 779 for (i=0;i<N;i++) 781 780 { ··· 793 792 for (i=0;i<N+M;i++) 794 793 { 795 794 spx_word16_t gamma; 796 - 795 + 797 796 /* Total noise estimate including residual echo and reverberation */ 798 797 spx_word32_t tot_noise = ADD32(ADD32(ADD32(EXTEND32(1), PSHR32(st->noise[i],NOISE_SHIFT)) , st->echo_noise[i]) , st->reverb_estimate[i]); 799 - 798 + 800 799 /* A posteriori SNR = ps/noise - 1*/ 801 800 st->post[i] = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT)); 802 801 st->post[i]=MIN16(st->post[i], QCONST16(100.f,SNR_SHIFT)); 803 - 802 + 804 803 /* Computing update gamma = .1 + .9*(old/(old+noise))^2 */ 805 804 gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(st->old_ps[i],ADD32(st->old_ps[i],tot_noise)))); 806 - 805 + 807 806 /* A priori SNR update = gamma*max(0,post) + (1-gamma)*old/noise */ 808 807 st->prior[i] = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,st->post[i])), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(st->old_ps[i],tot_noise))), 15)); 809 808 st->prior[i]=MIN16(st->prior[i], QCONST16(100.f,SNR_SHIFT)); ··· 824 823 for (i=N;i<N+M;i++) 825 824 Zframe = ADD32(Zframe, EXTEND32(st->zeta[i])); 826 825 Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,st->nbands))); 827 - 826 + 828 827 effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), MULT16_16(Pframe, st->echo_suppress_active)),15)); 829 - 828 + 830 829 compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M); 831 - 832 - /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale) 833 - Technically this is actually wrong because the EM gaim assumes a slightly different probability 830 + 831 + /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale) 832 + Technically this is actually wrong because the EM gaim assumes a slightly different probability 834 833 distribution */ 835 834 for (i=N;i<N+M;i++) 836 835 { ··· 847 846 #ifdef FIXED_POINT 848 847 spx_word16_t tmp; 849 848 #endif 850 - 849 + 851 850 prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT))); 852 851 theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT)); 853 852 ··· 872 871 /* Convert the EM gains and speech prob to linear frequency */ 873 872 filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2); 874 873 filterbank_compute_psd16(st->bank,st->gain+N, st->gain); 875 - 874 + 876 875 /* Use 1 for linear gain resolution (best) or 0 for Bark gain resolution (faster) */ 877 876 if (1) 878 877 { 879 878 filterbank_compute_psd16(st->bank,st->gain_floor+N, st->gain_floor); 880 - 879 + 881 880 /* Compute gain according to the Ephraim-Malah algorithm -- linear frequency */ 882 881 for (i=0;i<N;i++) 883 882 { ··· 887 886 spx_word16_t tmp; 888 887 spx_word16_t p; 889 888 spx_word16_t g; 890 - 889 + 891 890 /* Wiener filter gain */ 892 891 prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT))); 893 892 theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT)); ··· 898 897 g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM))); 899 898 /* Interpolated speech probability of presence */ 900 899 p = st->gain2[i]; 901 - 900 + 902 901 /* Constrain the gain to be close to the Bark scale gain */ 903 902 if (MULT16_16_Q15(QCONST16(.333f,15),g) > st->gain[i]) 904 903 g = MULT16_16(3,st->gain[i]); 905 904 st->gain[i] = g; 906 - 905 + 907 906 /* Save old power spectrum */ 908 907 st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]); 909 - 908 + 910 909 /* Apply gain floor */ 911 910 if (st->gain[i] < st->gain_floor[i]) 912 911 st->gain[i] = st->gain_floor[i]; 913 912 914 913 /* Exponential decay model for reverberation (unused) */ 915 914 /*st->reverb_estimate[i] = st->reverb_decay*st->reverb_estimate[i] + st->reverb_decay*st->reverb_level*st->gain[i]*st->gain[i]*st->ps[i];*/ 916 - 915 + 917 916 /* Take into account speech probability of presence (loudness domain MMSE estimator) */ 918 917 /* gain2 = [p*sqrt(gain)+(1-p)*sqrt(gain _floor) ]^2 */ 919 918 tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15))); ··· 927 926 { 928 927 spx_word16_t tmp; 929 928 spx_word16_t p = st->gain2[i]; 930 - st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]); 929 + st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]); 931 930 tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15))); 932 931 st->gain2[i]=SQR16_Q15(tmp); 933 932 } 934 933 filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2); 935 934 } 936 - 935 + 937 936 /* If noise suppression is off, don't apply the gain (but then why call this in the first place!) */ 938 937 if (!st->denoise_enabled) 939 938 { 940 939 for (i=0;i<N+M;i++) 941 940 st->gain2[i]=Q15_ONE; 942 941 } 943 - 942 + 944 943 /* Apply computed gain */ 945 944 for (i=1;i<N;i++) 946 945 { ··· 949 948 } 950 949 st->ft[0] = MULT16_16_P15(st->gain2[0],st->ft[0]); 951 950 st->ft[2*N-1] = MULT16_16_P15(st->gain2[N-1],st->ft[2*N-1]); 952 - 951 + 953 952 /*FIXME: This *will* not work for fixed-point */ 954 953 #ifndef FIXED_POINT 955 954 if (st->agc_enabled) ··· 978 977 } 979 978 } 980 979 #endif 981 - 980 + 982 981 /* Synthesis window (for WOLA) */ 983 982 for (i=0;i<2*N;i++) 984 983 st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]); ··· 988 987 x[i] = st->outbuf[i] + st->frame[i]; 989 988 for (i=0;i<N4;i++) 990 989 x[N3+i] = st->frame[N3+i]; 991 - 990 + 992 991 /* Update outbuf */ 993 992 for (i=0;i<N3;i++) 994 993 st->outbuf[i] = st->frame[st->frame_size+i]; 995 994 996 995 /* FIXME: This VAD is a kludge */ 996 + st->speech_prob = Pframe; 997 997 if (st->vad_enabled) 998 998 { 999 - if (Pframe > st->speech_prob_start || (st->was_speech && Pframe > st->speech_prob_continue)) 999 + if (st->speech_prob > st->speech_prob_start || (st->was_speech && st->speech_prob > st->speech_prob_continue)) 1000 1000 { 1001 1001 st->was_speech=1; 1002 1002 return 1; ··· 1010 1010 } 1011 1011 } 1012 1012 1013 - void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x) 1013 + EXPORT void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x) 1014 1014 { 1015 1015 int i; 1016 1016 int N = st->ps_size; ··· 1020 1020 1021 1021 M = st->nbands; 1022 1022 st->min_count++; 1023 - 1023 + 1024 1024 preprocess_analysis(st, x); 1025 1025 1026 1026 update_noise_prob(st); 1027 - 1027 + 1028 1028 for (i=1;i<N-1;i++) 1029 1029 { 1030 1030 if (!st->update_prob[i] || st->ps[i] < PSHR32(st->noise[i],NOISE_SHIFT)) ··· 1045 1045 } 1046 1046 1047 1047 1048 - int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr) 1048 + EXPORT int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr) 1049 1049 { 1050 1050 int i; 1051 1051 SpeexPreprocessState *st; ··· 1103 1103 case SPEEX_PREPROCESS_GET_VAD: 1104 1104 (*(spx_int32_t*)ptr) = st->vad_enabled; 1105 1105 break; 1106 - 1106 + 1107 1107 case SPEEX_PREPROCESS_SET_DEREVERB: 1108 1108 st->dereverb_enabled = (*(spx_int32_t*)ptr); 1109 1109 for (i=0;i<st->ps_size;i++) ··· 1121 1121 /* FIXME: Re-enable when de-reverberation is actually enabled again */ 1122 1122 /*(*(float*)ptr) = st->reverb_level;*/ 1123 1123 break; 1124 - 1124 + 1125 1125 case SPEEX_PREPROCESS_SET_DEREVERB_DECAY: 1126 1126 /* FIXME: Re-enable when de-reverberation is actually enabled again */ 1127 1127 /*st->reverb_decay = (*(float*)ptr);*/ ··· 1169 1169 st->echo_state = (SpeexEchoState*)ptr; 1170 1170 break; 1171 1171 case SPEEX_PREPROCESS_GET_ECHO_STATE: 1172 - ptr = (void*)st->echo_state; 1172 + (*(SpeexEchoState**)ptr) = (SpeexEchoState*)st->echo_state; 1173 1173 break; 1174 1174 #ifndef FIXED_POINT 1175 1175 case SPEEX_PREPROCESS_GET_AGC_LOUDNESS: 1176 1176 (*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP); 1177 1177 break; 1178 + case SPEEX_PREPROCESS_GET_AGC_GAIN: 1179 + (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->agc_gain)); 1180 + break; 1178 1181 #endif 1179 - 1182 + case SPEEX_PREPROCESS_GET_PSD_SIZE: 1183 + case SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE: 1184 + (*(spx_int32_t*)ptr) = st->ps_size; 1185 + break; 1186 + case SPEEX_PREPROCESS_GET_PSD: 1187 + for(i=0;i<st->ps_size;i++) 1188 + ((spx_int32_t *)ptr)[i] = (spx_int32_t) st->ps[i]; 1189 + break; 1190 + case SPEEX_PREPROCESS_GET_NOISE_PSD: 1191 + for(i=0;i<st->ps_size;i++) 1192 + ((spx_int32_t *)ptr)[i] = (spx_int32_t) PSHR32(st->noise[i], NOISE_SHIFT); 1193 + break; 1194 + case SPEEX_PREPROCESS_GET_PROB: 1195 + (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob, 100); 1196 + break; 1197 + #ifndef FIXED_POINT 1198 + case SPEEX_PREPROCESS_SET_AGC_TARGET: 1199 + st->agc_level = (*(spx_int32_t*)ptr); 1200 + if (st->agc_level<1) 1201 + st->agc_level=1; 1202 + if (st->agc_level>32768) 1203 + st->agc_level=32768; 1204 + break; 1205 + case SPEEX_PREPROCESS_GET_AGC_TARGET: 1206 + (*(spx_int32_t*)ptr) = st->agc_level; 1207 + break; 1208 + #endif 1180 1209 default: 1181 1210 speex_warning_int("Unknown speex_preprocess_ctl request: ", request); 1182 1211 return -1; 1183 1212 } 1184 1213 return 0; 1185 1214 } 1215 + 1216 + #ifdef FIXED_DEBUG 1217 + long long spx_mips=0; 1218 + #endif 1219 +
+34 -34
lib/rbcodec/codecs/libspeex/quant_lsp_bfin.h
··· 55 55 56 56 __asm__ __volatile__ 57 57 ( 58 - " %0 = 1 (X);\n\t" /* %0: best_dist */ 59 - " %0 <<= 30;\n\t" 60 - " %1 = 0 (X);\n\t" /* %1: best_i */ 58 + " %0 = 1 (X);\n\t" /* %0: best_dist */ 59 + " %0 <<= 30;\n\t" 60 + " %1 = 0 (X);\n\t" /* %1: best_i */ 61 61 " P2 = %3\n\t" /* P2: ptr to cdbk */ 62 62 " R5 = 0;\n\t" /* R5: best cb entry */ 63 63 ··· 68 68 " B0 = %2;\n\t" 69 69 70 70 " R2.L = W [I0++];\n\t" 71 - " LSETUP (lq1, lq2) LC0 = %4;\n\t" 72 - "lq1: R3 = 0;\n\t" /* R3: dist */ 73 - " LSETUP (lq3, lq4) LC1 = %5;\n\t" 74 - "lq3: R1 = B [P2++] (X);\n\t" 75 - " R1 <<= 5;\n\t" 76 - " R0.L = R2.L - R1.L || R2.L = W [I0++];\n\t" 77 - " R0 = R0.L*R0.L;\n\t" 78 - "lq4: R3 = R3 + R0;\n\t" 71 + " LSETUP (1f, 2f) LC0 = %4;\n\t" 72 + "1: R3 = 0;\n\t" /* R3: dist */ 73 + " LSETUP (3f, 4f) LC1 = %5;\n\t" 74 + "3: R1 = B [P2++] (X);\n\t" 75 + " R1 <<= 5;\n\t" 76 + " R0.L = R2.L - R1.L || R2.L = W [I0++];\n\t" 77 + " R0 = R0.L*R0.L;\n\t" 78 + "4: R3 = R3 + R0;\n\t" 79 79 80 - " cc =R3<%0;\n\t" 81 - " if cc %0=R3;\n\t" 82 - " if cc %1=R5;\n\t" 83 - "lq2: R5 += 1;\n\t" 80 + " cc =R3<%0;\n\t" 81 + " if cc %0=R3;\n\t" 82 + " if cc %1=R5;\n\t" 83 + "2: R5 += 1;\n\t" 84 84 " L0 = 0;\n\t" 85 85 : "=&d" (best_dist), "=&d" (best_id) 86 86 : "a" (x), "b" (cdbk), "a" (nbVec), "a" (nbDim) ··· 117 117 118 118 __asm__ __volatile__ 119 119 ( 120 - " %0 = 1 (X);\n\t" /* %0: best_dist */ 121 - " %0 <<= 30;\n\t" 122 - " %1 = 0 (X);\n\t" /* %1: best_i */ 120 + " %0 = 1 (X);\n\t" /* %0: best_dist */ 121 + " %0 <<= 30;\n\t" 122 + " %1 = 0 (X);\n\t" /* %1: best_i */ 123 123 " P2 = %4\n\t" /* P2: ptr to cdbk */ 124 124 " R5 = 0;\n\t" /* R5: best cb entry */ 125 125 ··· 128 128 " L0 = R0;\n\t" 129 129 " L1 = R0;\n\t" 130 130 " I0 = %2;\n\t" /* %2: &x[0] */ 131 - " I1 = %3;\n\t" /* %3: &weight[0] */ 131 + " I1 = %3;\n\t" /* %3: &weight[0] */ 132 132 " B0 = %2;\n\t" 133 - " B1 = %3;\n\t" 133 + " B1 = %3;\n\t" 134 134 135 - " LSETUP (lwq1, lwq2) LC0 = %5;\n\t" 136 - "lwq1: R3 = 0 (X);\n\t" /* R3: dist */ 137 - " LSETUP (lwq3, lwq4) LC1 = %6;\n\t" 138 - "lwq3: R0.L = W [I0++] || R2.L = W [I1++];\n\t" 135 + " LSETUP (1f, 2f) LC0 = %5;\n\t" 136 + "1: R3 = 0 (X);\n\t" /* R3: dist */ 137 + " LSETUP (3f, 4f) LC1 = %6;\n\t" 138 + "3: R0.L = W [I0++] || R2.L = W [I1++];\n\t" 139 139 " R1 = B [P2++] (X);\n\t" 140 - " R1 <<= 5;\n\t" 141 - " R0.L = R0.L - R1.L;\n\t" 140 + " R1 <<= 5;\n\t" 141 + " R0.L = R0.L - R1.L;\n\t" 142 142 " R0 = R0.L*R0.L;\n\t" 143 - " A1 = R2.L*R0.L (M,IS);\n\t" 144 - " A1 = A1 >>> 16;\n\t" 145 - " R1 = (A1 += R2.L*R0.H) (IS);\n\t" 146 - "lwq4: R3 = R3 + R1;\n\t" 143 + " A1 = R2.L*R0.L (M,IS);\n\t" 144 + " A1 = A1 >>> 16;\n\t" 145 + " R1 = (A1 += R2.L*R0.H) (IS);\n\t" 146 + "4: R3 = R3 + R1;\n\t" 147 147 148 - " cc =R3<%0;\n\t" 149 - " if cc %0=R3;\n\t" 150 - " if cc %1=R5;\n\t" 151 - "lwq2: R5 += 1;\n\t" 148 + " cc =R3<%0;\n\t" 149 + " if cc %0=R3;\n\t" 150 + " if cc %1=R5;\n\t" 151 + "2: R5 += 1;\n\t" 152 152 " L0 = 0;\n\t" 153 153 " L1 = 0;\n\t" 154 154 : "=&d" (best_dist), "=&d" (best_id)
+363 -372
lib/rbcodec/codecs/libspeex/resample.c
··· 1 - /* Copyright (C) 2007 Jean-Marc Valin 2 - 1 + /* Copyright (C) 2007-2008 Jean-Marc Valin 2 + Copyright (C) 2008 Thorvald Natvig 3 + 3 4 File: resample.c 4 5 Arbitrary resampling code 5 6 ··· 37 38 - Low memory requirement 38 39 - Good *perceptual* quality (and not best SNR) 39 40 40 - Warning: This resampler is relatively new. Although I think I got rid of 41 + Warning: This resampler is relatively new. Although I think I got rid of 41 42 all the major bugs and I don't expect the API to change anymore, there 42 43 may be something I've missed. So use with caution. 43 44 44 45 This algorithm is based on this original resampling algorithm: 45 46 Smith, Julius O. Digital Audio Resampling Home Page 46 - Center for Computer Research in Music and Acoustics (CCRMA), 47 + Center for Computer Research in Music and Acoustics (CCRMA), 47 48 Stanford University, 2007. 48 49 Web published at http://www-ccrma.stanford.edu/~jos/resample/. 49 50 50 - There is one main difference, though. This resampler uses cubic 51 + There is one main difference, though. This resampler uses cubic 51 52 interpolation instead of linear interpolation in the above paper. This 52 53 makes the table much smaller and makes it possible to compute that table 53 - on a per-stream basis. In turn, being able to tweak the table for each 54 - stream makes it possible to both reduce complexity on simple ratios 55 - (e.g. 2/3), and get rid of the rounding operations in the inner loop. 54 + on a per-stream basis. In turn, being able to tweak the table for each 55 + stream makes it possible to both reduce complexity on simple ratios 56 + (e.g. 2/3), and get rid of the rounding operations in the inner loop. 56 57 The latter both reduces CPU time and makes the algorithm more SIMD-friendly. 57 58 */ 58 59 59 60 #ifdef HAVE_CONFIG_H 60 - #include "config-speex.h" 61 + #include "config.h" 61 62 #endif 62 63 63 64 #ifdef OUTSIDE_SPEEX ··· 68 69 #include "speex_resampler.h" 69 70 #include "arch.h" 70 71 #else /* OUTSIDE_SPEEX */ 71 - 72 + 72 73 #include "speex/speex_resampler.h" 73 74 #include "arch.h" 74 75 #include "os_support.h" 75 76 #endif /* OUTSIDE_SPEEX */ 76 77 78 + #include "stack_alloc.h" 77 79 #include <math.h> 78 80 79 81 #ifndef M_PI ··· 81 83 #endif 82 84 83 85 #ifdef FIXED_POINT 84 - #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 86 + #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 85 87 #else 86 - #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) 88 + #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) 87 89 #endif 88 - 89 - /*#define float double*/ 90 - #define FILTER_SIZE 64 91 - #define OVERSAMPLE 8 92 90 93 91 #define IMAX(a,b) ((a) > (b) ? (a) : (b)) 94 92 #define IMIN(a,b) ((a) < (b) ? (a) : (b)) ··· 97 95 #define NULL 0 98 96 #endif 99 97 98 + #ifdef _USE_SSE 99 + #include "resample_sse.h" 100 + #endif 101 + 102 + /* Numer of elements to allocate on the stack */ 103 + #ifdef VAR_ARRAYS 104 + #define FIXED_STACK_ALLOC 8192 105 + #else 106 + #define FIXED_STACK_ALLOC 1024 107 + #endif 108 + 100 109 typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); 101 110 102 111 struct SpeexResamplerState_ { ··· 104 113 spx_uint32_t out_rate; 105 114 spx_uint32_t num_rate; 106 115 spx_uint32_t den_rate; 107 - 116 + 108 117 int quality; 109 118 spx_uint32_t nb_channels; 110 119 spx_uint32_t filt_len; 111 120 spx_uint32_t mem_alloc_size; 121 + spx_uint32_t buffer_size; 112 122 int int_advance; 113 123 int frac_advance; 114 124 float cutoff; 115 125 spx_uint32_t oversample; 116 126 int initialised; 117 127 int started; 118 - 128 + 119 129 /* These are per-channel */ 120 130 spx_int32_t *last_sample; 121 131 spx_uint32_t *samp_frac_num; 122 132 spx_uint32_t *magic_samples; 123 - 133 + 124 134 spx_word16_t *mem; 125 135 spx_word16_t *sinc_table; 126 136 spx_uint32_t sinc_table_length; 127 137 resampler_basic_func resampler_ptr; 128 - 138 + 129 139 int in_stride; 130 140 int out_stride; 131 141 } ; ··· 167 177 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, 168 178 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, 169 179 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; 170 - 180 + 171 181 static double kaiser6_table[36] = { 172 182 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, 173 183 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, ··· 180 190 double *table; 181 191 int oversample; 182 192 }; 183 - 193 + 184 194 static struct FuncDef _KAISER12 = {kaiser12_table, 64}; 185 195 #define KAISER12 (&_KAISER12) 186 196 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; ··· 202 212 203 213 204 214 /* This table maps conversion quality to internal parameters. There are two 205 - reasons that explain why the up-sampling bandwidth is larger than the 215 + reasons that explain why the up-sampling bandwidth is larger than the 206 216 down-sampling bandwidth: 207 217 1) When up-sampling, we can assume that the spectrum is already attenuated 208 218 close to the Nyquist rate (from an A/D or a previous resampling filter) ··· 228 238 { 229 239 float y, frac; 230 240 double interp[4]; 231 - int ind; 241 + int ind; 232 242 y = x*func->oversample; 233 243 ind = (int)floor(y); 234 244 frac = (y-ind); ··· 239 249 interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); 240 250 /* Just to make sure we don't have rounding problems */ 241 251 interp[1] = 1.f-interp[3]-interp[2]-interp[0]; 242 - 252 + 243 253 /*sum = frac*accum[1] + (1-frac)*accum[2];*/ 244 254 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; 245 255 } ··· 317 327 318 328 static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 319 329 { 320 - int N = st->filt_len; 330 + const int N = st->filt_len; 321 331 int out_sample = 0; 322 - spx_word16_t *mem; 323 332 int last_sample = st->last_sample[channel_index]; 324 333 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 325 - mem = st->mem + channel_index * st->mem_alloc_size; 334 + const spx_word16_t *sinc_table = st->sinc_table; 335 + const int out_stride = st->out_stride; 336 + const int int_advance = st->int_advance; 337 + const int frac_advance = st->frac_advance; 338 + const spx_uint32_t den_rate = st->den_rate; 339 + spx_word32_t sum; 340 + int j; 341 + 326 342 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 327 343 { 328 - int j; 329 - spx_word32_t sum=0; 330 - 331 - /* We already have all the filter coefficients pre-computed in the table */ 332 - const spx_word16_t *ptr; 333 - /* Do the memory part */ 334 - for (j=0;last_sample-N+1+j < 0;j++) 335 - { 336 - sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]); 337 - } 338 - 339 - /* Do the new part */ 340 - if (in != NULL) 341 - { 342 - ptr = in+st->in_stride*(last_sample-N+1+j); 343 - for (;j<N;j++) 344 - { 345 - sum += MULT16_16(*ptr,st->sinc_table[samp_frac_num*st->filt_len+j]); 346 - ptr += st->in_stride; 347 - } 344 + const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; 345 + const spx_word16_t *iptr = & in[last_sample]; 346 + 347 + #ifndef OVERRIDE_INNER_PRODUCT_SINGLE 348 + float accum[4] = {0,0,0,0}; 349 + 350 + for(j=0;j<N;j+=4) { 351 + accum[0] += sinc[j]*iptr[j]; 352 + accum[1] += sinc[j+1]*iptr[j+1]; 353 + accum[2] += sinc[j+2]*iptr[j+2]; 354 + accum[3] += sinc[j+3]*iptr[j+3]; 348 355 } 349 - 350 - *out = PSHR32(sum,15); 351 - out += st->out_stride; 352 - out_sample++; 353 - last_sample += st->int_advance; 354 - samp_frac_num += st->frac_advance; 355 - if (samp_frac_num >= st->den_rate) 356 + sum = accum[0] + accum[1] + accum[2] + accum[3]; 357 + #else 358 + sum = inner_product_single(sinc, iptr, N); 359 + #endif 360 + 361 + out[out_stride * out_sample++] = PSHR32(sum, 15); 362 + last_sample += int_advance; 363 + samp_frac_num += frac_advance; 364 + if (samp_frac_num >= den_rate) 356 365 { 357 - samp_frac_num -= st->den_rate; 366 + samp_frac_num -= den_rate; 358 367 last_sample++; 359 368 } 360 369 } 370 + 361 371 st->last_sample[channel_index] = last_sample; 362 372 st->samp_frac_num[channel_index] = samp_frac_num; 363 373 return out_sample; ··· 368 378 /* This is the same as the previous function, except with a double-precision accumulator */ 369 379 static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 370 380 { 371 - int N = st->filt_len; 381 + const int N = st->filt_len; 372 382 int out_sample = 0; 373 - spx_word16_t *mem; 374 383 int last_sample = st->last_sample[channel_index]; 375 384 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 376 - mem = st->mem + channel_index * st->mem_alloc_size; 385 + const spx_word16_t *sinc_table = st->sinc_table; 386 + const int out_stride = st->out_stride; 387 + const int int_advance = st->int_advance; 388 + const int frac_advance = st->frac_advance; 389 + const spx_uint32_t den_rate = st->den_rate; 390 + double sum; 391 + int j; 392 + 377 393 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 378 394 { 379 - int j; 380 - double sum=0; 381 - 382 - /* We already have all the filter coefficients pre-computed in the table */ 383 - const spx_word16_t *ptr; 384 - /* Do the memory part */ 385 - for (j=0;last_sample-N+1+j < 0;j++) 386 - { 387 - sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]); 388 - } 389 - 390 - /* Do the new part */ 391 - if (in != NULL) 392 - { 393 - ptr = in+st->in_stride*(last_sample-N+1+j); 394 - for (;j<N;j++) 395 - { 396 - sum += MULT16_16(*ptr,(double)st->sinc_table[samp_frac_num*st->filt_len+j]); 397 - ptr += st->in_stride; 398 - } 395 + const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; 396 + const spx_word16_t *iptr = & in[last_sample]; 397 + 398 + #ifndef OVERRIDE_INNER_PRODUCT_DOUBLE 399 + double accum[4] = {0,0,0,0}; 400 + 401 + for(j=0;j<N;j+=4) { 402 + accum[0] += sinc[j]*iptr[j]; 403 + accum[1] += sinc[j+1]*iptr[j+1]; 404 + accum[2] += sinc[j+2]*iptr[j+2]; 405 + accum[3] += sinc[j+3]*iptr[j+3]; 399 406 } 400 - 401 - *out = sum; 402 - out += st->out_stride; 403 - out_sample++; 404 - last_sample += st->int_advance; 405 - samp_frac_num += st->frac_advance; 406 - if (samp_frac_num >= st->den_rate) 407 + sum = accum[0] + accum[1] + accum[2] + accum[3]; 408 + #else 409 + sum = inner_product_double(sinc, iptr, N); 410 + #endif 411 + 412 + out[out_stride * out_sample++] = PSHR32(sum, 15); 413 + last_sample += int_advance; 414 + samp_frac_num += frac_advance; 415 + if (samp_frac_num >= den_rate) 407 416 { 408 - samp_frac_num -= st->den_rate; 417 + samp_frac_num -= den_rate; 409 418 last_sample++; 410 419 } 411 420 } 421 + 412 422 st->last_sample[channel_index] = last_sample; 413 423 st->samp_frac_num[channel_index] = samp_frac_num; 414 424 return out_sample; ··· 417 427 418 428 static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 419 429 { 420 - int N = st->filt_len; 430 + const int N = st->filt_len; 421 431 int out_sample = 0; 422 - spx_word16_t *mem; 423 432 int last_sample = st->last_sample[channel_index]; 424 433 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 425 - mem = st->mem + channel_index * st->mem_alloc_size; 434 + const int out_stride = st->out_stride; 435 + const int int_advance = st->int_advance; 436 + const int frac_advance = st->frac_advance; 437 + const spx_uint32_t den_rate = st->den_rate; 438 + int j; 439 + spx_word32_t sum; 440 + 426 441 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 427 442 { 428 - int j; 429 - spx_word32_t sum=0; 430 - 431 - /* We need to interpolate the sinc filter */ 432 - spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f}; 433 - spx_word16_t interp[4]; 434 - const spx_word16_t *ptr; 435 - int offset; 436 - spx_word16_t frac; 437 - offset = samp_frac_num*st->oversample/st->den_rate; 443 + const spx_word16_t *iptr = & in[last_sample]; 444 + 445 + const int offset = samp_frac_num*st->oversample/st->den_rate; 438 446 #ifdef FIXED_POINT 439 - frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 447 + const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 440 448 #else 441 - frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 449 + const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 442 450 #endif 443 - /* This code is written like this to make it easy to optimise with SIMD. 444 - For most DSPs, it would be best to split the loops in two because most DSPs 445 - have only two accumulators */ 446 - for (j=0;last_sample-N+1+j < 0;j++) 447 - { 448 - spx_word16_t curr_mem = mem[last_sample+j]; 449 - accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 450 - accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 451 - accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); 452 - accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 453 - } 454 - 455 - if (in != NULL) 456 - { 457 - ptr = in+st->in_stride*(last_sample-N+1+j); 458 - /* Do the new part */ 459 - for (;j<N;j++) 460 - { 461 - spx_word16_t curr_in = *ptr; 462 - ptr += st->in_stride; 463 - accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 464 - accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 465 - accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); 466 - accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 467 - } 451 + spx_word16_t interp[4]; 452 + 453 + 454 + #ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE 455 + spx_word32_t accum[4] = {0,0,0,0}; 456 + 457 + for(j=0;j<N;j++) { 458 + const spx_word16_t curr_in=iptr[j]; 459 + accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 460 + accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 461 + accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); 462 + accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 468 463 } 464 + 469 465 cubic_coef(frac, interp); 470 466 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]); 471 - 472 - *out = PSHR32(sum,15); 473 - out += st->out_stride; 474 - out_sample++; 475 - last_sample += st->int_advance; 476 - samp_frac_num += st->frac_advance; 477 - if (samp_frac_num >= st->den_rate) 467 + #else 468 + cubic_coef(frac, interp); 469 + sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 470 + #endif 471 + 472 + out[out_stride * out_sample++] = PSHR32(sum,15); 473 + last_sample += int_advance; 474 + samp_frac_num += frac_advance; 475 + if (samp_frac_num >= den_rate) 478 476 { 479 - samp_frac_num -= st->den_rate; 477 + samp_frac_num -= den_rate; 480 478 last_sample++; 481 479 } 482 480 } 481 + 483 482 st->last_sample[channel_index] = last_sample; 484 483 st->samp_frac_num[channel_index] = samp_frac_num; 485 484 return out_sample; ··· 490 489 /* This is the same as the previous function, except with a double-precision accumulator */ 491 490 static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 492 491 { 493 - int N = st->filt_len; 492 + const int N = st->filt_len; 494 493 int out_sample = 0; 495 - spx_word16_t *mem; 496 494 int last_sample = st->last_sample[channel_index]; 497 495 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 498 - mem = st->mem + channel_index * st->mem_alloc_size; 496 + const int out_stride = st->out_stride; 497 + const int int_advance = st->int_advance; 498 + const int frac_advance = st->frac_advance; 499 + const spx_uint32_t den_rate = st->den_rate; 500 + int j; 501 + spx_word32_t sum; 502 + 499 503 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 500 504 { 501 - int j; 502 - spx_word32_t sum=0; 503 - 504 - /* We need to interpolate the sinc filter */ 505 - double accum[4] = {0.f,0.f, 0.f, 0.f}; 506 - float interp[4]; 507 - const spx_word16_t *ptr; 508 - float alpha = ((float)samp_frac_num)/st->den_rate; 509 - int offset = samp_frac_num*st->oversample/st->den_rate; 510 - float frac = alpha*st->oversample - offset; 511 - /* This code is written like this to make it easy to optimise with SIMD. 512 - For most DSPs, it would be best to split the loops in two because most DSPs 513 - have only two accumulators */ 514 - for (j=0;last_sample-N+1+j < 0;j++) 515 - { 516 - double curr_mem = mem[last_sample+j]; 517 - accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 518 - accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 519 - accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); 520 - accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 521 - } 522 - if (in != NULL) 523 - { 524 - ptr = in+st->in_stride*(last_sample-N+1+j); 525 - /* Do the new part */ 526 - for (;j<N;j++) 527 - { 528 - double curr_in = *ptr; 529 - ptr += st->in_stride; 530 - accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 531 - accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 532 - accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); 533 - accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 534 - } 505 + const spx_word16_t *iptr = & in[last_sample]; 506 + 507 + const int offset = samp_frac_num*st->oversample/st->den_rate; 508 + #ifdef FIXED_POINT 509 + const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 510 + #else 511 + const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 512 + #endif 513 + spx_word16_t interp[4]; 514 + 515 + 516 + #ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE 517 + double accum[4] = {0,0,0,0}; 518 + 519 + for(j=0;j<N;j++) { 520 + const double curr_in=iptr[j]; 521 + accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 522 + accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 523 + accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); 524 + accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 535 525 } 526 + 536 527 cubic_coef(frac, interp); 537 - sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3]; 538 - 539 - *out = PSHR32(sum,15); 540 - out += st->out_stride; 541 - out_sample++; 542 - last_sample += st->int_advance; 543 - samp_frac_num += st->frac_advance; 544 - if (samp_frac_num >= st->den_rate) 528 + 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]); 529 + #else 530 + cubic_coef(frac, interp); 531 + sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 532 + #endif 533 + 534 + out[out_stride * out_sample++] = PSHR32(sum,15); 535 + last_sample += int_advance; 536 + samp_frac_num += frac_advance; 537 + if (samp_frac_num >= den_rate) 545 538 { 546 - samp_frac_num -= st->den_rate; 539 + samp_frac_num -= den_rate; 547 540 last_sample++; 548 541 } 549 542 } 543 + 550 544 st->last_sample[channel_index] = last_sample; 551 545 st->samp_frac_num[channel_index] = samp_frac_num; 552 546 return out_sample; ··· 556 550 static void update_filter(SpeexResamplerState *st) 557 551 { 558 552 spx_uint32_t old_length; 559 - 553 + 560 554 old_length = st->filt_len; 561 555 st->oversample = quality_map[st->quality].oversample; 562 556 st->filt_len = quality_map[st->quality].base_length; 563 - 557 + 564 558 if (st->num_rate > st->den_rate) 565 559 { 566 560 /* down-sampling */ ··· 636 630 st->int_advance = st->num_rate/st->den_rate; 637 631 st->frac_advance = st->num_rate%st->den_rate; 638 632 639 - 633 + 640 634 /* Here's the place where we update the filter memory to take into account 641 635 the change in filter length. It's probably the messiest part of the code 642 636 due to handling of lots of corner cases. */ 643 637 if (!st->mem) 644 638 { 645 639 spx_uint32_t i; 646 - st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 647 - for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 640 + st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 641 + st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 642 + for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) 648 643 st->mem[i] = 0; 649 - st->mem_alloc_size = st->filt_len-1; 650 644 /*speex_warning("init filter");*/ 651 645 } else if (!st->started) 652 646 { 653 647 spx_uint32_t i; 654 - st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 655 - for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 648 + st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 649 + st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 650 + for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) 656 651 st->mem[i] = 0; 657 - st->mem_alloc_size = st->filt_len-1; 658 652 /*speex_warning("reinit filter");*/ 659 653 } else if (st->filt_len > old_length) 660 654 { ··· 662 656 /* Increase the filter length */ 663 657 /*speex_warning("increase filter size");*/ 664 658 int old_alloc_size = st->mem_alloc_size; 665 - if (st->filt_len-1 > st->mem_alloc_size) 659 + if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size) 666 660 { 667 - st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 668 - st->mem_alloc_size = st->filt_len-1; 661 + st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 662 + st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 669 663 } 670 664 for (i=st->nb_channels-1;i>=0;i--) 671 665 { ··· 674 668 /*if (st->magic_samples[i])*/ 675 669 { 676 670 /* Try and remove the magic samples as if nothing had happened */ 677 - 671 + 678 672 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ 679 673 olen = old_length + 2*st->magic_samples[i]; 680 674 for (j=old_length-2+st->magic_samples[i];j>=0;j--) ··· 721 715 722 716 } 723 717 724 - SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 718 + EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 725 719 { 726 720 return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); 727 721 } 728 722 729 - 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) 723 + EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 730 724 { 731 725 spx_uint32_t i; 732 726 SpeexResamplerState *st; ··· 749 743 st->filt_len = 0; 750 744 st->mem = 0; 751 745 st->resampler_ptr = 0; 752 - 746 + 753 747 st->cutoff = 1.f; 754 748 st->nb_channels = nb_channels; 755 749 st->in_stride = 1; 756 750 st->out_stride = 1; 757 - 751 + 752 + #ifdef FIXED_POINT 753 + st->buffer_size = 160; 754 + #else 755 + st->buffer_size = 160; 756 + #endif 757 + 758 758 /* Per channel data */ 759 759 st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); 760 760 st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); ··· 769 769 speex_resampler_set_quality(st, quality); 770 770 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); 771 771 772 - 772 + 773 773 update_filter(st); 774 - 774 + 775 775 st->initialised = 1; 776 776 if (err) 777 777 *err = RESAMPLER_ERR_SUCCESS; ··· 779 779 return st; 780 780 } 781 781 782 - void speex_resampler_destroy(SpeexResamplerState *st) 782 + EXPORT void speex_resampler_destroy(SpeexResamplerState *st) 783 783 { 784 784 speex_free(st->mem); 785 785 speex_free(st->sinc_table); ··· 789 789 speex_free(st); 790 790 } 791 791 792 - 793 - 794 - static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 792 + static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 795 793 { 796 794 int j=0; 797 - int N = st->filt_len; 795 + const int N = st->filt_len; 798 796 int out_sample = 0; 799 - spx_word16_t *mem; 800 - spx_uint32_t tmp_out_len = 0; 801 - mem = st->mem + channel_index * st->mem_alloc_size; 797 + spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 798 + spx_uint32_t ilen; 799 + 802 800 st->started = 1; 803 - 804 - /* Handle the case where we have samples left from a reduction in filter length */ 805 - if (st->magic_samples[channel_index]) 806 - { 807 - int istride_save; 808 - spx_uint32_t tmp_in_len; 809 - spx_uint32_t tmp_magic; 810 - 811 - istride_save = st->in_stride; 812 - tmp_in_len = st->magic_samples[channel_index]; 813 - tmp_out_len = *out_len; 814 - /* magic_samples needs to be set to zero to avoid infinite recursion */ 815 - tmp_magic = st->magic_samples[channel_index]; 816 - st->magic_samples[channel_index] = 0; 817 - st->in_stride = 1; 818 - speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len); 819 - st->in_stride = istride_save; 820 - /*speex_warning_int("extra samples:", tmp_out_len);*/ 821 - /* If we couldn't process all "magic" input samples, save the rest for next time */ 822 - if (tmp_in_len < tmp_magic) 823 - { 824 - spx_uint32_t i; 825 - st->magic_samples[channel_index] = tmp_magic-tmp_in_len; 826 - for (i=0;i<st->magic_samples[channel_index];i++) 827 - mem[N-1+i]=mem[N-1+i+tmp_in_len]; 828 - } 829 - out += tmp_out_len*st->out_stride; 830 - *out_len -= tmp_out_len; 831 - } 832 - 801 + 833 802 /* Call the right resampler through the function ptr */ 834 - out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len); 835 - 803 + out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len); 804 + 836 805 if (st->last_sample[channel_index] < (spx_int32_t)*in_len) 837 806 *in_len = st->last_sample[channel_index]; 838 - *out_len = out_sample+tmp_out_len; 807 + *out_len = out_sample; 839 808 st->last_sample[channel_index] -= *in_len; 840 - 841 - for (j=0;j<N-1-(spx_int32_t)*in_len;j++) 842 - mem[j] = mem[j+*in_len]; 843 - for (;j<N-1;j++) 844 - mem[j] = in[st->in_stride*(j+*in_len-N+1)]; 845 - 809 + 810 + ilen = *in_len; 811 + 812 + for(j=0;j<N-1;++j) 813 + mem[j] = mem[j+ilen]; 814 + 846 815 return RESAMPLER_ERR_SUCCESS; 847 816 } 848 817 849 - #define FIXED_STACK_ALLOC 1024 818 + static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) { 819 + spx_uint32_t tmp_in_len = st->magic_samples[channel_index]; 820 + spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 821 + const int N = st->filt_len; 822 + 823 + speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len); 824 + 825 + st->magic_samples[channel_index] -= tmp_in_len; 826 + 827 + /* If we couldn't process all "magic" input samples, save the rest for next time */ 828 + if (st->magic_samples[channel_index]) 829 + { 830 + spx_uint32_t i; 831 + for (i=0;i<st->magic_samples[channel_index];i++) 832 + mem[N-1+i]=mem[N-1+i+tmp_in_len]; 833 + } 834 + *out += out_len*st->out_stride; 835 + return out_len; 836 + } 850 837 851 838 #ifdef FIXED_POINT 852 - 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) 853 - { 854 - spx_uint32_t i; 855 - int istride_save, ostride_save; 856 - #ifdef VAR_ARRAYS 857 - spx_word16_t x[*in_len]; 858 - spx_word16_t y[*out_len]; 859 - /*VARDECL(spx_word16_t *x); 860 - VARDECL(spx_word16_t *y); 861 - ALLOC(x, *in_len, spx_word16_t); 862 - ALLOC(y, *out_len, spx_word16_t);*/ 863 - istride_save = st->in_stride; 864 - ostride_save = st->out_stride; 865 - for (i=0;i<*in_len;i++) 866 - x[i] = WORD2INT(in[i*st->in_stride]); 867 - st->in_stride = st->out_stride = 1; 868 - speex_resampler_process_native(st, channel_index, x, in_len, y, out_len); 869 - st->in_stride = istride_save; 870 - st->out_stride = ostride_save; 871 - for (i=0;i<*out_len;i++) 872 - out[i*st->out_stride] = y[i]; 839 + EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) 873 840 #else 874 - spx_word16_t x[FIXED_STACK_ALLOC]; 875 - spx_word16_t y[FIXED_STACK_ALLOC]; 876 - spx_uint32_t ilen=*in_len, olen=*out_len; 877 - istride_save = st->in_stride; 878 - ostride_save = st->out_stride; 879 - while (ilen && olen) 880 - { 881 - spx_uint32_t ichunk, ochunk; 882 - ichunk = ilen; 883 - ochunk = olen; 884 - if (ichunk>FIXED_STACK_ALLOC) 885 - ichunk=FIXED_STACK_ALLOC; 886 - if (ochunk>FIXED_STACK_ALLOC) 887 - ochunk=FIXED_STACK_ALLOC; 888 - for (i=0;i<ichunk;i++) 889 - x[i] = WORD2INT(in[i*st->in_stride]); 890 - st->in_stride = st->out_stride = 1; 891 - speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); 892 - st->in_stride = istride_save; 893 - st->out_stride = ostride_save; 894 - for (i=0;i<ochunk;i++) 895 - out[i*st->out_stride] = y[i]; 896 - out += ochunk; 897 - in += ichunk; 898 - ilen -= ichunk; 899 - olen -= ochunk; 841 + EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 842 + #endif 843 + { 844 + int j; 845 + spx_uint32_t ilen = *in_len; 846 + spx_uint32_t olen = *out_len; 847 + spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; 848 + const int filt_offs = st->filt_len - 1; 849 + const spx_uint32_t xlen = st->mem_alloc_size - filt_offs; 850 + const int istride = st->in_stride; 851 + 852 + if (st->magic_samples[channel_index]) 853 + olen -= speex_resampler_magic(st, channel_index, &out, olen); 854 + if (! st->magic_samples[channel_index]) { 855 + while (ilen && olen) { 856 + spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; 857 + spx_uint32_t ochunk = olen; 858 + 859 + if (in) { 860 + for(j=0;j<ichunk;++j) 861 + x[j+filt_offs]=in[j*istride]; 862 + } else { 863 + for(j=0;j<ichunk;++j) 864 + x[j+filt_offs]=0; 865 + } 866 + speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk); 867 + ilen -= ichunk; 868 + olen -= ochunk; 869 + out += ochunk * st->out_stride; 870 + if (in) 871 + in += ichunk * istride; 872 + } 900 873 } 901 874 *in_len -= ilen; 902 - *out_len -= olen; 903 - #endif 875 + *out_len -= olen; 904 876 return RESAMPLER_ERR_SUCCESS; 905 877 } 906 - 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) 907 - { 908 - return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); 909 - } 878 + 879 + #ifdef FIXED_POINT 880 + EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 910 881 #else 911 - 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) 912 - { 913 - return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); 914 - } 915 - 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) 882 + EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) 883 + #endif 916 884 { 917 - spx_uint32_t i; 918 - int istride_save, ostride_save; 885 + int j; 886 + const int istride_save = st->in_stride; 887 + const int ostride_save = st->out_stride; 888 + spx_uint32_t ilen = *in_len; 889 + spx_uint32_t olen = *out_len; 890 + spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; 891 + const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1); 919 892 #ifdef VAR_ARRAYS 920 - spx_word16_t x[*in_len]; 921 - spx_word16_t y[*out_len]; 922 - /*VARDECL(spx_word16_t *x); 923 - VARDECL(spx_word16_t *y); 924 - ALLOC(x, *in_len, spx_word16_t); 925 - ALLOC(y, *out_len, spx_word16_t);*/ 926 - istride_save = st->in_stride; 927 - ostride_save = st->out_stride; 928 - for (i=0;i<*in_len;i++) 929 - x[i] = in[i*st->in_stride]; 930 - st->in_stride = st->out_stride = 1; 931 - speex_resampler_process_native(st, channel_index, x, in_len, y, out_len); 932 - st->in_stride = istride_save; 933 - st->out_stride = ostride_save; 934 - for (i=0;i<*out_len;i++) 935 - out[i*st->out_stride] = WORD2INT(y[i]); 893 + const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; 894 + VARDECL(spx_word16_t *ystack); 895 + ALLOC(ystack, ylen, spx_word16_t); 896 + #else 897 + const unsigned int ylen = FIXED_STACK_ALLOC; 898 + spx_word16_t ystack[FIXED_STACK_ALLOC]; 899 + #endif 900 + 901 + st->out_stride = 1; 902 + 903 + while (ilen && olen) { 904 + spx_word16_t *y = ystack; 905 + spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; 906 + spx_uint32_t ochunk = (olen > ylen) ? ylen : olen; 907 + spx_uint32_t omagic = 0; 908 + 909 + if (st->magic_samples[channel_index]) { 910 + omagic = speex_resampler_magic(st, channel_index, &y, ochunk); 911 + ochunk -= omagic; 912 + olen -= omagic; 913 + } 914 + if (! st->magic_samples[channel_index]) { 915 + if (in) { 916 + for(j=0;j<ichunk;++j) 917 + #ifdef FIXED_POINT 918 + x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]); 919 + #else 920 + x[j+st->filt_len-1]=in[j*istride_save]; 921 + #endif 922 + } else { 923 + for(j=0;j<ichunk;++j) 924 + x[j+st->filt_len-1]=0; 925 + } 926 + 927 + speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk); 928 + } else { 929 + ichunk = 0; 930 + ochunk = 0; 931 + } 932 + 933 + for (j=0;j<ochunk+omagic;++j) 934 + #ifdef FIXED_POINT 935 + out[j*ostride_save] = ystack[j]; 936 936 #else 937 - spx_word16_t x[FIXED_STACK_ALLOC]; 938 - spx_word16_t y[FIXED_STACK_ALLOC]; 939 - spx_uint32_t ilen=*in_len, olen=*out_len; 940 - istride_save = st->in_stride; 941 - ostride_save = st->out_stride; 942 - while (ilen && olen) 943 - { 944 - spx_uint32_t ichunk, ochunk; 945 - ichunk = ilen; 946 - ochunk = olen; 947 - if (ichunk>FIXED_STACK_ALLOC) 948 - ichunk=FIXED_STACK_ALLOC; 949 - if (ochunk>FIXED_STACK_ALLOC) 950 - ochunk=FIXED_STACK_ALLOC; 951 - for (i=0;i<ichunk;i++) 952 - x[i] = in[i*st->in_stride]; 953 - st->in_stride = st->out_stride = 1; 954 - speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); 955 - st->in_stride = istride_save; 956 - st->out_stride = ostride_save; 957 - for (i=0;i<ochunk;i++) 958 - out[i*st->out_stride] = WORD2INT(y[i]); 959 - out += ochunk; 960 - in += ichunk; 961 - ilen -= ichunk; 962 - olen -= ochunk; 937 + out[j*ostride_save] = WORD2INT(ystack[j]); 938 + #endif 939 + 940 + ilen -= ichunk; 941 + olen -= ochunk; 942 + out += (ochunk+omagic) * ostride_save; 943 + if (in) 944 + in += ichunk * istride_save; 963 945 } 946 + st->out_stride = ostride_save; 964 947 *in_len -= ilen; 965 - *out_len -= olen; 966 - #endif 948 + *out_len -= olen; 949 + 967 950 return RESAMPLER_ERR_SUCCESS; 968 951 } 969 - #endif 970 952 971 - int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 953 + EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 972 954 { 973 955 spx_uint32_t i; 974 956 int istride_save, ostride_save; ··· 989 971 return RESAMPLER_ERR_SUCCESS; 990 972 } 991 973 992 - 993 - 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) 974 + EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) 994 975 { 995 976 spx_uint32_t i; 996 977 int istride_save, ostride_save; ··· 1011 992 return RESAMPLER_ERR_SUCCESS; 1012 993 } 1013 994 1014 - int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) 995 + EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) 1015 996 { 1016 997 return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); 1017 998 } 1018 999 1019 - void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) 1000 + EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) 1020 1001 { 1021 1002 *in_rate = st->in_rate; 1022 1003 *out_rate = st->out_rate; 1023 1004 } 1024 1005 1025 - 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) 1006 + EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) 1026 1007 { 1027 1008 spx_uint32_t fact; 1028 1009 spx_uint32_t old_den; 1029 1010 spx_uint32_t i; 1030 1011 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) 1031 1012 return RESAMPLER_ERR_SUCCESS; 1032 - 1013 + 1033 1014 old_den = st->den_rate; 1034 1015 st->in_rate = in_rate; 1035 1016 st->out_rate = out_rate; ··· 1044 1025 st->den_rate /= fact; 1045 1026 } 1046 1027 } 1047 - 1028 + 1048 1029 if (old_den > 0) 1049 1030 { 1050 1031 for (i=0;i<st->nb_channels;i++) ··· 1055 1036 st->samp_frac_num[i] = st->den_rate-1; 1056 1037 } 1057 1038 } 1058 - 1039 + 1059 1040 if (st->initialised) 1060 1041 update_filter(st); 1061 1042 return RESAMPLER_ERR_SUCCESS; 1062 1043 } 1063 1044 1064 - void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) 1045 + EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) 1065 1046 { 1066 1047 *ratio_num = st->num_rate; 1067 1048 *ratio_den = st->den_rate; 1068 1049 } 1069 1050 1070 - int speex_resampler_set_quality(SpeexResamplerState *st, int quality) 1051 + EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality) 1071 1052 { 1072 1053 if (quality > 10 || quality < 0) 1073 1054 return RESAMPLER_ERR_INVALID_ARG; ··· 1079 1060 return RESAMPLER_ERR_SUCCESS; 1080 1061 } 1081 1062 1082 - void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) 1063 + EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) 1083 1064 { 1084 1065 *quality = st->quality; 1085 1066 } 1086 1067 1087 - void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) 1068 + EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) 1088 1069 { 1089 1070 st->in_stride = stride; 1090 1071 } 1091 1072 1092 - void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1073 + EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1093 1074 { 1094 1075 *stride = st->in_stride; 1095 1076 } 1096 1077 1097 - void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) 1078 + EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) 1098 1079 { 1099 1080 st->out_stride = stride; 1100 1081 } 1101 1082 1102 - void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1083 + EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1103 1084 { 1104 1085 *stride = st->out_stride; 1105 1086 } 1106 1087 1107 - int speex_resampler_skip_zeros(SpeexResamplerState *st) 1088 + EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st) 1089 + { 1090 + return st->filt_len / 2; 1091 + } 1092 + 1093 + EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st) 1094 + { 1095 + return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate; 1096 + } 1097 + 1098 + EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st) 1108 1099 { 1109 1100 spx_uint32_t i; 1110 1101 for (i=0;i<st->nb_channels;i++) ··· 1112 1103 return RESAMPLER_ERR_SUCCESS; 1113 1104 } 1114 1105 1115 - int speex_resampler_reset_mem(SpeexResamplerState *st) 1106 + EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st) 1116 1107 { 1117 1108 spx_uint32_t i; 1118 1109 for (i=0;i<st->nb_channels*(st->filt_len-1);i++) ··· 1120 1111 return RESAMPLER_ERR_SUCCESS; 1121 1112 } 1122 1113 1123 - const char *speex_resampler_strerror(int err) 1114 + EXPORT const char *speex_resampler_strerror(int err) 1124 1115 { 1125 1116 switch (err) 1126 1117 {
+128
lib/rbcodec/codecs/libspeex/resample_sse.h
··· 1 + /* Copyright (C) 2007-2008 Jean-Marc Valin 2 + * Copyright (C) 2008 Thorvald Natvig 3 + */ 4 + /** 5 + @file resample_sse.h 6 + @brief Resampler functions (SSE version) 7 + */ 8 + /* 9 + Redistribution and use in source and binary forms, with or without 10 + modification, are permitted provided that the following conditions 11 + are met: 12 + 13 + - Redistributions of source code must retain the above copyright 14 + notice, this list of conditions and the following disclaimer. 15 + 16 + - Redistributions in binary form must reproduce the above copyright 17 + notice, this list of conditions and the following disclaimer in the 18 + documentation and/or other materials provided with the distribution. 19 + 20 + - Neither the name of the Xiph.org Foundation nor the names of its 21 + contributors may be used to endorse or promote products derived from 22 + this software without specific prior written permission. 23 + 24 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 28 + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 + */ 36 + 37 + #include <xmmintrin.h> 38 + 39 + #define OVERRIDE_INNER_PRODUCT_SINGLE 40 + static inline float inner_product_single(const float *a, const float *b, unsigned int len) 41 + { 42 + int i; 43 + float ret; 44 + __m128 sum = _mm_setzero_ps(); 45 + for (i=0;i<len;i+=8) 46 + { 47 + sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i))); 48 + sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4))); 49 + } 50 + sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); 51 + sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); 52 + _mm_store_ss(&ret, sum); 53 + return ret; 54 + } 55 + 56 + #define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE 57 + static inline float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) { 58 + int i; 59 + float ret; 60 + __m128 sum = _mm_setzero_ps(); 61 + __m128 f = _mm_loadu_ps(frac); 62 + for(i=0;i<len;i+=2) 63 + { 64 + sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample))); 65 + sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample))); 66 + } 67 + sum = _mm_mul_ps(f, sum); 68 + sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); 69 + sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); 70 + _mm_store_ss(&ret, sum); 71 + return ret; 72 + } 73 + 74 + #ifdef _USE_SSE2 75 + #include <emmintrin.h> 76 + #define OVERRIDE_INNER_PRODUCT_DOUBLE 77 + 78 + static inline double inner_product_double(const float *a, const float *b, unsigned int len) 79 + { 80 + int i; 81 + double ret; 82 + __m128d sum = _mm_setzero_pd(); 83 + __m128 t; 84 + for (i=0;i<len;i+=8) 85 + { 86 + t = _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)); 87 + sum = _mm_add_pd(sum, _mm_cvtps_pd(t)); 88 + sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); 89 + 90 + t = _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)); 91 + sum = _mm_add_pd(sum, _mm_cvtps_pd(t)); 92 + sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); 93 + } 94 + sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); 95 + _mm_store_sd(&ret, sum); 96 + return ret; 97 + } 98 + 99 + #define OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE 100 + static inline double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) { 101 + int i; 102 + double ret; 103 + __m128d sum; 104 + __m128d sum1 = _mm_setzero_pd(); 105 + __m128d sum2 = _mm_setzero_pd(); 106 + __m128 f = _mm_loadu_ps(frac); 107 + __m128d f1 = _mm_cvtps_pd(f); 108 + __m128d f2 = _mm_cvtps_pd(_mm_movehl_ps(f,f)); 109 + __m128 t; 110 + for(i=0;i<len;i+=2) 111 + { 112 + t = _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample)); 113 + sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t)); 114 + sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t))); 115 + 116 + t = _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample)); 117 + sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t)); 118 + sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t))); 119 + } 120 + sum1 = _mm_mul_pd(f1, sum1); 121 + sum2 = _mm_mul_pd(f2, sum2); 122 + sum = _mm_add_pd(sum1, sum2); 123 + sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); 124 + _mm_store_sd(&ret, sum); 125 + return ret; 126 + } 127 + 128 + #endif
+21 -21
lib/rbcodec/codecs/libspeex/speex.c
··· 1 - /* Copyright (C) 2002 Jean-Marc Valin 1 + /* Copyright (C) 2002 Jean-Marc Valin 2 2 File: speex.c 3 3 4 4 Basic Speex functions ··· 6 6 Redistribution and use in source and binary forms, with or without 7 7 modification, are permitted provided that the following conditions 8 8 are met: 9 - 9 + 10 10 - Redistributions of source code must retain the above copyright 11 11 notice, this list of conditions and the following disclaimer. 12 - 12 + 13 13 - Redistributions in binary form must reproduce the above copyright 14 14 notice, this list of conditions and the following disclaimer in the 15 15 documentation and/or other materials provided with the distribution. 16 - 16 + 17 17 - Neither the name of the Xiph.org Foundation nor the names of its 18 18 contributors may be used to endorse or promote products derived from 19 19 this software without specific prior written permission. 20 - 20 + 21 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ··· 49 49 #define MAX_IN_SAMPLES 640 50 50 51 51 #ifndef SPEEX_DISABLE_ENCODER 52 - void *speex_encoder_init(const SpeexMode *mode) 52 + EXPORT void *speex_encoder_init(const SpeexMode *mode) 53 53 { 54 54 return mode->enc_init(mode); 55 55 } 56 56 #endif 57 57 58 - void *speex_decoder_init(const SpeexMode *mode) 58 + EXPORT void *speex_decoder_init(const SpeexMode *mode) 59 59 { 60 60 return mode->dec_init(mode); 61 61 } 62 62 63 63 #ifndef SPEEX_DISABLE_ENCODER 64 - void speex_encoder_destroy(void *state) 64 + EXPORT void speex_encoder_destroy(void *state) 65 65 { 66 66 (*((SpeexMode**)state))->enc_destroy(state); 67 67 } 68 68 #endif 69 69 70 - void speex_decoder_destroy(void *state) 70 + EXPORT void speex_decoder_destroy(void *state) 71 71 { 72 72 (*((SpeexMode**)state))->dec_destroy(state); 73 73 } ··· 90 90 91 91 #ifndef SPEEX_DISABLE_ENCODER 92 92 #ifndef DISABLE_FLOAT_API 93 - int speex_encode(void *state, float *in, SpeexBits *bits) 93 + EXPORT int speex_encode(void *state, float *in, SpeexBits *bits) 94 94 { 95 95 int i; 96 96 spx_int32_t N; ··· 109 109 } 110 110 #endif /* #ifndef DISABLE_FLOAT_API */ 111 111 112 - int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) 112 + EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) 113 113 { 114 114 SpeexMode *mode; 115 115 mode = *(SpeexMode**)state; ··· 118 118 #endif /* SPEEX_DISABLE_ENCODER */ 119 119 120 120 #ifndef DISABLE_FLOAT_API 121 - int speex_decode(void *state, SpeexBits *bits, float *out) 121 + EXPORT int speex_decode(void *state, SpeexBits *bits, float *out) 122 122 { 123 123 int i, ret; 124 124 spx_int32_t N; ··· 131 131 } 132 132 #endif /* #ifndef DISABLE_FLOAT_API */ 133 133 134 - int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) 134 + EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) 135 135 { 136 136 SpeexMode *mode = *(SpeexMode**)state; 137 137 return (mode)->dec(state, bits, out); ··· 139 139 140 140 #else 141 141 142 - int speex_encode(void *state, float *in, SpeexBits *bits) 142 + EXPORT int speex_encode(void *state, float *in, SpeexBits *bits) 143 143 { 144 144 return (*((SpeexMode**)state))->enc(state, in, bits); 145 145 } 146 146 147 - int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) 147 + EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) 148 148 { 149 149 int i; 150 150 spx_int32_t N; ··· 155 155 return (*((SpeexMode**)state))->enc(state, float_in, bits); 156 156 } 157 157 158 - int speex_decode(void *state, SpeexBits *bits, float *out) 158 + EXPORT int speex_decode(void *state, SpeexBits *bits, float *out) 159 159 { 160 160 return (*((SpeexMode**)state))->dec(state, bits, out); 161 161 } 162 162 163 - int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) 163 + EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) 164 164 { 165 165 int i; 166 166 spx_int32_t N; ··· 182 182 #endif 183 183 184 184 #ifndef SPEEX_DISABLE_ENCODER 185 - int speex_encoder_ctl(void *state, int request, void *ptr) 185 + EXPORT int speex_encoder_ctl(void *state, int request, void *ptr) 186 186 { 187 187 return (*((SpeexMode**)state))->enc_ctl(state, request, ptr); 188 188 } 189 189 #endif 190 190 191 - int speex_decoder_ctl(void *state, int request, void *ptr) 191 + EXPORT int speex_decoder_ctl(void *state, int request, void *ptr) 192 192 { 193 193 return (*((SpeexMode**)state))->dec_ctl(state, request, ptr); 194 194 } ··· 196 196 int nb_mode_query(const void *mode, int request, void *ptr) 197 197 { 198 198 const SpeexNBMode *m = (const SpeexNBMode*)mode; 199 - 199 + 200 200 switch (request) 201 201 { 202 202 case SPEEX_MODE_FRAME_SIZE: ··· 219 219 220 220 221 221 222 - int speex_lib_ctl(int request, void *ptr) 222 + EXPORT int speex_lib_ctl(int request, void *ptr) 223 223 { 224 224 switch (request) 225 225 {
+14 -14
lib/rbcodec/codecs/libspeex/speex_callbacks.c
··· 6 6 Redistribution and use in source and binary forms, with or without 7 7 modification, are permitted provided that the following conditions 8 8 are met: 9 - 9 + 10 10 - Redistributions of source code must retain the above copyright 11 11 notice, this list of conditions and the following disclaimer. 12 - 12 + 13 13 - Redistributions in binary form must reproduce the above copyright 14 14 notice, this list of conditions and the following disclaimer in the 15 15 documentation and/or other materials provided with the distribution. 16 - 16 + 17 17 - Neither the name of the Xiph.org Foundation nor the names of its 18 18 contributors may be used to endorse or promote products derived from 19 19 this software without specific prior written permission. 20 - 20 + 21 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ··· 40 40 #include "arch.h" 41 41 #include "os_support.h" 42 42 43 - int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) 43 + EXPORT int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) 44 44 { 45 45 int id; 46 46 SpeexCallback *callback; ··· 65 65 adv = 16; 66 66 else if (id<14) 67 67 adv = 32; 68 - else 68 + else 69 69 adv = 64; 70 70 speex_bits_advance(bits, adv); 71 71 } ··· 74 74 75 75 #if 0 76 76 /* Rockbox: unused */ 77 - int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data) 77 + EXPORT int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data) 78 78 { 79 79 (void)state; 80 80 spx_int32_t m; ··· 83 83 return 0; 84 84 } 85 85 86 - int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data) 86 + EXPORT int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data) 87 87 { 88 88 (void)state; 89 89 spx_int32_t m; ··· 92 92 return 0; 93 93 } 94 94 95 - int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data) 95 + EXPORT int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data) 96 96 { 97 97 (void)state; 98 98 spx_int32_t m; ··· 103 103 #endif 104 104 105 105 #ifndef DISABLE_VBR 106 - int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data) 106 + EXPORT int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data) 107 107 { 108 108 (void)state; 109 109 spx_int32_t vbr; ··· 115 115 116 116 #if 0 117 117 /* Rockbox: unused */ 118 - int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data) 118 + EXPORT int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data) 119 119 { 120 120 (void)state; 121 121 spx_int32_t enh; ··· 126 126 #endif 127 127 128 128 #ifndef DISABLE_VBR 129 - int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data) 129 + EXPORT int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data) 130 130 { 131 131 (void)state; 132 132 float qual; ··· 138 138 139 139 #if 0 140 140 /* Rockbox: unused */ 141 - int speex_std_char_handler(SpeexBits *bits, void *state, void *data) 141 + EXPORT int speex_std_char_handler(SpeexBits *bits, void *state, void *data) 142 142 { 143 143 (void)state; 144 144 unsigned char ch; ··· 150 150 #endif 151 151 152 152 /* Default handler for user callbacks: skip it */ 153 - int speex_default_user_handler(SpeexBits *bits, void *state, void *data) 153 + EXPORT int speex_default_user_handler(SpeexBits *bits, void *state, void *data) 154 154 { 155 155 (void)state; 156 156 (void)data;
+37 -18
lib/rbcodec/codecs/libspeex/speex_header.c
··· 1 - /* Copyright (C) 2002 Jean-Marc Valin 1 + /* Copyright (C) 2002 Jean-Marc Valin 2 2 File: speex_header.c 3 3 Describes the Speex header 4 4 5 5 Redistribution and use in source and binary forms, with or without 6 6 modification, are permitted provided that the following conditions 7 7 are met: 8 - 8 + 9 9 - Redistributions of source code must retain the above copyright 10 10 notice, this list of conditions and the following disclaimer. 11 - 11 + 12 12 - Redistributions in binary form must reproduce the above copyright 13 13 notice, this list of conditions and the following disclaimer in the 14 14 documentation and/or other materials provided with the distribution. 15 - 15 + 16 16 - Neither the name of the Xiph.org Foundation nor the names of its 17 17 contributors may be used to endorse or promote products derived from 18 18 this software without specific prior written permission. 19 - 19 + 20 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ··· 47 47 /** Convert little endian */ 48 48 static inline spx_int32_t le_int(spx_int32_t i) 49 49 { 50 - #ifdef ROCKBOX 50 + #ifdef ROCKBOX 51 51 return letoh32(i); 52 52 #elif !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) ) 53 53 spx_uint32_t ui, ret; ··· 86 86 */ 87 87 88 88 #ifndef SPEEX_DISABLE_ENCODER 89 - void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m) 89 + EXPORT void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m) 90 90 { 91 91 int i; 92 92 const char *h="Speex "; ··· 101 101 header->speex_version[i]=SPEEX_VERSION[i]; 102 102 for (;i<SPEEX_HEADER_VERSION_LENGTH;i++) 103 103 header->speex_version[i]=0; 104 - 104 + 105 105 header->speex_version_id = 1; 106 106 header->header_size = sizeof(SpeexHeader); 107 - 107 + 108 108 header->rate = rate; 109 109 header->mode = m->modeID; 110 110 header->mode_bitstream_version = m->bitstream_version; ··· 114 114 header->bitrate = -1; 115 115 speex_mode_query(m, SPEEX_MODE_FRAME_SIZE, &header->frame_size); 116 116 header->vbr = 0; 117 - 117 + 118 118 header->frames_per_packet = 0; 119 119 header->extra_headers = 0; 120 120 header->reserved1 = 0; 121 121 header->reserved2 = 0; 122 122 } 123 123 124 - char *speex_header_to_packet(SpeexHeader *header, int *size) 124 + EXPORT char *speex_header_to_packet(SpeexHeader *header, int *size) 125 125 { 126 126 SpeexHeader *le_header; 127 127 le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); 128 - 128 + 129 129 SPEEX_COPY(le_header, header, 1); 130 - 130 + 131 131 /*Make sure everything is now little-endian*/ 132 132 ENDIAN_SWITCH(le_header->speex_version_id); 133 133 ENDIAN_SWITCH(le_header->header_size); ··· 147 147 #endif /* SPEEX_DISABLE_ENCODER */ 148 148 149 149 static SpeexHeader global_le_header; /* Avoid malloc */ 150 - SpeexHeader *speex_packet_to_header(char *packet, int size) 150 + EXPORT SpeexHeader *speex_packet_to_header(char *packet, int size) 151 151 { 152 152 int i; 153 153 SpeexHeader *le_header = &global_le_header; ··· 158 158 speex_notify("This doesn't look like a Speex file"); 159 159 return NULL; 160 160 } 161 - 161 + 162 162 /*FIXME: Do we allow larger headers?*/ 163 163 if (size < (int)sizeof(SpeexHeader)) 164 164 { 165 165 speex_notify("Speex header too small"); 166 166 return NULL; 167 167 } 168 - 168 + 169 169 /* le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); */ 170 - 170 + 171 171 SPEEX_COPY(le_header, (SpeexHeader*)packet, 1); 172 - 172 + 173 173 /*Make sure everything is converted correctly from little-endian*/ 174 174 ENDIAN_SWITCH(le_header->speex_version_id); 175 175 ENDIAN_SWITCH(le_header->header_size); ··· 183 183 ENDIAN_SWITCH(le_header->frames_per_packet); 184 184 ENDIAN_SWITCH(le_header->extra_headers); 185 185 186 + if (le_header->mode >= SPEEX_NB_MODES || le_header->mode < 0) 187 + { 188 + speex_notify("Invalid mode specified in Speex header"); 189 + speex_free (le_header); 190 + return NULL; 191 + } 192 + 193 + if (le_header->nb_channels>2) 194 + le_header->nb_channels = 2; 195 + if (le_header->nb_channels<1) 196 + le_header->nb_channels = 1; 197 + 186 198 return le_header; 187 199 188 200 } 201 + 202 + #if 0 /* Unused by rockbox */ 203 + EXPORT void speex_header_free(void *ptr) 204 + { 205 + speex_free(ptr); 206 + } 207 + #endif
+28 -28
lib/rbcodec/codecs/libspeex/stereo.c
··· 1 - /* Copyright (C) 2002 Jean-Marc Valin 1 + /* Copyright (C) 2002 Jean-Marc Valin 2 2 File: stereo.c 3 3 4 4 Redistribution and use in source and binary forms, with or without 5 5 modification, are permitted provided that the following conditions 6 6 are met: 7 - 7 + 8 8 - Redistributions of source code must retain the above copyright 9 9 notice, this list of conditions and the following disclaimer. 10 - 10 + 11 11 - Redistributions in binary form must reproduce the above copyright 12 12 notice, this list of conditions and the following disclaimer in the 13 13 documentation and/or other materials provided with the distribution. 14 - 14 + 15 15 - Neither the name of the Xiph.org Foundation nor the names of its 16 16 contributors may be used to endorse or promote products derived from 17 17 this software without specific prior written permission. 18 - 18 + 19 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ··· 71 71 #ifdef FIXED_POINT 72 72 #define COMPATIBILITY_HACK(s) do {if ((s)->reserved1 != 0xdeadbeef) speex_stereo_state_reset((SpeexStereoState*)s); } while (0); 73 73 #else 74 - #define COMPATIBILITY_HACK(s) 74 + #define COMPATIBILITY_HACK(s) 75 75 #endif 76 76 77 77 static SpeexStereoState global_stereo_state; 78 - SpeexStereoState *speex_stereo_state_init() 78 + EXPORT SpeexStereoState *speex_stereo_state_init() 79 79 { 80 80 /* SpeexStereoState *stereo = speex_alloc(sizeof(SpeexStereoState)); */ 81 81 SpeexStereoState *stereo = &global_stereo_state; ··· 83 83 return stereo; 84 84 } 85 85 86 - void speex_stereo_state_reset(SpeexStereoState *_stereo) 86 + EXPORT void speex_stereo_state_reset(SpeexStereoState *_stereo) 87 87 { 88 88 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; 89 89 #ifdef FIXED_POINT ··· 100 100 stereo->smooth_right = 1.f; 101 101 stereo->reserved1 = 0; 102 102 stereo->reserved2 = 0; 103 - #endif 103 + #endif 104 104 } 105 105 106 - void speex_stereo_state_destroy(SpeexStereoState *stereo) 106 + EXPORT void speex_stereo_state_destroy(SpeexStereoState *stereo) 107 107 { 108 108 (void)stereo; 109 109 /* speex_free(stereo); */ ··· 111 111 112 112 #ifndef SPEEX_DISABLE_ENCODER 113 113 #ifndef DISABLE_FLOAT_API 114 - void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) 114 + EXPORT void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) 115 115 { 116 116 int i, tmp; 117 117 float e_left=0, e_right=0, e_tot=0; ··· 129 129 /*Quantization*/ 130 130 speex_bits_pack(bits, 14, 5); 131 131 speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4); 132 - 132 + 133 133 balance=4*log(balance); 134 134 135 135 /*Pack sign*/ ··· 140 140 balance=floor(.5+fabs(balance)); 141 141 if (balance>30) 142 142 balance=31; 143 - 143 + 144 144 speex_bits_pack(bits, (int)balance, 5); 145 - 145 + 146 146 /* FIXME: this is a hack */ 147 147 tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 4); 148 148 speex_bits_pack(bits, tmp, 2); 149 149 } 150 150 #endif /* #ifndef DISABLE_FLOAT_API */ 151 151 152 - void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits) 152 + EXPORT void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits) 153 153 { 154 154 int i, tmp; 155 155 spx_word32_t e_left=0, e_right=0, e_tot=0; ··· 159 159 #ifdef FIXED_POINT 160 160 int shift; 161 161 #endif 162 - 162 + 163 163 /* In band marker */ 164 164 speex_bits_pack(bits, 14, 5); 165 165 /* Stereo marker */ ··· 204 204 if (balance_id>30) 205 205 balance_id=31; 206 206 #endif 207 - 207 + 208 208 speex_bits_pack(bits, balance_id, 5); 209 - 209 + 210 210 /* "coherence" quantisation */ 211 211 #ifdef FIXED_POINT 212 212 shift = spx_ilog2(e_tot); ··· 217 217 #else 218 218 e_ratio = e_tot/(1.+e_left+e_right); 219 219 #endif 220 - 220 + 221 221 tmp=scal_quant(EXTRACT16(e_ratio), e_ratio_quant_bounds, 4); 222 222 /*fprintf (stderr, "%d %d %d %d\n", largest, smallest, balance_id, e_ratio);*/ 223 223 speex_bits_pack(bits, tmp, 2); ··· 225 225 #endif /* SPEEX_DISABLE_ENCODER */ 226 226 227 227 #ifndef DISABLE_FLOAT_API 228 - void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo) 228 + EXPORT void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo) 229 229 { 230 230 int i; 231 231 spx_word32_t balance; 232 232 spx_word16_t e_left, e_right, e_ratio; 233 233 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; 234 - 234 + 235 235 COMPATIBILITY_HACK(stereo); 236 - 236 + 237 237 balance=stereo->balance; 238 238 e_ratio=stereo->e_ratio; 239 - 239 + 240 240 /* These two are Q14, with max value just below 2. */ 241 241 e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); 242 242 e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); ··· 252 252 } 253 253 #endif /* #ifndef DISABLE_FLOAT_API */ 254 254 255 - void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo) 255 + EXPORT void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo) 256 256 { 257 257 int i; 258 258 spx_word32_t balance; ··· 260 260 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; 261 261 262 262 /* COMPATIBILITY_HACK(stereo); */ 263 - 263 + 264 264 balance=stereo->balance; 265 265 e_ratio=stereo->e_ratio; 266 - 266 + 267 267 /* These two are Q14, with max value just below 2. */ 268 268 e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); 269 269 e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); ··· 278 278 } 279 279 } 280 280 281 - int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) 281 + EXPORT int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) 282 282 { 283 283 (void)state; 284 284 RealSpeexStereoState *stereo; ··· 286 286 int tmp; 287 287 288 288 stereo = (RealSpeexStereoState*)data; 289 - 289 + 290 290 /* COMPATIBILITY_HACK(stereo); */ 291 291 292 292 if (speex_bits_unpack_unsigned(bits, 1))