I'm trying to model a sensor system that has an averaging behaviour. The frequency response is almost identical to a box filter and looks roughly like this:
Transferring this into a discrete time model would require a box filter of non-integer length - e.g. $N=2.5$ samples. Now I am looking for ways to model this system.
Here are my attempts and why they failed for me:
1. Ordinary Lowpass
As the desired frequency response has a lowpass characteristic, it would seem logical to try a lowpass filter first. However, they fail to reproduce the zero found in the desired frequency response. Also, they end in a zero at nyquist, which is not wanted.
2. Interpolated box filter
Using the impulse response $h[i] = [1, 1, f]$ where $0 < f < 1$ allows me to approximte a box filter with $N$ somewhere between 2 and 3. Here are the frequency responses of these filters for $Fs = 24kHz$ and $f = 0, 0.1, 0.2, ... , 1$:
The problem is that the attenuation only approaches zero for $N=2$ and $N=3$. For anything in between it becomes way less with the worst being $N=2.5$ where the attenuation is only about -16dB.
3. Downsampled Box Filter:
I designed the desired box filter for a higher samplerate, e.g. oversampled by a factor of $S=32$. Then I lowpass-filtered it with a windowed-sinc and got these impulse responses:
I downsampled this to my original samplerate by keeping only the samples $S/2 + i*S$ and got these impulse responses:
However, the frequency responses of this look very similar to the simple "interpolated" filters from attempt #2. They are so similar, that it doesn't even make sense to add another picture here. The major difference is a significantly higher computational load and an additional processing delay. Increasing the size of the windowed sinc lowpass kernel doesn't actually improve things much, it only adds additional delay due to the pre-ringing.
4. Crude oversampling
The idea was to interpolate $S$ samples for each actual sample and apply the box filter to these. I used 4-point interpolation that accounts for samples $i-1, i, i+1, i+2$ for each output sample at a position between $i$ and $i+1$. I can then re-arrange the formula to calculate the specific contribution of each input sample to the final output value like this:
h = zeros(ceil(N) + 2)
totalNumOversampledSamples = S * N
for i = 0 .. totalNumOversampledSamples:
samplePosition = i / S
intSamplePosition = floor(samplePosition)
fractional = samplePosition - floor(samplePosition)
// get interpolation coefficients for a 4pt interpolation
a,b,c,d = getInterpolationCoefficients(fractional)
// add those to the impulse response
h[intSamplePosition - 1] += a
h[intSamplePosition] += b
h[intSamplePosition + 1] += c
h[intSamplePosition + 2] += d
// normalize
h /= sum(h)
(I assumed the first $S$ samples to not be interpolated to avoid adding another coefficient to the front of my impulse response)
The resulting filter is quite efficient, but unfortunately, the resulting frequency response is pretty bad - probably due to the poor interpolation scheme used:
5. Additional thoughts
I though of upsampling my input data, then applying an ordinary box filter to it before downsampling again. With this method, I could actually realise a "fractional length" box filter because in the upsampled domain, the box filter can be of integer length. However, this operation is entirely linear, so it should be possible to transform the same operation to an ordinary FIR filter and skip the upsampling step - which I did attempt in my 3rd approach. I am not sure why it didn't work.
Here's the actual question:
How could I model this system to fulfill these criteria:
- Keep the characteristic shape, especially the "zero" of the desired transfer function, or at least a high attenuation.
- Be able to "sweep" the zero(s) across the frequency spectrum much like it would be possible with a "moving average" filter in a continuous-time system.
- Keep computational load within reason (this must be able to run in real time)
- Phase response is not important