A strict, mathematical engine for Modular Scales. It handles the arithmetic of progressions, designed for generative design, typography engines, and rhythmic computation.
composer require alto/scaleUse the Scale facade for fluent instantiation of any scale type.
use Alto\Scale\Scale;
use Alto\Scale\Ratio;
// Modular (Geometric): Base 16px, Ratio 1.25 (Major Third)
$type = Scale::majorThird(16.0);
// Linear (Arithmetic): Base 0, Increment 8
$grid = Scale::linear(0, 8);
// Fibonacci: Using Binet's formula
$fib = Scale::fibonacci();
// Multi-Strand: Interleaved scales (e.g., 16px and 12px strands)
$strands = Scale::strands([16, 12], Ratio::PerfectFifth);All scales implement the ScaleInterface and are IteratorAggregate.
echo $type->get(0); // 16.0
echo $type->get(1); // 20.0
echo $type->get(-1); // 12.8
// ModularScale is callable
echo $type(2); // 25.0Find the nearest mathematical step for any arbitrary value.
// Returns 20.0 (The nearest step on a Major Third scale starting at 16)
$value = $type->snap(19.8);// Scales are iterable (defaults to steps 0-10)
foreach ($type as $step => $value) {
// ...
}
// Custom ranges
$values = $type->range(-2, 2);
// Returns: [-2 => 10.24, -1 => 12.8, 0 => 16.0, 1 => 20.0, 2 => 25.0]Analyze messy datasets to find their underlying mathematical scale.
use Alto\Scale\Scale;
use Alto\Scale\ScaleGuesser;
$messyValues = [15.9, 20.1, 24.8, 31.5];
// Via the facade
$scale = Scale::guess($messyValues);
// Or directly with custom tolerance
$guesser = new ScaleGuesser(tolerance: 0.05);
$scale = $guesser->guess($messyValues);
// Align values to the guessed (or provided) scale
$aligned = $guesser->align($messyValues);Audit datasets for scale compliance and automatically harmonize them.
use Alto\Scale\ScaleLinter;
use Alto\Scale\Scale;
$linter = new ScaleLinter(Scale::linear(0, 8));
// Get a detailed compliance report
$report = $linter->lint([8, 15, 24]);
// Each entry: ['original', 'suggested', 'step', 'deviation', 'isValid']
// Returns [8.0, 16.0, 24.0]
$fixed = $linter->fix([8, 15, 24]);| Method | Returns |
|---|---|
modular(float $base, float|Ratio $ratio) |
ModularScale |
linear(float $base, float $increment) |
LinearScale |
fibonacci(float $multiplier) |
FibonacciScale |
strands(array $bases, float|Ratio $ratio) |
MultiStrandScale |
guess(array $values) |
ModularScale |
majorThird(float $base) |
ModularScale |
perfectFifth(float $base) |
ModularScale |
golden(float $base) |
ModularScale |
All scale classes (ModularScale, LinearScale, FibonacciScale, MultiStrandScale) implement:
| Method | Description |
|---|---|
get(int $step): float |
Get the value at a specific step |
stepOf(float $value): int |
Find the closest step index for a value |
snap(float $value): float |
Snap a value to the nearest step |
range(int $min, int $max): array |
Generate values between steps |
Geometric progression: value = base * (ratio ^ step)
| Method | Description |
|---|---|
areHarmonic(float $a, float $b, float $epsilon): bool |
Check if two values are harmonically related |
withBase(float $base): self |
Create a new scale with a different base |
withRatio(float|Ratio $ratio): self |
Create a new scale with a different ratio |
shift(int $steps): self |
Create a new scale shifted by N steps |
Arithmetic progression: value = base + (step * increment)
Fibonacci sequence using Binet's formula, with optional multiplier.
Interleaved modular scales sharing a common ratio, useful for multi-strand typographic scales.
| Method | Description |
|---|---|
guess(array $values): ModularScale |
Infer a modular scale from values |
align(array $values, ?ScaleInterface $scale): array |
Snap all values to a scale |
| Method | Description |
|---|---|
lint(array $values): array |
Audit values against a scale |
fix(array $values): array |
Harmonize values to the scale |
Standard musical/typographic ratios:
| Ratio | Value |
|---|---|
MinorSecond |
1.067 |
MajorSecond |
1.125 |
MinorThird |
1.200 |
MajorThird |
1.250 |
PerfectFourth |
1.333 |
AugmentedFourth |
1.414 |
PerfectFifth |
1.500 |
MinorSixth |
1.600 |
GoldenRatio |
1.618 |
MajorSixth |
1.667 |
MinorSeventh |
1.778 |
MajorSeventh |
1.875 |
Octave |
2.000 |
This project is licensed under the MIT License.