Completed
Push — master ( 0a9f53...f4298d )
by Patrick
01:54
created

Harmonic::getSeries()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace ExtendedStrings\Strings;
6
7
class Harmonic
8
{
9
    private $halfStop;
10
    private $baseStop;
11
12
    /**
13
     * Harmonic constructor.
14
     *
15
     * @param float $halfStop The string length of the harmonic-pressure stop.
16
     * @param float $baseStop The string length of the base stop (defaults to
17
     *                        1.0, the open string).
18
     */
19
    public function __construct(float $halfStop, float $baseStop = 1.0)
20
    {
21
        if ($halfStop > $baseStop) {
22
            throw new \InvalidArgumentException("The half-stop's string length cannot be longer than the base stop's.");
23
        }
24
25
        $this->baseStop = $baseStop;
26
        $this->halfStop = $halfStop;
27
    }
28
29
    /**
30
     * Returns the sounding frequency of the harmonic, on a given string.
31
     *
32
     * @param \ExtendedStrings\Strings\VibratingString $string
33
     *
34
     * @return float
35
     */
36
    public function getSoundingFrequency(VibratingString $string): float
37
    {
38
        // Transpose the half-stop onto the new string length, which was formed
39
        // by the stop.
40
        $pseudoString = new VibratingString($string->getStoppedFrequency($this->baseStop));
41
        $pseudoHalfStop = $this->halfStop / $this->baseStop;
42
43
        return $pseudoString->getHarmonicSoundingFrequency($pseudoHalfStop);
44
    }
45
46
    /**
47
     * Returns the string lengths that produce the given harmonic number.
48
     *
49
     * @param int  $number    The harmonic number.
50
     * @param bool $exclusive When enabled, equivalent lengths will only be
51
     *                        returned for the lowest harmonic number, e.g. the
52
     *                        string length 0.5 will only be returned for
53
     *                        harmonic 2 (not for harmonics 4, 6, 8, etc.).
54
     *
55
     * @return float[]
56
     */
57
    public static function getStringLengthsFromNumber(int $number, bool $exclusive = false): array
58
    {
59
        $harmonics = [];
60
        for ($numerator = 1; $numerator <= $number; $numerator++) {
61
            if (!$exclusive || $numerator === 1 || (int) Math::gcd($numerator, $number) === 1) {
62
                $harmonics[] = $numerator / $number;
63
            }
64
        }
65
66
        return $harmonics;
67
    }
68
69
    /**
70
     * Returns the harmonic series.
71
     *
72
     * @param int $limit
73
     *
74
     * @return float[]
75
     */
76
    public static function getSeries(int $limit): array
77
    {
78
        $series = [];
79
        $base = 0;
80
        for ($denominator = 1; $denominator <= $limit; $denominator++) {
81
            $base = $series[$denominator] = $base + 1 / $denominator;
82
        }
83
84
        return $series;
85
    }
86
}
87