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.