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
|
|
|
private $number; |
12
|
|
|
private $string; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Harmonic constructor. |
16
|
|
|
* |
17
|
|
|
* @param Stop $halfStop |
18
|
|
|
* The harmonic-pressure stop. |
19
|
|
|
* @param Stop|null $baseStop |
20
|
|
|
* The base stop (defaults to an open string). |
21
|
|
|
* @param VibratingStringInterface $string |
22
|
|
|
* The string. |
23
|
|
|
*/ |
24
|
|
|
public function __construct(Stop $halfStop, Stop $baseStop = null, VibratingStringInterface $string) |
25
|
|
|
{ |
26
|
|
|
$baseStop = $baseStop ?: new Stop(1.0, $string); |
|
|
|
|
27
|
|
|
if ($halfStop->getStringLength() > $baseStop->getStringLength()) { |
28
|
|
|
throw new \InvalidArgumentException("The half-stop cannot be lower than the base stop."); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
$this->baseStop = $baseStop; |
32
|
|
|
$this->halfStop = $halfStop; |
33
|
|
|
$this->number = intval(1 / Math::gcd(1, $halfStop->getStringLength() / $baseStop->getStringLength())); |
34
|
|
|
$this->string = $string; |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Returns the sounding frequency of the harmonic (in Hz). |
39
|
|
|
* |
40
|
|
|
* @return float |
41
|
|
|
*/ |
42
|
|
|
public function getSoundingFrequency(): float |
43
|
|
|
{ |
44
|
|
|
return $this->baseStop->getFrequency($this->string) * $this->number; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Returns the string lengths that produce a given harmonic number. |
49
|
|
|
* |
50
|
|
|
* @param int $number The harmonic number. |
51
|
|
|
* @param bool $exclusive When enabled, equivalent lengths will only be |
52
|
|
|
* returned for the lowest harmonic number, e.g. the |
53
|
|
|
* string length 0.5 will only be returned for |
54
|
|
|
* harmonic 2 (not for harmonics 4, 6, 8, etc.). |
55
|
|
|
* |
56
|
|
|
* @return float[] |
57
|
|
|
*/ |
58
|
|
|
public static function getStringLengthsFromNumber(int $number, bool $exclusive = false): array |
59
|
|
|
{ |
60
|
|
|
$harmonics = []; |
61
|
|
|
for ($numerator = 1; $numerator <= $number; $numerator++) { |
62
|
|
|
if (!$exclusive || $numerator === 1 || (int) Math::gcd($numerator, $number) === 1) { |
63
|
|
|
$harmonics[] = $numerator / $number; |
64
|
|
|
} |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
return $harmonics; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Returns the harmonic series. |
72
|
|
|
* |
73
|
|
|
* @param int $limit |
74
|
|
|
* |
75
|
|
|
* @return float[] |
76
|
|
|
*/ |
77
|
|
|
public static function getSeries(int $limit): array |
78
|
|
|
{ |
79
|
|
|
$series = []; |
80
|
|
|
$base = 0; |
81
|
|
|
for ($denominator = 1; $denominator <= $limit; $denominator++) { |
82
|
|
|
$base = $series[$denominator] = $base + 1 / $denominator; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
return $series; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Returns the harmonic-pressure stop. |
90
|
|
|
* |
91
|
|
|
* @return Stop |
92
|
|
|
*/ |
93
|
|
|
public function getHalfStop(): Stop |
94
|
|
|
{ |
95
|
|
|
return $this->halfStop; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Returns the base stop. |
100
|
|
|
* |
101
|
|
|
* @return Stop |
102
|
|
|
*/ |
103
|
|
|
public function getBaseStop(): Stop |
104
|
|
|
{ |
105
|
|
|
return $this->baseStop; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Returns the string. |
110
|
|
|
* |
111
|
|
|
* @return VibratingStringInterface |
112
|
|
|
*/ |
113
|
|
|
public function getString(): VibratingStringInterface |
114
|
|
|
{ |
115
|
|
|
return $this->string; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Returns whether this is a natural harmonic. |
120
|
|
|
* |
121
|
|
|
* @return bool |
122
|
|
|
*/ |
123
|
|
|
public function isNatural(): bool |
124
|
|
|
{ |
125
|
|
|
return Math::isZero(1 - $this->baseStop->getStringLength()); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Returns the harmonic number. |
130
|
|
|
* |
131
|
|
|
* @return int The harmonic number. |
132
|
|
|
*/ |
133
|
|
|
public function getNumber(): int |
134
|
|
|
{ |
135
|
|
|
return $this->number; |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.