⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ec.cc,v

📁 EC的语音编解码
💻 CC,V
字号:
head	1.6;access;symbols;locks; strict;comment	@// @;1.6date	97.01.06.00.24.42;	author ganapath;	state Exp;branches;next	1.5;1.5date	97.01.03.21.12.36;	author ganapath;	state Exp;branches;next	1.4;1.4date	96.12.28.04.20.49;	author ganapath;	state Exp;branches;next	1.3;1.3date	96.11.25.19.52.06;	author ganapath;	state Exp;branches;next	1.2;1.2date	96.11.05.17.20.25;	author ganapath;	state Exp;branches;next	1.1;1.1date	96.11.05.12.18.40;	author picone;	state Exp;branches;next	;desc@initial version.@1.6log@added a suppr_ceil parameter and a minimum db value.@text@// file: ec.cc//// system include files//#include <memory.h>#include <math.h>// local include files//#include "ec.h"#include "cb.h"#include "ec_constants.h"//-----------------------------------------------------------------------------//// public methods////-----------------------------------------------------------------------------//-----------------------------------------------------------------------------//// method: init_cc// description: initialization//// arguments: all user-controlled parameters related to the algorithm//// return: none//// this method initializes all internal parameters////-----------------------------------------------------------------------------void Echo_canceller::init_cc(double gamma, int N, int M, double beta1,			     double sigma_ly, double sigma_lu,			     double alpha_st, double alpha_yt, double cutoff,			     int hangt, double suppr, double tau) {  // reset parameters  //  gamma_d = gamma;  N_d = N;  M_d = M;  beta1_d = beta1;  beta2_d = beta1;  tau_d = tau;  start_speech_d = 0;  flag_d = 1;  sigma_Ly_d = sigma_ly;  sigma_Lu_d = sigma_lu;  alpha_st_d = alpha_st;  alpha_yt_d = alpha_yt;  CUTOFF_d = cutoff;  HANGT_d = hangt;  SUPPR_d = suppr;    // reset the high-pass filter  //  s_i_d = 0.0;  sdc_d = 0.0;  sdc_im1_d = 0.0;  // reset the circular buffers  //  y_d.allocate_cc(N_d + M_d);  s_d.allocate_cc(N_d + M_d);  u_d.allocate_cc(M_d);  e_d.allocate_cc(M_d);  // allocate a buffer for the reference signal power computation  //  y_tilde_d.allocate_cc(N_d);  // allocate coefficient memory  //  if (a_d != (double*)NULL)    {delete [] a_d;}  a_d = new double[N_d];  memset(a_d, (int)0, sizeof(double)*N_d);  // reset absolute time  //  i_d = (int)0;    // reset the power computations (for y and u)  //  Ly_d = CUTOFF_d;  Lu_d = 0.0;  // reset the near-end speech detector  //  s_tilde_d = 0.0;  HCNTR_d = (int)0;  // exit gracefully  //}//-----------------------------------------------------------------------------//// method: process_cc// description: processes one sample of data through the echo canceller//// arguments://  double ref: reference signal (outgoing speech)//  double sig: incoming signal (signal plus echo)//// return://  a double value containing the echo canceller output////-----------------------------------------------------------------------------double Echo_canceller::process_cc(double ref, double sig) {  // declare local variables that are used more than once  //  int k;  //***************************************************************************  //  // flow A on pg. 428  //  //***************************************************************************  // eq. (16): high-pass filter the input to generate the next value;  //           push the current value into the circular buffer  //  // sdc_im1_d = sdc_d;  // sdc_d = sig;  //  s_i_d = sdc_d;  //  s_d = s_i_d;  //  s_i_d = (double)(1.0 - gamma_d) * s_i_d  //    + (double)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d);    // push the reference data onto the circular buffer  //  y_d = ref;  s_d = sig;    // eq. (2): compute r  //  double r = 0;    for(k=0; k<N_d; k++) {    r += a_d[k] * (double)y_d(-k);  }    // eq. (3): compute the output value (see figure 3) and the error  // note: the error is the same as the output signal when near-end  // speech is not present  //  double u_suppr = (double)s_d - r;    e_d = u_d = u_suppr;    // eq. (12) and (13): update near-end speech detector  //  s_tilde_d = (1.0 - alpha_st_d) * s_tilde_d     + alpha_st_d * fabs((double)s_d);  y_tilde_d = (1.0 - alpha_yt_d) * (double)y_tilde_d     + alpha_st_d * fabs((double)y_d);    //***************************************************************************  //  // flow B on pg. 428  //  //***************************************************************************    // compute the new convergence factor  //  double Py = Ly_d * Ly_d;  if (HCNTR_d > 0){    Py = 1.0;  }    // Vary rate of adaptation depending on position in the file  // Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech  // has begun of the file to allow the echo cancellor to estimate the  // channel accurately  //  if ( start_speech_d != 0 ){    if ( i_d > (DEFAULT_T0 + start_speech_d)*(SAMPLE_FREQ) ){      beta2_d = max_cc(MIN_BETA,		       beta1_d * exp((-1/tau_d)*((i_d/(double)SAMPLE_FREQ) -						 DEFAULT_T0 -						 start_speech_d)));    }  }  else {beta2_d = beta1_d;}    double two_beta = beta2_d / Py;  if (two_beta > MAX_BETA)    {two_beta = MAX_BETA;}    // eq. (15): update power estimate of the return signal power  //  Lu_d = (1.0 - sigma_Lu_d) * Lu_d + sigma_Lu_d * fabs((double)u_d);    // eq. (10): update power estimate of the reference  //  Ly_d = (1.0 - sigma_Ly_d) * Ly_d + sigma_Ly_d * fabs((double)y_d);  if (Ly_d < CUTOFF_d)    {Ly_d = CUTOFF_d;}    // eq. (14): is there near-end speech?  //  double max_y_tilde = 0;  for (k=0; k<N_d; k++) {    if (max_y_tilde < y_tilde_d(-k))      {max_y_tilde = y_tilde_d(-k);}  }  if (s_tilde_d > (0.2*max_y_tilde))    {      HCNTR_d = HANGT_d;    }  else if (HCNTR_d > (int)0)    {      HCNTR_d--;    }  // update coefficients if no near-end speech  //  if ((HCNTR_d == 0) && (i_d % M_d == (int)0)){        // loop over all filter coefficients    //    for (k=0; k<N_d; k++) {            // eq. (7): compute an expectation over M_d samples       //      double grad = 0.0;            for (int m=0; m<M_d; m++)	{grad += (double)e_d(-m) * (double)y_d(-m-k);}            // eq. (7): update the coefficient      //      a_d[k] += two_beta * grad;    }  }  if ((flag_d == 1) && ((Ly_d/Lu_d) < pow((double)10.0,(ONSET_THRESH/10.0)))) {    start_speech_d = i_d/8000.0;    flag_d = 0;  }  // paragraph below eq. (15): if no near-end speech,  // check for residual error suppression  //  float  suppr_value = pow(10,SUPPR_d/10.0);  if ((HCNTR_d == 0) && ((Lu_d/Ly_d) < suppr_value) &&      ((10*log(Lu_d/Ly_d)) > EC_MIN_DB_VALUE)) {        float suppr_factor = (1/(float)(SUPPR_FLOOR-SUPPR_CEIL))*10*log(Lu_d/Ly_d)      - SUPPR_CEIL/(float)(SUPPR_FLOOR - SUPPR_CEIL);    u_suppr = pow(10.0,(suppr_factor)*RES_SUPR_FACTOR/10.0)*u_suppr;      }    // exit gracefully  //  i_d++;  return u_suppr;}//-----------------------------------------------------------------------------// method: constructor// description: creates an echo canceller object and initializes all buffers////-----------------------------------------------------------------------------Echo_canceller::Echo_canceller() {  // initialize coefficient memory  //  a_d = (double*)NULL;  // exit gracefully  //}Echo_canceller::~Echo_canceller() {    // free coefficient memory  //  delete [] a_d;  // exit gracefully  //}//-----------------------------------------------------------------------------//// method: max_cc// description: returns the maximum of two numbers (I hate macros!)////-----------------------------------------------------------------------------int Echo_canceller::max_cc(int x, int y) {  if (x > y)    {return x;}  else    {return y;}}double Echo_canceller::max_cc(double x, double y) {  if (x > y)    {return x;}  else    {return y;}}//-----------------------------------------------------------------------------//// method: clip_cc// description: clips a sample value to +/-MAX_AMPL////-----------------------------------------------------------------------------short int Echo_canceller::clip_cc(double value) {  // restore the range of value  //  value *= AMPL_SCALE_2;  // clip it to +/-AMPL_SCALE_2  //  if (value > AMPL_SCALE_2)    {return (short int)AMPL_SCALE_2;}  else if (value < -AMPL_SCALE_2)    {return (short int)-AMPL_SCALE_2;}  else    {return (short int)rint(value);}}@1.5log@*** empty log message ***@text@a209 6  /*    if ( i_d%500 == 0 ){    printf ( "%f %f\n", i_d/8000.0, s_tilde_d/max_y_tilde );  }  */    a255 6    /*    if ( i_d%500 == 0 ){      printf ( "%f %f %f %f\n", i_d/8000.0,10*log(Lu_d/Ly_d), suppr_factor, pow(10.0,(1-suppr_factor)*RES_SUPR_FACTOR/10.0) );    }    */    @1.4log@*** empty log message ***@text@d187 1a187 1d209 8a216 2    if (s_tilde_d > (0.5*max_y_tilde))d254 16a269 2  if ((HCNTR_d == 0) && ((Lu_d/Ly_d) < SUPPR_d)) {    u_suppr = pow(10.0,(RES_SUPR_FACTOR/10.0))*u_suppr;	@1.3log@corrected equation for u_suppr, changed onset_thresh to supr_factor.@text@d172 1a172 1d186 1a187 2  else {beta2_d = beta1_d;}  a209 1  d218 1a218 1  d221 1a221 1  if ((HCNTR_d == 0) && (i_d % M_d == (int)0)) {d239 1a239 1  d244 1a244 1  d248 2a249 2  if ((HCNTR_d == (int)0) && ((Lu_d/Ly_d) < SUPPR_d)) {    u_suppr = pow(10.0,(RES_SUPR_FACTOR/10.0))*ref;@1.2log@no changes made in algorithm. only cosmetic changes.@text@d251 1a251 1    u_suppr = pow(10.0,2*(ONSET_THRESH/10.0))*ref;@1.1log@Initial revision@text@a12 1d186 2a187 3  else {    beta2_d = beta1_d;  }d210 1a210 1d242 2a243 2  if ( (flag_d == 1) && ((Ly_d/Lu_d) < pow((double)10.0,(ONSET_THRESH/10.0)))){    start_speech_d = i_d /8000.0;d246 1a246 1d250 3a252 4  if ((HCNTR_d == (int)0) && (Lu_d/Ly_d) < SUPPR_d)     {      u_suppr = pow(10.0,2*(ONSET_THRESH/10.0))*ref;    }@

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -