Changeset 4728 for pjproject/trunk/pjmedia/src/pjmedia/echo_suppress.c
- Timestamp:
- Feb 4, 2014 10:13:56 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/echo_suppress.c
r4713 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include <pjmedia/types.h> … … 78 78 #if 0 79 79 # define TRACE_(expr) PJ_LOG(5,expr) 80 81 static const char *state_names[] = 82 { 83 "Null", 84 "local talking", 85 "remote silent", 86 "doubletalk", 87 "remote talking" 88 }; 89 80 90 #else 81 91 # define TRACE_(expr) … … 126 136 } talk_state_t; 127 137 128 static const char *state_names[] =129 {130 "Null",131 "local talking",132 "remote silent",133 "doubletalk",134 "remote talking"135 };136 137 138 138 139 /* Description: 139 140 140 141 The echo suppressor tries to find the position of echoed signal by looking 141 at the correlation between signal played to the speaker (played signal) 142 at the correlation between signal played to the speaker (played signal) 142 143 and the signal captured from the microphone (recorded signal). 143 144 144 To do this, it first divides the frames (from mic and speaker) into 145 To do this, it first divides the frames (from mic and speaker) into 145 146 segments, calculate the audio level of the segment, and save the level 146 147 information in the playback and record history (play_hist and rec_hist … … 151 152 152 153 The record history size is as large as the template size (tmpl_cnt), since 153 we will use the record history as the template to find the best matching 154 we will use the record history as the template to find the best matching 154 155 position in the playback history. 155 156 … … 188 189 similar) the signal is. The correlation value is done over the template 189 190 duration. 190 - the gain scaling factor, that is the ratio between mic signal and 191 - the gain scaling factor, that is the ratio between mic signal and 191 192 speaker signal. The ES calculates both the minimum and average ratios. 192 193 … … 210 211 Processing: 211 212 212 Once learning is done, the ES will change the level of the mic signal 213 Once learning is done, the ES will change the level of the mic signal 213 214 depending on the state of the conversation and according to the ratio that 214 215 has been found in the learning phase above. … … 264 265 265 266 /* 266 * Create. 267 * Create. 267 268 */ 268 269 PJ_DEF(pj_status_t) echo_supp_create( pj_pool_t *pool, … … 293 294 ec->play_hist_cnt = (pj_uint16_t)(ec->tail_cnt+ec->templ_cnt); 294 295 295 ec->max_calc = (pj_uint16_t)(MAX_CALC_DURATION_SEC * clock_rate / 296 ec->max_calc = (pj_uint16_t)(MAX_CALC_DURATION_SEC * clock_rate / 296 297 ec->samples_per_segment); 297 298 298 ec->rec_hist = (pj_uint16_t*) 299 ec->rec_hist = (pj_uint16_t*) 299 300 pj_pool_alloc(pool, ec->templ_cnt * 300 301 sizeof(ec->rec_hist[0])); 301 302 302 303 /* Note: play history has twice number of elements */ 303 ec->play_hist = (pj_uint16_t*) 304 ec->play_hist = (pj_uint16_t*) 304 305 pj_pool_alloc(pool, ec->play_hist_cnt * 305 306 sizeof(ec->play_hist[0])); 306 307 307 308 ec->corr_sum = (float*) 308 pj_pool_alloc(pool, ec->tail_cnt * 309 pj_pool_alloc(pool, ec->tail_cnt * 309 310 sizeof(ec->corr_sum[0])); 310 311 ec->tmp_corr = (float*) 311 pj_pool_alloc(pool, ec->tail_cnt * 312 pj_pool_alloc(pool, ec->tail_cnt * 312 313 sizeof(ec->tmp_corr[0])); 313 314 ec->min_factor = (float*) 314 pj_pool_alloc(pool, ec->tail_cnt * 315 pj_pool_alloc(pool, ec->tail_cnt * 315 316 sizeof(ec->min_factor[0])); 316 317 ec->avg_factor = (float*) 317 pj_pool_alloc(pool, ec->tail_cnt * 318 pj_pool_alloc(pool, ec->tail_cnt * 318 319 sizeof(ec->avg_factor[0])); 319 320 ec->tmp_factor = (float*) 320 pj_pool_alloc(pool, ec->tail_cnt * 321 pj_pool_alloc(pool, ec->tail_cnt * 321 322 sizeof(ec->tmp_factor[0])); 322 323 echo_supp_reset(ec); … … 328 329 329 330 /* 330 * Destroy. 331 * Destroy. 331 332 */ 332 333 PJ_DEF(pj_status_t) echo_supp_destroy(void *state) … … 394 395 395 396 /* Set state */ 396 static void echo_supp_set_state(echo_supp *ec, talk_state_t state, 397 static void echo_supp_set_state(echo_supp *ec, talk_state_t state, 397 398 unsigned level) 398 399 { … … 400 401 401 402 if (state != ec->talk_state) { 402 TRACE_((THIS_FILE, "[%03d.%03d] %s --> %s, level=%u", 403 (ec->update_cnt * SEGMENT_PTIME / 1000), 403 TRACE_((THIS_FILE, "[%03d.%03d] %s --> %s, level=%u", 404 (ec->update_cnt * SEGMENT_PTIME / 1000), 404 405 ((ec->update_cnt * SEGMENT_PTIME) % 1000), 405 406 state_names[ec->talk_state], … … 470 471 } else { 471 472 /* Update from previous calculation */ 472 ec->sum_rec_level = ec->sum_rec_level - old_rec_frm_level + 473 ec->sum_rec_level = ec->sum_rec_level - old_rec_frm_level + 473 474 ec->rec_hist[ec->templ_cnt-1]; 474 ec->rec_corr = ec->rec_corr - ((float)ec->rec_hist[0] / 475 ec->rec_corr = ec->rec_corr - ((float)ec->rec_hist[0] / 475 476 old_rec_frm_level) + 476 477 ((float)ec->rec_hist[ec->templ_cnt-1] / … … 483 484 * to detect echo. 484 485 */ 485 /* 486 * First phase: do full calculation for the first position 486 /* 487 * First phase: do full calculation for the first position 487 488 */ 488 489 if (ec->sum_play_level0 == 0) { … … 501 502 } else { 502 503 /* Update from previous calculation */ 503 ec->sum_play_level0 = ec->sum_play_level0 - old_play_frm_level + 504 ec->sum_play_level0 = ec->sum_play_level0 - old_play_frm_level + 504 505 ec->play_hist[ec->templ_cnt-1]; 505 ec->play_corr0 = ec->play_corr0 - ((float)ec->play_hist[0] / 506 ec->play_corr0 = ec->play_corr0 - ((float)ec->play_hist[0] / 506 507 old_play_frm_level) + 507 508 ((float)ec->play_hist[ec->templ_cnt-1] / … … 585 586 if (ec->tmp_factor[i] < ec->min_factor[i]) 586 587 ec->min_factor[i] = ec->tmp_factor[i]; 587 ec->avg_factor[i] = ((ec->avg_factor[i] * ec->tail_cnt) + 588 ec->avg_factor[i] = ((ec->avg_factor[i] * ec->tail_cnt) + 588 589 ec->tmp_factor[i]) / 589 590 (ec->tail_cnt + 1); … … 610 611 iavg = (int)(ec->avg_factor[ec->tail_index] * 1000); 611 612 612 PJ_LOG(4,(THIS_FILE, 613 PJ_LOG(4,(THIS_FILE, 613 614 "Echo suppressor updated at t=%03d.%03ds, echo tail=%d msec" 614 615 ", factor min/avg=%d.%03d/%d.%03d", … … 634 635 iavg = (int)(ec->avg_factor[ec->tail_index] * 1000); 635 636 636 PJ_LOG(4,(THIS_FILE, 637 PJ_LOG(4,(THIS_FILE, 637 638 "Echo suppressor learning done at t=%03d.%03ds, tail=%d ms" 638 639 ", factor min/avg=%d.%03d/%d.%03d", … … 647 648 648 649 /* Amplify frame */ 649 static void amplify_frame(pj_int16_t *frm, unsigned length, 650 static void amplify_frame(pj_int16_t *frm, unsigned length, 650 651 pj_ufloat_t factor) 651 652 { … … 657 658 } 658 659 659 /* 660 /* 660 661 * Perform echo cancellation. 661 662 */ … … 710 711 * if remote user is currently talking 711 712 */ 712 for (i=ec->play_hist_cnt -lookup_cnt -tail_cnt; 713 i<ec->play_hist_cnt-tail_cnt; ++i) 713 for (i=ec->play_hist_cnt -lookup_cnt -tail_cnt; 714 i<ec->play_hist_cnt-tail_cnt; ++i) 714 715 { 715 716 if (ec->play_hist[i] > play_level) … … 733 734 } else { 734 735 /* Speaker is active, but we've picked up large signal in 735 * the microphone. Assume that this is an echo, so bring 736 * the microphone. Assume that this is an echo, so bring 736 737 * the level down to minimum too. 737 738 */ … … 763 764 764 765 /* Amplify frame */ 765 amplify_frame(rec_frm, ec->samples_per_frame, 766 amplify_frame(rec_frm, ec->samples_per_frame, 766 767 pj_ufloat_from_float(factor)); 767 768 ec->last_factor = factor; … … 775 776 776 777 /* Accumulate average echo residue to see the ES effectiveness */ 777 ec->residue = ((ec->residue * ec->running_cnt) + level) / 778 ec->residue = ((ec->residue * ec->running_cnt) + level) / 778 779 (ec->running_cnt + 1); 779 780
Note: See TracChangeset
for help on using the changeset viewer.