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.

Help getting ECU in VoLIB to work



I am attempting to get the ECU module in the VoLIB to work on TMS320C6A8168 processor.

But it does not seem to work.
I feel like ECU buffer problems.
I want to consult on how to initialize the ECU module(ECU buffer).
Or give me some suggestions to make the ECU work properly.

Here I write some code:


#define siuMakeID(mid,chnum) ((tuint)(mid)<<8|(tuint)(chnum))

#define SIU_MAX_FRAME_LENGTH 80 /* 10ms maximum frame duration */
#define SIU_MAX_ECU_FILTER_LENGTH 1024 /* maximum echo tail in taps */
#define SIU_MAX_ECU_FLTSEG 3 /* maximum number of filter segments */
#define SIU_MAX_ECU_FLTSEG_LENGTH 256 /* maximum taps for all filter segments */
#define SIU_MAX_SYSTEM_DELAY 320 /* maximum extra system delay in samples */

#define SIU_VOICE_HEAP_SIZE 2048
tword siu_voice_heap[SIU_VOICE_HEAP_SIZE];

//void *cheap;
void *vheap;

/* Module ID's */
#define SIU_MID_SIU 0x01 /* SIU module */
#define SIU_MID_VCU 0x02 /* VCU module */
#define SIU_MID_VCA 0x03 /* VCA modules */
#define SIU_MID_PIU 0x04 /* PIU module */
#define SIU_MID_ECU 0x05 /* ECU module */
/* Buffer numbers. Ensure that these coincide with #defines in ecuinit.c */
#define ecu_FG_FLTSEG 1
#define ecu_BG_FLTSEG 2
#define ecu_BG_E_BUF 3
#define ecu_RECEIVE_IN 4
#define ecu_EXPAND_DL_BUF 5
#define ecu_BG_UPDATE_BUF 6

struct ecu_inst_params{
tuint ID;

void *ecu_Inst; /* Signal limiter Instance */
ecomemBuffer_t *ecu_buffers;
ecuConfig_t ecuCfg;
ecuControl_t ecuCtl;
ecuNewConfig_t ecuCfgNew;

tint ecu_rx_buffer[80];
tint ecu_tx_buffer[80];
tint ecu_ec_buffer[80];


};

struct ecu_inst_params ys_ecu_inst[64];


void my_exception(tuint _id, tuint _type, tuint _code, tuint _length, tuint *data)
{
System_printf("id: %x, type: %d, code: %d, len: %d", _id, _type, _code, _length);
}
ecuContext_t ecuContext = {
(vfnptr)my_exception,
NULL, /* Debug streaming function pointer */
NULL,
NULL, /* Search filter swapping function */
NULL,//ecu_send_out, /* Send out function pointer */
NULL,//piuReceiveIn, /* Receive out function pointer */
SIU_MAX_FRAME_LENGTH, /* Maximum number of samples per frame */
SIU_MAX_ECU_FILTER_LENGTH, /* Maximum filter length in taps */
SIU_MAX_ECU_FLTSEG_LENGTH, /* Maximum filter segment buffer length in taps */
SIU_MAX_ECU_FLTSEG, /* Maximum allowed active filter segments */
SIU_MAX_SYSTEM_DELAY + SIU_MAX_FRAME_LENGTH,
/* Maximum y2x delay in samples */
0L, /* Bitfield representing those portions of the
* delay line already expanded. */
NULL, /* Pointer to base of the scratch delay line */
NULL, /* TDM aligned pointer within scratch delay line */
NULL, /* TDM aligned pointer within packed delay line */
};

typedef struct {
Fract ecu_buf_1[512];
Fract ecu_buf_2[512];
linSample ecu_buf_3[80];
linSample ecu_buf_4[2048];
linSample ecu_buf_5[4096];
Fract ecu_buf_6[2048];

Fract ecu_buf_14[2048];
}ecu_buf_t;
ecu_buf_t ecu_buf[64];

void ecu_set_buffer(const ecomemBuffer_t *bufs, ecomemBuffer_t *ecuBufs, tint ecuNbufs, int inst_num)
{
int i;

for (i = 0; i < ecuNbufs; i++) {
ecuBufs[i] = bufs[i];
if (i == ecu_FG_FLTSEG) { /* FG Filter */
ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_1[0]);;
ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_1);
}
else if (i == ecu_BG_FLTSEG) { /* BG Filter */
ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_2[0]);;
ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_2);
}
else if (i == ecu_BG_E_BUF) { /* BG Error Buffer IRAM */
ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_3[0]);;
ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_3);
}

