Part Number: AM5728
Hi,
First, this might be considered as a repost. I am linking my former post below. I am posting this because previous post was kind of ignored.
I am trying to use VoLIB's ECU module in my application. I need to build an echo canceler unit on the C66 DSP. I have run the example under ti/mas/ecu/test and it has worked without any issues. I thought the test code was too complicated to integrate in the project so I have started for looking simpler examples on this forum. I have stumbled upon Stan Sidorov's post on this issue (link is provided below). I thought his code was a good starting point so I tried running it too.
I realize that Stan's example was running on C55 (for which tword is defined as uint16_t and linsample is defined as int16_t) and played with the types of my parameters. I have also tried two versions for coding the packed linear samples in big and little endian format. My code is given below.
The code is running OK, except it is not cancelling the echo. Sout is the same Sin.
Can you help me figure out the issue with my code?
I think the issue is here:
muaTblAlawCmpr (FRAME_SIZE, rin, rinCompr);
for (i=0; i<FRAME_SIZE; i++)
{
rinFinal[i] = 0;
}
/* Pack samples for delay line compression */
for (i=0, j = 0; i<FRAME_SIZE/2; i++)
{
rinFinal[i] = (((((uint16_t)rinCompr[j]) << 8) & 0xFF00) + (((uint16_t)rinCompr[j+1]) & 0x00FF));
j=j+2;
}
ecuSendIn(ecu_inst.ecu_Inst, sin, rinFinal, sout);
Entire Code:
/*
* ECU TEST PROJECT
*
* This project was designed to simplify ECU demo from VOLIB package
* and check ECU performance. In some cases code is obvious and there
* are some non-optimized functions and extra steps which make this
* example is easy to follow and understand. The results are absolutely
* the same as in ECU demo.
*
* Test environment:
* Picture with test environment is in the folder with audio files
*
* #define FILE_OUTDIR "c:/ti_projects/ECU_FROM_PC/vectors/"- just
* make sure you have the same path or change it on your own preference
*
* In general, the project can be run to any platform (checked on C55xx)
* because there is no any hardware dependencies. All files are being
* read and written by fread and fwrite functions.
*
* **NOTE**: you have to check data types. In my case(C55xx):
* tint - int (16bit)
* tword - unsigned int (16bit)
*
* **IMPORTANT**: Audio files are in A-law format (It is Fs-8000Hz, Res-16bit, A-law).
*
* I am using Cool Edit Pro or Abode Audition to edit audio files.
*
*
* Author: Stan Sidorov.
* CCS: 5.5
* Core: TMS320C5515
*
* If you have some questions related to this ECU test project, I can be contacted
* by email sidorov.stan@gmail.com
*
* Enjoy)
*
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ti/mas/util/ecomem.h>
#include <ti/mas/ecu/ecu.h>
#include <ti/mas/util/mua.h>
#include <ti/mas/vpe/pcm.h>
//..............................................................................
//..............................................................................
//..............................................................................
//******************************************************************************
// I/O
//******************************************************************************
//#define s90sec // Switch to 90 seconds audio files
#define FILE_OUTDIR "c:/Users/talha.uyar/workspace_v9/g729_ipc_encoder_aer_c66_v5_3/vectorsAlaw/" //
#ifndef s90sec
uint8_t printing = FALSE;
char *filename_sin = "sin.pcm";
char *filename_rin = "rin.pcm";
char *filename_sout = "sout.pcm";
char *filename_rout = "rout.pcm";
#define N_frames 1500 // 15sec track
#else
char *filename_sin = "sin90sec.pcm";
char *filename_rin = "rin90sec.pcm";
char *filename_sout = "sout90sec.pcm";
char *filename_rout = "rout90sec.pcm";
#define N_frames 9000 // 90sec track
#endif
char fstring_sin[128];
char fstring_rin[128];
char fstring_sout[128];
char fstring_rout[128];
FILE *file_sin;
FILE *file_rin;
FILE *file_sout;
FILE *file_rout;
//..............................................................................
//..............................................................................
//..............................................................................
//******************************************************************************
// API
//******************************************************************************
void *mhmCreate (void *base, tuint size, tword initPattern);
void *mhmAlloc (void *handle, tuint size);
void mhmFree (void *handle, void *base);
//..............................................................................
//..............................................................................
//..............................................................................
//******************************************************************************
// ECU DEFINITIONS
//******************************************************************************
#define SIU_VOICE_HEAP_SIZE 2048
tword siu_voice_heap[SIU_VOICE_HEAP_SIZE];
void *vheap;
#define siuMakeID(mid,chnum) ((tuint)(mid)<<8|(tuint)(chnum))
#define SIU_MID_ECU 0x05 // ECU module
//..............................................................................
//..............................................................................
//..............................................................................
#define FRAME_SIZE 80 // N of samples in the frame
#define SIU_MAX_FRAME_LENGTH FRAME_SIZE // 10ms maximum frame duration */
#define SIU_MAX_ECU_FILTER_LENGTH 256 // 1024 - 128 ms tail search filter
#define SIU_MAX_ECU_FLTSEG 3 // Maximum of 3 individual filter segments
#define SIU_MAX_ECU_FLTSEG_LENGTH 256 // 32 mS filter length
#define SIU_MAX_SYSTEM_DELAY 40 // maximum extra system delay in samples
#define IRAM_ECU_MAX_FLTSEG_LENGTH SIU_MAX_ECU_FLTSEG_LENGTH
#define IRAM_ECU_BLOCK_LENGTH SIU_MAX_SYSTEM_DELAY
#define IRAM_ECU_SRCH_FILTER_LENGTH SIU_MAX_ECU_FILTER_LENGTH
#define ecu_SIM_DLINE_SAMPLES_PER_WORD 2 // Delay line compression related
/* NOTE: The following limits the maximum frame size to 2 ECU blocks, (i.e., 10ms or 11ms)*/
#define ecu_DELAY_LINE_LENGTH (IRAM_ECU_SRCH_FILTER_LENGTH + 2*IRAM_ECU_BLOCK_LENGTH + SIU_MAX_SYSTEM_DELAY + SIU_MAX_FRAME_LENGTH)
#define IRAM_ECU_EXPAND_LENGTH (ecu_DELAY_LINE_LENGTH - IRAM_ECU_BLOCK_LENGTH)
#define IRAM_PIU_ECU_RECEIVE_LENGTH (ecu_DELAY_LINE_LENGTH/ecu_SIM_DLINE_SAMPLES_PER_WORD)
#define IRAM_ECU_BG_WORK_LENGTH IRAM_ECU_SRCH_FILTER_LENGTH /* changed from 8*/
/* 1024 for search filter length */
#define IRAM_ECU_BG_E_LENGTH IRAM_ECU_BLOCK_LENGTH /* linSample */
#define IRAM_ECU_BG_FLTSEG_LENGTH IRAM_ECU_MAX_FLTSEG_LENGTH /* Fract */
#define IRAM_ECU_FG_FLTSEG_LENGTH IRAM_ECU_MAX_FLTSEG_LENGTH /* Fract */
/* 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
#define ecu_SEARCH_FILTER_BUF 14
//..............................................................................
//..............................................................................
//..............................................................................
//..............................................................................
struct ecu_inst_params
{
void *ecu_Inst; /* Signal limiter Instance */
ecomemBuffer_t *ecu_buffers;
ecuConfig_t ecuCfg;
ecuControl_t ecuCtl;
ecuNewConfig_t ecuCfgNew;
};
struct ecu_inst_params ecu_inst;
void DebugInfo (tuint _id, tuint _type, tuint _code, tuint _length, tuint *_data)
{
printf("EXC-id:%x, Type: %d, Code: %d len:%d", _id, _type, _code,_length);
}
ecuContext_t ecuContext = {
(vfnptr) DebugInfo, /* Void function pointer to SIU exception handler */
NULL, /* Debug streaming function pointer */
NULL,
NULL, /* Search filter swapping function */
NULL, /* Send out function pointer */
NULL, /* 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 */
};
linSample ecu_pcm_expand[IRAM_ECU_EXPAND_LENGTH];//[2048];
tword piu_ecu_receive[IRAM_PIU_ECU_RECEIVE_LENGTH];
Fract ecu_srch_filter[IRAM_ECU_SRCH_FILTER_LENGTH];
Fract ecu_bg_work[IRAM_ECU_BG_WORK_LENGTH];
linSample ecu_bg_e[IRAM_ECU_BG_E_LENGTH];
Fract ecu_bg_filter[IRAM_ECU_BG_FLTSEG_LENGTH];
Fract ecu_fg_filter[IRAM_ECU_FG_FLTSEG_LENGTH];
typedef struct {
linSample *ecu_pcm_expand_ptr;
tword *piu_ecu_receive_ptr;
Fract *ecu_srch_filter_ptr;
Fract *ecu_bg_work_ptr;
linSample *ecu_bg_e_ptr;
Fract *ecu_bg_filter_ptr;
Fract *ecu_fg_filter_ptr;
} iramSeg_t;
iramSeg_t iramSeg;
iramSeg_t iramSeg = {
&ecu_pcm_expand[0],
&piu_ecu_receive[0],
&ecu_srch_filter[0],
&ecu_bg_work[0],
&ecu_bg_e[0],
&ecu_bg_filter[0],
&ecu_fg_filter[0]
};
//..............................................................................
//..............................................................................
//..............................................................................
//******************************************************************************
// FRAMEWORK BUFFERS
//******************************************************************************
linSample sin[FRAME_SIZE];
linSample rin[FRAME_SIZE];
linSample sout[FRAME_SIZE];
linSample rout[FRAME_SIZE];
tword scompr[FRAME_SIZE];
tword rcompr[FRAME_SIZE];
uint16_t rinFinal[FRAME_SIZE];
tint rinCompr[FRAME_SIZE];
//..............................................................................
//..............................................................................
//..............................................................................
//******************************************************************************
// ECU FUNCTIONS
//******************************************************************************
void ecu_set_buffer(const ecomemBuffer_t *bufs, ecomemBuffer_t *ecuBufs, tint ecuNbufs)
{
int i;
for (i = 0; i < ecuNbufs; i++)
{
ecuBufs[i] = bufs[i];
if (i == ecu_FG_FLTSEG)
{
/* FG Filter */
ecuBufs[i].base = iramSeg.ecu_fg_filter_ptr;
ecuBufs[i].size = IRAM_ECU_FG_FLTSEG_LENGTH*sizeof(Fract);
}
else if (i == ecu_BG_FLTSEG)
{
/* BG Filter */
ecuBufs[i].base = iramSeg.ecu_bg_filter_ptr;
ecuBufs[i].size = IRAM_ECU_BG_FLTSEG_LENGTH*sizeof(Fract);
}
else if (i == ecu_BG_E_BUF)
{
/* BG Error Buffer IRAM */
ecuBufs[i].base = iramSeg.ecu_bg_e_ptr;
ecuBufs[i].size = IRAM_ECU_BG_E_LENGTH*sizeof(linSample);
}
else if (i == ecu_RECEIVE_IN)
{
/* ECU's recv-in buffer is aligned! */
ecuBufs[i].volat = FALSE;
ecuBufs[i].base = iramSeg.piu_ecu_receive_ptr;
ecuBufs[i].size = IRAM_PIU_ECU_RECEIVE_LENGTH*sizeof(linSample);
}
else if (i == ecu_EXPAND_DL_BUF)
{
/* ECU's recv-in buffer is aligned! */
ecuBufs[i].volat = TRUE;
ecuBufs[i].base = iramSeg.ecu_pcm_expand_ptr;
ecuBufs[i].size = IRAM_ECU_EXPAND_LENGTH*sizeof(linSample);
}
else if (i == ecu_BG_UPDATE_BUF)
{
/* BG Work Buffer IRAM */
if (ecuBufs[i].size > 0)
{
ecuBufs[i].base = iramSeg.ecu_bg_work_ptr;
ecuBufs[i].size = IRAM_ECU_BG_WORK_LENGTH*sizeof(Fract);
}
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 = iramSeg.ecu_srch_filter_ptr;
ecuBufs[i].size = IRAM_ECU_SRCH_FILTER_LENGTH*sizeof(Fract);
}
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;
}
}
}
}
//..............................................................................
//..............................................................................
//..............................................................................
void ecu_new()
{
tint stat, ecuNbufs;
const ecomemBuffer_t *bufs;
ecu_inst.ecu_Inst = NULL;
stat = ecuGetSizes(&ecuNbufs, &bufs, (void *) NULL);
if (stat != ecu_NOERR) {
printf("ecuGetSizes fail\n");
}
if((ecu_inst.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, ecu_inst.ecu_buffers, ecuNbufs);
ecu_inst.ecuCfgNew.ID = siuMakeID (SIU_MID_ECU, 1);
stat = ecuNew(&(ecu_inst.ecu_Inst), ecuNbufs, ecu_inst.ecu_buffers, &(ecu_inst.ecuCfgNew));
if (stat != ecu_NOERR) {
// ecu_init_result = stat;
// return stat;
printf("ecuNew fail\n");
}
// return 0;
}
//..............................................................................
//..............................................................................
//..............................................................................
void ecu_open()
{
ecuConfigParam_t cfgParam;
ecu_inst.ecuCfg.cfgParam = &cfgParam;
// Start off with 0 to ensure causality, adjust once everything is working to
// preserve entire 128ms tail
ecu_inst.ecuCfg.y2x_delay = 0; /* One frame default y2x delay */
ecu_inst.ecuCfg.samples_per_frame = 10 * 8; /* 10ms default frame duration */
ecu_inst.ecuCfg.pcm_zero = (0x55D5);// A-law zero:0x55D5 , U-law zero:0xFFFF
ecu_inst.ecuCfg.pcm_expand_tbl = &muaTblAlaw[0];// &muaTblUlaw[0];//&;//muaTblAlaw
cfgParam.filter_length = SIU_MAX_ECU_FILTER_LENGTH; /* 128ms default ECU tail */
// Enable adaptive CNG level, 4-wire detection and clear all filters before use
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 ;
cfgParam.config_bitfield1 = ecu_ENABLE_NLP_PHASE_RND;
cfgParam.noise_level = 0; /* Use default (-70) if fixed */
cfgParam.nlp_aggress = 0; /* balance performance */
cfgParam.cn_config = 0; /* pink noise */
ecuOpen(ecu_inst.ecu_Inst, &(ecu_inst.ecuCfg));
}
ecu_init()
{
ecu_inst.ecu_Inst = NULL;
memset(ecu_inst.ecu_buffers, 0, sizeof(ecu_inst.ecu_buffers));
ecu_new();
ecu_open();
}
tsize i,j, frame_count, progress_count, progress_sec;
int main(void)
{
printf("ECU START SIMULATION\n");
ecu_init();
/* Open and prepare files */
strcpy (fstring_sin, FILE_OUTDIR);
strcat (fstring_sin, filename_sin);
if((file_sin = fopen (fstring_sin, "rb")) == NULL)
{
printf("Error in opening file sin.\n");
exit(1);
}
//..............................................................................
//..............................................................................
strcpy (fstring_rin, FILE_OUTDIR);
strcat (fstring_rin, filename_rin);
if((file_rin = fopen (fstring_rin, "rb")) == NULL)
{
printf("Error in opening file rin.\n");
exit(1);
}
//..............................................................................
//..............................................................................
strcpy (fstring_sout, FILE_OUTDIR);
strcat (fstring_sout, filename_sout);
if((file_sout = fopen (fstring_sout, "w")) == NULL)
{
printf("Error in opening file sout.\n");
exit(1);
};
//..............................................................................
//..............................................................................
strcpy (fstring_rout, FILE_OUTDIR);
strcat (fstring_rout, filename_rout);
if((file_rout = fopen (fstring_rout, "w")) == NULL)
{
printf("Error in opening file rout.\n");
exit(1);
};
printf("Files are opened\n");
progress_count = 0;
progress_sec = 0;
for (i=0; i<FRAME_SIZE; i++)
{
sin[i] = 0;
rin[i] = 0;
sout[i] = 0;
rout[i] = 0;
scompr[i] = 0;
rcompr[i] = 0;
rinCompr[i] = 0;
rinFinal[i] = 0;
}
// FRAMEWORK and ECU
for(frame_count = 0; frame_count < N_frames; frame_count++) // N of frames = duration(sec)/Frame(sec)
{
fread (scompr, 1, FRAME_SIZE, file_sin); // read 1 frame Sin
fread (rcompr, 1, FRAME_SIZE, file_rin); // read 1 frame Rin
pcmAlawDecoder(scompr, sin, FRAME_SIZE); // SIN expand a-law frame to linSample
pcmAlawDecoder(rcompr, rin, FRAME_SIZE); // RIN expand a-law frame to linSample
//..............................................................................
// ABOVE this line Sin and Rin are linSample
//..............................................................................
/* Compress A-law delay line samples */
muaTblAlawCmpr (FRAME_SIZE, rin, rinCompr);
for (i=0; i<FRAME_SIZE; i++)
{
rinFinal[i] = 0;
}
/* Pack samples for delay line compression */
for (i=0, j = 0; i<FRAME_SIZE/2; i++)
{
rinFinal[i] = (((((uint16_t)rinCompr[j]) << 8) & 0xFF00) + (((uint16_t)rinCompr[j+1]) & 0x00FF));
j=j+2;
}
ecuSendIn(ecu_inst.ecu_Inst, sin, rinFinal, sout);
pcmAlawEncoder(sout, scompr, FRAME_SIZE); // Compressing to a-law
fwrite ((void *) scompr, 1, FRAME_SIZE, file_sout); // Write frame to the file
fwrite ((void *) rcompr, 1, FRAME_SIZE, file_rout); // Write frame to the file
if(++progress_count == 100) // Progress counter
{
progress_sec++;
printf("Progress: %d seconds\n", progress_sec);
progress_count = 0;
}
}
fclose(file_sin);
fclose(file_rin);
fclose(file_sout);
fclose(file_rout);
printf("Files are closed\n");
while(1);
}
Link to Stan Sidorov's post: https://e2e.ti.com/support/processors/f/791/t/391242
Link to previous post: https://e2e.ti.com/support/processors/f/791/t/970969
Edit: I have worked on my code a little more and now I can see that inputs of ecuSendIn() function are the same as the test project. Maybe there was something wrong with my configuration.