Reply by Fred Marshall October 2, 20052005-10-02
"Umutesi Faith" <ma_nz1@yahoo.com> wrote in message 
news:9aednWhxVvIrdKLeRVn-vw@giganews.com...
>I don't mean to be annoying , but here i am again with the same question! > /*Input samples*/ > int Input[7] = {s0, s1, s2, s3, s4, s5, s6 ,s7};// array initialization in > C language > > Input[0] = newestsample > > Knowing that the newestsample is a certain variable which is assigned to > the Input[0] each time a next input sample is received,my concern is how > then to assign these inputs samples to the variable newestsample each > time!!(example,the first round would take newestsample = s0!!, and the > next round after the shifting of s0 it would take s1 at Input[0] and so > on....) > thanks!
I'll give you the same answer that Jerry did but will try to stick to your notation. I am not the best programmer so the goodness of the code should be questioned: you said: /*Input samples*/
> int Input[7] = {s0, s1, s2, s3, s4, s5, s6 ,s7};// array initialization in > C language
I'm going to modify the variable name here for clarity: k=0 /*Buffer samples*/ int Buffer[8]=[s0,s1, s2, s3, s4, s5, s6 ,s7};// array initialization in
> C language
/*Define filter*/ int filter[8]=[f0, f1, f2, f3, f4, f5, f6, f7];// filter initialization /*compute filter output*/ y(k)=s0*f7 + s1*f6 + s2*f5 + s3*f4 + s4*f3 + s5*f2 + s6*f1 +s7*f0 k=k+1 "get newsample" ; however you do this.... s7=s6 s6=s5 s5=s4 s4=s3 s3=s2 s2=s1 s1=s0 s0=newsample; // note the order of replacement. the sample that was in s7 goes away. /*compute filter output*/ y(k)=s0*f7 + s1*f6 + s2*f5 + s3*f4 + s4*f3 + s5*f2 + s6*f1 +s7*f0 ...build this into a loop. But, this is a pretty brute force approach so instead of doing all those replacements, we'll not move the data but index the buffer circularly instead: k=0 /*Buffer samples*/ int Buffer[8]=[s0,s1, s2, s3, s4, s5, s6 ,s7};// array initialization in
> C language
/*Define filter*/ int filter[8]=[f0, f1, f2, f3, f4, f5, f6, f7];// filter initialization /*compute filter output*/ y(k)=s0*f(7) + s1*f(6) + s2*f(5) + s3*f(4) + s4*f(3) + s5*f(2) + s6*f(1) +s7*f(0) "get newsample" ; however you do this.... s(7+k)=newsample; //replaces the sample that will go away with the newest sample// k=k+1 /*compute filter output*/ y(k)=s(0+k)*f(7) + s(1+k)*f(6) + s(2+k)*f(5) + s(3+k)*f(4) + s(4+k)*f(3) + s(5+k)*f(2) + s(6+k)*f(1) +s(7+k)*f(0); // x+k has to be done modulo 8 and I've not shown that ... there are surely "good" programs on dspguru.com // //repeat// "get newsample" ; however you do this.... s(7+k)=newsample; //replaces the sample that will go away with the newest sample so now s(7) is the "zeroeth" sample, s(0) is the 1st sample, s(1) is the 2nd sample ... and s(6) is the 7th sample // k=k+1 /*compute filter output*/ y(k)=s(0+k)*f(7) + s(1+k)*f(6) + s(2+k)*f(5) + s(3+k)*f(4) + s(4+k)*f(3) + s(5+k)*f(2) + s(6+k)*f(1) +s(7+k)*f(0); //so the "beginning" of the data moves through the array as the oldest sample is replaced with the newest sample.// I hope this is clear enough now. Fred
Reply by Jerry Avins October 2, 20052005-10-02
Umutesi Faith wrote:
> I don't mean to be annoying , but here i am again with the same question! > /*Input samples*/ > int Input[7] = {s0, s1, s2, s3, s4, s5, s6 ,s7};// array initialization in > C language > > Input[0] = newestsample > > Knowing that the newestsample is a certain variable which is assigned to > the Input[0] each time a next input sample is received,my concern is how > then to assign these inputs samples to the variable newestsample each > time!!(example,the first round would take newestsample = s0!!, and the > next round after the shifting of s0 it would take s1 at Input[0] and so > on....) > thanks!
Once you understand the what you need to do, the code will seem simple. The naive approach shifts all the data in the buffer each time a new sample is inserted: s7=s6; s6=s5; s5=s4; s4=s3; s3=s2; s2=s1; s1=s0; s0=newsample Now, multiply each sn by the coefficient assigned to it and add the result to an initially zero accumulator. (This step is called a MAC; Multiply and ACcumulate. some processors support it as a single instruction.) The accumulator is the filter output when all the sn have been processed. Then do it again for the next output. One is tempted to code the buffer shift as a loop. Don't bother. Instead, get rid of the shift by using a circular buffer. (Q.V.) Some processors support circular buffering in hardware. circular buffers are not unique to DSP. That are also very useful, for example, for UART operation, especially when the UART service routine is interrupt driven. Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
Reply by Umutesi Faith October 2, 20052005-10-02
I don't mean to be annoying , but here i am again with the same question!
/*Input samples*/
int Input[7] = {s0, s1, s2, s3, s4, s5, s6 ,s7};// array initialization in
C language
   