else if (i == ecu_RECEIVE_IN) { /* ECU's recv-in buffer is aligned! */
ecuBufs[i].volat = FALSE;
ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_4[0]);;
ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_4);
}
else if (i == ecu_EXPAND_DL_BUF) { /* ECU's recv-in buffer is aligned! */
ecuBufs[i].volat = TRUE;
ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_5[0]);;
ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_5);
}

else if (i == ecu_BG_UPDATE_BUF) { /* BG Work Buffer IRAM */
if (ecuBufs[i].size > 0) {
ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_6[0]);;
ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_6);

}
else { /* Float version may not use this buffer */
ecuBufs[i].base = NULL;
ecuBufs[i].size = 0;
}
}

else if (i == ecu_SEARCH_FILTER_BUF) { /* Search filter buffer IRAM */
ecuBufs[i].volat = FALSE;
ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_14[0]);;
ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_14);
}

else {
if (ecuBufs[i].size > 0) {
ecuBufs[i].volat = FALSE;
ecuBufs[i].base = (mhmAlloc (vheap, bufs[i].size));
}
else { /* no buffer allocated if size zero or less */
ecuBufs[i].base = NULL;
ecuBufs[i].size = 0;
}
}
}

}

int ys_ecu_new(int chan)
{
tint stat, ecuNbufs;
const ecomemBuffer_t *bufs;

stat = ecuGetSizes (&ecuNbufs, &bufs, (void *)NULL);
if (stat != ecu_NOERR) {
Log_print1(Diags_EXIT,"[+X] ecuGetSizes failed >return %d\n",stat);
return stat;
}

ys_ecu_inst[chan].ecu_buffers = (ecomemBuffer_t*)calloc (ecuNbufs,sizeof(ecomemBuffer_t));
if(ys_ecu_inst[chan].ecu_buffers == NULL) {
Log_print0(Diags_EXIT,"[+X] the ecu_buffers allocated failed \n");
return -1;
}
vheap = mhmCreate (siu_voice_heap, SIU_VOICE_HEAP_SIZE,0);
ecu_set_buffer(bufs, ys_ecu_inst[chan].ecu_buffers, ecuNbufs, chan);

ys_ecu_inst[chan].ecuCfgNew.ID = siuMakeID (SIU_MID_ECU, chan);
stat = ecuNew (&(ys_ecu_inst[chan].ecu_Inst), ecuNbufs, ys_ecu_inst[chan].ecu_buffers, &(ys_ecu_inst[chan].ecuCfgNew));

if (stat != ecu_NOERR) {
Log_print2(Diags_EXIT, "[+X] ecuNew %d failed > return %d\n", chan, stat);
return stat;
}

return 0;
}

int ys_ecu_open(int chan)
{
ecuConfigParam_t cfgParam;

ys_ecu_inst[chan].ecuCfg.cfgParam = &cfgParam;
ys_ecu_inst[chan].ecuCfg.y2x_delay = 40; /* One frame default y2x delay */
ys_ecu_inst[chan].ecuCfg.samples_per_frame = 10*8; /* 5ms default frame duration */
ys_ecu_inst[chan].ecuCfg.pcm_zero = 0;//(0x55D5);
ys_ecu_inst[chan].ecuCfg.pcm_expand_tbl = NULL;//&_a2lin[0];

cfgParam.filter_length = SIU_MAX_ECU_FILTER_LENGTH ; /* 128ms default ECU tail */
cfgParam.noise_level = 0; /* Use default (-70) if fixed */
cfgParam.config_bitfield = ecu_ENABLE_ECHO_CANCELLER | /* ENABLE ECU, ENABLE NLP, ENABLE UPDATE */
ecu_ENABLE_UPDATE |
ecu_ENABLE_NLP |
ecu_ENABLE_AUTO_UPDATE |
ecu_ENABLE_SEARCH |
ecu_ENABLE_CNG_ADAPT |
ecu_ENABLE_OPNLP_DETECT;
cfgParam.config_bitfield1 = ecu_ENABLE_NLP_PHASE_RND;
cfgParam.nlp_aggress = 0; /* balance performance */
cfgParam.cn_config = 0; /* pink noise */

ecuOpen (ys_ecu_inst[chan].ecu_Inst, &(ys_ecu_inst[chan].ecuCfg));

return 0;
}

