Why not IIR filters + a global phase linearization by FIR

An analog or IIR lowpass has a more or less constant group-delay within its pas pand while the "constant" group-delay region of a higpass lies below its passband..
There is quite some effort needed to EQ those to flat group-delay so it isn't impossible....
But the group delay of the HPF is not a "delay",...
The following is a second order Bessel highpass filter (1kHz cutoff) whose phase has been cleaned out all the way to 20kHz. The blue trace is the uncompensated filter.

1729976037863.png


Code:
%HIGHPASS
freq1 = 1000;
Q = 1/sqrt(3);
wc = 2*pi*freq1;                                                               % Cutoff frequency  
hpf = tf([1,0,0],[1, wc/Q, wc*wc]);                                     % analogue highpass transfer function

%ALLPASS1
freq = 3000;
Q = 1;
wc = 2*pi*freq;                                                            
apf1 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function

%ALLPASS2
freq = 5500;
Q = 1.8;
wc = 2*pi*freq;                                                              
apf2 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function

%ALLPASS3
freq = 8500;
Q = 2.6;
wc = 2*pi*freq;                                                              
apf3 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function

%ALLPASS4
freq = 11000;
Q = 3.9;
wc = 2*pi*freq;                                                             
apf4 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function

%ALLPASS5
freq = 14000;
Q = 5;
wc = 2*pi*freq;                                                             
apf5 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function

%ALLPASS6
freq = 17000;
Q = 6.3;
wc = 2*pi*freq;                                                                           
apf6 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function

%ALLPASS7
freq = 19500;
Q = 9;
wc = 2*pi*freq;                                                                       
apf7 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function


apf = apf1*apf2*apf3*apf4*apf5*apf6*apf7;


% DISPLAY
options = bodeoptions;                                                     % bode plot
options.FreqUnits = 'Hz';
options.XLim = [10,20000];
options.YLim = [-2700,0];
options.grid = 'On';
options.Freqscale ='Linear';
options.MagVisible = 'Off';
options.PhaseWrapping = 'Off';
options.PhaseMatching = 'On';

figure(1)    
bode(-hpf,-hpf*apf,options);
 
Yep, that's my take on phase audibility too. Seems recent research is leaning towards the lower the frequency, the more likely the audibility.

I tried listening to LR4-style phase rotations at 100 Hz and 250 Hz: the latter could be heard as a flattening of the crack of a snare drum, whereas removing 100 Hz phase rotation made bass guitar and kick drum more distinct. The 250 Hz seemed more noticeable, however.

That could be part of the reason why full-range fans consider their speakers more lively than big multiway systems. I heard it myself at an early BAF, where a recording was so compelling I had to find out what was making that lovely sound. Perhaps it wasn't the flattest frequency response but the thing was there.
 
  • Like
Reactions: savan
...how did you determine the parameters for those allpass filters, and if you plot the group delay, how close is it to equiripple?
I did a manual, and I coudn't find anything in MATLAB that shows the GD of a 'tf' object (if you know, please help). It'd be nice to see the GD and what adjustments need to be made to get it to equiripple. The target GD ripple would also tell the user the number of biquads needed for the job.

Isn't that a low pass?
The numerator and denominator vectors carry the coefficients in the order of decreasing power (of 's') giving a highpass transfer. A lowpass would have to be tf ( [wc*wc] , [1, wc/Q, wc*wc] ) or tf ( [0, 0, wc*wc] , [1, wc/Q, wc*wc] ) ...
 
.... if you plot the group delay, how close is it to equiripple?
Figured the GD, new tunings below. Again this was manual, by hand but your curve fitting software might do better like maybe smaller allpass for same GD ripple etc.

1730020894894.png


1730020951626.png


Code:
f = 1:10:22000;

%HIGHPASS
freq1 = 1000;
Q1 = 1/sqrt(3);
wc = 2*pi*freq1;                                                            % Cutoff frequency 
hpf = tf([1,0,0],[1, wc/Q1, wc*wc]);                                    % analogue lowpass transfer function
[num, den] = tfdata(hpf,'v'); 
h = freqs(num,den,2*pi*f);
gd = -diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS1
freq = 2600;
Q = 1.1;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf1 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf1,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS2
freq = 4650;
Q = 1.95;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf2 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf2,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS3
freq = 6800;
Q = 2.75;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf3 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf3,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS4
freq = 9050;
Q = 3.6;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf4 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf4,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS5
freq = 11300;
Q = 4.7;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf5 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf5,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS6
freq = 13500;
Q = 5.5;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf6 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf6,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS7
freq = 15700;
Q = 6.5;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf7 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf7,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS8
freq = 17850;
Q = 7.6;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf8 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf8,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

%ALLPASS9
freq = 19800;
Q = 10;
wc = 2*pi*freq;                                                            % Cutoff frequency 
apf9 = tf([1, -wc/Q, wc*wc],[1, wc/Q, wc*wc]);                          % analogue allpass transfer function
[num, den] = tfdata(apf9,'v'); 
h = freqs(num,den,2*pi*f);
gd = gd-diff(unwrap(angle(h)))./diff(2*pi*f);

apf = apf1*apf2*apf3*apf4*apf5*apf6*apf7*apf8*apf9;


% DISPLAY
options = bodeoptions;                                                     % bode plot
options.FreqUnits = 'Hz';
options.XLim = [10,20000];
options.YLim = [-3250,0];
options.grid = 'On';
options.Freqscale ='Linear';
options.MagVisible = 'Off';
options.PhaseWrapping = 'Off';
options.PhaseMatching = 'On';

