Changeset 6129
- Timestamp:
- Jan 9, 2020 9:05:50 AM (5 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 4 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/echo_common.c
r5982 r6129 100 100 static struct ec_operations speex_aec_op = 101 101 { 102 " AEC",102 "Speex AEC", 103 103 &speex_aec_create, 104 104 &speex_aec_destroy, -
pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c
r4981 r6129 36 36 { 37 37 SpeexEchoState *state; 38 SpeexPreprocessState *preprocess; 38 SpeexDecorrState *decorr; 39 SpeexPreprocessState **preprocess; 39 40 40 41 unsigned samples_per_frame; 41 unsigned prefetch; 42 unsigned channel_count; 43 unsigned spf_per_channel; 42 44 unsigned options; 43 45 pj_int16_t *tmp_frame; … … 58 60 { 59 61 speex_ec *echo; 60 int sampling_rate;62 int i, sampling_rate; 61 63 62 64 *p_echo = NULL; … … 65 67 PJ_ASSERT_RETURN(echo != NULL, PJ_ENOMEM); 66 68 69 echo->channel_count = channel_count; 67 70 echo->samples_per_frame = samples_per_frame; 71 echo->spf_per_channel = samples_per_frame / channel_count; 68 72 echo->options = options; 69 73 70 #if 071 echo->state = speex_echo_state_init_mc(echo->s amples_per_frame,74 #if 1 75 echo->state = speex_echo_state_init_mc(echo->spf_per_channel, 72 76 clock_rate * tail_ms / 1000, 73 77 channel_count, channel_count); … … 80 84 clock_rate * tail_ms / 1000); 81 85 #endif 82 if (echo->state == NULL) {86 if (echo->state == NULL) 83 87 return PJ_ENOMEM; 84 } 88 89 echo->decorr = speex_decorrelate_new(clock_rate, channel_count, 90 echo->spf_per_channel); 91 if (echo->decorr == NULL) 92 return PJ_ENOMEM; 85 93 86 94 /* Set sampling rate */ … … 89 97 &sampling_rate); 90 98 91 echo->preprocess = speex_preprocess_state_init(echo->samples_per_frame, 92 clock_rate); 93 if (echo->preprocess == NULL) { 94 speex_echo_state_destroy(echo->state); 99 /* We need to create one state per channel processed. */ 100 echo->preprocess = PJ_POOL_ZALLOC_T(pool, SpeexPreprocessState *); 101 for (i = 0; i < channel_count; i++) { 102 spx_int32_t enabled; 103 104 echo->preprocess[i] = speex_preprocess_state_init( 105 echo->spf_per_channel, clock_rate); 106 if (echo->preprocess[i] == NULL) { 107 speex_aec_destroy(echo); 108 return PJ_ENOMEM; 109 } 110 111 /* Enable/disable AGC & denoise */ 112 enabled = PJMEDIA_SPEEX_AEC_USE_AGC; 113 speex_preprocess_ctl(echo->preprocess[i], SPEEX_PREPROCESS_SET_AGC, 114 &enabled); 115 116 enabled = PJMEDIA_SPEEX_AEC_USE_DENOISE; 117 speex_preprocess_ctl(echo->preprocess[i], 118 SPEEX_PREPROCESS_SET_DENOISE, &enabled); 119 120 /* Currently, VAD and dereverb are set at default setting. */ 121 /* 122 enabled = 1; 123 speex_preprocess_ctl(echo->preprocess[i], SPEEX_PREPROCESS_SET_VAD, 124 &enabled); 125 speex_preprocess_ctl(echo->preprocess[i], 126 SPEEX_PREPROCESS_SET_DEREVERB, 127 &enabled); 128 */ 129 130 /* Control echo cancellation in the preprocessor */ 131 speex_preprocess_ctl(echo->preprocess[i], 132 SPEEX_PREPROCESS_SET_ECHO_STATE, echo->state); 133 } 134 135 /* Create temporary frame for echo cancellation */ 136 echo->tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, sizeof(pj_int16_t) * 137 channel_count * 138 samples_per_frame); 139 if (!echo->tmp_frame) { 140 speex_aec_destroy(echo); 95 141 return PJ_ENOMEM; 96 142 } 97 98 /* Disable all preprocessing, we only want echo cancellation */99 #if 0100 disabled = 0;101 enabled = 1;102 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DENOISE,103 &enabled);104 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC,105 &disabled);106 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_VAD,107 &disabled);108 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DEREVERB,109 &enabled);110 #endif111 112 /* Enable/disable AGC & denoise */113 {114 spx_int32_t enabled;115 116 enabled = PJMEDIA_SPEEX_AEC_USE_AGC;117 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC,118 &enabled);119 120 enabled = PJMEDIA_SPEEX_AEC_USE_DENOISE;121 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DENOISE,122 &enabled);123 }124 125 /* Control echo cancellation in the preprocessor */126 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE,127 echo->state);128 129 130 /* Create temporary frame for echo cancellation */131 echo->tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, 2*samples_per_frame);132 PJ_ASSERT_RETURN(echo->tmp_frame != NULL, PJ_ENOMEM);133 143 134 144 /* Done */ … … 145 155 { 146 156 speex_ec *echo = (speex_ec*) state; 157 unsigned i; 147 158 148 159 PJ_ASSERT_RETURN(echo && echo->state, PJ_EINVAL); … … 153 164 } 154 165 166 if (echo->decorr) { 167 speex_decorrelate_destroy(echo->decorr); 168 echo->decorr = NULL; 169 } 170 155 171 if (echo->preprocess) { 156 speex_preprocess_state_destroy(echo->preprocess); 172 for (i = 0; i < echo->channel_count; i++) { 173 if (echo->preprocess[i]) { 174 speex_preprocess_state_destroy(echo->preprocess[i]); 175 echo->preprocess[i] = NULL; 176 } 177 } 157 178 echo->preprocess = NULL; 158 179 } … … 182 203 { 183 204 speex_ec *echo = (speex_ec*) state; 205 unsigned i; 184 206 185 207 /* Sanity checks */ … … 193 215 194 216 195 /* Preprocess output */ 196 speex_preprocess_run(echo->preprocess, (spx_int16_t*)echo->tmp_frame); 217 /* Preprocess output per channel */ 218 for (i = 0; i < echo->channel_count; i++) { 219 spx_int16_t *buf = (spx_int16_t*)echo->tmp_frame; 220 unsigned j; 221 222 /* De-interleave each channel. */ 223 if (echo->channel_count > 1) { 224 for (j = 0; j < echo->spf_per_channel; j++) { 225 rec_frm[j] = echo->tmp_frame[j * echo->channel_count + i]; 226 } 227 buf = (spx_int16_t*)rec_frm; 228 } 229 230 speex_preprocess_run(echo->preprocess[i], buf); 231 232 if (echo->channel_count > 1) { 233 for (j = 0; j < echo->spf_per_channel; j++) { 234 echo->tmp_frame[j * echo->channel_count + i] = rec_frm[j]; 235 } 236 } 237 } 197 238 198 239 /* Copy temporary buffer back to original rec_frm */ … … 213 254 /* Sanity checks */ 214 255 PJ_ASSERT_RETURN(echo && play_frm, PJ_EINVAL); 256 257 /* Channel decorrelation algorithm is useful for multi-channel echo 258 * cancellation only . 259 */ 260 if (echo->channel_count > 1) { 261 pjmedia_copy_samples(echo->tmp_frame, play_frm, echo->samples_per_frame); 262 speex_decorrelate(echo->decorr, (spx_int16_t*)echo->tmp_frame, 263 (spx_int16_t*)play_frm, 100); 264 } 215 265 216 266 speex_echo_playback(echo->state, (spx_int16_t*)play_frm); … … 228 278 { 229 279 speex_ec *echo = (speex_ec*) state; 280 unsigned i; 230 281 231 282 /* Sanity checks */ … … 235 286 236 287 /* Cancel echo */ 237 pjmedia_copy_samples(echo->tmp_frame, rec_frm, echo->samples_per_frame);238 288 speex_echo_capture(echo->state, 239 (spx_int16_t*)echo->tmp_frame, 240 (spx_int16_t*)rec_frm); 241 242 /* Apply preprocessing */ 243 speex_preprocess_run(echo->preprocess, (spx_int16_t*)rec_frm); 289 (spx_int16_t*)rec_frm, 290 (spx_int16_t*)echo->tmp_frame); 291 292 /* Apply preprocessing per channel. */ 293 for (i = 0; i < echo->channel_count; i++) { 294 spx_int16_t *buf = (spx_int16_t*)echo->tmp_frame; 295 unsigned j; 296 297 /* De-interleave each channel. */ 298 if (echo->channel_count > 1) { 299 for (j = 0; j < echo->spf_per_channel; j++) { 300 rec_frm[j] = echo->tmp_frame[j * echo->channel_count + i]; 301 } 302 buf = (spx_int16_t*)rec_frm; 303 } 304 305 speex_preprocess_run(echo->preprocess[i], buf); 306 307 if (echo->channel_count > 1) { 308 for (j = 0; j < echo->spf_per_channel; j++) { 309 echo->tmp_frame[j * echo->channel_count + i] = rec_frm[j]; 310 } 311 } 312 } 313 314 pjmedia_copy_samples(rec_frm, echo->tmp_frame, echo->samples_per_frame); 244 315 245 316 return PJ_SUCCESS; -
pjproject/trunk/third_party/build/speex/Makefile
r4786 r6129 40 40 quant_lsp.o resample.o sb_celp.o smallft.o \ 41 41 speex.o speex_callbacks.o speex_header.o \ 42 s tereo.o vbr.o vq.o window.o42 scal.o stereo.o vbr.o vq.o window.o 43 43 44 44 export SPEEX_CFLAGS = -DHAVE_CONFIG_H $(_CFLAGS) -
pjproject/trunk/third_party/speex/include/speex/speex_buffer.h
r2002 r6129 35 35 #define SPEEX_BUFFER_H 36 36 37 #include "speex /speex_types.h"37 #include "speexdsp_types.h" 38 38 39 39 #ifdef __cplusplus -
pjproject/trunk/third_party/speex/include/speex/speex_echo.h
r2002 r6129 38 38 * @{ 39 39 */ 40 #include "speex /speex_types.h"40 #include "speexdsp_types.h" 41 41 42 42 #ifdef __cplusplus -
pjproject/trunk/third_party/speex/include/speex/speex_jitter.h
r2002 r6129 42 42 */ 43 43 44 #include "speex /speex_types.h"44 #include "speexdsp_types.h" 45 45 46 46 #ifdef __cplusplus -
pjproject/trunk/third_party/speex/include/speex/speex_preprocess.h
r2002 r6129 44 44 */ 45 45 46 #include "speex /speex_types.h"46 #include "speexdsp_types.h" 47 47 48 48 #ifdef __cplusplus -
pjproject/trunk/third_party/speex/include/speex/speex_resampler.h
r2002 r6129 83 83 #define spx_uint32_t unsigned int 84 84 85 #define speex_assert(cond) 86 85 87 #else /* OUTSIDE_SPEEX */ 86 88 87 #include "speex /speex_types.h"89 #include "speexdsp_types.h" 88 90 89 91 #endif /* OUTSIDE_SPEEX */ … … 105 107 RESAMPLER_ERR_INVALID_ARG = 3, 106 108 RESAMPLER_ERR_PTR_OVERLAP = 4, 109 RESAMPLER_ERR_OVERFLOW = 5, 107 110 108 111 RESAMPLER_ERR_MAX_ERROR … … 303 306 spx_uint32_t *stride); 304 307 305 /** Get the latency in input samples introduced by the resampler.308 /** Get the latency introduced by the resampler measured in input samples. 306 309 * @param st Resampler state 307 310 */ 308 311 int speex_resampler_get_input_latency(SpeexResamplerState *st); 309 312 310 /** Get the latency in output samples introduced by the resampler.313 /** Get the latency introduced by the resampler measured in output samples. 311 314 * @param st Resampler state 312 315 */ -
pjproject/trunk/third_party/speex/libspeex/arch.h
r2002 r6129 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 … … 50 50 #error You cannot compile as floating point and fixed point at the same time 51 51 #endif 52 #ifdef _USE_SSE52 #ifdef USE_SSE 53 53 #error SSE is only for floating-point 54 54 #endif … … 76 76 77 77 #ifndef OUTSIDE_SPEEX 78 #include "speex/speex _types.h"78 #include "speex/speexdsp_types.h" 79 79 #endif 80 80 … … 90 90 91 91 typedef spx_int16_t spx_word16_t; 92 typedef spx_int32_t 92 typedef spx_int32_t spx_word32_t; 93 93 typedef spx_word32_t spx_mem_t; 94 94 typedef spx_word16_t spx_coef_t; … … 109 109 #define SIG_SHIFT 14 110 110 #define GAIN_SHIFT 6 111 112 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 111 113 112 114 #define VERY_SMALL 0 … … 172 174 #define SATURATE16(x,a) (x) 173 175 #define SATURATE32(x,a) (x) 176 #define SATURATE32PSHR(x,shift,a) (x) 174 177 175 178 #define PSHR(a,shift) (a) … … 211 214 #define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) 212 215 213 216 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : \ 217 ((x) > 32766.5f ? 32767 : (spx_int16_t)floor(.5 + (x)))) 214 218 #endif 215 219 … … 218 222 219 223 /* 2 on TI C5x DSP */ 220 #define BYTES_PER_CHAR 2 224 #define BYTES_PER_CHAR 2 221 225 #define BITS_PER_CHAR 16 222 226 #define LOG2_BITS_PER_CHAR 4 223 227 224 #else 228 #else 225 229 226 230 #define BYTES_PER_CHAR 1 -
pjproject/trunk/third_party/speex/libspeex/buffer.c
r2002 r6129 1 1 /* Copyright (C) 2007 Jean-Marc Valin 2 2 3 3 File: buffer.c 4 4 This is a very simple ring buffer implementation. It is not thread-safe … … 39 39 #include "os_support.h" 40 40 #include "arch.h" 41 #include <speex/speex_buffer.h>41 #include "speex/speex_buffer.h" 42 42 43 43 struct SpeexBuffer_ { … … 100 100 EXPORT int speex_buffer_writezeros(SpeexBuffer *st, int len) 101 101 { 102 /* This is almost the same as for speex_buffer_write() but using 102 /* This is almost the same as for speex_buffer_write() but using 103 103 SPEEX_MEMSET() instead of SPEEX_COPY(). Update accordingly. */ 104 104 int end; … … 136 136 if (len > st->available) 137 137 { 138 SPEEX_MEMSET(data+st->available, 0, st->size-st->available);138 SPEEX_MEMSET(data+st->available, 0, len - st->available); 139 139 len = st->available; 140 140 } -
pjproject/trunk/third_party/speex/libspeex/fftwrap.c
r2002 r6129 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 … … 63 63 { 64 64 out[i] = SHL16(in[i], shift); 65 } 65 } 66 66 return shift; 67 67 } … … 166 166 } 167 167 168 #elif defined(USE_INTEL_IPP) 169 170 #include <ipps.h> 171 172 struct ipp_fft_config 173 { 174 IppsDFTSpec_R_32f *dftSpec; 175 Ipp8u *buffer; 176 }; 177 178 void *spx_fft_init(int size) 179 { 180 int bufferSize = 0; 181 int hint; 182 struct ipp_fft_config *table; 183 184 table = (struct ipp_fft_config *)speex_alloc(sizeof(struct ipp_fft_config)); 185 186 /* there appears to be no performance difference between ippAlgHintFast and 187 ippAlgHintAccurate when using the with the floating point version 188 of the fft. */ 189 hint = ippAlgHintAccurate; 190 191 ippsDFTInitAlloc_R_32f(&table->dftSpec, size, IPP_FFT_DIV_FWD_BY_N, hint); 192 193 ippsDFTGetBufSize_R_32f(table->dftSpec, &bufferSize); 194 table->buffer = ippsMalloc_8u(bufferSize); 195 196 return table; 197 } 198 199 void spx_fft_destroy(void *table) 200 { 201 struct ipp_fft_config *t = (struct ipp_fft_config *)table; 202 ippsFree(t->buffer); 203 ippsDFTFree_R_32f(t->dftSpec); 204 speex_free(t); 205 } 206 207 void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) 208 { 209 struct ipp_fft_config *t = (struct ipp_fft_config *)table; 210 ippsDFTFwd_RToPack_32f(in, out, t->dftSpec, t->buffer); 211 } 212 213 void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) 214 { 215 struct ipp_fft_config *t = (struct ipp_fft_config *)table; 216 ippsDFTInv_PackToR_32f(in, out, t->dftSpec, t->buffer); 217 } 218 168 219 #elif defined(USE_GPL_FFTW3) 169 220 … … 220 271 } 221 272 222 void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) 273 void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) 223 274 { 224 275 int i; … … 235 286 236 287 fftwf_execute(t->ifft); 237 288 238 289 for(i=0;i<N;++i) 239 290 out[i] = optr[i]; -
pjproject/trunk/third_party/speex/libspeex/fixed_bfin.h
r2002 r6129 9 9 modification, are permitted provided that the following conditions 10 10 are met: 11 11 12 12 - Redistributions of source code must retain the above copyright 13 13 notice, this list of conditions and the following disclaimer. 14 14 15 15 - Redistributions in binary form must reproduce the above copyright 16 16 notice, this list of conditions and the following disclaimer in the 17 17 documentation and/or other materials provided with the distribution. 18 18 19 19 - Neither the name of the Xiph.org Foundation nor the names of its 20 20 contributors may be used to endorse or promote products derived from 21 21 this software without specific prior written permission. 22 22 23 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 24 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT … … 36 36 #ifndef FIXED_BFIN_H 37 37 #define FIXED_BFIN_H 38 39 #include "bfin.h" 38 40 39 41 #undef PDIV32_16 … … 58 60 : "=m" (res) 59 61 : "m" (a), "m" (bb) 60 : "P0", "R0", "R1", " cc");62 : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); 61 63 return res; 62 64 } … … 67 69 spx_word32_t res, bb; 68 70 bb = b; 69 /* Make the roundinf consistent with the C version 71 /* Make the roundinf consistent with the C version 70 72 (do we need to do that?)*/ 71 if (a<0) 73 if (a<0) 72 74 a += (b-1); 73 75 __asm__ ( … … 85 87 : "=m" (res) 86 88 : "m" (a), "m" (bb) 87 : "P0", "R0", "R1", " cc");89 : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); 88 90 return res; 89 91 } … … 99 101 : "=d" (res) 100 102 : "%d" (a), "d" (b) 103 : "ASTAT" 101 104 ); 102 105 return res; … … 114 117 : "=&W" (res), "=&d" (b) 115 118 : "d" (a), "1" (b) 116 : "A1" 119 : "A1", "ASTAT" 117 120 ); 118 121 return res; … … 131 134 : "=&W" (res), "=&d" (b) 132 135 : "d" (a), "1" (b), "d" (c) 133 : "A1" 136 : "A1", "ASTAT" 134 137 ); 135 138 return res; … … 148 151 : "=W" (res), "=d" (a), "=d" (b) 149 152 : "1" (a), "2" (b) 150 : "A1" 153 : "A1", "ASTAT" 151 154 ); 152 155 return res; … … 166 169 : "=&W" (res), "=&d" (b) 167 170 : "d" (a), "1" (b), "d" (c) 168 : "A1" 171 : "A1", "ASTAT" 169 172 ); 170 173 return res; -
pjproject/trunk/third_party/speex/libspeex/fixed_generic.h
r2002 r6129 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 … … 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 55 #define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \ 56 (x)<=-(SHL32(a,shift)) ? -(a) : \ 57 (PSHR32(x, shift))) 54 58 55 59 #define SHR(a,shift) ((a) >> (shift)) -
pjproject/trunk/third_party/speex/libspeex/jitter.c
r2002 r6129 56 56 57 57 #include "arch.h" 58 #include <speex/speex.h>59 #include <speex/speex_bits.h>60 58 #include <speex/speex_jitter.h> 61 59 #include "os_support.h" … … 467 465 int i; 468 466 unsigned int j; 469 int incomplete = 0;470 467 spx_int16_t opt; 471 468 … … 572 569 { 573 570 i=besti; 574 incomplete = 1;575 571 /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span);*/ 576 572 } -
pjproject/trunk/third_party/speex/libspeex/math_approx.h
r2002 r6129 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 … … 169 169 } 170 170 x = SUB16(16384,x); 171 171 172 172 x = x >> 1; 173 173 sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3)))))); 174 174 ret = spx_sqrt(SHL32(EXTEND32(sq),13)); 175 175 176 176 /*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/ 177 177 if (s) … … 209 209 { 210 210 spx_word16_t x2; 211 211 212 212 x2 = MULT16_16_P15(x,x); 213 213 return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2)))))))); -
pjproject/trunk/third_party/speex/libspeex/mdf.c
r2198 r6129 1 /* Copyright (C) 2003-200 6Jean-Marc Valin1 /* Copyright (C) 2003-2008 Jean-Marc Valin 2 2 3 3 File: mdf.c … … 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 … … 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 … … 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 … … 132 132 int saturated; 133 133 int screwed_up; 134 int C; /** Number of input channels (microphones) */ 135 int K; /** Number of output channels (loudspeakers) */ 134 136 spx_int32_t sampling_rate; 135 137 spx_word16_t spec_average; … … 138 140 spx_word32_t sum_adapt; 139 141 spx_word16_t leak_estimate; 140 142 141 143 spx_word16_t *e; /* scratch */ 142 144 spx_word16_t *x; /* Far-end input buffer (2N) */ … … 172 174 spx_word16_t *prop; 173 175 void *fft_table; 174 spx_word16_t memX, memD,memE;176 spx_word16_t *memX, *memD, *memE; 175 177 spx_word16_t preemph; 176 178 spx_word16_t notch_radius; 177 spx_mem_t notch_mem[2];179 spx_mem_t *notch_mem; 178 180 179 181 /* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */ … … 183 185 }; 184 186 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 )187 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 188 { 187 189 int i; … … 191 193 #else 192 194 den2 = radius*radius + .7*(1-radius)*(1-radius); 193 #endif 195 #endif 194 196 /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/ 195 197 for (i=0;i<len;i++) 196 198 { 197 spx_word16_t vin = in[i ];199 spx_word16_t vin = in[i*stride]; 198 200 spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15); 199 201 #ifdef FIXED_POINT … … 235 237 } 236 238 239 /** Compute power spectrum of a half-complex (packed) vector and accumulate */ 240 static inline void power_spectrum_accum(const spx_word16_t *X, spx_word32_t *ps, int N) 241 { 242 int i, j; 243 ps[0]+=MULT16_16(X[0],X[0]); 244 for (i=1,j=1;i<N-1;i+=2,j++) 245 { 246 ps[j] += MULT16_16(X[i],X[i]) + MULT16_16(X[i+1],X[i+1]); 247 } 248 ps[j]+=MULT16_16(X[i],X[i]); 249 } 250 237 251 /** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */ 238 252 #ifdef FIXED_POINT … … 331 345 } 332 346 333 static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, spx_word16_t *prop)334 { 335 int i, j ;347 static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, int P, spx_word16_t *prop) 348 { 349 int i, j, p; 336 350 spx_word16_t max_sum = 1; 337 351 spx_word32_t prop_sum = 1; … … 339 353 { 340 354 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))); 355 for (p=0;p<P;p++) 356 for (j=0;j<N;j++) 357 tmp += MULT16_16(EXTRACT16(SHR32(W[p*N*M + i*N+j],18)), EXTRACT16(SHR32(W[p*N*M + i*N+j],18))); 343 358 #ifdef FIXED_POINT 344 359 /* Just a security in case an overflow were to occur */ … … 379 394 380 395 /** Creates a new echo canceller state */ 381 SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) 382 { 383 int i,N,M; 396 EXPORT SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) 397 { 398 return speex_echo_state_init_mc(frame_size, filter_length, 1, 1); 399 } 400 401 EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers) 402 { 403 int i,N,M, C, K; 384 404 SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState)); 385 405 406 st->K = nb_speakers; 407 st->C = nb_mic; 408 C=st->C; 409 K=st->K; 386 410 #ifdef DUMP_ECHO_CANCEL_DATA 387 411 if (rFile || pFile || oFile) … … 391 415 oFile = fopen("aec_out.sw", "wb"); 392 416 #endif 393 417 394 418 st->frame_size = frame_size; 395 419 st->window_size = 2*frame_size; … … 413 437 414 438 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));439 440 st->e = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 441 st->x = (spx_word16_t*)speex_alloc(K*N*sizeof(spx_word16_t)); 442 st->input = (spx_word16_t*)speex_alloc(C*st->frame_size*sizeof(spx_word16_t)); 443 st->y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 444 st->last_y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 421 445 st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 422 446 st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); … … 425 449 st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 426 450 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));451 st->X = (spx_word16_t*)speex_alloc(K*(M+1)*N*sizeof(spx_word16_t)); 452 st->Y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 453 st->E = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 454 st->W = (spx_word32_t*)speex_alloc(C*K*M*N*sizeof(spx_word32_t)); 431 455 #ifdef TWO_PATH 432 st->foreground = (spx_word16_t*)speex_alloc(M*N* sizeof(spx_word16_t));456 st->foreground = (spx_word16_t*)speex_alloc(M*N*C*K*sizeof(spx_word16_t)); 433 457 #endif 434 458 st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); … … 451 475 for (i=0;i<=st->frame_size;i++) 452 476 st->power_1[i] = FLOAT_ONE; 453 for (i=0;i<N*M ;i++)477 for (i=0;i<N*M*K*C;i++) 454 478 st->W[i] = 0; 455 479 { … … 466 490 for (i=M-1;i>=0;i--) 467 491 { 468 st->prop[i] = DIV32(MULT16_16(QCONST16(.8,15), st->prop[i]),sum); 469 } 470 } 471 472 st->memX=st->memD=st->memE=0; 492 st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum); 493 } 494 } 495 496 st->memX = (spx_word16_t*)speex_alloc(K*sizeof(spx_word16_t)); 497 st->memD = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); 498 st->memE = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); 473 499 st->preemph = QCONST16(.9,15); 474 500 if (st->sampling_rate<12000) … … 479 505 st->notch_radius = QCONST16(.992, 15); 480 506 481 st->notch_mem [0] = st->notch_mem[1] = 0;507 st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t)); 482 508 st->adapted = 0; 483 509 st->Pey = st->Pyy = FLOAT_ONE; 484 510 485 511 #ifdef TWO_PATH 486 512 st->Davg1 = st->Davg2 = 0; 487 513 st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 488 514 #endif 489 490 st->play_buf = (spx_int16_t*)speex_alloc( (PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t));515 516 st->play_buf = (spx_int16_t*)speex_alloc(K*(PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); 491 517 st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; 492 518 st->play_buf_started = 0; 493 519 494 520 return st; 495 521 } 496 522 497 523 /** Resets echo canceller state */ 498 void speex_echo_state_reset(SpeexEchoState *st)499 { 500 int i, M, N ;524 EXPORT void speex_echo_state_reset(SpeexEchoState *st) 525 { 526 int i, M, N, C, K; 501 527 st->cancel_count=0; 502 528 st->screwed_up = 0; 503 529 N = st->window_size; 504 530 M = st->M; 531 C=st->C; 532 K=st->K; 505 533 for (i=0;i<N*M;i++) 506 534 st->W[i] = 0; … … 522 550 st->last_y[i] = 0; 523 551 } 524 for (i=0;i<N ;i++)552 for (i=0;i<N*C;i++) 525 553 { 526 554 st->E[i] = 0; 555 } 556 for (i=0;i<N*K;i++) 557 { 527 558 st->x[i] = 0; 528 559 } 529 st->notch_mem[0] = st->notch_mem[1] = 0; 530 st->memX=st->memD=st->memE=0; 560 for (i=0;i<2*C;i++) 561 st->notch_mem[i] = 0; 562 for (i=0;i<C;i++) 563 st->memD[i]=st->memE[i]=0; 564 for (i=0;i<K;i++) 565 st->memX[i]=0; 531 566 532 567 st->saturated = 0; … … 546 581 547 582 /** Destroys an echo canceller state */ 548 void speex_echo_state_destroy(SpeexEchoState *st)583 EXPORT void speex_echo_state_destroy(SpeexEchoState *st) 549 584 { 550 585 spx_fft_destroy(st->fft_table); … … 577 612 speex_free(st->wtmp2); 578 613 #endif 614 speex_free(st->memX); 615 speex_free(st->memD); 616 speex_free(st->memE); 617 speex_free(st->notch_mem); 618 579 619 speex_free(st->play_buf); 580 620 speex_free(st); 581 621 582 622 #ifdef DUMP_ECHO_CANCEL_DATA 583 623 fclose(rFile); … … 588 628 } 589 629 590 void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out)630 EXPORT void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out) 591 631 { 592 632 int i; … … 611 651 } 612 652 613 void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play)653 EXPORT void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) 614 654 { 615 655 /*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/ … … 638 678 639 679 /** 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)680 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 681 { 642 682 speex_echo_cancellation(st, in, far_end, out); … … 644 684 645 685 /** 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)647 { 648 int i,j ;649 int N,M ;686 EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out) 687 { 688 int i,j, chan, speak; 689 int N,M, C, K; 650 690 spx_word32_t Syy,See,Sxx,Sdd, Sff; 651 691 #ifdef TWO_PATH … … 659 699 spx_word16_t RER; 660 700 spx_word32_t tmp32; 661 701 662 702 N = st->window_size; 663 703 M = st->M; 704 C = st->C; 705 K = st->K; 706 664 707 st->cancel_count++; 665 708 #ifdef FIXED_POINT … … 671 714 #endif 672 715 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++) 677 { 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) 683 { 684 tmp32 = 32767; 685 st->saturated = M+1; 686 } 687 if (tmp32 < -32767) 688 { 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))); 697 #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) 705 { 706 tmp32 = -32767; 707 if (st->saturated == 0) 708 st->saturated = 1; 709 } 710 #endif 711 st->memD = st->input[i]; 712 st->input[i] = tmp32; 713 } 714 715 /* Shift memory: this could be optimized eventually*/ 716 for (j=M-1;j>=0;j--) 717 { 718 for (i=0;i<N;i++) 719 st->X[(j+1)*N+i] = st->X[j*N+i]; 720 } 721 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 716 for (chan = 0; chan < C; chan++) 717 { 718 /* Apply a notch filter to make sure DC doesn't end up causing problems */ 719 filter_dc_notch16(in+chan, st->notch_radius, st->input+chan*st->frame_size, st->frame_size, st->notch_mem+2*chan, C); 720 /* Copy input data to buffer and apply pre-emphasis */ 721 /* Copy input data to buffer */ 722 for (i=0;i<st->frame_size;i++) 723 { 724 spx_word32_t tmp32; 725 /* FIXME: This core has changed a bit, need to merge properly */ 726 tmp32 = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD[chan]))); 727 #ifdef FIXED_POINT 728 if (tmp32 > 32767) 729 { 730 tmp32 = 32767; 731 if (st->saturated == 0) 732 st->saturated = 1; 733 } 734 if (tmp32 < -32767) 735 { 736 tmp32 = -32767; 737 if (st->saturated == 0) 738 st->saturated = 1; 739 } 740 #endif 741 st->memD[chan] = st->input[chan*st->frame_size+i]; 742 st->input[chan*st->frame_size+i] = EXTRACT16(tmp32); 743 } 744 } 745 746 for (speak = 0; speak < K; speak++) 747 { 748 for (i=0;i<st->frame_size;i++) 749 { 750 spx_word32_t tmp32; 751 st->x[speak*N+i] = st->x[speak*N+i+st->frame_size]; 752 tmp32 = SUB32(EXTEND32(far_end[i*K+speak]), EXTEND32(MULT16_16_P15(st->preemph, st->memX[speak]))); 753 #ifdef FIXED_POINT 754 /*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */ 755 if (tmp32 > 32767) 756 { 757 tmp32 = 32767; 758 st->saturated = M+1; 759 } 760 if (tmp32 < -32767) 761 { 762 tmp32 = -32767; 763 st->saturated = M+1; 764 } 765 #endif 766 st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32); 767 st->memX[speak] = far_end[i*K+speak]; 768 } 769 } 770 771 for (speak = 0; speak < K; speak++) 772 { 773 /* Shift memory: this could be optimized eventually*/ 774 for (j=M-1;j>=0;j--) 775 { 776 for (i=0;i<N;i++) 777 st->X[(j+1)*N*K+speak*N+i] = st->X[j*N*K+speak*N+i]; 778 } 779 /* Convert x (echo input) to frequency domain */ 780 spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]); 781 } 782 783 Sxx = 0; 784 for (speak = 0; speak < K; speak++) 785 { 786 Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); 787 power_spectrum_accum(st->X+speak*N, st->Xf, N); 788 } 789 790 Sff = 0; 791 for (chan = 0; chan < C; chan++) 792 { 731 793 #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); 738 #endif 739 794 /* Compute foreground filter */ 795 spectral_mul_accum16(st->X, st->foreground+chan*N*K*M, st->Y+chan*N, N, M*K); 796 spx_ifft(st->fft_table, st->Y+chan*N, st->e+chan*N); 797 for (i=0;i<st->frame_size;i++) 798 st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->e[chan*N+i+st->frame_size]); 799 Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 800 #endif 801 } 802 740 803 /* Adjust proportional adaption rate */ 741 mdf_adjust_prop (st->W, N, M, st->prop); 804 /* FIXME: Adjust that for C, K*/ 805 if (st->adapted) 806 mdf_adjust_prop (st->W, N, M, C*K, st->prop); 742 807 /* Compute weight gradient */ 743 808 if (st->saturated == 0) 744 809 { 745 for (j=M-1;j>=0;j--) 746 { 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 810 for (chan = 0; chan < C; chan++) 811 { 812 for (speak = 0; speak < K; speak++) 813 { 814 for (j=M-1;j>=0;j--) 815 { 816 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); 817 for (i=0;i<N;i++) 818 st->W[chan*N*K*M + j*N*K + speak*N + i] += st->PHI[i]; 819 } 820 } 751 821 } 752 822 } else { 753 823 st->saturated--; 754 824 } 755 825 826 /* FIXME: MC conversion required */ 756 827 /* Update weight to prevent circular convolution (MDF / AUMDF) */ 757 for (j=0;j<M;j++) 758 { 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) 762 { 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++) 828 for (chan = 0; chan < C; chan++) 829 { 830 for (speak = 0; speak < K; speak++) 831 { 832 for (j=0;j<M;j++) 768 833 { 769 st->wtmp[i]=0; 834 /* This is a variant of the Alternatively Updated MDF (AUMDF) */ 835 /* Remove the "if" to make this an MDF filter */ 836 if (j==0 || st->cancel_count%(M-1) == j-1) 837 { 838 #ifdef FIXED_POINT 839 for (i=0;i<N;i++) 840 st->wtmp2[i] = EXTRACT16(PSHR32(st->W[chan*N*K*M + j*N*K + speak*N + i],NORMALIZE_SCALEDOWN+16)); 841 spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 842 for (i=0;i<st->frame_size;i++) 843 { 844 st->wtmp[i]=0; 845 } 846 for (i=st->frame_size;i<N;i++) 847 { 848 st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); 849 } 850 spx_fft(st->fft_table, st->wtmp, st->wtmp2); 851 /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ 852 for (i=0;i<N;i++) 853 st->W[chan*N*K*M + j*N*K + speak*N + i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); 854 #else 855 spx_ifft(st->fft_table, &st->W[chan*N*K*M + j*N*K + speak*N], st->wtmp); 856 for (i=st->frame_size;i<N;i++) 857 { 858 st->wtmp[i]=0; 859 } 860 spx_fft(st->fft_table, st->wtmp, &st->W[chan*N*K*M + j*N*K + speak*N]); 861 #endif 862 } 770 863 } 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); 779 #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]); 786 #endif 787 } 788 } 789 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); 793 864 } 865 } 866 867 /* So we can use power_spectrum_accum */ 868 for (i=0;i<=st->frame_size;i++) 869 st->Rf[i] = st->Yf[i] = st->Xf[i] = 0; 870 871 Dbf = 0; 872 See = 0; 794 873 #ifdef TWO_PATH 795 874 /* 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); 799 #endif 800 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); 875 for (chan = 0; chan < C; chan++) 876 { 877 spectral_mul_accum(st->X, st->W+chan*N*K*M, st->Y+chan*N, N, M*K); 878 spx_ifft(st->fft_table, st->Y+chan*N, st->y+chan*N); 879 for (i=0;i<st->frame_size;i++) 880 st->e[chan*N+i] = SUB16(st->e[chan*N+i+st->frame_size], st->y[chan*N+i+st->frame_size]); 881 Dbf += 10+mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 882 for (i=0;i<st->frame_size;i++) 883 st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); 884 See += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 885 } 886 #endif 887 804 888 #ifndef TWO_PATH 805 889 Sff = See; … … 808 892 #ifdef TWO_PATH 809 893 /* Logic for updating the foreground filter */ 810 894 811 895 /* For two time windows, compute the mean of the energy difference, as well as the variance */ 812 896 st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See))); … … 814 898 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 899 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 900 817 901 /* Equivalent float code: 818 902 st->Davg1 = .6*st->Davg1 + .4*(Sff-See); … … 821 905 st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf; 822 906 */ 823 907 824 908 update_foreground = 0; 825 909 /* Check if we have a statistically significant reduction in the residual echo */ … … 831 915 else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2)))) 832 916 update_foreground = 1; 833 917 834 918 /* Do we update? */ 835 919 if (update_foreground) … … 838 922 st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 839 923 /* Copy background filter to foreground filter */ 840 for (i=0;i<N*M ;i++)924 for (i=0;i<N*M*C*K;i++) 841 925 st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16)); 842 926 /* 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]); 927 for (chan = 0; chan < C; chan++) 928 for (i=0;i<st->frame_size;i++) 929 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 930 } else { 846 931 int reset_background=0; … … 855 940 { 856 941 /* Copy foreground filter to background filter */ 857 for (i=0;i<N*M ;i++)942 for (i=0;i<N*M*C*K;i++) 858 943 st->W[i] = SHL32(EXTEND32(st->foreground[i]),16); 859 944 /* 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]); 945 for (chan = 0; chan < C; chan++) 946 { 947 for (i=0;i<st->frame_size;i++) 948 st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size]; 949 for (i=0;i<st->frame_size;i++) 950 st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); 951 } 864 952 See = Sff; 865 953 st->Davg1 = st->Davg2 = 0; … … 869 957 #endif 870 958 871 /* Compute error signal (for the output with de-emphasis) */ 872 for (i=0;i<st->frame_size;i++) 873 { 874 spx_word32_t tmp_out; 959 Sey = Syy = Sdd = 0; 960 for (chan = 0; chan < C; chan++) 961 { 962 /* Compute error signal (for the output with de-emphasis) */ 963 for (i=0;i<st->frame_size;i++) 964 { 965 spx_word32_t tmp_out; 875 966 #ifdef TWO_PATH 876 tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->e[i+st->frame_size])); 877 #else 878 tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->y[i+st->frame_size])); 879 #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))); 967 tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->e[chan*N+i+st->frame_size])); 968 #else 969 tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->y[chan*N+i+st->frame_size])); 970 #endif 971 tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE[chan]))); 886 972 /* This is an arbitrary test for saturation in the microphone signal */ 887 if (in[i] <= -32000 || in[i] >= 32000) 888 { 889 tmp_out = 0; 973 if (in[i*C+chan] <= -32000 || in[i*C+chan] >= 32000) 974 { 890 975 if (st->saturated == 0) 891 976 st->saturated = 1; 892 }893 out[i] = (spx_int16_t)tmp_out;894 st->memE= tmp_out;895 }896 977 } 978 out[i*C+chan] = WORD2INT(tmp_out); 979 st->memE[chan] = tmp_out; 980 } 981 897 982 #ifdef DUMP_ECHO_CANCEL_DATA 898 dump_audio(in, far_end, out, st->frame_size); 899 #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; 906 } 907 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 983 dump_audio(in, far_end, out, st->frame_size); 984 #endif 985 986 /* Compute error signal (filter update version) */ 987 for (i=0;i<st->frame_size;i++) 988 { 989 st->e[chan*N+i+st->frame_size] = st->e[chan*N+i]; 990 st->e[chan*N+i] = 0; 991 } 992 993 /* Compute a bunch of correlations */ 994 /* FIXME: bad merge */ 995 Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); 996 Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); 997 Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size); 998 999 /* Convert error to frequency domain */ 1000 spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N); 1001 for (i=0;i<st->frame_size;i++) 1002 st->y[i+chan*N] = 0; 1003 spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N); 1004 1005 /* Compute power spectrum of echo (X), error (E) and filter response (Y) */ 1006 power_spectrum_accum(st->E+chan*N, st->Rf, N); 1007 power_spectrum_accum(st->Y+chan*N, st->Yf, N); 1008 1009 } 1010 913 1011 /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/ 914 1012 915 1013 /* Do some sanity check */ 916 1014 if (!(Syy>=0 && Sxx>=0 && See >= 0) … … 922 1020 /* Things have gone really bad */ 923 1021 st->screwed_up += 50; 924 for (i=0;i<st->frame_size ;i++)1022 for (i=0;i<st->frame_size*C;i++) 925 1023 out[i] = 0; 926 1024 } else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6))) … … 942 1040 See = MAX32(See, SHR32(MULT16_16(N, 100),6)); 943 1041 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); 949 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 1042 for (speak = 0; speak < K; speak++) 1043 { 1044 Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); 1045 power_spectrum_accum(st->X+speak*N, st->Xf, N); 1046 } 1047 1048 955 1049 /* Smooth far end energy estimate over time */ 956 1050 for (j=0;j<=st->frame_size;j++) 957 1051 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 more960 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 1052 974 1053 /* Compute filtered spectra and (cross-)correlations */ … … 988 1067 #endif 989 1068 } 990 1069 991 1070 Pyy = FLOAT_SQRT(Pyy); 992 1071 Pey = FLOAT_DIVU(Pey,Pyy); … … 1016 1095 st->leak_estimate = SHL16(st->leak_estimate,1); 1017 1096 /*printf ("%f\n", st->leak_estimate);*/ 1018 1097 1019 1098 /* Compute Residual to Error Ratio */ 1020 1099 #ifdef FIXED_POINT … … 1072 1151 spx_word16_t adapt_rate=0; 1073 1152 1074 if (Sxx > SHR32(MULT16_16(N, 1000),6)) 1153 if (Sxx > SHR32(MULT16_16(N, 1000),6)) 1075 1154 { 1076 1155 tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx); … … 1092 1171 } 1093 1172 1094 /* Save residual echo so it can be used by the nonlinear processor */ 1095 if (st->adapted) 1096 { 1097 /* If the filter is adapted, take the filtered echo */ 1173 /* FIXME: MC conversion required */ 1098 1174 for (i=0;i<st->frame_size;i++) 1099 1175 st->last_y[i] = st->last_y[st->frame_size+i]; 1176 if (st->adapted) 1177 { 1178 /* If the filter is adapted, take the filtered echo */ 1100 1179 for (i=0;i<st->frame_size;i++) 1101 1180 st->last_y[st->frame_size+i] = in[i]-out[i]; … … 1114 1193 spx_word16_t leak2; 1115 1194 int N; 1116 1195 1117 1196 N = st->window_size; 1118 1197 … … 1120 1199 for (i=0;i<N;i++) 1121 1200 st->y[i] = MULT16_16_Q15(st->window[i],st->last_y[i]); 1122 1201 1123 1202 /* Compute power spectrum of the echo */ 1124 1203 spx_fft(st->fft_table, st->y, st->Y); 1125 1204 power_spectrum(st->Y, residual_echo, N); 1126 1205 1127 1206 #ifdef FIXED_POINT 1128 1207 if (st->leak_estimate > 16383) … … 1139 1218 for (i=0;i<=st->frame_size;i++) 1140 1219 residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]); 1141 1142 } 1143 1144 int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr)1220 1221 } 1222 1223 EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) 1145 1224 { 1146 1225 switch(request) 1147 1226 { 1148 1227 1149 1228 case SPEEX_ECHO_GET_FRAME_SIZE: 1150 1229 (*(int*)ptr) = st->frame_size; … … 1170 1249 (*(int*)ptr) = st->sampling_rate; 1171 1250 break; 1251 case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE: 1252 /*FIXME: Implement this for multiple channels */ 1253 *((spx_int32_t *)ptr) = st->M * st->frame_size; 1254 break; 1255 case SPEEX_ECHO_GET_IMPULSE_RESPONSE: 1256 { 1257 int M = st->M, N = st->window_size, n = st->frame_size, i, j; 1258 spx_int32_t *filt = (spx_int32_t *) ptr; 1259 for(j=0;j<M;j++) 1260 { 1261 /*FIXME: Implement this for multiple channels */ 1262 #ifdef FIXED_POINT 1263 for (i=0;i<N;i++) 1264 st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN)); 1265 spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 1266 #else 1267 spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); 1268 #endif 1269 for(i=0;i<n;i++) 1270 filt[j*n+i] = PSHR32(MULT16_16(32767,st->wtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN); 1271 } 1272 } 1273 break; 1172 1274 default: 1173 1275 speex_warning_int("Unknown speex_echo_ctl request: ", request); -
pjproject/trunk/third_party/speex/libspeex/misc_bfin.h
r2002 r6129 2 2 /** 3 3 @file misc_bfin.h 4 @author Jean-Marc Valin 4 @author Jean-Marc Valin 5 5 @brief Various compatibility routines for Speex (Blackfin version) 6 6 */ … … 9 9 modification, are permitted provided that the following conditions 10 10 are met: 11 11 12 12 - Redistributions of source code must retain the above copyright 13 13 notice, this list of conditions and the following disclaimer. 14 14 15 15 - Redistributions in binary form must reproduce the above copyright 16 16 notice, this list of conditions and the following disclaimer in the 17 17 documentation and/or other materials provided with the distribution. 18 18 19 19 - Neither the name of the Xiph.org Foundation nor the names of its 20 20 contributors may be used to endorse or promote products derived from 21 21 this software without specific prior written permission. 22 22 23 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 24 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT … … 33 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 34 */ 35 36 #include "bfin.h" 35 37 36 38 #define OVERRIDE_SPEEX_MOVE … … 49 51 : "=a" (src), "=a" (dest) 50 52 : "a" ((n>>2)-1), "0" (src), "1" (dest) 51 : "R0", "I0", "L0", "memory" 53 : "R0", "I0", "L0", "memory" BFIN_HWLOOP0_REGS 52 54 ); 53 55 return dest; -
pjproject/trunk/third_party/speex/libspeex/os_support.h
r2002 r6129 1 1 /* Copyright (C) 2007 Jean-Marc Valin 2 2 3 3 File: os_support.h 4 4 This is the (tiny) OS abstraction layer. Aside from math.h, this is the … … 46 46 #endif 47 47 48 /** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free 48 /** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free 49 49 NOTE: speex_alloc needs to CLEAR THE MEMORY */ 50 50 #ifndef OVERRIDE_SPEEX_ALLOC 51 51 static inline void *speex_alloc (int size) 52 52 { 53 /* WARNING: this is not equivalent to malloc(). If you want to use malloc() 53 /* WARNING: this is not equivalent to malloc(). If you want to use malloc() 54 54 or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise 55 55 you will experience strange bugs */ … … 91 91 #endif 92 92 93 /** Copy n bytes of memoryfrom src to dst. The 0* term provides compile-time type checking */93 /** Copy n elements from src to dst. The 0* term provides compile-time type checking */ 94 94 #ifndef OVERRIDE_SPEEX_COPY 95 95 #define SPEEX_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) 96 96 #endif 97 97 98 /** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term98 /** Copy n elements from src to dst, allowing overlapping regions. The 0* term 99 99 provides compile-time type checking */ 100 100 #ifndef OVERRIDE_SPEEX_MOVE … … 102 102 #endif 103 103 104 /** Set n bytes of memory to value of c, starting at address s*/104 /** For n elements worth of memory, set every byte to the value of c, starting at address dst */ 105 105 #ifndef OVERRIDE_SPEEX_MEMSET 106 106 #define SPEEX_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst)))) -
pjproject/trunk/third_party/speex/libspeex/resample.c
r2002 r6129 1 1 /* Copyright (C) 2007-2008 Jean-Marc Valin 2 2 Copyright (C) 2008 Thorvald Natvig 3 3 4 4 File: resample.c 5 5 Arbitrary resampling code … … 39 39 - Good *perceptual* quality (and not best SNR) 40 40 41 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 42 42 all the major bugs and I don't expect the API to change anymore, there 43 43 may be something I've missed. So use with caution. … … 45 45 This algorithm is based on this original resampling algorithm: 46 46 Smith, Julius O. Digital Audio Resampling Home Page 47 Center for Computer Research in Music and Acoustics (CCRMA), 47 Center for Computer Research in Music and Acoustics (CCRMA), 48 48 Stanford University, 2007. 49 Web published at http ://www-ccrma.stanford.edu/~jos/resample/.50 51 There is one main difference, though. This resampler uses cubic 49 Web published at https://ccrma.stanford.edu/~jos/resample/. 50 51 There is one main difference, though. This resampler uses cubic 52 52 interpolation instead of linear interpolation in the above paper. This 53 53 makes the table much smaller and makes it possible to compute that table 54 on a per-stream basis. In turn, being able to tweak the table for each 55 stream makes it possible to both reduce complexity on simple ratios 56 (e.g. 2/3), and get rid of the rounding operations in the inner loop. 54 on a per-stream basis. In turn, being able to tweak the table for each 55 stream makes it possible to both reduce complexity on simple ratios 56 (e.g. 2/3), and get rid of the rounding operations in the inner loop. 57 57 The latter both reduces CPU time and makes the algorithm more SIMD-friendly. 58 58 */ … … 64 64 #ifdef OUTSIDE_SPEEX 65 65 #include <stdlib.h> 66 static void *speex_alloc (int size) {return calloc(size,1);} 67 static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} 68 static void speex_free (void *ptr) {free(ptr);} 66 static void *speex_alloc(int size) {return calloc(size,1);} 67 static void *speex_realloc(void *ptr, int size) {return realloc(ptr, size);} 68 static void speex_free(void *ptr) {free(ptr);} 69 #ifndef EXPORT 70 #define EXPORT 71 #endif 69 72 #include "speex_resampler.h" 70 73 #include "arch.h" 71 74 #else /* OUTSIDE_SPEEX */ 72 75 73 76 #include "speex/speex_resampler.h" 74 77 #include "arch.h" … … 76 79 #endif /* OUTSIDE_SPEEX */ 77 80 78 #include "stack_alloc.h"79 81 #include <math.h> 82 #include <limits.h> 80 83 81 84 #ifndef M_PI 82 #define M_PI 3.14159263 83 #endif 84 85 #ifdef FIXED_POINT 86 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 87 #else 88 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) 89 #endif 90 85 #define M_PI 3.14159265358979323846 86 #endif 87 91 88 #define IMAX(a,b) ((a) > (b) ? (a) : (b)) 92 89 #define IMIN(a,b) ((a) < (b) ? (a) : (b)) … … 96 93 #endif 97 94 98 #ifdef _USE_SSE 95 #ifndef UINT32_MAX 96 #define UINT32_MAX 4294967295U 97 #endif 98 99 #ifdef USE_SSE 99 100 #include "resample_sse.h" 101 #endif 102 103 #ifdef USE_NEON 104 #include "resample_neon.h" 100 105 #endif 101 106 … … 114 119 spx_uint32_t num_rate; 115 120 spx_uint32_t den_rate; 116 121 117 122 int quality; 118 123 spx_uint32_t nb_channels; … … 126 131 int initialised; 127 132 int started; 128 133 129 134 /* These are per-channel */ 130 135 spx_int32_t *last_sample; 131 136 spx_uint32_t *samp_frac_num; 132 137 spx_uint32_t *magic_samples; 133 138 134 139 spx_word16_t *mem; 135 140 spx_word16_t *sinc_table; 136 141 spx_uint32_t sinc_table_length; 137 142 resampler_basic_func resampler_ptr; 138 143 139 144 int in_stride; 140 145 int out_stride; 141 146 } ; 142 147 143 static double kaiser12_table[68] = {148 static const double kaiser12_table[68] = { 144 149 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, 145 150 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, … … 155 160 0.00001000, 0.00000000}; 156 161 /* 157 static double kaiser12_table[36] = {162 static const double kaiser12_table[36] = { 158 163 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, 159 164 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, … … 163 168 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; 164 169 */ 165 static double kaiser10_table[36] = {170 static const double kaiser10_table[36] = { 166 171 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, 167 172 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, … … 171 176 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000}; 172 177 173 static double kaiser8_table[36] = {178 static const double kaiser8_table[36] = { 174 179 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, 175 180 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, … … 178 183 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, 179 184 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; 180 181 static double kaiser6_table[36] = {185 186 static const double kaiser6_table[36] = { 182 187 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, 183 188 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, … … 188 193 189 194 struct FuncDef { 190 double *table;195 const double *table; 191 196 int oversample; 192 197 }; 193 194 static struct FuncDef _KAISER12 = {kaiser12_table, 64}; 195 #define KAISER12 (&_KAISER12) 196 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; 197 #define KAISER12 (&_KAISER12)*/ 198 static struct FuncDef _KAISER10 = {kaiser10_table, 32}; 199 #define KAISER10 (&_KAISER10) 200 static struct FuncDef _KAISER8 = {kaiser8_table, 32}; 201 #define KAISER8 (&_KAISER8) 202 static struct FuncDef _KAISER6 = {kaiser6_table, 32}; 203 #define KAISER6 (&_KAISER6) 198 199 static const struct FuncDef kaiser12_funcdef = {kaiser12_table, 64}; 200 #define KAISER12 (&kaiser12_funcdef) 201 static const struct FuncDef kaiser10_funcdef = {kaiser10_table, 32}; 202 #define KAISER10 (&kaiser10_funcdef) 203 static const struct FuncDef kaiser8_funcdef = {kaiser8_table, 32}; 204 #define KAISER8 (&kaiser8_funcdef) 205 static const struct FuncDef kaiser6_funcdef = {kaiser6_table, 32}; 206 #define KAISER6 (&kaiser6_funcdef) 204 207 205 208 struct QualityMapping { … … 208 211 float downsample_bandwidth; 209 212 float upsample_bandwidth; 210 struct FuncDef *window_func;213 const struct FuncDef *window_func; 211 214 }; 212 215 213 216 214 217 /* This table maps conversion quality to internal parameters. There are two 215 reasons that explain why the up-sampling bandwidth is larger than the 218 reasons that explain why the up-sampling bandwidth is larger than the 216 219 down-sampling bandwidth: 217 220 1) When up-sampling, we can assume that the spectrum is already attenuated … … 235 238 }; 236 239 /*8,24,40,56,80,104,128,160,200,256,320*/ 237 static double compute_func(float x, struct FuncDef *func)240 static double compute_func(float x, const struct FuncDef *func) 238 241 { 239 242 float y, frac; 240 243 double interp[4]; 241 int ind; 244 int ind; 242 245 y = x*func->oversample; 243 246 ind = (int)floor(y); … … 250 253 /* Just to make sure we don't have rounding problems */ 251 254 interp[1] = 1.f-interp[3]-interp[2]-interp[0]; 252 255 253 256 /*sum = frac*accum[1] + (1-frac)*accum[2];*/ 254 257 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; … … 270 273 #ifdef FIXED_POINT 271 274 /* The slow way of computing a sinc for the table. Should improve that some day */ 272 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)275 static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func) 273 276 { 274 277 /*fprintf (stderr, "%f ", x);*/ … … 283 286 #else 284 287 /* The slow way of computing a sinc for the table. Should improve that some day */ 285 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)288 static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func) 286 289 { 287 290 /*fprintf (stderr, "%f ", x);*/ … … 338 341 const spx_uint32_t den_rate = st->den_rate; 339 342 spx_word32_t sum; 340 int j;341 343 342 344 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 343 345 { 344 const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];346 const spx_word16_t *sinct = & sinc_table[samp_frac_num*N]; 345 347 const spx_word16_t *iptr = & in[last_sample]; 346 348 347 349 #ifndef OVERRIDE_INNER_PRODUCT_SINGLE 348 float accum[4] = {0,0,0,0}; 349 350 int j; 351 sum = 0; 352 for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]); 353 354 /* This code is slower on most DSPs which have only 2 accumulators. 355 Plus this this forces truncation to 32 bits and you lose the HW guard bits. 356 I think we can trust the compiler and let it vectorize and/or unroll itself. 357 spx_word32_t accum[4] = {0,0,0,0}; 350 358 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];359 accum[0] += MULT16_16(sinct[j], iptr[j]); 360 accum[1] += MULT16_16(sinct[j+1], iptr[j+1]); 361 accum[2] += MULT16_16(sinct[j+2], iptr[j+2]); 362 accum[3] += MULT16_16(sinct[j+3], iptr[j+3]); 355 363 } 356 364 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); 365 */ 366 sum = SATURATE32PSHR(sum, 15, 32767); 367 #else 368 sum = inner_product_single(sinct, iptr, N); 369 #endif 370 371 out[out_stride * out_sample++] = sum; 362 372 last_sample += int_advance; 363 373 samp_frac_num += frac_advance; … … 389 399 const spx_uint32_t den_rate = st->den_rate; 390 400 double sum; 391 int j;392 401 393 402 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 394 403 { 395 const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];404 const spx_word16_t *sinct = & sinc_table[samp_frac_num*N]; 396 405 const spx_word16_t *iptr = & in[last_sample]; 397 406 398 407 #ifndef OVERRIDE_INNER_PRODUCT_DOUBLE 408 int j; 399 409 double accum[4] = {0,0,0,0}; 400 410 401 411 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];412 accum[0] += sinct[j]*iptr[j]; 413 accum[1] += sinct[j+1]*iptr[j+1]; 414 accum[2] += sinct[j+2]*iptr[j+2]; 415 accum[3] += sinct[j+3]*iptr[j+3]; 406 416 } 407 417 sum = accum[0] + accum[1] + accum[2] + accum[3]; 408 418 #else 409 sum = inner_product_double(sinc , iptr, N);419 sum = inner_product_double(sinct, iptr, N); 410 420 #endif 411 421 … … 436 446 const int frac_advance = st->frac_advance; 437 447 const spx_uint32_t den_rate = st->den_rate; 438 int j;439 448 spx_word32_t sum; 440 449 … … 453 462 454 463 #ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE 464 int j; 455 465 spx_word32_t accum[4] = {0,0,0,0}; 456 466 … … 464 474 465 475 cubic_coef(frac, interp); 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]); 476 sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1)); 477 sum = SATURATE32PSHR(sum, 15, 32767); 467 478 #else 468 479 cubic_coef(frac, interp); 469 480 sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 470 481 #endif 471 472 out[out_stride * out_sample++] = PSHR32(sum,15);482 483 out[out_stride * out_sample++] = sum; 473 484 last_sample += int_advance; 474 485 samp_frac_num += frac_advance; … … 498 509 const int frac_advance = st->frac_advance; 499 510 const spx_uint32_t den_rate = st->den_rate; 500 int j;501 511 spx_word32_t sum; 502 512 … … 515 525 516 526 #ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE 527 int j; 517 528 double accum[4] = {0,0,0,0}; 518 529 … … 531 542 sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 532 543 #endif 533 544 534 545 out[out_stride * out_sample++] = PSHR32(sum,15); 535 546 last_sample += int_advance; … … 548 559 #endif 549 560 550 static void update_filter(SpeexResamplerState *st) 551 { 552 spx_uint32_t old_length; 553 554 old_length = st->filt_len; 561 /* This resampler is used to produce zero output in situations where memory 562 for the filter could not be allocated. The expected numbers of input and 563 output samples are still processed so that callers failing to check error 564 codes are not surprised, possibly getting into infinite loops. */ 565 static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 566 { 567 int out_sample = 0; 568 int last_sample = st->last_sample[channel_index]; 569 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 570 const int out_stride = st->out_stride; 571 const int int_advance = st->int_advance; 572 const int frac_advance = st->frac_advance; 573 const spx_uint32_t den_rate = st->den_rate; 574 575 (void)in; 576 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 577 { 578 out[out_stride * out_sample++] = 0; 579 last_sample += int_advance; 580 samp_frac_num += frac_advance; 581 if (samp_frac_num >= den_rate) 582 { 583 samp_frac_num -= den_rate; 584 last_sample++; 585 } 586 } 587 588 st->last_sample[channel_index] = last_sample; 589 st->samp_frac_num[channel_index] = samp_frac_num; 590 return out_sample; 591 } 592 593 static int multiply_frac(spx_uint32_t *result, spx_uint32_t value, spx_uint32_t num, spx_uint32_t den) 594 { 595 spx_uint32_t major = value / den; 596 spx_uint32_t remain = value % den; 597 /* TODO: Could use 64 bits operation to check for overflow. But only guaranteed in C99+ */ 598 if (remain > UINT32_MAX / num || major > UINT32_MAX / num 599 || major * num > UINT32_MAX - remain * num / den) 600 return RESAMPLER_ERR_OVERFLOW; 601 *result = remain * num / den + major * num; 602 return RESAMPLER_ERR_SUCCESS; 603 } 604 605 static int update_filter(SpeexResamplerState *st) 606 { 607 spx_uint32_t old_length = st->filt_len; 608 spx_uint32_t old_alloc_size = st->mem_alloc_size; 609 int use_direct; 610 spx_uint32_t min_sinc_table_length; 611 spx_uint32_t min_alloc_size; 612 613 st->int_advance = st->num_rate/st->den_rate; 614 st->frac_advance = st->num_rate%st->den_rate; 555 615 st->oversample = quality_map[st->quality].oversample; 556 616 st->filt_len = quality_map[st->quality].base_length; 557 617 558 618 if (st->num_rate > st->den_rate) 559 619 { 560 620 /* down-sampling */ 561 621 st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; 562 /* FIXME: divide the numerator and denominator by a certain amount if they're too large */563 st->filt_len = st->filt_len*st->num_rate / st->den_rate;564 /* Round down to make sure we have a multiple of 4*/565 st->filt_len &= (~0x3);622 if (multiply_frac(&st->filt_len,st->filt_len,st->num_rate,st->den_rate) != RESAMPLER_ERR_SUCCESS) 623 goto fail; 624 /* Round up to make sure we have a multiple of 8 for SSE */ 625 st->filt_len = ((st->filt_len-1)&(~0x7))+8; 566 626 if (2*st->den_rate < st->num_rate) 567 627 st->oversample >>= 1; … … 578 638 st->cutoff = quality_map[st->quality].upsample_bandwidth; 579 639 } 580 640 641 #ifdef RESAMPLE_FULL_SINC_TABLE 642 use_direct = 1; 643 if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len) 644 goto fail; 645 #else 581 646 /* Choose the resampling type that requires the least amount of memory */ 582 if (st->den_rate <= st->oversample) 647 use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 648 && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len; 649 #endif 650 if (use_direct) 651 { 652 min_sinc_table_length = st->filt_len*st->den_rate; 653 } else { 654 if ((INT_MAX/sizeof(spx_word16_t)-8)/st->oversample < st->filt_len) 655 goto fail; 656 657 min_sinc_table_length = st->filt_len*st->oversample+8; 658 } 659 if (st->sinc_table_length < min_sinc_table_length) 660 { 661 spx_word16_t *sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,min_sinc_table_length*sizeof(spx_word16_t)); 662 if (!sinc_table) 663 goto fail; 664 665 st->sinc_table = sinc_table; 666 st->sinc_table_length = min_sinc_table_length; 667 } 668 if (use_direct) 583 669 { 584 670 spx_uint32_t i; 585 if (!st->sinc_table)586 st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));587 else if (st->sinc_table_length < st->filt_len*st->den_rate)588 {589 st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));590 st->sinc_table_length = st->filt_len*st->den_rate;591 }592 671 for (i=0;i<st->den_rate;i++) 593 672 { … … 609 688 } else { 610 689 spx_int32_t i; 611 if (!st->sinc_table)612 st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));613 else if (st->sinc_table_length < st->filt_len*st->oversample+8)614 {615 st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));616 st->sinc_table_length = st->filt_len*st->oversample+8;617 }618 690 for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) 619 691 st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func); … … 628 700 /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ 629 701 } 630 st->int_advance = st->num_rate/st->den_rate; 631 st->frac_advance = st->num_rate%st->den_rate; 632 633 702 634 703 /* Here's the place where we update the filter memory to take into account 635 704 the change in filter length. It's probably the messiest part of the code 636 705 due to handling of lots of corner cases. */ 637 if (!st->mem) 706 707 /* Adding buffer_size to filt_len won't overflow here because filt_len 708 could be multiplied by sizeof(spx_word16_t) above. */ 709 min_alloc_size = st->filt_len-1 + st->buffer_size; 710 if (min_alloc_size > st->mem_alloc_size) 711 { 712 spx_word16_t *mem; 713 if (INT_MAX/sizeof(spx_word16_t)/st->nb_channels < min_alloc_size) 714 goto fail; 715 else if (!(mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*min_alloc_size * sizeof(*mem)))) 716 goto fail; 717 718 st->mem = mem; 719 st->mem_alloc_size = min_alloc_size; 720 } 721 if (!st->started) 638 722 { 639 723 spx_uint32_t 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++)643 st->mem[i] = 0;644 /*speex_warning("init filter");*/645 } else if (!st->started)646 {647 spx_uint32_t 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 724 for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) 651 725 st->mem[i] = 0; … … 653 727 } else if (st->filt_len > old_length) 654 728 { 655 spx_ int32_t i;729 spx_uint32_t i; 656 730 /* Increase the filter length */ 657 731 /*speex_warning("increase filter size");*/ 658 int old_alloc_size = st->mem_alloc_size; 659 if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size) 732 for (i=st->nb_channels;i--;) 660 733 { 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)); 663 } 664 for (i=st->nb_channels-1;i>=0;i--) 665 { 666 spx_int32_t j; 734 spx_uint32_t j; 667 735 spx_uint32_t olen = old_length; 668 736 /*if (st->magic_samples[i])*/ 669 737 { 670 738 /* Try and remove the magic samples as if nothing had happened */ 671 739 672 740 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ 673 741 olen = old_length + 2*st->magic_samples[i]; 674 for (j=old_length- 2+st->magic_samples[i];j>=0;j--)742 for (j=old_length-1+st->magic_samples[i];j--;) 675 743 st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; 676 744 for (j=0;j<st->magic_samples[i];j++) … … 713 781 } 714 782 } 715 783 return RESAMPLER_ERR_SUCCESS; 784 785 fail: 786 st->resampler_ptr = resampler_basic_zero; 787 /* st->mem may still contain consumed input samples for the filter. 788 Restore filt_len so that filt_len - 1 still points to the position after 789 the last of these samples. */ 790 st->filt_len = old_length; 791 return RESAMPLER_ERR_ALLOC_FAILED; 716 792 } 717 793 … … 723 799 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) 724 800 { 725 spx_uint32_t i;726 801 SpeexResamplerState *st; 727 if (quality > 10 || quality < 0) 802 int filter_err; 803 804 if (nb_channels == 0 || ratio_num == 0 || ratio_den == 0 || quality > 10 || quality < 0) 728 805 { 729 806 if (err) … … 732 809 } 733 810 st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); 811 if (!st) 812 { 813 if (err) 814 *err = RESAMPLER_ERR_ALLOC_FAILED; 815 return NULL; 816 } 734 817 st->initialised = 0; 735 818 st->started = 0; … … 744 827 st->mem = 0; 745 828 st->resampler_ptr = 0; 746 829 747 830 st->cutoff = 1.f; 748 831 st->nb_channels = nb_channels; 749 832 st->in_stride = 1; 750 833 st->out_stride = 1; 751 752 #ifdef FIXED_POINT 834 753 835 st->buffer_size = 160; 754 #else 755 st->buffer_size = 160; 756 #endif 757 836 758 837 /* Per channel data */ 759 st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); 760 st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); 761 st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); 762 for (i=0;i<nb_channels;i++) 763 { 764 st->last_sample[i] = 0; 765 st->magic_samples[i] = 0; 766 st->samp_frac_num[i] = 0; 767 } 838 if (!(st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t)))) 839 goto fail; 840 if (!(st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)))) 841 goto fail; 842 if (!(st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)))) 843 goto fail; 768 844 769 845 speex_resampler_set_quality(st, quality); 770 846 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); 771 847 772 773 update_filter(st); 774 775 st->initialised = 1; 848 filter_err = update_filter(st); 849 if (filter_err == RESAMPLER_ERR_SUCCESS) 850 { 851 st->initialised = 1; 852 } else { 853 speex_resampler_destroy(st); 854 st = NULL; 855 } 776 856 if (err) 777 *err = RESAMPLER_ERR_SUCCESS;857 *err = filter_err; 778 858 779 859 return st; 860 861 fail: 862 if (err) 863 *err = RESAMPLER_ERR_ALLOC_FAILED; 864 speex_resampler_destroy(st); 865 return NULL; 780 866 } 781 867 … … 797 883 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 798 884 spx_uint32_t ilen; 799 885 800 886 st->started = 1; 801 887 802 888 /* Call the right resampler through the function ptr */ 803 889 out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len); 804 890 805 891 if (st->last_sample[channel_index] < (spx_int32_t)*in_len) 806 892 *in_len = st->last_sample[channel_index]; 807 893 *out_len = out_sample; 808 894 st->last_sample[channel_index] -= *in_len; 809 895 810 896 ilen = *in_len; 811 897 … … 820 906 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 821 907 const int N = st->filt_len; 822 908 823 909 speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len); 824 910 825 911 st->magic_samples[channel_index] -= tmp_in_len; 826 912 827 913 /* If we couldn't process all "magic" input samples, save the rest for next time */ 828 914 if (st->magic_samples[channel_index]) … … 850 936 const int istride = st->in_stride; 851 937 852 if (st->magic_samples[channel_index]) 938 if (st->magic_samples[channel_index]) 853 939 olen -= speex_resampler_magic(st, channel_index, &out, olen); 854 940 if (! st->magic_samples[channel_index]) { … … 856 942 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; 857 943 spx_uint32_t ochunk = olen; 858 944 859 945 if (in) { 860 946 for(j=0;j<ichunk;++j) … … 874 960 *in_len -= ilen; 875 961 *out_len -= olen; 876 return RESAMPLER_ERR_SUCCESS;962 return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 877 963 } 878 964 … … 892 978 #ifdef VAR_ARRAYS 893 979 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); 980 spx_word16_t ystack[ylen]; 896 981 #else 897 982 const unsigned int ylen = FIXED_STACK_ALLOC; … … 900 985 901 986 st->out_stride = 1; 902 987 903 988 while (ilen && olen) { 904 989 spx_word16_t *y = ystack; … … 937 1022 out[j*ostride_save] = WORD2INT(ystack[j]); 938 1023 #endif 939 1024 940 1025 ilen -= ichunk; 941 1026 olen -= ochunk; … … 948 1033 *out_len -= olen; 949 1034 950 return RESAMPLER_ERR_SUCCESS;1035 return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 951 1036 } 952 1037 … … 955 1040 spx_uint32_t i; 956 1041 int istride_save, ostride_save; 957 spx_uint32_t bak_len = *out_len; 1042 spx_uint32_t bak_out_len = *out_len; 1043 spx_uint32_t bak_in_len = *in_len; 958 1044 istride_save = st->in_stride; 959 1045 ostride_save = st->out_stride; … … 961 1047 for (i=0;i<st->nb_channels;i++) 962 1048 { 963 *out_len = bak_len; 1049 *out_len = bak_out_len; 1050 *in_len = bak_in_len; 964 1051 if (in != NULL) 965 1052 speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); … … 969 1056 st->in_stride = istride_save; 970 1057 st->out_stride = ostride_save; 971 return RESAMPLER_ERR_SUCCESS;972 } 973 1058 return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 1059 } 1060 974 1061 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) 975 1062 { 976 1063 spx_uint32_t i; 977 1064 int istride_save, ostride_save; 978 spx_uint32_t bak_len = *out_len; 1065 spx_uint32_t bak_out_len = *out_len; 1066 spx_uint32_t bak_in_len = *in_len; 979 1067 istride_save = st->in_stride; 980 1068 ostride_save = st->out_stride; … … 982 1070 for (i=0;i<st->nb_channels;i++) 983 1071 { 984 *out_len = bak_len; 1072 *out_len = bak_out_len; 1073 *in_len = bak_in_len; 985 1074 if (in != NULL) 986 1075 speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); … … 990 1079 st->in_stride = istride_save; 991 1080 st->out_stride = ostride_save; 992 return RESAMPLER_ERR_SUCCESS;1081 return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 993 1082 } 994 1083 … … 1002 1091 *in_rate = st->in_rate; 1003 1092 *out_rate = st->out_rate; 1093 } 1094 1095 static inline spx_uint32_t compute_gcd(spx_uint32_t a, spx_uint32_t b) 1096 { 1097 while (b != 0) 1098 { 1099 spx_uint32_t temp = a; 1100 1101 a = b; 1102 b = temp % b; 1103 } 1104 return a; 1004 1105 } 1005 1106 … … 1009 1110 spx_uint32_t old_den; 1010 1111 spx_uint32_t i; 1112 1113 if (ratio_num == 0 || ratio_den == 0) 1114 return RESAMPLER_ERR_INVALID_ARG; 1115 1011 1116 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) 1012 1117 return RESAMPLER_ERR_SUCCESS; 1013 1118 1014 1119 old_den = st->den_rate; 1015 1120 st->in_rate = in_rate; … … 1017 1122 st->num_rate = ratio_num; 1018 1123 st->den_rate = ratio_den; 1019 /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ 1020 for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) 1021 { 1022 while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) 1023 { 1024 st->num_rate /= fact; 1025 st->den_rate /= fact; 1026 } 1027 } 1028 1124 1125 fact = compute_gcd(st->num_rate, st->den_rate); 1126 1127 st->num_rate /= fact; 1128 st->den_rate /= fact; 1129 1029 1130 if (old_den > 0) 1030 1131 { 1031 1132 for (i=0;i<st->nb_channels;i++) 1032 1133 { 1033 st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; 1134 if (multiply_frac(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS) 1135 return RESAMPLER_ERR_OVERFLOW; 1034 1136 /* Safety net */ 1035 1137 if (st->samp_frac_num[i] >= st->den_rate) … … 1037 1139 } 1038 1140 } 1039 1141 1040 1142 if (st->initialised) 1041 update_filter(st);1143 return update_filter(st); 1042 1144 return RESAMPLER_ERR_SUCCESS; 1043 1145 } … … 1057 1159 st->quality = quality; 1058 1160 if (st->initialised) 1059 update_filter(st);1161 return update_filter(st); 1060 1162 return RESAMPLER_ERR_SUCCESS; 1061 1163 } … … 1107 1209 { 1108 1210 spx_uint32_t i; 1211 for (i=0;i<st->nb_channels;i++) 1212 { 1213 st->last_sample[i] = 0; 1214 st->magic_samples[i] = 0; 1215 st->samp_frac_num[i] = 0; 1216 } 1109 1217 for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 1110 1218 st->mem[i] = 0; -
pjproject/trunk/third_party/speex/libspeex/resample_sse.h
r2002 r6129 10 10 modification, are permitted provided that the following conditions 11 11 are met: 12 12 13 13 - Redistributions of source code must retain the above copyright 14 14 notice, this list of conditions and the following disclaimer. 15 15 16 16 - Redistributions in binary form must reproduce the above copyright 17 17 notice, this list of conditions and the following disclaimer in the 18 18 documentation and/or other materials provided with the distribution. 19 19 20 20 - Neither the name of the Xiph.org Foundation nor the names of its 21 21 contributors may be used to endorse or promote products derived from 22 22 this software without specific prior written permission. 23 23 24 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 25 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT … … 72 72 } 73 73 74 #ifdef _USE_SSE274 #ifdef USE_SSE2 75 75 #include <emmintrin.h> 76 76 #define OVERRIDE_INNER_PRODUCT_DOUBLE … … 92 92 sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); 93 93 } 94 sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128)sum));94 sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum)); 95 95 _mm_store_sd(&ret, sum); 96 96 return ret; … … 121 121 sum2 = _mm_mul_pd(f2, sum2); 122 122 sum = _mm_add_pd(sum1, sum2); 123 sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128)sum));123 sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum)); 124 124 _mm_store_sd(&ret, sum); 125 125 return ret; -
pjproject/trunk/third_party/speex/libspeex/scal.c
r2002 r6129 52 52 #include <math.h> 53 53 #include <stdlib.h> 54 55 #ifndef M_PI 56 #define M_PI 3.14159265358979323846 /* pi */ 57 #endif 54 58 55 59 #define ALLPASS_ORDER 20 … … 172 176 173 177 x = buff+st->frame_size; 174 beta = 1.-.3*amount*amount;175 178 if (amount>1) 176 179 beta = 1-sqrt(.4*amount);
Note: See TracChangeset
for help on using the changeset viewer.