This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Acoustic Echo cancelllation for DM365

Hi All,

    I just downloaded the AEC code for the DM365.  I compiled and ran the test app ant it seems to run fine. Now I would integrate this echo canceller in my application but it is not very clear from the documentation how to use the library.

Looking this

http://processors.wiki.ti.com/index.php/DM365_Audio_Codecs_Integration_with_DVSDK_2.10.01.18_Demos

the AEC should be enabled on the CE but differently from the audio codecs, it is not clear how to enable, configure and use it. My impression is that this way is still under development and I have to link the static library ignoring the CE and XDC. Can someone confirm this? I wonder is someone has already tried to integrate this AEC in his application.

 

 

  • I was able to make the AEC working.

    1) add this to the cfg file

    var AEC = xdc.useModule('ittiam.codecs.aec.ce.AEC');

    var Engine = xdc.useModule('ti.sdo.ce.Engine');
    var myEngine = Engine.create("enginename", [
        {name: "jpegenc", mod: JPEGENC, local: true, groupId: 1},  
        {name: "jpegdec", mod: JPEGDEC, local: true, groupId: 1}, 

    ....
        {name: "aec",     mod: AEC, local: true, groupId: 1}, 
    ]);
    algSettings = xdc.useModule('ti.sdo.ce.alg.Settings');
    algSettings.useCache = true;

    2) Follow the aec_ce_sapp.c in the aec_app directory.

    I splitted the processing function into 3 subfunctions:

    - aecInit()

    - aecProcess()   which takes far end and near end signals and gives an updated far end and the residual.

    - aecClose()

     

    The AEC is working for sure (mostly in half duplex, maybe because I have the ERL too low). I have to perform further tests to evaluate the performances of the algorithms.

     

  • 8360.aaec.rar

    hi,

    I'm trying to add AEC to dmai, see attached files.

    and I use it like below:

    ##########################################################################################

    Creation:

     AAec_Handle hAec    = NULL;
     AEC_ITTIAM_Params    AecParams;
     AEC_ITTIAM_DynamicParams AecDynParams;
     
     Buffer_Handle hFarEndBuf   = NULL;
     Buffer_Handle hNearEndBuf  = NULL;
     Buffer_Handle hResidueBuf  = NULL;
     Buffer_Handle hUpdatedFarEndBuf = NULL;

     if(envp->sampleRate > 16000)
     {
      __ERR("Aec only support samplerate less than 16K!!!\n");   
     }
     else
     {  
      AecParams.base.size = sizeof(AEC_ITTIAM_Params);
      AecDynParams.base.size = sizeof(AEC_ITTIAM_DynamicParams);
      
      AecParams.samp_freq    = envp->sampleRate;  /* sampling frequency for AEC in Hz  */
      AecParams.tail_length   = 2048*2;  /* X32 */
      AecParams.frame_length   = 256;//160*2;   /* X8, Number of samples to be processed  in this process call */
      AecParams.erle_thresh_level  = 36;      /* ERLE threshold for determining    */ 
      
      AecDynParams.inhibit_conv   = 0;
      AecDynParams.enable_nlp   = 1;
      AecDynParams.enable_cng   = 1;
      AecDynParams.enable_aec   = 1;  /* Enable/Disable AEC echo cancel    */
      AecDynParams.enable_tx_sat_det = 0;  /* 1:enable, 0:disable Tx saturation detector                          */
      AecDynParams.enable_rx_sat_det = 0;  /* 1:enable, 0:disable Rx saturation detector                          */
      AecDynParams.tx_sat_thresh  = 0;  /* Tx saturation detector thresh: Q0 */
      AecDynParams.rx_sat_thresh  = 0;  /* Rx saturation detector thresh: Q0 */
      AecDynParams.tx_digital_gain = 0;  /* Tx path digital gain applied within AEC, in 0.5dB steps, Q1 (dB)      */
      AecDynParams.rx_digital_gain = 0;  /* Rx path digital gain applied within AEC, in 0.5dB steps, Q1 (dB)      */
      AecDynParams.operating_mode  = 1;
       
      hAec = AAec_create(hEngine, &AecParams, &AecDynParams);
      if(hAec == NULL)
      {
       __ERR("Failed to create AEC!!!\n");   
       //cleanup(THREAD_FAILURE);
      }
      
      __ERR("create AEC OK!!!\n");
      
        hFarEndBuf = Buffer_create(AAec_getInBufSize(hAec,0), &bAttrs);
         if (hFarEndBuf == NULL)
      {
             __ERR("Failed to allocate hFarEndBuf.\n");
             cleanup(THREAD_FAILURE);
         }  
        
        hNearEndBuf = Buffer_create(AAec_getInBufSize(hAec,1), &bAttrs);
         if (hNearEndBuf == NULL)
      {
             __ERR("Failed to allocate hNearEndBuf.\n");
             cleanup(THREAD_FAILURE);
         }  
        
        hResidueBuf = Buffer_create(AAec_getOutBufSize(hAec,0), &bAttrs);
         if (hResidueBuf == NULL)
      {
             __ERR("Failed to allocate hResidueBuf.\n");
             cleanup(THREAD_FAILURE);
         }  
        
        hUpdatedFarEndBuf = Buffer_create(AAec_getOutBufSize(hAec,1), &bAttrs);
         if (hUpdatedFarEndBuf == NULL)
      {
             __ERR("Failed to allocate hUpdatedFarEndBuf.\n");
             cleanup(THREAD_FAILURE);
         }
        
         __ERR("create AEC 4 buffers OK!!!\n");             
     }

     

     

    Process:

    ...

           /* Read samples from the Sound device */
            if (Sound_read(hSound, hInBuf) < 0)
      {
                __ERR("Failed to read speech buffer\n");
                cleanup(THREAD_FAILURE);
      }


      if(hAec)
      {
       int blksize = 256*2;
       int count = 4096/blksize;
       int i;
       struct timeval t1,t2;
       int usetime;
       
       gettimeofday(&t1,NULL);
       
       for(i=0;i<count;i++)
       {
        memcpy(Buffer_getUserPtr(hFarEndBuf), Buffer_getUserPtr(hInBuf) + i*blksize, blksize);
        memset(Buffer_getUserPtr(hNearEndBuf), 0, blksize);     //just for test, should use the playing sound buffer
        Buffer_setNumBytesUsed(hFarEndBuf, blksize);
        Buffer_setNumBytesUsed(hNearEndBuf, blksize);
            
        if(Dmai_EOK != AAec_process(hAec, hFarEndBuf, hNearEndBuf, hResidueBuf, hUpdatedFarEndBuf))
        {     
         __ERR("Failed to do AEC process!!!\n"); 
         break;
        }
        
        memcpy(Buffer_getUserPtr(hInBuf) + i*blksize, Buffer_getUserPtr(hResidueBuf), blksize);    
       }
          
       gettimeofday(&t2, NULL);   
       usetime = (t2.tv_sec - t1.tv_sec)*1000 + (t2.tv_usec - t1.tv_usec)/1000;
       //__ERR("AEC use time: %d\n", usetime);
      }

    Problem:

    1. can we set  AecParams.frame_length   to a bigger one such as 4096, the size of our read buffer? I tried but this will cause AAec_create() fail.

    2. AEC will use a long time(more than 700ms) to handle one frame, it's unaccepable.

    3. I just want to adjust the readed sound buffer and then encode it, do I need to adjust the buffer to be played?

    Please give me some advice.

    Thank you.

    Regards,

    Johnny Ling