figure(1)   
bode(-hpf,-hpf*apf,options);

gd(length(f))= 0;
figure(2)
plot(f,gd*1000);
Xlim([1,22000]);
Ylim([0,1]);
grid on; grid minor;
XLabel('Frequency (Hz)');
YLabel('Group delay (ms)');
 
  • Like
Reactions: DSP_Geek
I coudn't find anything in MATLAB that shows the GD of a 'tf' object (if you know, please help)
I don't think that there's any direct method. You could use tf2zp() to find the zeroes and poles, use those to determine the transfer function polynomials, then use grpdelay() to compute the group delay.

EDIT: tf2sos() is an alternative; it will return second-order sections.
 
  • Thank You
Reactions: newvirus2008
I do have to say, having analyzed lots and lots of different MDS crossover configurations: a linear-phase 4th-order Linkwitz-Riley response is very hard to beat for the compromize between transition band slopes and impulse response duration.
For the handful of MDS crossovers I compared against linear-phase LR4s, I thought the LR4s were compelling both for straightforward simplicity, and for ease of implementation.
Given my DIYs are usually 4-5 way, both of those comparative factors become even more important for me.
Sometimes, I'm not sure why I stay curious about IIR, LoL and sigh.

That said, right now I'm playing with straight IIR EQs using them as mag and phase flattening prior to lin-phase xovers in a FIR file.
(as opposed to just embedding the min-phase flattening EQ's into the FIR file)
Clearly helps with low-frequency work given tap count limitations and a desire to reduce latency.

I've found an auto-IIR filter generator, much like REW's auto-EQ, but that has considerably greater capability. It allows over a hundred discrete EQ's to be used with whatever chosen level of smoothing. Generates a set of biquads, for import into a qsys DSP which can handle up to 256 biquads per channel.

If desired, the auto-IIR can flatten mag and phase with a precision that rivals FIR's effective impulse inversion !


I'd like to see some guru come up with an auto-IIR generator that can both flatten in-band response and also match acoustic xover targets.
Iow, like FIR can do, but all via IIR. Would be a killer home run I think (for folks who want to stay away from FIR haha)
 
My question was whether anyone had done a subtractive delay crossover with a defined HPF and the LP derived from that, as described above. The dual of Lipshitz & Vanderkooy, similar to Berchin's but continuous time.
Using the phase linearisation allpass chain from post #809, I've calculated two MDS crossovers in the continuous s-domain, one each, using the HPF and then the LPF as the basis filter. Note that the filters have been squared to the 4th order and are therefore not Bessel (Q = 0.577) anymore. However, I believe the results would be more or less the same with another kind of filter.

Hope that helps.


1730044771762.png



1730044817867.png
 
The basic subtractive crossover construction is straight forward.

TF(HP,LP)= exp(jwTd) - TF(LP,HP), where TF(A,,B) means either A or B.

As @gberchin said, how it's implemented is irrelevant.

In the case where the "base" filer, (on the right of the equation) is linear phase, the "subtractive" filter will also be linear phase provided that Q of the base filter is less than or equal to 0.707... and it matters not whether the base filter is HP or LP. The summed response will be linear phase. For Q greater than 0.707.... the subtractive filter will have a notched response in the stop band and it's phase will flip 180 degrees at the notch, but the summed response will remain linear phase.

However, it may be of interest that that if the base filter (the one on the left) is linear phase with Butterworth amplitude, (LP or HP), and Td is the delay of that filter, the subtractive filter, (HP or LP) will roll off at twice the the rate of the base filter.

I have attached a paper I wrote back in 2002 on the subject of SD filters based on linear phase base filters for those interested.

But it should be recognized that removing nonlinear GD from filter is not the ultimate goal. You stll have to deal with the GD inherent to the drivers due to their minimum phase behavior.
 

Attachments

However, it may be of interest that that if the base filter (the one on the left) is linear phase with Butterworth amplitude, (LP or HP), and Td is the delay of that filter, the subtractive filter, (HP or LP) will roll off at twice the the rate of the base filter.
Now that is very interesting! For my paper I only studied linear-phase Linkwitz-Riley responses, because LR is so prevalent in the current audio world. Your observation opens-up a whole new world of possibilities.

But it should be recognized that removing nonlinear GD from filter is not the ultimate goal. You stll have to deal with the GD inherent to the drivers due to their minimum phase behavior.
Yes. It remains to be seen whether it's better to separate the driver compensation from the crossover response, and design each separately, or to try to incorporate both into one overall filter design.
 
Hello,

Please ignore post #815 above as there was an error in my script. Both HP and LP work well as the basis filter as long as their group delays are matched to that of the delay line. Sorry for the mistake.

In the case where the "base" filer, (on the right of the equation) is linear phase, the "subtractive" filter will also be linear phase provided that Q of the base filter is less than or equal to 0.707... and it matters not whether the base filter is HP or LP. The summed response will be linear phase.
What if the base filter is HP and not linear phase and we do an MDS using the pure delay ? Would you get the LPF output as usual ? I'm asking this because I do not seem to get anything that resembles an LPF, in either continuous (below) or discrete (post# 783) domain.

Now, if what I'm getting is what it really is, then it

  • clearly violates the conventional wisdom that either filter, HP or LP, could be used as the base filter.
  • makes @Dave Zan 's question about MDS crossovers more relevant.
  • probably needs to be included in @gberchin 's MDS paper.

1730127980543.png
 
Last edited:
  • Like
Reactions: Dave Zan