Page 2 of 4

Re: Hilbert Shifter

PostPosted: Mon Dec 29, 2014 12:08 am
by martinvicanek
Yes, same structure but higher degree. I'll post a non optimized schematic tomorrow, hopefully easier to understand.

Re: Hilbert Shifter

PostPosted: Mon Dec 29, 2014 8:06 am
by martinvicanek
Here you go. Notice that Olli Niemitalo's coefficients enter squared.

Re: Hilbert Shifter

PostPosted: Mon Dec 29, 2014 10:17 pm
by cbbuntz
Thanks. I'm not sure where I went wrong. I've noticed you get significantly better performance on Olli's version if you square the coefficients before converting to 32 bit. I have a version of his that is close to linear phase (as in all frequencies -90 degrees) using a backwards IIR with one half of the coefficients and normal allpass with the other half. I post it here if I get it working. It could use some optimization.

The backwards filter is something I came up with. It is made by a series of delays spaced at powers of 2. For every power of 2 delay, the coefficient is squared. You can also use a similar method to make lowpass filters with low cutoffs with quite low roundoff error. Here's a version of Olli's coefficients.

Re: Hilbert Shifter

PostPosted: Tue Dec 30, 2014 4:37 am
by cbbuntz
Here are some more examples of stuff with that filter structure. I've got lots of different versions of it (some of them rather old) and I didn't test them before uploading but I think they should work fine. I made a simplified example so that it would be easier to follow what I'm doing.

One advantage of this filter structure is that you can do backwards filters without reversing windows, and since it only contains log 2 n summations, rounding error should be reduced. A disadvantage is that you are limited to 1st order filters (maybe there's a way to do complex poles, but I haven't found anything that works well). I really could use some help optimizing this. A while back I tried making a version with a single array and I never got it to behave right and the code got really messy. It would be simple if there was a way to shift array indices.

Re: Hilbert Shifter

PostPosted: Tue Dec 30, 2014 12:40 pm
by Tronic
Hi cbbuntz,
any lecture for your Backwards filter technique?

Backwards FIlter Structure

PostPosted: Tue Dec 30, 2014 6:15 pm
by martinvicanek
Hey cbbuntz,

thanks for sharing your stuff, although I must admit that I have absolutely no clue how your filter works, even after spending quite a while with your schematic. :oops: All I can say that your mixed phase crossover does work, the bands split nicely at the correct frequencies and they add up to unity. Very cool! 8-)

There is room for optimization, though. Regarding delays check out KohuGaly's post in the Downloads section at Flowstone Guru. tan(x) etc. can be evaluated much faster, check out my Math Functions download at FS Guru.

I am still intrigued by your schematic, it is clear that you have put a lot of brains and effort into it, however I don't even understand the very basic idea behind it. :o :? :oops: Please could you explain, or point to a reference?

Re: Hilbert Shifter

PostPosted: Mon Jan 05, 2015 3:48 am
by cbbuntz
I made a new one with your 16th order coefficients and I optimized the filter with asm. The impulse response looks very "correct" with your coefficients and the CPU hit is nearly 1/4th of what it was! I modified the code from one of the optimized delay code generators.

I'm glad you like the crossover. I found it pretty cool that a 3rd order Butterworth with the 1st order section backwards behaves like a 1st order filter in terms of phase response, so you can get complimentary hp/lp sections my simply subtracting the input from the filter.

I realized my simplified example was wrong after I uploaded it. Each delay needs to be summed before the next delay is applied. My filter takes advantage of the fact that in an exponential decay, the decay is squared. Let's say the decay is 0.5, and I use the forward version to keep things from being confusing.

a1 = 0.5
a2 = a1 * a1
a3 = a2 * a2
a4 = a3 * a3

y1 = in + delay1 * a1
(then delay y1 by 2)
y2 = y1 + delay2 * a2
(then delay y2 by 4)
y3 = y2 + delay4 * a3
(then delay y3 by 8)
y4 = y3 + delay8 * a3

If you want to reverse the filter, you simply swap where the coefficients go
y1 = in * a1 + delay1
y2 = y1 * a2 + delay2
y3 = y2 * a3 + delay4
y4 = y3 * a3 + delay8

I've tried reversing buffers and filtering those but I hate the the impulse response changes as the windows "fade" in and out.

Re: Hilbert Shifter

PostPosted: Mon Jan 05, 2015 11:52 pm
by martinvicanek
OK thanks. I undertand the exponetial decay example. That would explain how to implement a leaky integrator (just one single real pole). How do you go about multiple poles or complex conjugate poles as in biquads?

Re: Hilbert Shifter

PostPosted: Tue Jan 06, 2015 6:56 pm
by martinvicanek
cbbuntz, I realized that your filter is actually a true Hilbert transformer, as opposed to my original allpass network! :o
KG, that's what you had asked for! ;)
So I took the oportunity to optimize some more and managed to reduce CPU load by another factor 3 or so. It is still more CPU hungry than my allpass network, but certainly much lighter than an equivalent FIR filter would be. Good job, cbbuntz! :geek:

Re: Hilbert Shifter

PostPosted: Tue Jan 06, 2015 8:42 pm
by KG_is_back
This is truly very interesting. Still trying to understand how it works, but obviously it does. exactly what I was looking for!