TuningFork.Scale (TuningFork v0.1.11)

Copy Markdown View Source

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

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

Summary

Functions

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

The MIDI note degree stands for in scale.

Every scale name, sorted.

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

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

Types

name()

@type name() :: atom()

Functions

interval(steps, degree)

@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(scale, degree)

@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()

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

Every scale name, sorted.

parse(text)

@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(name)

@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.