DSPRelated.com
Forums

Re: Realtime filtering

Started by Jeff Brower September 18, 2008
Ramaraju-
> According to system requirement, DSP has to acquire sampled data around 5 seconds @
> 51KHz sampling fervency.
> To implement real time filter, we configured 2 ping-pong buffers. While McBSP fills
> one buffer, another buffer can be used for processing (which was already filled).
> There will be considerable time gap between two fills, which is sufficient to
> execute filter algorithm.
> Consider that buffer length is M words, &filter tap length is N
> My doubt is after computing the first buffer how I can shift to 2nd buffer.
> i.e you need to have (N-1) previous sample to compute current sum. How can
> implement this?
> Can any one guide me in this regard?

One way to do it is to create a "save" buffer that stores M-N samples of the most
recent ping or pong buffer, to be used the next time. Then, at the start of each new
buffer, you can use this save buffer until the filter input index (i-N) is no longer
negative. At the end of each buffer processing (filtering), run a quick loop to
update the save buffer.

Does this make sense?

-Jeff
Hi,
i am having one basic doubt. Suppose if we have filter tap length nh &
no.of samples are nr then according to convolution operation well get
nr+nh-1 outputs. Filter is nothing but convolution of samples and filter
kernel.

Can u see this filter code, which I have taken from TIs DSP library
document (spru565a pdg.no 86)
x[nr+nhC1] Pointer to input array of size nr + nh C 1.
h[nh] Pointer to coefficient array of size nh.
r[nr] Pointer to output array of size nr. Must be word aligned.
nh Number of coefficients. Must be .
nr Number of samples to calculate. Must be a multiple of 4.
void DSP_fir_gen(short x[ ], short h[ ], short r[ ],
int nh, int nr)
{
int i, j, sum;
for (j = 0; j < nr; j++)
{
sum = 0;
for (i = 0; i < nh; i++)
sum += x[i + j] * h[i];
r[j] = sum >> 15;
}
}

This algorithm takes nh+nr-1 inputs and produces nr outputs. Where as in
matlab for n number of input samples you can get n (same) number of
filtered data. How I can implement that.

My second doubt:

I have taken same filter algorithm for my application.

typedef struct
{
float m_fHistory[FILTER_LENGTH -1];
float m_fInputSamples[BUF_LENGTH];
}st_PingPong;
I decelerated two buffers which are having current samples along with
previous (nh-1) samples of previous data. In actual scenario before
processing filter algorithm, last (nh-1) samples will be copied in to
second buffers history filed.
include
#include

#define FILTER_LENGTH 64
#define BUF_LENGTH 512
#define SAMPLE_FREQ 5000
#define PI (float)(22/7)
float g_fOutPut[BUF_LENGTH *4];
float *g_pfDestAdd=NULL;

typedef struct
{
float m_fHistory[FILTER_LENGTH -1];
float m_fInputSamples[BUF_LENGTH];
}st_PingPong;
st_PingPong Buffer1, Buffer2;

