Hi there,
CCS5.5
C5515EVM
VoLib_2_1_0_1 CPU3
I am trying to get ECU worked but it always stop cancelling echo after 30 - 60 second. For testing purposes I am using ECU demo tracks(Sin and Rin) which come from PC to the board. Frames are synchronized and there is no delay between them.
Within 30-60 sec it is working well, even better than I expected but after that time Sout is just a copy of Sin.
My code:
#define SIU_MAX_FRAME_LENGTH DMA_BUFFER_SIZE // 10ms maximum frame duration */ #define SIU_MAX_ECU_FILTER_LENGTH 1024 // 128ms tail search filter #define SIU_MAX_ECU_FLTSEG 3 // Maximum of 3 individual filter segments #define SIU_MAX_ECU_FLTSEG_LENGTH 256 // 32ms total BG filter coefficients #define SIU_MAX_SYSTEM_DELAY 120 // 15ms maximum system delay between Rout/Sin
#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 #define ecu_SEARCH_FILTER_BUF 14
ecuContext_t ecuContext = {
(vfnptr) my_exception, //NULL,
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,
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;
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 tst_ecu_new(int chan) {
tint stat, ecuNbufs;
const ecomemBuffer_t *bufs;
tst_ecu_inst[chan].ecu_Inst = NULL;
stat = ecuGetSizes(&ecuNbufs, &bufs, (void *) NULL);
if (stat != ecu_NOERR) {
return stat;
}
if((tst_ecu_inst[chan].ecu_buffers = (ecomemBuffer_t*) calloc(ecuNbufs, sizeof(ecomemBuffer_t))) == NULL)
{
printf("no memory\n");
}
vheap = mhmCreate(siu_voice_heap, SIU_VOICE_HEAP_SIZE, 0);
ecu_set_buffer(bufs, tst_ecu_inst[chan].ecu_buffers, ecuNbufs, chan);
tst_ecu_inst[chan].ecuCfgNew.ID = siuMakeID (SIU_MID_ECU, chan);
stat = ecuNew(&(tst_ecu_inst[chan].ecu_Inst), ecuNbufs, tst_ecu_inst[chan].ecu_buffers, &(tst_ecu_inst[chan].ecuCfgNew));
if (stat != ecu_NOERR) {
ecu_init_result = stat;
// return stat;
printf("ecuNew fail\n");
}
return 0;
}
int tst_ecu_open(int chan) {
ecuConfigParam_t cfgParam;
tst_ecu_inst[chan].ecuCfg.cfgParam = &cfgParam;
tst_ecu_inst[chan].ecuCfg.samples_per_frame = 10 * 8; /* 10ms default frame duration */
tst_ecu_inst[chan].ecuCfg.pcm_zero = (0x55D5);// A-law zero: 0x55D5, U-law zero: 0xFFFF
tst_ecu_inst[chan].ecuCfg.pcm_expand_tbl = &muaTblAlaw[0];//NULL
cfgParam.filter_length = SIU_MAX_ECU_FILTER_LENGTH; /* 128ms default ECU tail */
cfgParam.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;
cfgParam.config_bitfield1 = 0;
cfgParam.noise_level = 0; /* Use default (-70) if fixed */
cfgParam.nlp_aggress = 0; /* balance performance */
cfgParam.cn_config = 0; /* pink noise */
ecuOpen(tst_ecu_inst[chan].ecu_Inst, &(tst_ecu_inst[chan].ecuCfg));
}
/* Compress A-law delay line samples */
muaTblAlawCmpr (DMA_BUFFER_SIZE, rinLinearPING_prt, rinCompr_prt);
/* Pack samples for delay line compression */
for (i=0; i<DMA_BUFFER_SIZE; i++) {
rinBuffer[i] = rinCompr[i] & 0xFF;
}
ecuSendIn(tst_ecu_inst[0].ecu_Inst, sinBufferPING_prt, rinBuffer_prt, soutBufferPING_prt);
Thank you.



