From 58ee87a861a62e52b81213d82769b499aa8f9bee Mon Sep 17 00:00:00 2001 From: Joop Schilder Date: Thu, 29 Apr 2021 21:58:02 +0200 Subject: [PATCH] Initial commit --- .gitignore | 2 + bin/app.php | 35 ++++ composer.json | 13 ++ composer.lock | 270 ++++++++++++++++++++++++++++++ src/Components/Capacitor.php | 19 +++ src/Components/Inductor.php | 19 +++ src/Driver.php | 17 ++ src/FirstOrderTwoWayCrossover.php | 44 +++++ src/Lib/helpers.php | 10 ++ src/Scientific/Capacitance.php | 16 ++ src/Scientific/CrossoverSlope.php | 26 +++ src/Scientific/Frequency.php | 16 ++ src/Scientific/Impedance.php | 7 + src/Scientific/Inductance.php | 16 ++ src/Scientific/Quantity.php | 86 ++++++++++ src/Scientific/Resistance.php | 16 ++ src/Scientific/Unit.php | 117 +++++++++++++ 17 files changed, 729 insertions(+) create mode 100644 .gitignore create mode 100644 bin/app.php create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 src/Components/Capacitor.php create mode 100644 src/Components/Inductor.php create mode 100644 src/Driver.php create mode 100644 src/FirstOrderTwoWayCrossover.php create mode 100644 src/Lib/helpers.php create mode 100644 src/Scientific/Capacitance.php create mode 100644 src/Scientific/CrossoverSlope.php create mode 100644 src/Scientific/Frequency.php create mode 100644 src/Scientific/Impedance.php create mode 100644 src/Scientific/Inductance.php create mode 100644 src/Scientific/Quantity.php create mode 100644 src/Scientific/Resistance.php create mode 100644 src/Scientific/Unit.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f7f8ac3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.idea/ +/vendor/ diff --git a/bin/app.php b/bin/app.php new file mode 100644 index 0000000..14a056d --- /dev/null +++ b/bin/app.php @@ -0,0 +1,35 @@ +getTweeterCapacitor($tweeter); +$inductor = $crossover->getWooferInductor($woofer); + +printf( + 'First order 2-way crossover @ %s (slope = %s):%s', + $crossover->getFrequency(), + $crossover->getSlope(), + PHP_EOL +); +printf( + ' - %s capacitor in series with %s tweeter%s', + $capacitor->getCapacitance(), + $tweeter->getImpedance(), + PHP_EOL +); +printf( + ' - %s inductor in series with %s woofer%s', + $inductor->getInductance()->format('milli'), + $woofer->getImpedance(), + PHP_EOL +); diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..3bd43a8 --- /dev/null +++ b/composer.json @@ -0,0 +1,13 @@ +{ + "name": "joopschilder/speaker-params", + "description": "Speaker parameter modelling program", + "autoload": { + "files": ["src/Lib/helpers.php"], + "psr-0": { + "": ["src"] + } + }, + "require-dev": { + "symfony/var-dumper": "^5.2" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..af497c4 --- /dev/null +++ b/composer.lock @@ -0,0 +1,270 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "997f1773a8a4495e430433bfebab7f7c", + "packages": [], + "packages-dev": [ + { + "name": "symfony/polyfill-mbstring", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-22T09:19:47+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "89412a68ea2e675b4e44f260a5666729f77f668e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/89412a68ea2e675b4e44f260a5666729f77f668e", + "reference": "89412a68ea2e675b4e44f260a5666729f77f668e", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.2.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-28T09:42:18+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.0.0" +} diff --git a/src/Components/Capacitor.php b/src/Components/Capacitor.php new file mode 100644 index 0000000..4095395 --- /dev/null +++ b/src/Components/Capacitor.php @@ -0,0 +1,19 @@ +capacitance); + } +} diff --git a/src/Components/Inductor.php b/src/Components/Inductor.php new file mode 100644 index 0000000..74a557d --- /dev/null +++ b/src/Components/Inductor.php @@ -0,0 +1,19 @@ +inductance); + } +} diff --git a/src/Driver.php b/src/Driver.php new file mode 100644 index 0000000..688ff26 --- /dev/null +++ b/src/Driver.php @@ -0,0 +1,17 @@ +impedance; + } +} diff --git a/src/FirstOrderTwoWayCrossover.php b/src/FirstOrderTwoWayCrossover.php new file mode 100644 index 0000000..687e14b --- /dev/null +++ b/src/FirstOrderTwoWayCrossover.php @@ -0,0 +1,44 @@ +frequency; + } + + public function getSlope(): CrossoverSlope + { + return CrossoverSlope::fromDecibelPerOctave(6.); + } + + public function getTweeterCapacitor(Driver $driver): Capacitor + { + $f = $this->getFrequency()->getValue()->unit(); + $z = $driver->getImpedance()->getValue()->unit(); + + return new Capacitor(1. / (self::TWO_PI * $f * $z)); + } + + public function getWooferInductor(Driver $driver): Inductor + { + $f = $this->getFrequency()->getValue()->unit(); + $z = $driver->getImpedance()->getValue()->unit(); + + return new Inductor($z / (self::TWO_PI * $f)); + } +} diff --git a/src/Lib/helpers.php b/src/Lib/helpers.php new file mode 100644 index 0000000..47f6a1a --- /dev/null +++ b/src/Lib/helpers.php @@ -0,0 +1,10 @@ +format('deci'); + } +} diff --git a/src/Scientific/Frequency.php b/src/Scientific/Frequency.php new file mode 100644 index 0000000..9f3b520 --- /dev/null +++ b/src/Scientific/Frequency.php @@ -0,0 +1,16 @@ + 'Y', + 'zetta' => 'Z', + 'exa' => 'E', + 'peta' => 'P', + 'tera' => 'T', + 'giga' => 'G', + 'mega' => 'M', + 'kilo' => 'k', + 'hecto' => 'h', + 'deca' => 'da', + 'unit' => '', + 'deci' => 'd', + 'centi' => 'c', + 'milli' => 'm', + 'micro' => 'μ', + 'nano' => 'n', + 'pico' => 'p', + 'femto' => 'f', + 'atto' => 'a', + 'zepto' => 'z', + 'yocto' => 'y', + ]; + + abstract protected function getSymbol(): string; + + abstract protected function getName(): string; + + public function __construct( + private Unit $value + ) + { + } + + final public static function fromValue(float $value): static + { + return new static(new Unit($value)); + } + + final public function getValue(): Unit + { + return $this->value; + } + + final public function format(string $prefix = 'auto'): string + { + if ($prefix === 'auto') { + $prefix = $this->getAppropriatePrefix(); + } else if (!method_exists($this->value, $prefix)) { + throw new InvalidArgumentException('Invalid size: ' . $prefix); + } + + $value = $this->value->{$prefix}(); + $prefix = self::METRIC_PREFIXES[$prefix] ?? '?'; + $symbol = $this->getSymbol(); + + return sprintf('%.3g %s%s', $value, $prefix, $symbol); + } + + private function getAppropriatePrefix(): string + { + foreach (array_keys(self::METRIC_PREFIXES) as $prefix) { + $value = $this->value->{$prefix}(); + if ($value >= 1. && $value < 1000.) { + return $prefix; + } + } + return 'unit'; + } + + public function __toString(): string + { + return $this->format(); + } +} diff --git a/src/Scientific/Resistance.php b/src/Scientific/Resistance.php new file mode 100644 index 0000000..e04c0f0 --- /dev/null +++ b/src/Scientific/Resistance.php @@ -0,0 +1,16 @@ +zetta() / 1000.; + } + + public function zetta(): float + { + return $this->exa() / 1000.; + } + + public function exa(): float + { + return $this->peta() / 1000.; + } + + public function peta(): float + { + return $this->tera() / 1000.; + } + + public function tera(): float + { + return $this->giga() / 1000.; + } + + public function giga(): float + { + return $this->mega() / 1000.; + } + + public function mega(): float + { + return $this->kilo() / 1000.; + } + + public function kilo(): float + { + return $this->unit() / 1000.; + } + + public function hecto(): float + { + return $this->unit() / 100.; + } + + public function deca(): float + { + return $this->unit() / 10.; + } + + public function unit(): float + { + return $this->value; + } + + public function deci(): float + { + return 10. * $this->unit(); + } + + public function centi(): float + { + return 100. * $this->unit(); + } + + public function milli(): float + { + return 1000. * $this->unit(); + } + + public function micro(): float + { + return 1000. * $this->milli(); + } + + public function nano(): float + { + return 1000. * $this->micro(); + } + + public function pico(): float + { + return 1000. * $this->nano(); + } + + public function femto(): float + { + return 1000. * $this->pico(); + } + + public function atto(): float + { + return 1000. * $this->femto(); + } + + public function zepto(): float + { + return 1000. * $this->atto(); + } + + public function yocto(): float + { + return 1000. * $this->yocto(); + } +}