Crossover design and simulation
% Remco Bloemen % 2009-10-25, last updated 2014-03-04
A friend asked me to design a crossover for his new speakers. I have done this before for my own speakers, which turned out beautifully. I did this using a MatlabOctave simulation of the entire system of filters and speakers. Unfortunatly, I lost this simulation, so join me in recreating it!
Speaker drivers
Woofer: Eminence Kappa 12 Rms power handling: 450 W, Sensitivity: 99.3 dB Frequency range: 62 Hz – 4.2 kHz
Tweeter: Monacor MHD-240 Rms power handling: 40 W Sensitivity: 107 dB Frequency range: 1.5 kHz – 20 kHz
Filter design
Using an online filter generator I got initial values of C = 5.68 µF and L = 0.36 mH for a first order Butterworth at 3.5 kHz.
The response of this filter is:
Looks good doesn’t it? The crossover point is nicely at 3.5 kHz and there is the typical +3 dB hump of a Butterworth crossover with coherent speakers, which is very smooth and should pose a problem. Unfortunately, the graph represents voltages on the terminals, not sound pressures in the room and this is where things get complicated. Brace yourself for a quest to simulate how these speakers would actually sound!
Sensitivity
One parameter I have not yet used is the sensitivity. This number represents how efficiently the speaker converts energy into sound and is measured as the sound pressure level of the speaker at one meter distance when supplied with a signal of 2.83 V_{RMS}.
This means that a signal of 2.83 V_{RMS} in the woofer will produce a sound level of 99.3 dB whereas the tweeter would produce a loud 107 dB. If I take this difference into account the speakers would sound more like:
This is of course unacceptable, the treble is much to loud! Luckily, this can be fixed by putting a resistor in series with the tweeter to dampen it a bit. A value of 11 Ω in series with the 8 Ω tweeters should drop it by about 8 dB. Simulating this results in:
Aaarggh! The crossover point has shifted to 2 kHz and the hump has increased to 5 dB! The high-pass hasn’t shifted down 7dB as I had hoped, instead it just got flatter and shifted left a bit (compare the graphs). The explanation is that the resistor interacts with the filter and changes it’s properties. Clearly the naive use-values-from-a-website approach does not work for crossovers. Let’s go all in and take as much into account as we can.
First, the amplifier. This is easy since audio amplifiers are almost perfect voltage sources, their internal resistance can be ignored, even when they are connected to demanding 4 Ω loads. The impedance of the cables from the amplifier to the speakers will also be ignored, I just can’t see how it would significant enough to produce and audible effect. That said, there are so-called audiophiles that demand nothing less than tube amplifiers (which audibly distort the sound in a pleasant way) and golden cables.
The next thing connected directly to the cables is my filter, which I simulate in full detail. Connected to the filter are the speakers. They can be simulated using their ThieleSmall parameters, but this is only accurate at low frequencies.
Simulating with SPL and impedance curves
To accurately simulate the response of the speaker drivers I use the SPL curves, this can be seen as sensitivity measured for each frequency (the sensitivity varies enormously with frequency, the stated sensitivity is some average over the "usable range"). The SPL curves for any good speakers can be found on the manufacturers site, for the given drivers they are:
The second curve on the graphs is the impedance, it shows how the resistance of the speaker changes with the frequency. The stated 8 Ω is a roughly the minimal resistance in the usable range. Eminence seems to cheat a bit by going as low as 6 Ω, this could in theory harm an amplifier designed for 8 Ω, but pro audio amplifiers are very rugged, so don’t worry.
I digitized these curves using Engauge. This gives me a nice set of numbers to calculate with in Octave (using the QtOctave GUI).
I then redeveloped the simulation I made and lost half a year ago, the source is at the end of this post. The result of the simulation for the filter with C = 5.68 µF, L = 0.36 mH and R = 11 Ω is:
Wow! What a mess! Clearly the SPL and speaker impedance have a large effect on the filter. It almost looks as if the woofer has no filter at all! Let’s look at the voltages across the terminals and just take the stated sensitivities instead of the full SPL curves:
Now things become clearer, the woofers low pass has shifted a few octaves to the right, just like the the tweeters high pass shifted left when I added the resistor. This filter needs a lot of tuning.
Tuning the filter
I tuned the filter by trying out various value of the components, sticking to the preferred numbers from the E12 series. The advantage of these numbers is that they are easy to tune with and components with these values are readily available.
After some heavy tuning, a filter with C = 1.0 µF, L = 1.5 mH and R = 12 Ω gives the flattest response:
But the response is still not very good, if I increase L to dampen the woofers hump at 2.3 kHz it also shifts much of the mid range down. Maybe I should design a second order filter, the higher slope would allow me to tune the hump more precisely.
Furthermore, there are a lot of things not taken into account which are relevant; the enclosure response, the phase response of everything, the ThieleSmall parameters, speaker alignment, off-axis response, etc. The version I lost also calculated the phase of the filter and the power dissipation in the resistor and drivers.
Source
% Simple crossover filters for speakers
% Author: Remco Bloemen, 2009
clear;
% Filter components
C = 1.0E-6 ; % Farad
R = 12; % Ohm
L = 1.5E-3; % Henry
% Create a frequency space
N = 100;
f = logspace(log10(40), log10(22e3), N);
omega = 2 * pi * f;
% Load the SPL and impedance curves
load 'S_tweeter.csv';
S_tweeter = interp1(S_tweeter(:,1), S_tweeter(:,2), f);
load 'S_woofer.csv';
S_woofer = interp1(S_woofer(:,1), S_woofer(:,2), f);
load 'R_tweeter.csv';
R_tweeter = interp1(R_tweeter(:,1), R_tweeter(:,2), f);
load 'R_woofer.csv';
R_woofer = interp1(R_woofer(:,1), R_woofer(:,2), f);
% Calculate the circuit
U_in = 2.83 * ones(1, N);
Z_C = 1 . (i * omega * C);
Z_R = R * ones(1, N);
Z_L = i * omega * L;
I_tweeter = U_in . (Z_R + R_tweeter + Z_C);
I_woofer = U_in . (R_woofer + Z_L);
U_tweeter = abs(I_tweeter .* R_tweeter);
U_woofer = abs(I_woofer .* R_woofer);
% Calculate the SPL curves, add coherently
spl_tweeter = S_tweeter + 20 * log10(U_tweeter . 2.83);
spl_woofer = S_woofer + 20 * log10(U_woofer . 2.83);
spl = 20 * log10(10.^(spl_tweeter 20) + 10.^(spl_woofer 20));
figure; hold on;
title('Fine-tuned response');xlabel('Frequency [Hz]'); ylabel('Sound pressure level [dB re]');
grid on; xlim([40, 22e3]); ylim([80, 110]);
set(gca, 'XTick', [40,60,80,100,150,200,300,400,600,800,1000,1500,2000,3000,4000,6000,8000,1e4,15e3,2e4]);
semilogx(f, spl_tweeter,'r');
semilogx(f, spl_woofer,'b');
semilogx(f, spl, 'linewidth', 2, 'color', [0,0,0]);
Nice tutorial! You have used some new programs too. I’ll check them out. To reduce the bump in the middle: have you tried switching + and
- of the tweeter?
— Fred van Dam 2010-03-18
Thanks! Switching the + and - would be equivalent to a 180 degree phase shift. Now, if the tweeter and woofer are completely in phase, you can just add the amplitudes, if they are 180 degree out of phase, you need to subtract them.
The problem is, in real life, the phase difference also depends on the physical distance between the drivers, which in turn depends on your cabinet design, your listening position and the frequency. At 3 kHz it takes only 5 centimetres of difference for a 180 degree phase shift.
So in this case (I didn’t have the cabinet design) I have completely no knowledge about the phase relation between the tweeter and the woofer. It’s been a while, but I believe I treated them as uncorrelated signals (i.e. no-phase relation). I think this is a reasonable assumption, considering that these are party speakers, to be listened from various positions.
— Remco Bloemen 2010-03-18