int ecu_init()
{
int chan;
int res;
memset(ys_ecu_inst, 0, sizeof(struct ecu_inst_params) * 64);
for (chan=0; chan<64; chan++) {
res = ys_ecu_new(chan);
if(res != 0){
Log_print1(Diags_EXIT, "[+X] ys_ecu_new faild> return (0x%x)", res);
return res;
}

ys_ecu_open(chan);

return 0;
}

int ys_ecu_process(int chan, int codec, short* rx, short * tx, short * ec)
{
int i;

for(i = 0; i <80; i ++){
ys_ecu_inst[chan].ecu_rx_buffer[i] = rx[i];
ys_ecu_inst[chan].ecu_tx_buffer[i] = tx[i];
}

ecuSendIn(ys_ecu_inst[chan].ecu_Inst, ys_ecu_inst[chan].ecu_rx_buffer, ys_ecu_inst[chan].ecu_tx_buffer, ys_ecu_inst[chan].ecu_ec_buffer);

for(i = 0; i <80; i ++){
ec[i] =ys_ecu_inst[chan].ecu_ec_buffer[i];
}

return 0;
}

  • Hi Caspar,

     

    I should be able to help with this.  First off -- a few questions in case we can't fix this quick:

    • What is the specific problem you are seeing?
    • What ECU (or VoLIB) version are you using?

    I quickly reviewed the code you provided and I suspect one problem is that you're not packing the TX (to TDM) samples before passing to the ECU.  Since the ECU offered in VoLIB has been compiled with delay line compression enabled, it expects packed PCM for input to the delay line.  That is, the PCM samples should be compressed (see muaTblUlawCmpr & muaTblAlawCmpr in the "util" component), then packed two samples per 16-bit entity (tint, in this case).  The packing should be performed in little-endian format (always).

    Let me know if this helps.

    Regards,
    Charlie

     

     

     

  • Hi  Charlie

    Volib version is 2.0.3  and ECU version is  10.92.0.3.

    I  don't   use Code Composer Studio.

    Ezsdk  version is 5.02  and bios version  is  6.32.01.38.

    The code seems to be working - with the exception that the echo canceller is not cancelling the echo.

    I have a few questions:

          1. The  Volib and ECU support  C64x  DSPs.    Can  C674x  DSPs   be supported ?

          2.  In  chapter 5 of  ECU  Users Manual (Version 1.10),  "Table 15. Buffer placement strategy"  tells  the buffer  palcement.

    No

    Buffer

    SA/DA RAM

    Static/Scratch

    Requirement

    1

    FG_FILTER

    SARAM

    Static

    Different bank from 2

    2

    RX_BUF

    DARAM

    Static

    None

    3

    BG_FILTER

    SARAM

    Static

    Different bank from 2,4

    4

    BG_UPDATE_BUF

    SARAM

    Scratch

    Different bank from 2,3

    5

    SRCH_FILTER

    SARAM

    Static

    Different bank from 2,4

    6

    Stack

    Different bank from 2

               Should  I strictly accoding to the  Buffer placement strategy ?

                I think that  buffers  placement  is designed to save MIPS  and it can't effect  the  echo canceller. 

          3.   I  don't  use CCS  and I don't  know how to  place  the above buffers  in different  segment  or bank.

          4.   I   don't konw whether  I  correctly  packed my companded  transmitted data before I fed it into the algorithm.

                The original data  is  a-Law format.

                I  tested two  ways:

                First: 

                vsend_in = 80 samples, 16-bit linear data,  near end received data

                vrecv_in  =  80 samples, packed u-Law audio, near end transmitted data

                vsend_out = buffer for 80 samples, 16-bit linear data. Should be echo removed.

                Second:

                vsend_in = 80 samples, 16-bit linear data,  near end received data

                vrecv_in  =  80 samples, 16-bit linear data, near end transmitted data

                vsend_out = buffer for 80 samples, 16-bit linear data. Should be echo removed.

               Finally,  the ECU can't  cancel  echo anyway.

               Please  suggest me  how the format should  be packed.

    Thanks,

    Caspar

              

  • Hi Caspar,

    Answers and comments to your questions follow:

    Caspar Cai said:
      
    1. The Volib and ECU support  C64x  DSPs.    Can  C674x  DSPs   be supported ?

    1. Yes, the C64x+ libraries will execute on the C674x DSP core.  From the "TMS320C674x DSP Megamodule Reference Guide" (sprufk5a) -- "The C674x CPU combines support of the C64x+ DSP and C67x+ DSP instruction sets. The C674x devices are object code compatible with the C64x+ and C67x+ devices."

    Caspar Cai said:
      
    In chapter 5 of  ECU  Users Manual (Version 1.10),  "Table 15. Buffer placement strategy"  tells  the buffer  palcement. ...

    2. Correct, the buffer placement strategy serves (served)  to avoid bank conflicts in C54x/C55x devices and has become less important as cache has been used increasingly.  We can ignore this for now and revisit once the ECU is working to ensure your MIPS are optimal.

    Caspar Cai said:
     
    3.  I don't use CCS and I don't  know how to  place  the above buffers  in different  segment  or bank

    3. We can revisit once the ECU is working properly.

    Caspar Cai said:
     
    4.  I don't konw whether  I  correctly  packed my companded  transmitted data before I fed it into the algorithm.

    4. I've placed some code below to illustrate how to pack the PCM data for the call to ecuSendIn()

        linSample sinBuffer[80];
        linSample soutBuffer[80];
        linSample rinLinear[80];
        tint      rinCompr[80];
        tword     rinBuffer[80];
        tint length = 80;
        tint i;
       
        /* Compress A-law delay line samples */
        muaTblAlawCmpr (length, rinLinear, rinCompr);

        /* Pack samples for delay line compression */
        for (i=0; i<length; i++) {
          rinBuffer[i] = rinCompr[i] & 0xFF;
        }

        /* ECU send-path processing */
        ecuSendIn (inst, (void *) sinBuffer, (void *) rinBuffer, (void *) soutBuffer);
       
       
    I have a few questions as well:

    1.  How are you modelling the echo path?
    2.  Can you attach your Rin and Sin samples?

    Regards,
    Charlie

     

  • Hi  Charlie,

    The echo path and Rin/Sin samples  are  OK.  Because  AER (another  echo  cancel  library)  can  work  well  and the  echo can be removed by AER.

    According to your code about packing the PCM data,  the  echo canceller is  still  not cancelling the echo.

     I have a few questions as well:

    1. I use GetFilter()  to  see the coefficients.  While the code is running, I can see that the Foreground/Background  Filter segment coefficients are not updating.  All the   Foreground  Filter segment coefficients  are 0.   I  don't konw that  whether  data  is  put into the Far-end expanded delay line.

        Why  aer  the Foreground  Filter segment coefficients   0 ?

  • Hi Caspar,

    Caspar Cai said:

    The echo path and Rin/Sin samples  are  OK.  Because  AER (another  echo  cancel  library)  can  work  well  and the  echo can be removed by AER.

    Are you referring to TI's Acoustic echo canceller or a third-part Line echo canceller?  If, by AER, you mean the acoustic echo canceller -- then it's not safe to assume that our line echo canceller can handle similar echo paths.  There are many reasons for this, of which the two most prominent are:

    • The AER can easily handle negative ERLs - the ECU will only handle 6dB ERL unless explicitly configured for 0dB or 3dB
    • The AER has a default tail length of 200ms while the ECU is configurable up to 128ms

    If you provide the input I can analyze and confirm whether our ECU should be cancelling the echo.  I was one of the primary contributors to the development of the ECU and can help resolve this quickly if I know what the input is.

    It's difficult to guess why the ECU is not passing the BG coefficients to the FG filter when I'm not sure what the input is.  It could be due to constant doubletalk, ERL below 6dB, non-linear echo path, configuration, incorrectly configured Y-to-X delay, etc, etc, etc. 

    I can verify your configuration and gleen some information regarding ECU functionality if you have implemented the ecuGetPerformance() API in your code and can provide its output after the ECU has attempted to cancel echo (see echo.h). 

    Regards,
    Charlie

     

  • Hi Charlie,

    The  input files: 8231.Rx_Tx_pcm.rar

    The values in my ecuContext are:

    Samples Per Frame = 80

    Max Filter Length = 1024

    Search Filter Length = 1024

    Max Filter Segment Length = 256

    Max y2x delay = 120

    The config in my Open are:

    ecuCfg.cfgParam                       =  &configParam;
     ecuCfg.y2x_delay                     =  20;      /* One frame default y2x delay */
    ecuCfg.samples_per_frame    =  80;      /* 5ms default frame duration */
    ecuCfg.pcm_zero                       =  0x55D5;
     ecuCfg.pcm_expand_tbl         =  &muaTblAlaw[0];

    configParam.filter_length        = 1024;   // 128 Millisecond tail


      configParam.config_bitfield  =  ecu_ENABLE_ECHO_CANCELLER |
                    ecu_ENABLE_UPDATE         |
                    ecu_ENABLE_NLP            |
                    ecu_ENABLE_AUTO_UPDATE    |
                    ecu_ENABLE_SEARCH         ;
       configParam.config_bitfield1 =0 ;

       configParam.noise_level      = 0 ;  /* Use default (-70) if fixed */
       configParam.nlp_aggress      = 0 ;   /* Balance Performance */
        configParam.cn_config        = 0;   /* 0 = pink noise, 0x7fff = white noise, 0x3fff mix of each */

    The buffer allocate:

    void ecu_set_buffer(const ecomemBuffer_t *bufs, ecomemBuffer_t *ecuBufs, tint ecuNbufs, int inst_num)
    {
        int i;
        for (i = 0; i < ecuNbufs; i++) {
            ecuBufs[i]       = bufs[i];
            if(ecuBufs[i].size > 0){
                if(i == 5){
                     ecuBufs[i].base  = (void *)MEM_calloc(0, 4096, 1 << ecuBufs[i].log2align );
                     ecuBufs[i].size  = 4096;
                }
                else        
                     ecuBufs[i].base  = (void *)MEM_calloc(0, ecuBufs[i].size, 1 << ecuBufs[i].log2align );
            }
        }
    }

    The  ecuSendIn() called:

    int  ecu_process(int chan)
    {
        char i=0;
        tint      rinCompr[80];
        tword     rinBuffer[80];
        muaTblAlawCmpr (80, ecu_tx_buffer, rinCompr);
        for (i=0; i<80; i++)  
                  rinBuffer[i] = rinCompr[i] & 0xFF;
        ecuSendIn(ecu_Inst, ecu_rx_buffer, rinBuffer, ecu_ec_buffer);

    The ecuGetPerformance()  return result:

    state_bf: ffff824c       niose_x: 0       noise_y: 0       rerl: 127       tail_len: 1024        rustat: 0


    ecuPerform.Px:33932208    ecuPerform.Py: 667812    ecuPerform.Pe: 38076     ecuPerform.erlest: 0     ecuPerform.acomest: 0


    ustat.attempt_update:147        ustat.attempt_search: 2        ustat.erle_bypass: 0    ustat.xtone_bypass: 145      ustat.other_bypass: 0
    ustat.xidle: 1                               ustat.double_talk: 33             ustat.dt_cps: 0              ustat.dt_cpt: 0                         ustat.nlp: 249
    ustat.divergence: 0                   ustat.srch_divergence: 0       ustat.fg_switch: 28       ustat.bg_switch: 0                 ustat.openloop_found: 0
    ustat.numseg_change: 0        ustat.segment_change: 0      ustat.converge_exit: 0  ustat. txbssat_events: 0       ustat. rxbssat_events: 0

    ......

     ecuPerform.Px:44786412           ecuPerform.Py: 667812          ecuPerform.Pe: 24270          ecuPerform.erlest: 0          ecuPerform.acomest: 0


    ustat. attempt_update:149            ustat. attempt_search: 2         ustat.erle_bypass: 0              ustat.xtone_bypass: 147   ustat.other_bypass: 0
    ustat.xidle: 1                                    ustat.double_talk: 33               ustat.dt_cps: 0                        ustat.dt_cpt: 0                      ustat.nlp: 253
     ustat.divergence: 0                       ustat.srch_divergence: 0         ustat.fg_switch: 29                ustat.bg_switch: 0               ustat.openloop_found: 0
     ustat.numseg_change: 0             ustat.segment_change: 0        ustat.converge_exit: 0         ustat.txbssat_events: 0      ustat.rxbssat_events: 0

    ......

    When ecu_ENABLE_NLP is enabled, the vsend_out  become mute and  vsend_out   buffer  data are 0.

    When ecu_ENABLE_NLP is disabled, the ECU  can't  cancel echo .

    Regards,

    Caspar



       

  • Hi Caspar,

    Caspar Cai said:

    The input files: 8231.Rx_Tx_pcm.rar

    This appears to be a musical recording and its corresponding echo.  While the NLP will probably handle this, music and tones in general respresent one of the more difficult operating scenarios for an echo canceller due to their narrowband nature.  I would suggest starting with a simple voice example to begin with.  Once you're sure the ECU is working properly, then you can experiment with various difficult conditions (of which music is one).


    Caspar Cai said:

    The values in my ecuContext are:
    Samples Per Frame         = 80
    Max Filter Length         = 1024
    Search Filter Length      = 1024
    Max Filter Segment Length = 256
    Max y2x delay             = 120

    Following are the ECU context member variables and suggested settings:
    max_samples_per_frame   = 80    // 10ms frames
    max_filter_length       = 1024  // 128ms search filter
    max_filter_seg_length   = 256   // 32ms total BG filter coefficients
    max_filter_seg_count    = 3     // Maximum of 3 individual filter segments
    max_y2x_delay           = 120   // 15ms maximum system delay between Rout/Sin


    Caspar Cai said:

    The config in my Open are:
    ecuCfg.cfgParam              = &configParam;
    ecuCfg.y2x_delay             = 20;      /* One frame default y2x delay */
    ecuCfg.samples_per_frame     = 80;      /* 5ms default frame duration */
    ecuCfg.pcm_zero              = 0x55D5;
    ecuCfg.pcm_expand_tbl        = &muaTblAlaw[0];
    configParam.filter_length    = 1024;   // 128 Millisecond tail
    configParam.config_bitfield  = ecu_ENABLE_ECHO_CANCELLER |
                                   ecu_ENABLE_UPDATE         |
                                   ecu_ENABLE_NLP            |
                                   ecu_ENABLE_AUTO_UPDATE    |
                                   ecu_ENABLE_SEARCH;
    configParam.config_bitfield1 = 0;
    configParam.noise_level      = 0;   /* Use default (-70) if fixed */
    configParam.nlp_aggress      = 0;   /* Balance Performance */
    configParam.cn_config        = 0;   /* 0 = pink noise, 0x7fff = white noise, 0x3fff mix of each */

    You may consider making the following minor changes until you feel comfortable
    with the ECU operation:
    // Start off with 0 to ensure causality, adjust once everything is working to
    // preserve entire 128ms tail  
    ecuCfg.y2x_delay = 0; 
    // Enable adaptive CNG level, 4-wire detection and clear all filters before use
    configParam.config_bitfield  = ecu_ENABLE_ECHO_CANCELLER  |
                                   ecu_ENABLE_UPDATE          |
                                   ecu_ENABLE_NLP             |
                                   ecu_ENABLE_AUTO_UPDATE     |
                                   ecu_ENABLE_SEARCH          |
                                   ecu_ENABLE_CNG_ADAPT       |
                                   ecu_ENABLE_OPNLP_DETECT    |
                                   ecu_CLEAR_FG               |
                                   ecu_CLEAR_BG               |
                                   ecu_CLEAR_SEARCH;

    To summarize, try a single-talk speech file and set the Y-to-X delay to zero then
    retest.  This will help ensure that your integration and configuration are correct
    and that the samples the ECU receives represent a causal system.  You can move on
    to more difficult speech, noise, etc. scenarios once everything is working.
                                  
    Regards,
    Charlie

                                    

      

  • Hi  Charlie,

    I try a single-talk speech file , but  ECU can't cancel any  echo. I also try  sine wave file , unlucky, the result  is same.

    I think that  configuration is  OK.  What other things should  considered ?  Whether buffer  allocation is right or not ?

  • Hi Caspar,

    Are you testing a single channel or multiple channels?  I would suggest starting with a single channel (if you aren't already) to simplify the problem.

    It also appears that you are checking the output from ecuGetSizes() and ecu New().  This implies that all buffer sizes and alignment properties are valid.  However, when I look at the structure from which you allocate, it suggests that buffer 5 wouldn't have proper alignment.  What address do you see for:

    ecuContext->rxout_buf_base

    Regards,
    Charlie

     

  • Hi  Charlie,

    I  have tested a single channel.  The ecuContext->rxout_buf_base   address  is 0xB7136000.

    One  questions:

    1. The buffer are  allocated  by  static array  or  MEM_alloc()  function.  Can  echo   be  processed  by the two different  buffer allocation ? 

  • Hi Caspar,

    Yes, the ECU should be able to handle any buffer location as long as the alignment and size are correct.  Buffer locations should only affect the efficiency (MIPS).

    Do you have the ability to capture the three ECU input/output buffers synchronously?  If so, could you attach three files (one per buffer) so I can compare input/output and analyze the echo path?  This would be best for the single-talk example you mentioned in an earlier post.

    Also, the ECU statistics from ecuGetPerformance() at the end of the input would be helpful.

    Regards,
    Charlie

     

  • Hi Charlie,

    The three samples files:

    4760.ecu_samples.rar

    The  sample  files are  mono, 16-bit  PCM samples(a  sample  per 16-bit).

    The NLP is disabled.  Sample_length is 40  and  delay line compressed  is not  enabled.  Even if the delay line compressed is enabled, the result  is same.

    I  can get the output of  ecuGetPerformance(),  but  I  don't  konw how to analyze the value.

    Regards,

    Charlie

  • Hi Caspar,

    Based on my response to your previous post, can you run this again using packed PCM input (since delay line compression is always enabled), and share the synchronized inputs and output?

    Regards,

    Charlie

  • Hi Charlie,

    I  have tried to pack  PCM and not pack PCM. The result is same.  The soutBuffer  is same as sinBuffer.  It means that  echo canceller  don't  cancel any echo.

    The sinBuffer, rinBuffer and soutBuffer:

    6675.in_out_Buffer.rar

    The values in my configuration are:

    Samples Per Frame = 80

    Max Filter Length = 1024

    The config in my Open are:

     ecuCfg.pcm_zero            =  0x55D5;
     ecuCfg.pcm_expand_tbl        =  &muaTblAlaw[0];

      configParam.filter_length    = 1024;  
      configParam.config_bitfield  =  ecu_ENABLE_ECHO_CANCELLER |  ecu_ENABLE_UPDATE  | ecu_ENABLE_AUTO_UPDATE  | ecu_ENABLE_SEARCH ;
      configParam.config_bitfield1 =0 ;

    A few question:

    1.   I  get  the output  of  ecuGetFilter(), but  the  FG filter  coefficients  is  0,  so  echo  can't be cancelled. But BG filter coefficients  are  updated.

           I   get the data  in Foreground filter segment  buffer(BUFFER  1), the  all  data  don't  be  updated.

           The data  in Background filter segment  buffer(BUFFER  2)  can  be updated. 

    2.    I  get the data in Far-end delay line  buffer (BUFFER 4)  and Far-end expanded delay line  buffer (BUFFER 5),  but  I don't  konw  whether  the data is right or not ?

    3.    The data in Background error signal buffer (BUFFER 3)   can be updated,  it means that  filter  incorrectly  run ?

  • Hi Charlie,

    I  see the BG  filter coefficients  can be updated  but  FG  filter coefficients  is 0.

    It  is possible that  rinBuffer(TX path)   data  don't  be  stored  in Far-end delay  buffer  and  Far-end expanded delay  line buffer.

    It  is also  possible that  data in Far-end delay  buffer  and  Far-end expanded delay  line buffer    is   incorrect.

    After  ecuSendIn( ) is called,  I print  the  data in  Far-end delay  buffer  and Far-end expanded delay  line buffer.

    I found the data  in Far-end expanded delay  line buffer is strange.

      The data:  u-law, 40 samples per frame

    ......

    Far-end delay  buffer:

    255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
    255 255 255 255 255 255 255 255 255 255 255 169 155 148 144 144 147 154 167 219

    Far-end expanded delay  line buffe:

     0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124
     0 -32124 0 -32124 0 -32124 5628 -32124 10364 -32124 13948 -32124 15996 -32124 15996 -32124 14460 -32124 10876 -32124

    .....

    Far-end delay  buffer:

    43 28 20 16 15 19 25 37 77 173 156 149 144 143 146 153 164 197 47 29
    21 16 15 18 24 34 62 179 158 150 145 143 145 151 160 186 55 31 23 17

    Far-end expanded delay  line buffer:

     -4092 -32124 -9340 -32124 -13436 -32124 -15996 -32124 -16764 -32124 -14972 -32124 -11900 -32124 -7420 -32124 -2108 -32124 3516 -32124
     8828 -32124 12924 -32124 15484 -32124 16764 -32124 15484 -32124 12412 -32124 7932 -32124 2620 -32124 -3004 -32124 -8316 -32124

    ......

    I  found that  -32124  in a couple data.  "-32124"  stands  0 in u-law format.

    Whether  the data is wrong  in Far-end expanded delay  line buffer ?

  • Hi Tiger,

    It looks as though you are using either muaTblUlawCmpr() or something similar to compress the samples.  While this is the first step to create packed samples for the ECU "vrecv_in" buffer, the samples at this point are compressed, but still stored as the lower 8-bits of a 16-bit "tint".  This will produce the delay-line pattern you see since every other 8-bits, as read by the ECU, will be PCM zero.  You can achieve proper compression in the following manner:

        linSample rinLinear[N];
        tint      rinCompr[N];
        tword     rinBuffer[N];
        tint length = N;
        tint i;
       
        /* Compress U-law delay line samples */
        muaTblUlawCmpr (length, rinLinear, rinCompr);

        /* Pack samples for delay line compression */
        for (i=0; i<length; i++) {
          rinBuffer[i] = rinCompr[i] & 0xFF;
        }

    Note that "rinBuffer" is of type "tword".  This represents the atomic type on a platform (8-bits on C6000).

    Please let me know if this helps, I believe it will.

    Regards,
    Charlie

     

  • Hi Charlie,

    My  manner  is same as your manner.   I  see that  rinBuffer(tword, 8-bit)   have no PCM zero. But  data  in  Far-end expanded delay  line buffer   have  a  PCM zero  every  couple  samples.    I  think that  rinBuffer and   Far-end delay  buffer  are  correct.   The problem  is that  Far-end delay  buffer   is   expanded  to    Far-end expanded delay  line buffer. 

    u-law  compress:    muaTblUlawCmpr()

    u-law  expand:        pcm_zero            = 0xFFFF;    pcm_expand_tbl        =  &muaTblUlaw[0];

    The echo  is cancelled  by  comparing   the data  in sinBuffer  and Far-end expanded delay  line buffer.

    Far-end delay  buffer   is   expanded  to    Far-end expanded delay  line buffer  by &muaTblUlaw[0].  

    Can you explain  how  data is stored  in  Far-end expanded delay  line buffer ?

    Can you give me a example about  data in  Far-end delay  buffer  and Far-end expanded delay  line buffer ?

    I  don't  konw  how  ecuSendIn( )  to process the rinBuffer  and produce FG  filter coefficients. 

    Input (sinBuffer, rinBuffer)  and configuration  are  right .   The all  buffer is also allocated properly.

    Why   FG  filter coefficients is 0 and  Far-end expanded delay  line buffer is incorrect ?

  • Just to re-iterate what Charlie said. The Transmit buffer requires two samples to be packed into each single 16-bit word.

    Here is the code I used for the filling the transmit buffer.

                    ulaw1 = mulaw_compress( transmitData[ii]);
                    ulaw2 = mulaw_compress( transmitData[ii+1]);

                   tx_buffer[index] = ( ( ulaw1 << 8 ) & 0xff00 ) | ( ulaw2 & 0xff );

    Where mulaw_compress() converts a linear PCM sample into a mulaw sample.

  • Hi  Paul,

    I  tried  the way  what  you said,  but the result  is   unchanged.   All  FG  filter coefficients  is  still  0  and ECU’s search filter  buffer is also 0.

    ecuGetPerformance()  return  struct  ecuUpdateStat_t:

    attempt_update:1           attempt_search: 0        erle_bypass: 0         xtone_bypass: 1        other_bypass: 0

    xidle: 0                              double_talk: 0              dt_cps: 0                    dt_cpt: 0  nlp: 2          divergence: 0

    srch_divergence: 0        fg_switch: 0                   bg_switch: 0              openloop_found: 0   numseg_change: 0

    segment_change: 0       converge_exit: 0          txbssat_events: 0      rxbssat_events: 0

    When NLP  is enable,  the sout_buffer  is 0  whatever   data   is  in tx_buffer  and rx_buffer.

    I think that   buffer alloaction  is   incorrect, but  the buffer  align   and size  is right.  Moreover,  the ecuNew()  return  true.




  • Hi  Charlie,

    I  have  tried  the manner   you  said.   The  sout_buffer  is still same as  sin_buffer.  

    While the code is running, I can see that there is no data being put into the Far-end expanded delay line  and that the Foreground Filter segment coefficients are not updating.  

    I  see that  ecuContext.expand_ptr   is not   updating.   The value is always 0xB700409E  and ecuContext.rxout_buf_base  is 0xB7004000.

    The ecuContext.pack_ptr  is updating.

    Can you tell me  how   Far-end delay line  is  expanded   to   Far-end expanded delay line  by  pcm_expand_tbl ?

    I  have allocated all the memory as requested by the ecuGetSizes function and confirmed the correct  size and allignment on the memory blocks I pass into ecuNew.

    I  doubt   whether   ECU  is  compatible  with  C674  dsp  or  C6A816x  platform.  It  is possible that  a bug exist  when  ECU  is used  in  C674 or C6A816x platform.

    Regards,

    Tiger

  • This thread appears to be a duplicate of http://e2e.ti.com/support/embedded/bios/f/355/p/199331/716381.aspx#716381.  I am marking this as Answered with the understanding that the  other thread will continue.

    Dave

  • Hi CharlieF,

    I  can  run ECU  code in CCS  project. I new  a ccs project  and add my code to this project.  I  compare  output pcm flile with input file,  the echo can be cancelled.

    When I  add the same code to EZSDK,  the ECU can't cancel echo.  In EZSDK,  Codec Engine is used to call the ECU API  and process  voice data.

    The  voice data  are read from app part.,  then  codec part  get the data  to process.   In codec,  ECU APIs  are called.   Scale example  of  Codecs  is packed  to   call  ECU API.

    The EZSDK version  is 5.02.    CCS  version is 5.2.1.00018 .

    I  can see  the delay line  expand  buffer  data  is wrong  when I  set   rinBuffer(u law)  to 0xFF.

    delay line expand buffer:

        0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124
        0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124
        0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124
        0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124
        0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124
        0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124 0 -32124