Last active
December 30, 2019 13:12
-
-
Save drupol/831da434de8f69dfc684a5f9a3ab32a7 to your computer and use it in GitHub Desktop.
Pythagorian and harmonic music scales using functionnal PHP and a lazy collection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @file | |
* Example/demo file. | |
* @see https://github.com/drupol/collection | |
*/ | |
declare(strict_types=1); | |
include 'vendor/autoload.php'; | |
use drupol\collection\Collection; | |
// From: https://stackoverflow.com/questions/14330713/converting-float-decimal-to-fraction | |
function float2rat(float $value, $tolerance = 1.e-12) { | |
$num=1; $h2=0; | |
$den=0; $k2=1; | |
if ($value === 0) { | |
return 0; | |
} | |
$b = 1/$value; | |
do { | |
$b = 1/$b; | |
$a = floor($b); | |
$aux = $num; $num = $a*$num+$h2; $h2 = $aux; | |
$aux = $den; $den = $a*$den+$k2; $k2 = $aux; | |
$b -= $a; | |
} while (abs($value-$num/$den) > $value*$tolerance); | |
return $num . '/' . $den; | |
} | |
// Harmonic scale serie generator | |
$harmonic = static function ($value) { | |
$s = 1; | |
for ($i = 1; $i <= $value; $i++) { | |
$s += 1 / $i; | |
} | |
return $s; | |
}; | |
// Pythagorian scale serie generator | |
$pythagorian = static function ($value) { | |
return (3/2) ** $value; | |
}; | |
$scale = Collection::range(0, 12) | |
// Choose the scale: $harmonic or $pythagorian | |
->map($harmonic) | |
// Scale the values between the interval 1 and 2 (logarithmic) | |
->map( | |
static function (float $value) { | |
while ($value > 2) { | |
$value /= 2; | |
} | |
return $value; | |
} | |
) | |
// Sort values ASC | |
->sort(static function ($a, $b) {return $a <=> $b;}) | |
// Convert float to rational numbers (fraction) | |
->map(static function ($value) {return float2rat($value);}); | |
print_r($scale->all()); | |
/* | |
Pythagorian: | |
Array ( | |
[0] => 1/1 | |
[1] => 2187/2048 | |
[2] => 9/8 | |
[3] => 19683/16384 | |
[4] => 81/64 | |
[5] => 177147/131072 | |
[6] => 729/512 | |
[7] => 3/2 | |
[8] => 6561/4096 | |
[9] => 27/16 | |
[10] => 59049/32768 | |
[11] => 243/128 | |
) | |
Harmonic: | |
Array ( | |
[0] => 1/1 | |
[1] => 111431/110880 | |
[2] => 5/4 | |
[3] => 17/12 | |
[4] => 37/24 | |
[5] => 197/120 | |
[6] => 69/40 | |
[7] => 503/280 | |
[8] => 1041/560 | |
[9] => 9649/5040 | |
[10] => 9901/5040 | |
[11] => 2/1 | |
) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment