# `TuningFork.Scale`
[🔗](https://github.com/jaman/tuning_fork/blob/v0.1.11/tuning_fork/lib/tuning_fork/scale.ex#L1)

Named scales, and the MIDI notes their degrees stand for.

    iex> TuningFork.Scale.midi("g:minor", 4)
    62

# `name`

```elixir
@type name() :: atom()
```

# `interval`

```elixir
@spec interval([non_neg_integer()], integer()) :: integer()
```

How many semitones above the root `degree` sits, wrapping into octaves.

    iex> TuningFork.Scale.interval([0, 2, 3, 5, 7, 8, 10], 9)
    15

# `midi`

```elixir
@spec midi(String.t() | {integer(), name()}, integer()) :: integer() | nil
```

The MIDI note `degree` stands for in `scale`.

`scale` is a `"root:name"` string as `parse/1` reads it, or a `{root_midi, name}` pair.
Degree 0 is the root; degrees past the scale's length carry into the octave above and
negative degrees into the octave below. Returns `nil` for a scale it cannot read.

    iex> TuningFork.Scale.midi("g:minor", 7)
    67
    iex> TuningFork.Scale.midi("g:minor", -1)
    53

# `names`

```elixir
@spec names() :: [name()]
```

Every scale name, sorted.

# `parse`

```elixir
@spec parse(String.t()) :: {:ok, integer(), name()} | {:error, String.t()}
```

Split `"g2:minor"` into its root note and scale.

The root is a letter with `s` for sharp or `b` for flat and an optional octave. Returns
`{:ok, root_midi, scale}` or `{:error, reason}`. Without an octave the root is in octave
3; without a scale it is `:major`.

    iex> TuningFork.Scale.parse("eb2:dorian")
    {:ok, 39, :dorian}

# `steps`

```elixir
@spec steps(name() | String.t()) :: [non_neg_integer()] | nil
```

The semitones a scale's degrees sit on, from its root.

    iex> TuningFork.Scale.steps(:minor)
    [0, 2, 3, 5, 7, 8, 10]

Returns `nil` for a name there is no scale for.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
