Tones

class pytheory.tones.Interval[source]

Bases: object

Named constants for common musical intervals (in semitones).

UNISON = 0
MINOR_SECOND = 1
MAJOR_SECOND = 2
MINOR_THIRD = 3
MAJOR_THIRD = 4
PERFECT_FOURTH = 5
TRITONE = 6
PERFECT_FIFTH = 7
MINOR_SIXTH = 8
MAJOR_SIXTH = 9
MINOR_SEVENTH = 10
MAJOR_SEVENTH = 11
OCTAVE = 12
class pytheory.tones.Tone(name, *, alt_names: list[str] | None = None, octave: int | None = None, system: str | object = 'western', _validate: bool = True)[source]

Bases: object

__init__(name, *, alt_names: list[str] | None = None, octave: int | None = None, system: str | object = 'western', _validate: bool = True) None[source]

Initialize a Tone with a name, optional octave, and musical system.

Parameters:
  • name – The note name as a string ("C", "C#4") or an int for numbered systems (0, 11). Ints are converted to strings and wrapped to the system’s range (e.g. 22 in a 22-tone system becomes 0 at octave+1).

  • alt_names – Alternate spellings for this tone (e.g. enharmonics).

  • octave – The octave number. Overrides any octave parsed from name.

  • system – The tuning system, either as a string key ("western") or a ToneSystem instance.

property exists: bool

True if this tone’s name is found in the associated system.

property system: object

The ToneSystem associated with this tone.

Lazily resolved from system_name on first access and cached.

property full_name: str

The tone name with octave appended, e.g. 'C4' or 'C'.

names() list[str][source]

Return a list containing the primary name and all alternate names.

property scientific: str

Scientific pitch notation (e.g. 'C4', 'A#3').

This is the default notation used throughout PyTheory — note name followed by octave number. Middle C is C4. Same as full_name.

property helmholtz: str

Helmholtz pitch notation.

