Changeset 6129 for pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c
- Timestamp:
- Jan 9, 2020 9:05:50 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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;
Note: See TracChangeset
for help on using the changeset viewer.