php-crossover-calculator/public/index.php
2021-05-10 23:32:04 +02:00

154 lines
6.1 KiB
PHP

<?php
const FORM_METHOD = 'GET'; // or 'POST'
const FALLBACK_DRIVER_IMPEDANCE = 4.;
const TWO_PI = 2. * 3.1415926535;
const FREQ_MIN = 500.;
const FREQ_MAX = 16000.;
$form = FORM_METHOD === 'POST' ? $_POST : $_GET;
$form_submitted = !empty($form);
$tweeter_impedance = $woofer_impedance = FALLBACK_DRIVER_IMPEDANCE;
if ($form_submitted) {
$tweeter_impedance = @(float)($form['tweeter_impedance']) ?: FALLBACK_DRIVER_IMPEDANCE;
$woofer_impedance = @(float)($form['woofer_impedance']) ?: FALLBACK_DRIVER_IMPEDANCE;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>First-order crossover component calculator</title>
<style>
* {
font-size: 12pt;
font-family: sans-serif;
line-height: 1.5;
color: #EED;
background-color: #22222A;
max-width: 1024px;
}
.narrow {
width: 80%;
}
.with-breating-room {
margin: 1.5em 1em;
}
.right-aligned {
text-align: right;
}
.explaining {
margin-top: 2rem;
margin-bottom: 1rem;
font-style: italic;
}
.source {
margin-top: 1rem;
margin-left: 1rem;
}
.monospace {
font-family: monospace;
}
.bordered {
border: 1px solid;
border-color: #666674;
border-collapse: collapse;
}
.height-padded {
padding-top: 0.45rem;
padding-bottom: 0.45rem;
}
.left-padded {
padding-left: 1rem;
}
.right-padded {
padding-right: 1rem;
}
.width-padded {
padding-left: 1rem;
padding-right: 1rem;
}
.underlined {
border-bottom: 1px solid #888;
}
</style>
</head>
<body>
<div class="with-breating-room">
This is a simple component calculator for a first-order crossover.
Component values are calculated with the following formulae:
<div class="with-breating-room height-padded">
<span class="monospace">C = 1 / (2 * π * f * R)</span><br/>
<span class="monospace">L = R / (2 * π * f)</span>
</div>
</div>
<div class="with-breating-room explaining underlined">
First-order filters have a 20 dB/decade (or 6 dB/octave) slope.
All first-order filters have a Butterworth filter characteristic.
[...]
First-order filters are considered by many audiophiles to be ideal for crossovers.
This is because this filter type is 'transient perfect',
meaning it passes both amplitude and phase unchanged across the range of interest.
[...]
In practice, speaker systems with true first-order acoustic slopes are difficult to design
because they require large overlapping driver bandwidth,
and the shallow slopes mean that non-coincident drivers interfere
over a wide frequency range and cause large response shifts off-axis.
<br/>
<div class="with-breating-room source">
From Wikipedia: <a href="https://en.wikipedia.org/wiki/Audio_crossover">Audio Crossover</a>
</div>
</div>
<div class="with-breating-room underlined height-padded">
<form class="height-padded" action="" method="<?php echo FORM_METHOD; ?>">
<table>
<tr>
<td class="height-padded right-padded">Tweeter impedance (Ω):</td>
<td class="height-padded">
<input class="monospace left-padded" type="number" min="0.5" step="0.5"
name="tweeter_impedance" placeholder="Tweeter Ω" value="<?php echo $tweeter_impedance; ?>">
</td>
</tr>
<tr>
<td class="height-padded right-padded">Woofer impedance (Ω):</td>
<td class="height-padded">
<input class="monospace left-padded" type="number" min="0.5" step="0.5"
name="woofer_impedance" placeholder="Woofer Ω" value="<?php echo $woofer_impedance; ?>">
</td>
</tr>
<tr>
<td class="height-padded" colspan="2"><input type="submit" value="Calculate"></td>
</tr>
</table>
</form>
</div>
<?php if ($form_submitted): ?>
<div class="with-breathing-room height-padded width-padded">
<table class="bordered narrow">
<tr><th class="width-padded height-padded bordered" colspan="100%">
Component table for <?php printf("%.3g Ω ", $tweeter_impedance) ?> tweeter
and <?php printf("%.3g Ω", $woofer_impedance) ?> woofer
</th></tr>
<tr>
<th class="width-padded height-padded bordered">Crossover Frequency (Hz)</th>
<th class="width-padded height-padded bordered">Tweeter Capacitor (μF)</th>
<th class="width-padded height-padded bordered">Woofer Inductor (mH)</th>
</tr>
<?php for ($f = FREQ_MIN; $f <= FREQ_MAX; $f += FREQ_MIN): ?>
<tr>
<td class="width-padded height-padded bordered monospace">
<?php printf("%g", $f); ?>
</td>
<td class="width-padded height-padded bordered monospace">
<?php printf("%.4g", 1000_000. * (1. / (TWO_PI * $f * $tweeter_impedance))); ?>
</td>
<td class="width-padded height-padded bordered monospace">
<?php printf("%.4g", 1000. * ($woofer_impedance / (TWO_PI * $f))); ?>
</td>
</tr>
<?php endfor ?>
</table>
</div>
<?php endif ?>
</body>
</html>