The older European convention still used in some contexts:

  • C2 → CC (sub-contra)

  • C3 → C (great octave)

  • C4 → c (small octave / middle C)

  • C5 → c' (one-line)

  • C6 → c'' (two-line)

  • C7 → c'''

Accidentals are preserved as-is (e.g. c#').

Example:

>>> Tone.from_string("C4").helmholtz
'c'
>>> Tone.from_string("C3").helmholtz
'C'
>>> Tone.from_string("C5").helmholtz
"c'"
>>> Tone.from_string("A2").helmholtz
'AA'
property is_natural: bool

True if this is a natural note (no sharp or flat).

property is_sharp: bool

True if this tone has a sharp (#).

property is_flat: bool

True if this tone has a flat (b after the first character).

property letter: str

The letter name without any accidental.

Example:

>>> Tone.from_string("C#4").letter
'C'
>>> Tone.from_string("Bb4").letter
'B'
>>> Tone.from_string("G4").letter
'G'
property enharmonic: str | None

The enharmonic equivalent of this tone, or None if there isn’t one.

Returns the alternate spelling: C# → Db, Db → C#, etc. Natural notes (C, D, E, F, G, A, B) have no enharmonic.

Example:

>>> Tone.from_string("C#4").enharmonic
'Db'
property solfege: str

Map Western note names to fixed-Do solfege syllables.

Uses fixed Do system where C is always Do regardless of key.

  • C->Do, D->Re, E->Mi, F->Fa, G->Sol, A->La, B->Ti

  • Sharps: C#->Di, D#->Ri, F#->Fi, G#->Si, A#->Li

  • Flats: Db->Ra, Eb->Me, Gb->Se, Ab->Le, Bb->Te

Returns the note name unchanged if the system isn’t western or the name isn’t recognized.

Example:

>>> Tone.from_string("C4").solfege
'Do'
>>> Tone.from_string("F#4").solfege
'Fi'
__repr__() str[source]

Return repr(self).

__str__() str[source]

Return str(self).

__add__(interval: int) Tone[source]
__sub__(other: int | Tone) Tone | int[source]
__lt__(other: Tone) bool[source]

Return self<value.

__le__(other: Tone) bool[source]

Return self<=value.

__gt__(other: Tone) bool[source]

Return self>value.

__ge__(other: Tone) bool[source]

Return self>=value.

__eq__(other: object) bool[source]

Return self==value.

__hash__() int[source]

Return hash(self).

classmethod from_string(s: str, system: str | object | None = None) Tone[source]

Create a Tone by parsing a string like 'C#4' or 'Bb'.

Parameters:
  • s – A note string, optionally including an octave number.

  • system – The tuning system to associate with the tone.

Returns:

A new Tone instance.

classmethod from_tuple(t: tuple[str, ...]) Tone[source]

Create a Tone from a tuple of (name, *alt_names).

Parameters:

t – A tuple where the first element is the primary name and any remaining elements are alternate names (enharmonics).

Returns:

A new Tone instance.

classmethod from_frequency(hz: float, system: str | object = 'western') Tone[source]

Create a Tone from a frequency in Hz.

Finds the nearest note in 12-TET tuning (A4=440Hz).

Example:

>>> Tone.from_frequency(440)
<Tone A4>
>>> Tone.from_frequency(261.63)
<Tone C4>
classmethod from_midi(note_number: int, system: str | object = 'western') Tone[source]

Create a Tone from a MIDI note number.

MIDI note 60 = C4 (middle C), 69 = A4 (440 Hz).

Example:

>>> Tone.from_midi(60)
<Tone C4>
>>> Tone.from_midi(69)
<Tone A4>
classmethod from_index(i: int, *, octave: int, system: object, prefer_flats: bool = False) Tone[source]

Create a Tone from its index within a tuning system.

Parameters:
  • i – The index of the tone in the system’s tone list.

  • octave – The octave number.

  • system – The ToneSystem instance.

  • prefer_flats – If True and the tone has a flat spelling, use it instead of the default sharp spelling.

Returns:

A new Tone instance.

add(interval: int, *, prefer_flats: bool = False) Tone[source]

Return a new Tone that is interval semitones above this one.

Parameters:
  • interval – Number of semitones to add (positive = up).

  • prefer_flats – If True, use flat spellings (Bb, Eb) instead of sharp spellings (A#, D#) for accidentals.

Returns:

A new Tone instance.

subtract(interval: int) Tone[source]

Return a new Tone that is interval semitones below this one.

Parameters:

interval – Number of semitones to subtract (positive = down).

Returns:

A new Tone instance.

interval_to(other: Tone) str[source]

Name the interval between this tone and another.

Returns a string like "perfect 5th", "major 3rd", or "octave". For intervals larger than an octave, returns the compound form (e.g. "minor 2nd + 1 octave").

Example:

>>> C4.interval_to(G4)
'perfect 5th'
>>> C4.interval_to(C5)
'octave'
property midi: int | None

MIDI note number (C4 = 60, A4 = 69).

The MIDI standard assigns integer note numbers from 0–127. Middle C (C4) is 60, and each semitone increments by 1.

Returns:

the MIDI note number, or None if no octave is set.

Return type:

int

transpose(semitones: int) Tone[source]

Return a new Tone transposed by the given number of semitones.

Alias for tone + semitones / tone - semitones. Positive values transpose up, negative values transpose down.

cents_difference(other: Tone, *, temperament: str = 'equal') float[source]

Difference in cents between this tone and another.

One semitone = 100 cents. Musicians use cents to measure fine pitch differences — e.g. comparing equal temperament to Pythagorean tuning, or checking how far out of tune a note is.

Parameters:
  • other – The tone to compare against.

  • temperament – Tuning temperament for both tones.

Returns:

Signed float — positive means other is higher.

Example:

>>> a4 = Tone.from_string("A4", system="western")
>>> a4.cents_difference(a4 + 1)  # one semitone
100.0
>>> a4_pyth = a4.pitch(temperament="pythagorean")
>>> a4_equal = a4.pitch(temperament="equal")
circle_of_fifths() list[Tone][source]

The circle of fifths starting from this tone.

Each step ascends by a perfect fifth (7 semitones in 12-TET). After N steps (where N = number of tones in the system) you return to the starting tone. The circle of fifths is the backbone of Western harmony — it determines key signatures, chord relationships, and modulation paths.

Returns:

A list of Tones (12 for Western, N for other systems).

circle_of_fourths() list[Tone][source]

The circle of fourths starting from this tone.

Each step ascends by a perfect fourth — the reverse direction of the circle of fifths.

Returns:

A list of Tones (12 for Western, N for other systems).

property frequency: float

The frequency of this tone in Hz (equal temperament, A4=440).

The result is cached after the first computation.

overtones(n: int = 8) list[float][source]

The first n overtones (harmonic series) of this tone.

The harmonic series is the foundation of timbre and consonance. When a string or air column vibrates, it produces not just the fundamental frequency but also integer multiples: 2f, 3f, 4f…

The intervals between consecutive harmonics form the basis of Western harmony:

Harmonic  Ratio  Interval from fundamental
1         1:1    Unison (the fundamental)
2         2:1    Octave
3         3:1    Octave + perfect 5th
4         4:1    Two octaves
5         5:1    Two octaves + major 3rd
6         6:1    Two octaves + perfect 5th
7         7:1    Two octaves + minor 7th (slightly flat)
8         8:1    Three octaves

The reason a perfect fifth sounds consonant is that the 3rd harmonic of the lower note aligns with the 2nd harmonic of the upper note (when the upper note is a fifth above). More shared harmonics = more consonance.

Parameters:

n – Number of harmonics to return (default 8).

Returns:

List of frequencies in Hz.

pitch(*, reference_pitch: float = 440, temperament: str = 'equal', symbolic: bool = False, precision: int | None = None) float[source]