Input[0] = newestsample

Knowing that the newestsample is a certain variable which is assigned to
the Input[0] each time a next input sample is received,my concern is how 
then to assign these inputs samples to the variable newestsample each
time!!(example,the first round would take newestsample = s0!!, and the
next round after the shifting of s0 it would take s1 at Input[0] and so
on....)
thanks!

>"Umutesi Faith" <ma_nz1@yahoo.com> wrote in message >news:XJGdnSYHAtBNXaPeRVn-qA@giganews.com... >> >> Well, this is the most common form of array initialization in C
language.
>> This array has 8 elements running from s0 to s7! >> My intention was just to make sure if i understood well "the pseudo
code"
>> so that i can continue with fixed ideas in my studying about the FIR >> filter implementation! > >OK - I hope this helped then... > >Fred > > >
This message was sent using the Comp.DSP web interface on www.DSPRelated.com
Reply by Fred Marshall October 1, 20052005-10-01
"Umutesi Faith" <ma_nz1@yahoo.com> wrote in message 
news:XJGdnSYHAtBNXaPeRVn-qA@giganews.com...
> > Well, this is the most common form of array initialization in C language. > This array has 8 elements running from s0 to s7! > My intention was just to make sure if i understood well "the pseudo code" > so that i can continue with fixed ideas in my studying about the FIR > filter implementation!
OK - I hope this helped then... Fred
Reply by Umutesi Faith October 1, 20052005-10-01
Well, this is the most common form of array initialization in C language.
This array has 8 elements running from s0 to s7!
My intention was just to make sure if i understood well "the pseudo code"
so that i can continue with fixed ideas in my studying about the FIR
filter implementation!

>> /*input samples*/
int Input[7] ={s0,s1,s2,s3,s4,s5,s6,s7};
>> >> this would be like Input[0]=xnew; >> How is this "xnew" accessing the data in the Input[7] array? >> Thanks! >> >> Umutesi > >I don't understand your notation. You seem to be using Input as both a >vector and a scalar. That is, an array of multiple elements and an array
of
>1 element. Note that I'm not trying to write code for you, so this is
all
>pseudo code gibberish that you have to put properly into the language of
>your choice. > >I said there is a very brute force and inefficient method that may be >instructive: > >b(n)=b(n-1) >b(n-1)=b(n-2) >. >Fred > > >
This message was sent using the Comp.DSP web interface on www.DSPRelated.com
Reply by Fred Marshall October 1, 20052005-10-01
"Umutesi Faith" <ma_nz1@yahoo.com> wrote in message 
news:quKdnVpLQtqq8aPeRVn-vA@giganews.com...
> Hello > > I have tried to understand this shifting method you discribed below, if > understood it correct ,xnew is the new sample. So if for instance > /*input samples*/ > Input[7] ={s0,s1,s2,s3,s4,s5,s6,s7}; > > this would be like Input[0]=xnew; > How is this "xnew" accessing the data in the Input[7] array? > Thanks! > > Umutesi
I don't understand your notation. You seem to be using Input as both a vector and a scalar. That is, an array of multiple elements and an array of 1 element. Note that I'm not trying to write code for you, so this is all pseudo code gibberish that you have to put properly into the language of your choice. I said there is a very brute force and inefficient method that may be instructive: b(n)=b(n-1) b(n-1)=b(n-2) . . b(1)=b(0) b(0)=xnew where "b()" is the buffer. And, I was assuming this was a streaming implementation - so you get xnew at each time step and don't know what it is beforehand. If you are doing this in something like Matlab and already have all the inputs in memory then it might look like this: inputs=[1 2 3 4 3 4 3 5 6 5 4 3 2 1 2 ...... 8 5 9 3 4 6 9] (and of course the number format can be anything you like - I just showed positive integers because I'm being lazy) Now you have inputs(1) inputs(2), etc. and I will state that inputs(1) is the oldest / first data point / sample. Then convolve the inputs vector with the filter unit sample response. loop k=1 y(k)=inputs(k)*filter(1) + inputs(1+k)*filter(2) .... + inputs(N-1+k)*filter(N) k=k+1 continue until (N-1+k) is the maximum index in the array "inputs" where "filter" is the array of filter coefficients (reversed I believe- that is, filter(N) is the first unit sample output value) and I have left out the startup and ending transient computations altogether for simplicity. In this implementation, the filter slides along the data and the data of interest is whatever lines up with the filter coefficients at each sample time. Since the data is all contained in the vector "inputs", the implementation just changes "k" to move the filter along the data. Fred
Reply by Umutesi Faith October 1, 20052005-10-01
Hello