void InputGenatation( void);
void fir_filter(float *pInput, float *pFilterCoeff, float *pOutput ,int
nFilterLen, int nNoOfOutputSamp);
void main(void)
{
int nTotalNoOfLoops;
int index;
float *pfInputSamp;
float *pfFilterCoeff;
float *pfOutput;
char cBufferFlag=0;

/** genarate input data **/
InputGenatation();
g_pfDestAdd=g_fOutPut;
nTotalNoOfLoops=0;
/** in actual scenario this condition will be changed according to
availability of data **/
while( nTotalNoOfLoops!=0)
{
pfFilterCoeff=g_fFilterCoeff;

/** before appling filter algo ,save last 63(equal
to filter tap length) samples in buf2 **/

for(index=0;index {
if(cBufferFlag)
{
Buffer2.m_fHistory[index]Buffer1.m_fInputSamples[BUF_LENGTH-FILTER_LENGTH+ index];
cBufferFlag=0;

pfInputSamp=Buffer1.m_fHistory;
//pfInputSamp=Buffer1.m_fInputSamples;
}
else
{
Buffer1.m_fHistory[index]Buffer2.m_fInputSamples[BUF_LENGTH-FILTER_LENGTH-1+ index];
cBufferFlag=1;
//pfInputSamp=Buffer1.m_fInputSamples;
pfInputSamp=Buffer2.m_fHistory;
}

}

/** apply filter **/

fir_filter(pfInputSamp,pfFilterCoeff,g_pfDestAdd,FILTER_LENGTH,BUF_LENGTH);
nTotalNoOfLoops--;

}

While(1)
{
/**infinite loop **/
}
}

void InputGenatation( void)
{
unsigned int index;
float FreqP.00;
for(index=0;index {
Buffer1.m_fHistory[index]=0;
Buffer2.m_fHistory[index]=0;
}

for(index=0;index {
Buffer1.m_fInputSamples[index](float)sin(2*PI*index*Freq/SAMPLE_FREQ);
Buffer2.m_fInputSamples[index]Buffer1.m_fInputSamples[index];
}
}
/** FIR Filter **/

void fir_filter(float *pInput, float *pFilterCoeff, float *pOutput ,int
nFilterLen, int nNoOfOutputSamp)
{
static int index1,index2;
static float sum;

for (index1= 0; index1 < nNoOfOutputSamp; index1++)
{
sum = 0;
for (index2 = 0; index2 < nFilterLen; index2++)
{
sum += pInput[index2 + index1] *
pFilterCoeff[index2];
}

pOutput[index1]= sum ;
}
/** update next destination address**/
g_pfDestAdd=g_pfDestAdd+nNoOfOutputSamp;
}

I have taken filter coefficients for low pass filter (cutoff freq 1.2 KHz)
from matlab (fda tool)

But output is not matching with expected results.
Can anyone guide me in this regard,..
Thanks in Advance.
Regards,
SVS
Jeff Brower
Sent by: c...
09/18/2008 10:32 PM

To
Ramaraju SVS
cc
c...
Subject
Re: [c6x] Realtime filtering
Ramaraju-

> According to system requirement, DSP has to acquire sampled data around
5 seconds @
> 51KHz sampling fervency.
> To implement real time filter, we configured 2 ping-pong buffers. While
McBSP fills
> one buffer, another buffer can be used for processing (which was already
filled).
> There will be considerable time gap between two fills, which is
sufficient to
> execute filter algorithm.
> Consider that buffer length is M words, &filter tap length is N
> My doubt is after computing the first buffer how I can shift to 2nd
buffer.
> i.e you need to have (N-1) previous sample to compute current sum. How
can
> implement this?
> Can any one guide me in this regard?

One way to do it is to create a "save" buffer that stores M-N samples of
the most
recent ping or pong buffer, to be used the next time. Then, at the start
of each new
buffer, you can use this save buffer until the filter input index (i-N) is
no longer
negative. At the end of each buffer processing (filtering), run a quick
loop to
update the save buffer.

Does this make sense?

-Jeff
Ramaraju SVS-

> i am having one basic doubt. Suppose if we have filter tap length nh &
> no.of samples are nr then according to convolution operation well get
> nr+nh-1 outputs. Filter is nothing but convolution of samples and filter
> kernel.
>
> Can u see this filter code, which I have taken from TIs DSP library
> document (spru565a pdg.no 86)
>
> x[nr+nhC1] Pointer to input array of size nr + nh C 1.
> h[nh] Pointer to coefficient array of size nh.
> r[nr] Pointer to output array of size nr. Must be word aligned.
> nh Number of coefficients. Must be .
> nr Number of samples to calculate. Must be a multiple of 4.
>
> void DSP_fir_gen(short x[ ], short h[ ], short r[ ],
> int nh, int nr)
> {
> int i, j, sum;
> for (j = 0; j < nr; j++)
> {
> sum = 0;
> for (i = 0; i < nh; i++)
> sum += x[i + j] * h[i];
> r[j] = sum >> 15;
> }
> }
>
> This algorithm takes nh+nr-1 inputs and produces nr outputs. Where as in
> matlab for n number of input samples you can get n (same) number of
> filtered data. How I can implement that.

A couple of comments:

1) MATLAB assumes zero padding so that functions such as convolution will produce as
many output samples as input samples. MATLAB function are not designed to be used in
a continuous, real-time system. They are designed to operate on a "finite data
chunk" -- i.e. that typically means a file. For continuous operation, you have to
add some frame processing code that glues together data flow between functions.

2) Before you talked about implementing ping-pong buffers. I assume the purpose is
continuous, real-time operation, otherwise you don't need to do that. If you are
serious about doing that, then why not explore it in MATLAB? If you get it working,
then you will see the issues involved and the DSP coding questions you are asking
will resolve.

-Jeff

> My second doubt:
>
> I have taken same filter algorithm for my application.
>
> typedef struct
> {
> float m_fHistory[FILTER_LENGTH -1];
> float m_fInputSamples[BUF_LENGTH];
> }st_PingPong;
>
> I decelerated two buffers which are having current samples along with
> previous (nh-1) samples of previous data. In actual scenario before
> processing filter algorithm, last (nh-1) samples will be copied in to
> second buffers history filed.
>
> include
> #include #define FILTER_LENGTH 64
> #define BUF_LENGTH 512
> #define SAMPLE_FREQ 5000
> #define PI (float)(22/7)
>
> float g_fOutPut[BUF_LENGTH *4];
> float *g_pfDestAdd=NULL;
>
> typedef struct
> {
> float m_fHistory[FILTER_LENGTH -1];
> float m_fInputSamples[BUF_LENGTH];
> }st_PingPong;
>
> st_PingPong Buffer1, Buffer2;
>
> void InputGenatation( void);
> void fir_filter(float *pInput, float *pFilterCoeff, float *pOutput ,int
> nFilterLen, int nNoOfOutputSamp);
>
> void main(void)
> {
> int nTotalNoOfLoops;
> int index;
> float *pfInputSamp;
> float *pfFilterCoeff;
> float *pfOutput;
> char cBufferFlag=0;
>
> /** genarate input data **/
> InputGenatation();
> g_pfDestAdd=g_fOutPut;
> nTotalNoOfLoops=0;
> /** in actual scenario this condition will be changed according to
> availability of data **/
> while( nTotalNoOfLoops!=0)
> {
> pfFilterCoeff=g_fFilterCoeff;
>
> /** before appling filter algo ,save last 63(equal
> to filter tap length) samples in buf2 **/
>
> for(index=0;index > {
> if(cBufferFlag)
> {
> Buffer2.m_fHistory[index]> Buffer1.m_fInputSamples[BUF_LENGTH-FILTER_LENGTH+ index];
> cBufferFlag=0;
>
> pfInputSamp=Buffer1.m_fHistory;
> //pfInputSamp=Buffer1.m_fInputSamples;
> }
> else
> {
> Buffer1.m_fHistory[index]> Buffer2.m_fInputSamples[BUF_LENGTH-FILTER_LENGTH-1+ index];
> cBufferFlag=1;
> //pfInputSamp=Buffer1.m_fInputSamples;
> pfInputSamp=Buffer2.m_fHistory;
> }
>
> }
>
> /** apply filter **/
>
> fir_filter(pfInputSamp,pfFilterCoeff,g_pfDestAdd,FILTER_LENGTH,BUF_LENGTH);
> nTotalNoOfLoops--;
>
> }
>
> While(1)
> {
> /**infinite loop **/
> }
>
> }
>
> void InputGenatation( void)
> {
> unsigned int index;
> float FreqP.00;
>
> for(index=0;index > {
> Buffer1.m_fHistory[index]=0;
> Buffer2.m_fHistory[index]=0;
> }
>
> for(index=0;index > {
> Buffer1.m_fInputSamples[index]> (float)sin(2*PI*index*Freq/SAMPLE_FREQ);
> Buffer2.m_fInputSamples[index]> Buffer1.m_fInputSamples[index];
> }
> }
>
> /** FIR Filter **/
>
> void fir_filter(float *pInput, float *pFilterCoeff, float *pOutput ,int
> nFilterLen, int nNoOfOutputSamp)
> {
> static int index1,index2;
> static float sum;
>
> for (index1= 0; index1 < nNoOfOutputSamp; index1++)
> {
> sum = 0;
> for (index2 = 0; index2 < nFilterLen; index2++)
> {
> sum += pInput[index2 + index1] *
> pFilterCoeff[index2];
> }
>
> pOutput[index1]= sum ;
> }
> /** update next destination address**/
> g_pfDestAdd=g_pfDestAdd+nNoOfOutputSamp;
> }
>
> I have taken filter coefficients for low pass filter (cutoff freq 1.2 KHz)
> from matlab (fda tool)
>
> But output is not matching with expected results.
> Can anyone guide me in this regard,..
> Thanks in Advance.
> Regards,
> SVS
>
> Jeff Brower
> Sent by: c...
> 09/18/2008 10:32 PM
>
> To
> Ramaraju SVS
> cc
> c...
> Subject
> Re: [c6x] Realtime filtering
>
> Ramaraju-
>
> > According to system requirement, DSP has to acquire sampled data around
> 5 seconds @
> > 51KHz sampling fervency.
> > To implement real time filter, we configured 2 ping-pong buffers. While
> McBSP fills
> > one buffer, another buffer can be used for processing (which was already
> filled).
> > There will be considerable time gap between two fills, which is
> sufficient to
> > execute filter algorithm.
> > Consider that buffer length is M words, &filter tap length is N
> > My doubt is after computing the first buffer how I can shift to 2nd
> buffer.
> > i.e you need to have (N-1) previous sample to compute current sum. How
> can
> > implement this?
> > Can any one guide me in this regard?
>
> One way to do it is to create a "save" buffer that stores M-N samples of
> the most
> recent ping or pong buffer, to be used the next time. Then, at the start
> of each new
> buffer, you can use this save buffer until the filter input index (i-N) is
> no longer
> negative. At the end of each buffer processing (filtering), run a quick
> loop to
> update the save buffer.
>
> Does this make sense?
>
> -Jeff
Ramaraju,

I see what I think are a couple of problems with the code.

first:
This code:
/** apply filter **/
>
> fir_filter(pfInputSamp,pfFilterCoeff,g_pfDestAdd,FILTER_LENGTH,
> BUF_LENGTH); nTotalNoOfLoops--;
>
causes nTotalNoOfLoops to be 0,-1,-2,-3,...

Then, as if that was not enough,
This code:
> /** update next destination address**/
> g_pfDestAdd=g_pfDestAdd+nNoOfOutputSamp;
>
does not increment the DestAdd pointer, but rather
(because nTotalNoOfLoops is negative)
actually sets the DestAdd pointer to an earlier location in memory
not to the next location in the buffer pointed to by the DestAdd pointer.

R. Williams

---------- Original Message -----------
From: Ramaraju SVS
To: Jeff Brower
Cc: c...
Sent: Fri, 19 Sep 2008 17:01:27 +0530
Subject: Re: [c6x] Realtime filtering

> Hi,
> i am having one basic doubt. Suppose if we have filter tap length
> nh & no.of samples are nr then according to convolution
> operation well get nr+nh-1 outputs. Filter is nothing but
> convolution of samples and filter kernel.
>
> Can u see this filter code, which I have taken from TIs DSP library
> document (spru565a pdg.no 86)
>
> x[nr+nhC1] Pointer to input array of size nr + nh C 1.
> h[nh] Pointer to coefficient array of size nh.
> r[nr] Pointer to output array of size nr. Must be word aligned.
> nh Number of coefficients. Must be .
> nr Number of samples to calculate. Must be a multiple of 4.
>
> void DSP_fir_gen(short x[ ], short h[ ], short r[ ],
> int nh, int nr)
> {
> int i, j, sum;
> for (j = 0; j < nr; j++)
> {
> sum = 0;
> for (i = 0; i < nh; i++)
> sum += x[i + j] * h[i];
> r[j] = sum >> 15;
> }
> }
>
> This algorithm takes nh+nr-1 inputs and produces nr outputs. Where
> as in matlab for n number of input samples you can get n
> (same) number of filtered data. How I can implement that.
>
> My second doubt:
>
> I have taken same filter algorithm for my application.
>
> typedef struct
> {
> float m_fHistory[FILTER_LENGTH -1];
> float m_fInputSamples[BUF_LENGTH];
> }st_PingPong;
>
> I decelerated two buffers which are having current samples along with
> previous (nh-1) samples of previous data. In actual scenario before
> processing filter algorithm, last (nh-1) samples will be copied in to
> second buffers history filed.
>
> include
> #include #define FILTER_LENGTH 64
> #define BUF_LENGTH 512
> #define SAMPLE_FREQ 5000
> #define PI (float)(22/7)
>
> float g_fOutPut[BUF_LENGTH *4];
> float *g_pfDestAdd=NULL;
>
> typedef struct
> {
> float m_fHistory[FILTER_LENGTH -1];
> float m_fInputSamples[BUF_LENGTH];
> }st_PingPong;
>
> st_PingPong Buffer1, Buffer2;
>
> void InputGenatation( void);
> void fir_filter(float *pInput, float *pFilterCoeff, float *pOutput
> ,int nFilterLen, int nNoOfOutputSamp);
>
> void main(void)
> {
> int nTotalNoOfLoops;
> int index;
> float *pfInputSamp;
> float *pfFilterCoeff;
> float *pfOutput;
> char cBufferFlag=0;
>
> /** genarate input data **/
> InputGenatation();
> g_pfDestAdd=g_fOutPut;
> nTotalNoOfLoops=0;
> /** in actual scenario this condition will be changed according to
> availability of data **/
> while( nTotalNoOfLoops!=0)
> {
>
> pfFilterCoeff=g_fFilterCoeff;
>
> /** before appling filter algo ,save last
> 63(equal to filter tap length) samples in buf2 **/
>
> for(index=0;index > {
> if(cBufferFlag)
> {
> Buffer2.m_fHistory[index]> Buffer1.m_fInputSamples[BUF_LENGTH-FILTER_LENGTH+ index];
> cBufferFlag=0;
>
> pfInputSamp=Buffer1.m_fHistory;
> //pfInputSamp=Buffer1.m_fInputSamples;
>
> }
> else
> {
> Buffer1.m_fHistory[index]> Buffer2.m_fInputSamples[BUF_LENGTH-FILTER_LENGTH-1+ index];
> cBufferFlag=1;
> //pfInputSamp=Buffer1.m_fInputSamples;
>
> pfInputSamp=Buffer2.m_fHistory; }
>
> }
>
> /** apply filter **/
>
> fir_filter(pfInputSamp,pfFilterCoeff,g_pfDestAdd,FILTER_LENGTH,
> BUF_LENGTH); nTotalNoOfLoops--;
>
> }
>
> While(1)
> {
> /**infinite loop **/
> }
>
> }
>
> void InputGenatation( void)
> {
> unsigned int index;
> float FreqP.00;
>
> for(index=0;index > {
> Buffer1.m_fHistory[index]=0;
> Buffer2.m_fHistory[index]=0;
> }
>
> for(index=0;index > {
> Buffer1.m_fInputSamples[index]> (float)sin(2*PI*index*Freq/SAMPLE_FREQ);
> Buffer2.m_fInputSamples[index]> Buffer1.m_fInputSamples[index];
> }
>
> }
>
> /** FIR Filter **/
>
> void fir_filter(float *pInput, float *pFilterCoeff, float *pOutput
> ,int nFilterLen, int nNoOfOutputSamp) { static int index1,
> index2; static float sum;
>
> for (index1= 0; index1 < nNoOfOutputSamp; index1++)
> {
> sum = 0;
> for (index2 = 0; index2 < nFilterLen; index2++)
> {
> sum += pInput[index2 + index1] *
> pFilterCoeff[index2];
> }
>
> pOutput[index1]= sum ;
> }
> /** update next destination address**/
> g_pfDestAdd=g_pfDestAdd+nNoOfOutputSamp;
> }
>
> I have taken filter coefficients for low pass filter (cutoff freq 1.2
> KHz) from matlab (fda tool)
>
> But output is not matching with expected results.
> Can anyone guide me in this regard,..
> Thanks in Advance.
> Regards,
> SVS
>
> Jeff Brower
> Sent by: c...
> 09/18/2008 10:32 PM
>
> To
> Ramaraju SVS
> cc
> c...
> Subject
> Re: [c6x] Realtime filtering
>
> Ramaraju-
>
> > According to system requirement, DSP has to acquire sampled data around
> 5 seconds @
> > 51KHz sampling fervency.
> > To implement real time filter, we configured 2 ping-pong buffers. While
> McBSP fills
> > one buffer, another buffer can be used for processing (which was already
> filled).
> > There will be considerable time gap between two fills, which is
> sufficient to
> > execute filter algorithm.
> > Consider that buffer length is M words, &filter tap length is N
> > My doubt is after computing the first buffer how I can shift to 2nd
> buffer.
> > i.e you need to have (N-1) previous sample to compute current sum. How
> can
> > implement this?
> > Can any one guide me in this regard?
>
> One way to do it is to create a "save" buffer that stores M-N samples
> of the most recent ping or pong buffer, to be used the next time. Then,
> at the start of each new buffer, you can use this save buffer until
> the filter input index (i-N) is no longer negative. At the end of each
> buffer processing (filtering), run a quick loop to update the save buffer.
>
> Does this make sense?
>
> -Jeff
------- End of Original Message -------
Hi,
I would like to implement FIR Filter with Decimation. Can anyone suggest
an efficient technique for the practical implementation .
Thanks & regards,
SVS