I had been looking for a good DC noise filter and stumbled upon the "DSP
Trick: Fixed-Point DC BlockingFilter With Noise-Shaping" entry on dspguru.
I have minimal signal processing experience, so I was looking for
something
I could drop into my application. I needed to filter out, in real-time,
the
DC offset from a low frequency (variable 2-15Hz) sinusoidal. I tried to
****t the algorithm for single word input and output but the resultant
output did not seem to converge. My input is an unsigned 16-bit INT, and I
tried to adapt the algorithm to that. I tried two different
implementations. One was a near direct ****t of the C implementation, the
other was a ****t of the 'y[n] & e[n]' algorithm. The second version seemed
to produce better results but neither worked. I was hoping that someone
might be able to offer some recommendations for fixing/correcting whatever
mistakes I made.
Version #1 - The input is in the range of 44000 with a swing of about
400-600 around that center. When I examined the output, the sequence
seemed
to randomly switch between relatively small positive and negative numbers
(~+/- 50).
#define kPole ((float) 0.9999)
#define kGain ((uInt32) (32768.0 * (1.0 - kPole)))
static Int32 si32PreviousInput =0, si32PreviousOutput =0;
Int16 i16DcBlockingFilter(uInt16 ui16Input)
{
Int32 i32Ac***ulator =0;
i32Ac***ulator -= si32PreviousInput;
si32PreviousInput = ((Int16) (ui16Input>>1)); // convert to a
signed Int16
si32PreviousInput = (si32PreviousInput << 15);
i32Ac***ulator += si32PreviousInput;
i32Ac***ulator -= kGain * si32PreviousOutput;
si32PreviousOutput = i32Ac***ulator >> 15; // quantization
happens here
return (Int16) si32PreviousOutput;
}
Version #2 - Again, same input range. Here the output started in the 22000
range but gradually and inexplicably decreased by ~10 each time the
routine
was called. In this version, I was not sure if I had properly implemented
either the Output or Error terms. The algorithm suggested that e[n] be
included in the y[n] calculation and that y[n] be included in the e[n]
calculation. This seemed like a circular reference to me, but I coded it
in
that manner.
#define kPole ((float) 0.9999)
#define kGain ((uInt32) (32768.0 * (1.0 - kPole)))
Int16 si16ErrorTerm =0, si16ErrorTermLast =0;
uInt16 sui16Output =0, sui16PreviousOutput =0;
uInt16 sui16PreviousInput =0;
uInt16 ui16DcBlockingFilter(uInt16 ui16Input)
{
sui16Output = ((kPole*sui16PreviousOutput) +
(ui16Input - sui16PreviousInput) -
si16ErrorTermLast) +
si16ErrorTerm;
si16ErrorTerm = sui16Output -
( (kPole*sui16PreviousOutput) +
(ui16Input - sui16PreviousInput)
-
si16ErrorTermLast);
si16ErrorTermLast = si16ErrorTerm;
sui16PreviousInput = ui16Input;
sui16PreviousOutput = sui16Output;
return sui16ThoraxOutput;
}
Any help would be most appreciated.
Sincerely,
gsam


|