DSPRelated.com
Forums

What are all the "really efficient" filter algoritms?

Started by Tony March 3, 2009
I've played with several "standard" generalized routines for up- and down-sampling of
audio, and now I want to get into the ones that really are more efficient in hardware or
software - haven't decided yet - just know I want the most grunt for the least power, and
because I'll be introducing nonlinearities and don't want artifacts.

I presume I'll want to resample by factors of 2^n, which is OK as that would work well
with interleaved code, and the design is still wide open. Any suggestions for links that
might help me?

The subject has also intrigued me on a more general level, and I'd like to explore even
those algorithms that don't directly relate to the proposed project.

Cheers, Tony
Tony wrote:

> I've played with several "standard" generalized routines for up- > and down-sampling of audio, and now I want to get into the ones > that really are more efficient in hardware or software - haven't > decided yet - just know I want the most grunt for the least > power, and because I'll be introducing nonlinearities and don't > want artifacts.
Perhaps you've seen them before, but I've been satisfied with the polyphase-IIR halfband filters at http://www.musicdsp.org/archive.php?classid=3#39 . That code provides only single-rate processing, so you'll want to add rate-changing operations that actually exploit the polyphase structure. Here's how. Note that I'm writing this from the top of my head because I use my own adaptation of Dave Malham's code. I list the original single-rate processing first for comparison, then the additions: double CHalfBandFilter::process(const double input) { const double output=(filter_a->process(input)+oldout)*0.5; oldout=filter_b->process(input); return output; } double CHalfBandFilter::decimate(const double* input) { const double output = (filter_a->process(input[0]) + oldout)*0.5; oldout = filter_b->process(input[1]); return output; } void CHalfBandFilter::interpolate(const double input, double* output) { input *= 0.5; output[0] = filter_a->process(input); output[1] = filter_b->process(input); } Martin -- Quidquid latine scriptum est, altum videtur.
On Mar 3, 1:35&#4294967295;pm, Martin Eisenberg <martin.eisenb...@udo.edu> wrote:
> Tony wrote: > > I've played with several "standard" generalized routines for up- > > and down-sampling of audio, and now I want to get into the ones > > that really are more efficient in hardware or software - haven't > > decided yet - just know I want the most grunt for the least > > power, and because I'll be introducing nonlinearities and don't > > want artifacts. > > Perhaps you've seen them before, but I've been satisfied with the > polyphase-IIR halfband filters athttp://www.musicdsp.org/archive.php?classid=3#39. That code provides > only single-rate processing, so you'll want to add rate-changing > operations that actually exploit the polyphase structure. > > Here's how. Note that I'm writing this from the top of my head > because I use my own adaptation of Dave Malham's code. I list the > original single-rate processing first for comparison, then the > additions: > > double CHalfBandFilter::process(const double input) > { > &#4294967295; const double output=(filter_a->process(input)+oldout)*0.5; > &#4294967295; oldout=filter_b->process(input); > &#4294967295; return output; > > } > > double CHalfBandFilter::decimate(const double* input) > { > &#4294967295; const double output = (filter_a->process(input[0]) + oldout)*0.5; > &#4294967295; oldout = filter_b->process(input[1]); > &#4294967295; return output; > > } > > void CHalfBandFilter::interpolate(const double input, double* output) > { > &#4294967295; input *= 0.5; > &#4294967295; output[0] = filter_a->process(input); > &#4294967295; output[1] = filter_b->process(input); > > } > > Martin > > -- > Quidquid latine scriptum est, altum videtur.
You need to first choose whether or not linear phase is important to you (or your customer). This should be simply a matter of science (that is, what do controlled listening tests say?) but like many topics in audio you will encounter those who adhere to one view or another with a conviction approaching religious fervor. You need to decide this first because the hardware implementations for IIR versus FIR is very different. You should be very skeptical of Matlab results that say, "filter A needs 20 multipliers and 30 adders, whereas filter B needs 15 multipliers and 20 adders, therefore filter B will be cheaper to implement". Anyone with any real experience in this area knows enough to disregard such advice; the bag of tricks that can be brought to bear is quite large. Bob Adams
On 3 Mar, 07:55, Tony <t...@nowhere.com> wrote:
> I've played with several "standard" generalized routines for up- and down-sampling of > audio, and now I want to get into the ones that really are more efficient in hardware or > software - haven't decided yet - just know I want the most grunt for the least power,
What does 'power' mean? Watts or computational capacity?
> and > because I'll be introducing nonlinearities and don't want artifacts.
That's happens only in the ideal world. In the real world your task is to decide what artifacts you can live with. Rune
> Here's how. Note that I'm writing this from the top of my head > because I use my own adaptation of Dave Malham's code. I list the > original single-rate processing first for comparison, then the > additions: > > double CHalfBandFilter::process(const double input) > { > const double output=(filter_a->process(input)+oldout)*0.5; > oldout=filter_b->process(input); > return output; > } > > double CHalfBandFilter::decimate(const double* input) > { > const double output = (filter_a->process(input[0]) + oldout)*0.5; > oldout = filter_b->process(input[1]); > return output; > } > > void CHalfBandFilter::interpolate(const double input, double* output) > { > input *= 0.5; > output[0] = filter_a->process(input); > output[1] = filter_b->process(input); > }
That's interesting. If I decimate into low and high pass, then add these together, would that be a perfect reconstruction? By high pass, I subtract the oldout like: double CHalfBandFilter::decimateHigh(const double* input) { const double output = (filter_a->process(input[0]) - oldout)*0.5; oldout = filter_b->process(input[1]); return output; } Is that correct? Thanks, VC
Martin Eisenberg wrote:

