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.

ECU (VoLIB) stop working after 30-60 sec

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.

  • I made it worked but it needs to be explained. Actually I put ecuControl function after ecuSendIn being called. The crucial thing is clearing any buffer or all (BG, FG or SEARCH).

    void tst_ecu_control(int chan)
    {
    tst_ecu_inst[chan].ecuCtl.ctl_code = ecu_CTL_MASK;
    tst_ecu_inst[chan].ecuCtl.u.ctl_mask[0] = 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 |
    // ecu_CLEAR_FG ;// |
    // ecu_CLEAR_BG;// |
    ecu_CLEAR_SEARCH;


    ecuControl (tst_ecu_inst[chan].ecu_Inst, &(tst_ecu_inst[chan].ecuCtl));
    }
    But why it does not work without clearing buffers? I thought it is ECU responsibility to update buffers.



    Thanks
  • Does TI support VoLib now or not?

  • Sorry about the delay. The support team is out for the holiday. I will follow up after the holiday.
    Regards.
  • Hi Steve,

    Thank you for the update.

  • Hi Stan,

    It is true that the BG, FG and SEARCH buffers are updated by ECU, and not expected to have ecuControl function to clear these buffers . In the case that if echo has been successfully cancelled for 30-60 seconds, the ECU initialiation and control bits in ecuControl seems have been setup properly. Have you verified the lower layer PCM data driver of receiving/sending data, i.e. if you diable ECU, are you always able to get Sout/Rout as Sin/Rin? There are a lot of buffer allocation discussion in the thread http://e2e.ti.com/support/embedded/tirtos/f/355/t/299040#pi239031349=2 : ECU (VoLIB 2.1.0.1) crashes when running on multiple channels in real time, but root cause was DMA/MCSBSP configuration. Also, is echo path changed in the Rin/Sin signal after 30-60 seconds? The Rin/Sin in the VoLIB is 15 seconds only, can you post your Rin/Sin and Rout/Sout signals here captured on EVM?

    Regards, Garrett

  • Hi Garrett,

    Thanks for your reply.

    Have you verified the lower layer PCM data driver of receiving/sending data, i.e. if you diable ECU, are you always able to get Sout/Rout as Sin/Rin?

    Ans. Yes. When I disable ECU and use memcpy to copy signal  from Sin to Sout and from Rin to Rout I can hear music, voice or DTMF tones without being corrupted.

    Also, is echo path changed in the Rin/Sin signal after 30-60 seconds?

    Ans. No. All pachs are always the same. See picture. I am using audio files which were provided with demo.

    Can you post your Rin/Sin and Rout/Sout signals here captured on EVM?

    Ans. Will do.

    I changed the code trying to reproduce ECU performance like in demo. So C-file is attached. 

    //******************************************************************************
    //                                 DMA
    //******************************************************************************
    #define DMA_BUFFER_SIZE 80
    //==============================================================================
    //								Input part.
    //==============================================================================
    Uint16   			DMAinChannel_L = 4; // DMA1 connected to I2S2
    
    #pragma DATA_ALIGN (DmaPingDstInBufLeftCh, 2)
    linSample DmaPingDstInBufLeftCh[DMA_BUFFER_SIZE];	// IN left
    #pragma DATA_ALIGN (DmaPongDstInBufLeftCh, 2)
    linSample DmaPongDstInBufLeftCh[DMA_BUFFER_SIZE];
    
    Uint16   			DMAinChannel_R = 6; // DMA1 connected to I2S2
    
    #pragma DATA_ALIGN (DmaPingDstInBufRightCh, 2)
    linSample DmaPingDstInBufRightCh[DMA_BUFFER_SIZE];	// IN right
    #pragma DATA_ALIGN (DmaPongDstInBufRightCh, 2)
    linSample DmaPongDstInBufRightCh[DMA_BUFFER_SIZE];
    
    
    //==============================================================================
    //								Output part.
    //==============================================================================
    Uint16   			DMAoutChannel_L = 5; // DMA1 connected to I2S2
    
    #pragma DATA_ALIGN (DmaPingOutBufLeftCh, 2)
    linSample DmaPingOutBufLeftCh[DMA_BUFFER_SIZE];
    #pragma DATA_ALIGN (DmaPongOutBufLeftCh, 2)
    linSample DmaPongOutBufLeftCh[DMA_BUFFER_SIZE];
    
    
    Uint16   			DMAoutChannel_R = 7; // DMA1 connected to I2S2
    
    #pragma DATA_ALIGN (DmaPingOutBufRightCh, 2)
    linSample DmaPingOutBufRightCh[DMA_BUFFER_SIZE];
    #pragma DATA_ALIGN (DmaPongOutBufRightCh, 2)
    linSample DmaPongOutBufRightCh[DMA_BUFFER_SIZE];
    
    tint      rinCompr[DMA_BUFFER_SIZE]; // A-law buffer
    
    //==============================================================================
    //								Pointers
    //==============================================================================
    linSample *sinBufferPING_prt,// | Sin
    	      *sinBufferPONG_prt,// |
    		  
    	      *soutBufferPING_prt,//| Sout
    	      *soutBufferPONG_prt,//|
    
    		  *rinLinearPING_prt,// | Rin
    		  *rinLinearPONG_prt,// | 
    		  
    		  *routLinearPING_prt,//| Rout
    		  *routLinearPONG_prt,//| 
    
    tint* rinCompr_prt;//           | Compressed  
    //==================================================================================
    /*
    sinBufferPING_prt = DmaPingDstInBufLeftCh;
    sinBufferPONG_prt = DmaPongDstInBufLeftCh;
    
    soutBufferPING_prt = DmaPingOutBufLeftCh;
    soutBufferPONG_prt = DmaPongOutBufLeftCh;
    
    rinLinearPING_prt = DmaPingDstInBufRightCh;
    rinLinearPONG_prt = DmaPongDstInBufRightCh;
    
    routLinearPING_prt = DmaPingOutBufRightCh;
    routLinearPONG_prt = DmaPongOutBufRightCh;
    
    
    rinCompr_prt = rinCompr;*/
    //=======================================================================================
    
    #define SIU_MAX_FRAME_LENGTH DMA_BUFFER_SIZE       // 10ms maximum frame duration */
    #define SIU_MAX_ECU_FILTER_LENGTH 1024 			   // 1024 - 128 ms tail search filter
    												   // 512  - 64  ms tail
    												   // 256  - 32  ms tail
    												   // 128  - 16  ms tail
    												   // 64   - 8   ms tail
    
    #define SIU_MAX_ECU_FLTSEG 3 					   // Maximum of 3 individual filter segments
    #define SIU_MAX_ECU_FLTSEG_LENGTH 256 			   // 256 
    
    
    #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
    
    /* Delay line compression related */
    #define ecu_SIM_DLINE_SAMPLES_PER_WORD   2
    
    /* 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 */
                                                /* Fract (see ecuport.h, eculms.s) */
    #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 */
    
    
    
    #define siuMakeID(mid,chnum) ((tuint)(mid)<<8|(tuint)(chnum))
    
    #define SIU_VOICE_HEAP_SIZE 2048
    tword siu_voice_heap[SIU_VOICE_HEAP_SIZE];
    
    void *vheap;
    
    /* Module ID's */
    #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
    #define ecu_SEARCH_FILTER_BUF 14
    
    //#define ECU_CHAN_COUNT 1
    
    //..............................................................................
    //..............................................................................
    //..............................................................................
    //..............................................................................
    
    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;
    };
    
    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,//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 */
    };
    
    
    linSample ecu_pcm_expand[IRAM_ECU_EXPAND_LENGTH];
    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]
    };
    
    //
    
    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;;
        	printf("ecuNew fail\n");
        }
    }
    //..............................................................................
    //..............................................................................
    //..............................................................................
    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];//NULL
        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 |  // 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   |
                                   ecu_CLEAR_FG              |
                                   ecu_CLEAR_BG              |
                                   ecu_CLEAR_SEARCH;
    
        cfgParam.config_bitfield1 = 0;//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));
    }
    //..............................................................................
    //..............................................................................
    //..............................................................................
    void ecu_control()
    {
    	ecu_inst.ecuCtl.ctl_code      = ecu_CTL_MASK;
    	ecu_inst.ecuCtl.u.ctl_mask[0] = 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   |
    	                                         ecu_CLEAR_FG              |
    	                                         ecu_CLEAR_BG              |
    	                                         ecu_CLEAR_SEARCH;
    
    	ecu_inst.ecuCtl.u.ctl_mask[1] = 0;//ecu_ENABLE_NLP_PHASE_RND;
    
        ecuControl (ecu_inst.ecu_Inst, &(ecu_inst.ecuCtl));
    
    }
    
    ecu_init() {
    
    	ecu_inst.ecu_Inst = NULL;
        memset(ecu_inst.ecu_buffers, 0, sizeof(ecu_inst.ecu_buffers));
    
        ecu_new();
        ecu_open();
      //     ecu_control();
    
    }
    
    void main(void)
    {
    
    	printf("INIT START\n");
    	sysInit();
    
    	printf("ECU INIT START\n");
    	ecu_init();
    
    sinBufferPING_prt = DmaPingDstInBufLeftCh;
    sinBufferPONG_prt = DmaPongDstInBufLeftCh;
    
    soutBufferPING_prt = DmaPingOutBufLeftCh;
    soutBufferPONG_prt = DmaPongOutBufLeftCh;
    
    rinLinearPING_prt = DmaPingDstInBufRightCh;
    rinLinearPONG_prt = DmaPongDstInBufRightCh;
    
    routLinearPING_prt = DmaPingOutBufRightCh;
    routLinearPONG_prt = DmaPongOutBufRightCh;
    
    
    rinCompr_prt = rinCompr;
    	
    	printf("GO!\n");
    
    	while(1)
    	{
    		if(FLAGS.bit.DMA_INT)
    		{
    			if(FLAGS.bit.Ping_IN) // PING
    			{
    
    //===============================================================================
    				//LEFT->ECU->VAU->SPEAKER
    
    			    /* Compress A-law delay line samples */
    			    muaTblAlawCmpr (DMA_BUFFER_SIZE, rinLinearPING_prt, rinCompr_prt);
    				
    //			    /* Pack samples for delay line compression */				   Useless for C55
    //			    for (i=0; i<DMA_BUFFER_SIZE; i++) {
    //			    	rinBuffer[i] = rinCompr[i] & 0xFF;
    //			    }
    				ecuSendIn(ecu_inst.ecu_Inst, sinBufferPING_prt, rinCompr_prt, soutBufferPING_prt);
    
    				ecu_control();
    
    //................................................................................
    			    //RIGHT->VAU->TEL_In
    			    memcpy(routLinearPING_prt, rinLinearPING_prt, (DMA_BUFFER_SIZE));
    //===============================================================================
    				FLAGS.bit.Ping_IN = 0;
    			}
    
    			if(FLAGS.bit.Pong_IN) // PONG
    			{
    //===============================================================================
    				//LEFT->ECU->VAU->SPEAKER
    				
    				/* Compress A-law delay line samples */
    				muaTblAlawCmpr (DMA_BUFFER_SIZE, rinLinearPONG_prt, rinCompr_prt);
    				
    //			    /* Pack samples for delay line compression */                    Useless for C55
    //			    for (i=0; i<DMA_BUFFER_SIZE; i++) {
    //			    	rinBuffer[i] = rinCompr[i] & 0xFF;
    //			    }
    				ecuSendIn(ecu_inst.ecu_Inst, sinBufferPONG_prt, rinCompr_prt, soutBufferPONG_prt);
    				
    				ecu_control();
    
    //................................................................................
    				//RIGHT->VAU->TEL_In
    			    memcpy(routLinearPONG_prt, rinLinearPONG_prt, (DMA_BUFFER_SIZE));
    //===============================================================================
    
    				FLAGS.bit.Pong_IN = 0;
    			}
    	    FLAGS.bit.DMA_INT = 0;
    		}
    	}
    }
    
    
    
    Buffers allocation
    
    Buffer  Base	Size	log2align
    0		0x1832	328		1
    1		0x308C	256		1
    2		0x2F8C	256		1
    3		0x2F64	40		0	
    4		0x2500	612		0	
    5		0x2060	1184	11
    6		0x2B64	1024	1
    7		0x197A	14		1
    8		0x1988	27		0
    9		0x19A4	27		0
    10		0x19C0	6		0
    11		0x19C6	6		0
    12 -
    13 -
    14		0x2764	1024	1
    15		0x19CC	256		1
    16		0x1ACC	128		0
    

    Here is my buffers, they are the same as in demo:

    Buffer      Base	Size 	log2align
    0 0x1832 328 1 1 0x308C 256 1 2 0x2F8C 256 1 3 0x2F64 40 0 4 0x2500 612 0 5 0x2060 1184 11 6 0x2B64 1024 1 7 0x197A 14 1 8 0x1988 27 0 9 0x19A4 27 0 10 0x19C0 6 0 11 0x19C6 6 0 12 - 13 - 14 0x2764 1024 1 15 0x19CC 256 1 16 0x1ACC 128 0

    Currently I have two difficulties:

    1. ECU still does not work without ecuControl calling every time after ecuSendIn.

    2. ECU works only if voice is 12dB higher than reflection in Sin signal. While in demo 6dB is enough to have pure voice without reflection.

  • The audio file I am using.

    Fs-8000Hz,  Res-16bit, u-Law. PC provides linSample for both LEFT(Sin) and RIGHT(Rin) channels

    ECU_test_audio.zip

  • Stan,

    The delay line compression handling is correct in your previous post but doesn't match with the ECU_E2E.c you attached.

    Clearing BG/FG buffer in ecu_control() followed by ecuSendIn() in each frame will break ECAN coffecients tranining and fail to cancel the echo.

    The ECU_test_audio.pcm includes the Rin/Sin signal and appears near end speech is added in original 15 seconds demo composite source signal, what does the Rin/Sout signal look like in the case if you don't call ecu_control()? If you could post the following test case result without calling ecu_control(), it will be more helpful:
    1. Sout/Rout with 15 seconds demo Rin/Sin PCM samples.
    2. Sout/Rout with 90 seconds Rin/Sin PCM samples. It's interesting to know how you compose/extend the 15 seconds demo PCM files.

    Regards,
    Garrett

  • Garrett,

    Thank you for your reply.

    Now I am preparing as the simplest test as possible to provide requested information. I will update my post with diagrams,c-file and results.

    Thank you

  • Garrett,

    The test project is ready.

    1. Lets set up a target. I would like to have the same result as in the ECU demo project, sin/rin and sout/rout attached. It is Fs-8kHz, Res-16bit, u-law.

    ECU_demo_results.zip

    2. My test environment:

    3. Results (all files Fs-8kHz, Res-16bit, A-law):

       Sout/Rout with 15 seconds demo Rin/Sin PCM samples.

    5515evm_15sec_alaw.zip

    Sout/Rout with 90 seconds Rin/Sin PCM samples.

    5515evm_90sec_alaw.zip

    4. Test project and also c-file just for the convenience (everything was done according to your recommendation): 

    ECU_PC.zip

    #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				// Swith to 90 seconds Rin and Rout
    
    #define FILE_OUTDIR   "c:/ti_projects/ECU_FROM_PC/vectors/"
    
    #ifndef s90sec
    
    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
    
    #define SIU_MAX_FRAME_LENGTH 			FRAME_SIZE       // 10ms maximum frame duration */
    #define SIU_MAX_ECU_FILTER_LENGTH 		1024 			 // 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 			 // 256 - 128 mS tail
    #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];
    
    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: , U-law zero:0xFFFF
        ecu_inst.ecuCfg.pcm_expand_tbl = 		&muaTblAlaw[0];// &muaTblUlaw[0];//&;//NULL
        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   |
    											ecu_CLEAR_FG              |
    											ecu_CLEAR_BG              |
    											ecu_CLEAR_SEARCH;
    
        cfgParam.config_bitfield1 = 			0;//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));
    }
    //..............................................................................
    //..............................................................................
    //..............................................................................
    void ecu_control()
    {
    	ecu_inst.ecuCtl.ctl_code      = 		ecu_CTL_MASK;
    	ecu_inst.ecuCtl.u.ctl_mask[0] = 		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   |
    	                                        ecu_CLEAR_FG              |
    	                                        ecu_CLEAR_BG              |
    	                                        ecu_CLEAR_SEARCH;
    
    	ecu_inst.ecuCtl.u.ctl_mask[1] = 0;//ecu_ENABLE_NLP_PHASE_RND;
    
        ecuControl (ecu_inst.ecu_Inst, &(ecu_inst.ecuCtl));
    
    }
    //..............................................................................
    //..............................................................................
    //..............................................................................
    ecu_init()
    {
    	ecu_inst.ecu_Inst = NULL;
    
        memset(ecu_inst.ecu_buffers, 0, sizeof(ecu_inst.ecu_buffers));
    
    
        ecu_new();
        ecu_open();
        //ecu_control();
    }
    //..............................................................................
    //..............................................................................
    //..............................................................................
    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;
    
    	// FRAMEWORKS and ECU
    
    	for(frame_count = 0; frame_count < N_frames; frame_count++)		// file is 15sec duration, Frame is 10mS.
    																	// N of frames = duration(sec)/Frame(sec)
    	{
    		fread (scompr, 1, FRAME_SIZE, file_sin); 					// read 1 frame
    		fread (rcompr, 1, FRAME_SIZE, file_rin); 					// read 1 frame
    
    		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);
    
    		/* Pack samples for delay line compression */
    		for (i=0; i<FRAME_SIZE; i++)
    		{
    			rcompr[i] = rinCompr[i] & 0xFF;
    		}
    
    		ecuSendIn(ecu_inst.ecu_Inst, sin, rcompr, 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_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);
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    All Sin and Rin are identical except duration.

    As you can see from 90 sec sout-file one problem has gone. I do not need to call ecuControl every coming frame to get ECU worked. I can accept that something is wrong with DMA ping-pong mode in my main project. But still there is a reflection within the voice part. However, I do not see this echo in demo Sout. Moreover, ECU is cutting even a speech in my sout-files but in demo everything is perfect.

    Questions:

    1. Why adaptive filter does not work in my test project?

    2. Why there is not enough SNR for ECU in my case that causes cutting the speech, but demo works well?

    PS: Sorry for demo files saved in u-law. It seems like demo does not work with a-law. I changes with

      ecuSim->pcm_format  = const_COMP_ALAW_8;               /* u-law is default companding law */
     
      ecuSim->frame_size        = 10*8;                        /* 10ms default frame duration */                    // The same for u-law
      ecuSim->ecu_y2x_delay     = 10*8;                        /* One frame default y2x delay */               // The same for u-law

    but sout is really weird. If it helps I can upload these out-files too. 

    Thank you.

    Stan

  • Stan,

    The demo has NLP disabled but your test project has it enabled which more aggressively removes residual non-linear echo, and the side effect would be clipping speech in the near end signal you composed. In a real field scenarion, you should not notice such obvious clipping as shown in your test files. To disable NLP, comment out ecu_ENABLE_NLP from cfgParam.config_bitfield as below.

    cfgParam.config_bitfield = ecu_ENABLE_ECHO_CANCELLER |

              ecu_ENABLE_UPDATE  |

    //ecu_ENABLE_NLP  |

    ecu_ENABLE_AUTO_UPDATE    |

    ......

    Regards, Garrett

  • Hello Garrett,

    If I disable ecu_ENABLE_NLP ECU just stops working.

    5515_15sec_NLP_dis.zip

    Thank you

  • Stan,

    If you try to enable NLP with ECU demo project as below, you should see the same result as in your test project. Make sure you don't call ecu_control( ) to clear BG/FG buffer in each frame.

      ecuSim->ecuCtl.ctl_code      = ecu_CTL_MASK;
      ecuSim->ecuCtl.u.ctl_mask[0] = 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;
      ecuSim->ecuCtl.u.ctl_mask[1] = ecu_ENABLE_NLP_PHASE_RND;  
     
    Regards, Garrett

  • Hi Garrett,

    There is still residential echo during a speech, however in demo the speech is clean. 

    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 ;//  |
    //											ecu_CLEAR_FG              |
    //											ecu_CLEAR_BG              |
    //											ecu_CLEAR_SEARCH;
    
        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));
    }

    I do not call ecucontrol since I have this ECU test project.

    Results:

    From my project with above settings (a-law):

    ecu_test_sout.zip

    From Demo with ecu_ENABLE_NLP enabled (u-law):

    demo_sout.zip

    Thank you

  • Hi Stan,

    >>I can accept that something is wrong with DMA ping-pong mode in my main project. But still there is a reflection within the voice part.
    Are you using the same MCBSP/DMA driver for the test and demo project? If DMA ping-ping mode is not setup properly and that causes any PCM sample lost which basically changes the echo path, makes ECAN to re-train and eventually degrades the echo cancallation performance.

    Also, the system delay is set to ecuSim->ecu_y2x_delay = 10*8, you can try to match the same to your test project (ecu_y2x_delay = 0 in your main.c).

    Did you find out why disabling NLP causes ECAN completely failed?

    Regards,
    Garrett

  • Are you using the same MCBSP/DMA driver for the test and demo project? If DMA ping-ping mode is not setup properly and that causes any PCM sample lost which basically changes the echo path, makes ECAN to re-train and eventually degrades the echo cancallation performance.

    The demo project as well as my ECU test project does not have any hardware dependencies. They can be run in any platform as long as fread and fwrite functions are being used to take samples from PC.

    Also, the system delay is set to ecuSim->ecu_y2x_delay = 10*8, you can try to match the same to your test project (ecu_y2x_delay = 0 in your main.c).

    Of course I tried everything but just for your reference demo project uses

      ecuSim->ecu_y2x_delay  = 0;                     /* 0 y2x delay when reading from files */        

    it is 859 line in ecusimfunc.c

    I have found the solution, I will update my post later with real working project. It is easy to follow and reproduce.

    Thank you

  • Are you using the same MCBSP/DMA driver for the test and demo project? If DMA ping-ping mode is not setup properly and that causes any PCM sample lost which basically changes the echo path, makes ECAN to re-train and eventually degrades the echo cancallation performance.

    The demo project as well as my ECU test project does not have any hardware dependencies. They can be run in any platform as long as fread and fwrite functions are being used to take samples from PC.

    Also, the system delay is set to ecuSim->ecu_y2x_delay = 10*8, you can try to match the same to your test project (ecu_y2x_delay = 0 in your main.c).

    Of course I tried everything but just for your reference demo project uses

      ecuSim->ecu_y2x_delay  = 0;                     /* 0 y2x delay when reading from files */        

    it is 859 line in ecusimfunc.c

    I have found the solution, I will update my post later with real working project. It is easy to follow and reproduce.

    Thank you

  • Hi Stan,

    I was thinking you have a real MCBSP/DMA driver in your test project and add on top of demo project as I asked if you verified the lower layer PCM data driver.

    Please do update the post with your working project that would be benifical for others.

    Thanks, Garrett

  • Hi Garrett,

    The main problem was in packing samples for delay line.

    All suggestions like:

        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;
        }

    were misleading! 

    I am using C5515 core. In my case:

    tint is int (16bit)

    tword is unsigned int (16bit)

    So an example above is simply doing nothing. rinBuffer equals to rinCompr and it is a half packed data buffer.

    The more efficient way doing this is:

        linSample sin[N];
        linSample sout[N];
    
        linSample rinLinear[N];
        tint      rinCompr[N];
        tword     rinBuffer[N];
        tint length = N;
        tint i,j;
        
        /* Compress U-law or A-law delay line samples */
        muaTblUlawCmpr (length, rinLinear, rinCompr);  // for A-law  muaTblAlawCmpr (length, rinLinear, rinCompr);
    
        /* Pack samples for delay line compression */
        for (i=0, j = 0; i<length/2; i++)
    	{
    	        rinBuffer[i] = (((rinCompr[j] << 8) & 0xFF00) + (rinCompr[j+1] & 0x00FF));
    		j=j+2;
    	}
    
        ecuSendIn((void*)ecu_Inst, sin, rinBuffer, sout);

    I would say that ECU is quite poor documented. There is a general information in ECU_manual.pdf, but there is no ECU implementation guide or something like that.
    Even though the project works well I would like to get a feedback from ECU experts to prove that it is correct.

    Thank you

  • * 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).

    ECU_FRAMEWORK.zip

    Enjoy)

  • Hi

    thanks for useful example project !
    i try to use Volib for Line Echo Cancellation on c6678 , i change loop for c66 data type:

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

    I success to cancel echo when rin and sin haven’t delay (similar your PCM sample in your project) but when I use sample PCM with 90ms delay, echo canceler not work.



    i modify tail length:

    #define SIU_MAX_ECU_FILTER_LENGTH 1024 //EA: 256->1024 1024 - 128 ms tail search filter

    Can you please help me how to modify config for 128 ms max delay ?



    Thanks for your time

    Ebi

  • Hey Ebi,

    ebi alinejad said:
    /* Pack samples for delay line compression */
    for (i=0; i<FRAME_SIZE; i++)
    {
    rcompr[i] = rinCompr[i] & 0xFF;
    }

    You are simply doing nothing here. You need to compress it. Please look at one of my previous posts here about the compression or you can copy it from my demo project. As a example you need to do this if your MAU is16bit:

    		/* Pack samples for delay line compression */
    		for (i=0, j = 0; i<FRAME_SIZE/2; i++)
    		{
    			rcompr[i] = (((rinCompr[j] << 8) & 0xFF00) + (rinCompr[j+1] & 0x00FF));
    			j=j+2;
    		}

    One small note. Before the compression just make sure you do the conversion to u-law or a-law.

    ebi alinejad said:
    i modify tail length:

    #define SIU_MAX_ECU_FILTER_LENGTH 1024 //EA: 256->1024 1024 - 128 ms tail search filter

    Can you please help me how to modify config for 128 ms max delay ?

    As far as I remember in TI demo by default it is 128ms. So you do not need to change anything.

    Cheers,

    Stan

     

  • Stan

    thanks for your reply !

    Stan Sidorov said:
    /* Pack samples for delay line compression */ for (i=0, j = 0; i<FRAME_SIZE/2; i++) { rcompr[i] = (((rinCompr[j] << 8) & 0xFF00) + (rinCompr[j+1] & 0x00FF)); j=j+2; }

    in my platform (c66) tint size is 16bit and tword size is 8bit and i modify loop according to this post:

    Stan Sidorov said:

    One small note. Before the compression just make sure you do the conversion to u-law or a-law.

    i use your project with some modifications, rin compressed using muaTblAlawCmpr before sample packing (main.c file

    /*
     * 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   "E:/CCSc6_Project/ECU_test_3/vectors/" //
    
    #ifndef s90sec
    
    char *filename_sin = "sin.pcm";
    char *filename_rin = "rin.pcm";
    
    char *filename_sout = "sout.pcm";
    char *filename_rout = "rout.pcm";
    
    #define N_frames 800	// 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 		1024 			 //EA: 256->1024 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];
    
    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; /*EA: 0->90 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();
    	int size_t=0;
    
    	size_t=sizeof(tint);
    	size_t=sizeof(tword);
    
    
    	/* 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;
    	}
    
    
    	// 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++)
    		{
    			rcompr[i] = 0;
    		}
    
    		/* Pack samples for delay line compression */
    		for (i=0; i<FRAME_SIZE; i++)
    		{
    			rcompr[i] = rinCompr[i] & 0xFF;
    		}
    
    		ecuSendIn(ecu_inst.ecu_Inst, sin, rcompr, 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);
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
     ) 

    Stan Sidorov said:
    As far as I remember in TI demo by default it is 128ms. So you do not need to change anything

    yes, in TI demo SIU_MAX_ECU_FILTER_LENGTH macro set to 1024 (128ms) when ecu_SEARCH_ENABLE set to 1, but in your example project :

    #define SIU_MAX_ECU_FILTER_LENGTH 256 

    rin and sin test in your project haven't  delay.can you please confirm that default config in your project work correctly for max 128 ms delay between rin and sin?

    thanks

    Ebi

  • Ebi,

    ebi alinejad said:

    yes, in TI demo SIU_MAX_ECU_FILTER_LENGTH macro set to 1024 (128ms) when ecu_SEARCH_ENABLE set to 1, but in your example project :

    #define SIU_MAX_ECU_FILTER_LENGTH 256 

    You are right, for some reason in ECU_FRAMEWORK project I am using:

    #define SIU_MAX_ECU_FILTER_LENGTH 		256

    However, I have looked at my release code and the length is 1024 exactly as in TI demo . So it should work anyway.

     

    ebi alinejad said:
    in my platform (c66) tint size is 16bit and tword size is 8bit and i modify loop according to this post:

    Can you show me this:

    // types.h
    
    typedef uint_least8_t tword;
    
    
    
    // stdint.h
    
    typedef uint16_t uint_least8_t;
    
    typedef unsigned int   uint16_t;
    

    One important note: I remember reading it but unfortunately cannot find a reference now. So some buffers have to be placed at the same memory page (NOT bank but PAGE)! You can ask TI experts if they can help to clarify that.

    Cheers,

    Stan

  • Stan Sidorov said:

    Can you show me this:

    // types.h
    
    typedef uint_least8_t tword;
    
    
    
    // stdint.h
    
    typedef uint16_t uint_least8_t;
    
    typedef unsigned int   uint16_t;

    types.h :
    
     * <b>IMPLEMENTATION NOTE:</b> Although we could have used UInt8 to define this
     * type, we decided to use uchar instead. This was done in order to remain
     * true to the actual type description.</p>
     */
    typedef uint_least8_t tword;
    
    stdint.h :
    
        typedef unsigned char  uint8_t;
        ...
        typedef uint8_t  uint_least8_t;
    
    

    i check size with "sizeof" function too !

    i understand from:

    Stan Sidorov said:
    However, I have looked at my release code and the length is 1024 exactly as in TI demo . So it should work anyway.

    and 

    Stan Sidorov said:
    One important note: I remember reading it but unfortunately cannot find a reference now. So some buffers have to be placed at the same memory page (NOT bank but PAGE)! You can ask TI experts if they can help to clarify that.

    your project work correctly for max 128 ms delay between rin and sin and you think buffer location , cause  problem . please confirm if i understand correctly.

    thanks

    Ebi

  • ebi alinejad said:
    your project work correctly for max 128 ms delay between rin and sin and you think buffer location , cause  problem . please confirm if i understand correctly.

    Buffer allocation is another thing that you need to address. It may cause this problem but may not as well. Since I am not an author of the ECU I cannot guarantee this. The HW I was using at that time gave 80mS delay max. However, I am pretty sure it is capably to digest 128 ms delay as well.

    Cheers,

    Stan

  • Hi Stan !

    Stan Sidorov said:
    Since I am not an author of the ECU I cannot guarantee this

    you are right ! . i don't expect you to guarantee.thanks a lot for support and useful information

    best regards

    Ebi

  • Hi Ebi,

    You are welcome. Hope it helped.

    Cheers,

    Stan

  • Hi

    small point about port your Project to c6000 DSP :

    #define ecu_SIM_DLINE_SAMPLES_PER_WORD  1 				 //EA:for C6000 2->1 Delay line compression related

    (from ecu/test/src/c64/ecusimport.h)

    i hope my post useful for others

    Ebi