I have tried to understand this shifting method you discribed below, if
understood it correct ,xnew is the new sample. So if for instance
/*input samples*/
Input[7] ={s0,s1,s2,s3,s4,s5,s6,s7};

this would be like Input[0]=xnew;
How is this "xnew" accessing the data in the Input[7] array?
Thanks!

Umutesi
******************************************************************

Re: Odd symmetric FIR filter - Fred Marshall - 12:57 24-09-05

***So, the software version of one of these would have a number of memory

locations to represent the "buckets" or the locations in the shift
register.
A brute-force method will move the data in the same fashion like this:

b(n)=b(n-1)
b(n-1)=b(n-2)
Reply by Umutesi Faith September 25, 20052005-09-25
Thank you all for your help. I did read quite a lot tutorial about these
FIR filters, but i guess there have been some missing details for me to
understand them properly. With all the help i got from here i hope 
finally to be able to do my implementation! I will keep posting once i get
stuck again!!
 
Umutesi
		
This message was sent using the Comp.DSP web interface on
www.DSPRelated.com
Reply by Fred Marshall September 24, 20052005-09-24
"Umutesi Faith" <ma_nz1@yahoo.com> wrote in message 
news:XYSdnQCIAq5JiKjeRVn-uw@giganews.com...
> It was a typing mistake the FIR filter was intended to be odd symmetric!!
***Actually, I'm not used to the term "odd symmetric" and I'm a little concerned that you could mean: - antisymmetric as in 1 2 3 0 -3 -2 -1 or in 1 2 3 -3 -2 -1 instead of: - odd length *and* symmetric as in 1 2 3 4 3 2 1 That's because the latter is an Even sequence of Odd length (if you define time zero at the center anyway - for discussion purposes) and The former examples are both Odd sequences of Odd or Even length (again if you define time zero at the center).
> Thank you for your replies, at least i can have a small idea on how this > filter was implemented! I'm myself trying to implement a FIR filter,i > cannot use assembler as i don't know much about it, but i can try to do it > in a simple C code, but so far i have found the following steps which are > not obvious to understand : > Basic Algorithm for implementing FIR filters > > -Put the input signal in the delay line.// what do they mean by this ??
***In the olden days the filters operated in continuous time using "analog" delay lines. The delay lines had taps on them (that is, interim output points) The outputs (which include the input and the final output as well as the interim outputs) were each weighted and then all the weighted results were summed to get the filter output.
> -Multiply each sample in the delay line by the corresponding coefficient > and accumulate the result.
***Note that a discrete version of a delay line is a memory. In the not quite so olden days we built FIR filters out of bucket-brigade delay lines (continuous values with discrete "buckets") and we built them out of shift-register types of memories (discrete values ... bits ... with discrete memory registers that were coupled together in a serial manner). Both versions were clocked to accomplish the shifts. So, if the shifting clock rate was the same as the sample rate the data would move along the chain as each new sample entered and as the oldest sample disappeared as it was replaced by the next oldest sample. Note that this ties the sample rate and the delay values together .. which makes sense, eh? ***So, the software version of one of these would have a number of memory locations to represent the "buckets" or the locations in the shift register. A brute-force method will move the data in the same fashion like this: b(n)=b(n-1) b(n-1)=b(n-2) . . b(1)=b(0) b(0)=xnew then multiply the locations by the same coefficients each time A more sophisticated method (look up "circular buffer") avoids moving all the data and moves a reference pointer /offset instead: offset=k; 0<=k<=(n-1) i=k to (n-1)+k modulo n b(k)=xnew then multiply the *offset* locations by the coefficients
> -Shift the delay line by one sample to make room for the next input > sample. > > //this is how i see this algorithm > For instance if the length of the filter is 4 and the number of input > samples is 16, putting the input in the delay does it mean starting from > input[0]?? .
***yes. If the filter is a0 a1 a2 a3 and the data is d0 d1 d2 .... d15 then the multiplies start: y0 = a0*d0 y1 = a0*d1 + a1*d0 y2 = a0*d2 + a1*d1 + a2*d0 y3 = a0*d3 + a1*d2 + a2*d1 + a3*d0 y4 = a0*d4 + a1*d3 + a2*d2 + a3*d1 . . . . . . . . . . y15 = a0*d15 + a1*d14 + a2*d13 + a3*d12 y16 = a1*d15 + a2*d14 + a3*d13 y17= a2*d15 + a3*d14 y18= a3*d15 Note that the filter fills up in N-1, that is, 3 sample times and it "unloads" over 3 samples times. These are startup and ending transients that are of length 1 less than the length of the filter. You might well disregard these outputs.
> For the second step the multiply and accumulate is to sum up the the > multiplication of the input sample and fir coefficients! > So this shifting step , the filtering start at input[1] and the oldest > sample is dropped??
Yes, as above.
> I am not sure if i do understand it in the correct way, why i am so > struggling implementing these filters , are there some tricks to > follow???
The address change vs. actually shifting the data is one. If the filter is symmetrical then you might add two samples and multiply once - assuming that makes any difference in your machine. Then there might be things about scaling and affects in roundoff errors. Then you might modify the coefficients to be sums of powers of two to eliminate multiplies altogether in favor of shifts. Again, it depends on your machine. This works well in FPGA implementations, for example. That is .. a coefficient of 0.50222 might be rounded to 0.5 and a simple shift will replace a multiply. Or, 0.627 would be 0.5 + 0.125 which would be two shifts and and add to replace the multiply. Do read the things that Jerry pointed to. Fred
Reply by Jerry Avins September 24, 20052005-09-24
Umutesi Faith wrote:
> It was a typing mistake the FIR filter was intended to be odd symmetric!! > Thank you for your replies, at least i can have a small idea on how this > filter was implemented! I'm myself trying to implement a FIR filter,i > cannot use assembler as i don't know much about it, but i can try to do it > in a simple C code, but so far i have found the following steps which are > not obvious to understand : > Basic Algorithm for implementing FIR filters > > -Put the input signal in the delay line.// what do they mean by this ?? > -Multiply each sample in the delay line by the corresponding coefficient > and accumulate the result. > -Shift the delay line by one sample to make room for the next input > sample. > > //this is how i see this algorithm > For instance if the length of the filter is 4 and the number of input > samples is 16, putting the input in the delay does it mean starting from > input[0]?? . > For the second step the multiply and accumulate is to sum up the the > multiplication of the input sample and fir coefficients! > So this shifting step , the filtering start at input[1] and the oldest > sample is dropped?? > I am not sure if i do understand it in the correct way, why i am so > struggling implementing these filters , are there some tricks to > follow??? > Thanks > > Umutesi > > This message was sent using the Comp.DSP web interface on > www.DSPRelated.com
You don't need tricks, but you do need to understand the process. You have most of it, with some missing details. Read Chapter 6 in http://www.dspguide.com/ and more starting with Chapter 14. To be sure you understand the details, follow the code examples. When confused, ask more questions here. You will also find good material at http://www.dspguru.com/ and the free on-line courses at http://www.bores.com/. Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;