> http://www.musicdsp.org/archive.php?classid=3#39
> Note that I'm writing this from the top of my head because I use > my own adaptation of Dave Malham's code.
What I forgot about -- Dave's code directly follows the polyphase formula H(z) = A(z^2) + B(z^2)/z where A(z) and B(z) are cascades of 1st-order allpasses, and thus implements 2nd-order allpass stages with a zero coefficient on the z^(-1) terms. In contrast, the multirate functions I gave assume that the subfilters implement the 1st-order cascades A(z), B(z) as such. This means that the multirate and single-rate versions are going to be separate classes with different CAllPassFilter member types. Still, decimate() and interpolate() can be in the same class (but not sensibly used on the same object without clearing state in between). Martin -- Quidquid latine scriptum est, altum videtur.
VelociChicken wrote:

> If I decimate into low and high pass, then add these together, > would that be a perfect reconstruction?
That doesn't make sense; I presume you meant adding the channels after interpolating again. Then the answer is No due to nonlinear phase, though there's no magnitude distortion. You got the highpass formation right, and it makes the band filters a QMF pair. Hence, with H(z) denoting either one of them, the perfect- reconstruction condition is H(z)^2 - H(-z)^2 = a*z^d for some constants a,d. That is, the overall analysis-synthesis system must amount to a pure delay and gain. This fails in the present case, as the condition's left-hand side simplifies to a nontrivial allpass. A quick source for the QMF PR condition would be [1] eq. 11.7 -- but note that shouldn't say "constant" on the lhs, as seen by comparing with [2] 11.4 which 11.7 instantiates. [1] http://ccrma.stanford.edu/~jos/sasp/Quadrature_Mirror_Filters_QMF.html [2] http://ccrma.stanford.edu/~jos/sasp/Two_Channel_Critically_Sampled_Filter.html Martin -- Quidquid latine scriptum est, altum videtur.
>> If I decimate into low and high pass, then add these together, >> would that be a perfect reconstruction? > > That doesn't make sense; I presume you meant adding the channels > after interpolating again. Then the answer is No due to nonlinear > phase, though there's no magnitude distortion. > > You got the highpass formation right, and it makes the band filters a > QMF pair. Hence, with H(z) denoting either one of them, the perfect- > reconstruction condition is H(z)^2 - H(-z)^2 = a*z^d for some > constants a,d. That is, the overall analysis-synthesis system must > amount to a pure delay and gain. This fails in the present case, as > the condition's left-hand side simplifies to a nontrivial allpass. > > A quick source for the QMF PR condition would be [1] eq. 11.7 -- but > note that shouldn't say "constant" on the lhs, as seen by comparing > with [2] 11.4 which 11.7 instantiates. > > [1] http://ccrma.stanford.edu/~jos/sasp/Quadrature_Mirror_Filters_QMF.html > [2] > http://ccrma.stanford.edu/~jos/sasp/Two_Channel_Critically_Sampled_Filter.html > > Martin
Thank-you for your thoughtful and helpful reply Martin. Cheers.
Robert Adams wrote:

> You need to first choose whether or not linear phase is > important to you (or your customer). This should be simply a > matter of science (that is, what do controlled listening tests > say?) [...]
How will Tony test filters he doesn't have? Martin -- Quidquid latine scriptum est, altum videtur.