Comprehensive music theory documentation pass

Every guide page rewritten with deep music theory content:

- Tones: scientific pitch notation, frequency/pitch relationship,
  temperament history (equal/Pythagorean/meantone), interval table
  with song examples, circle of fifths
- Scales: interval pattern construction, major/minor/harmonic minor
  theory, all 7 modes with character descriptions and song references,
  scale degree names and functions, diatonic harmony and common
  chord progressions (I-IV-V, I-V-vi-IV, ii-V-I)
- Chords: triad and seventh chord construction tables, all 12 chord
  qualities with interval formulas, consonance/dissonance theory
  (Pythagoras to Plomp-Levelt), beat frequency perceptual ranges
- Fretboard: how frets work, string interval explanation, reading
  fingering notation, 8 alternate tunings with musical context,
  custom instrument examples (banjo, mandolin)
- Playback: waveform physics (harmonics, Fourier), temperament
  listening guide
- Quickstart: updated feature list (6 systems, 40+ scales, 144 chords)
- Fix duplicate logo/title in sidebar

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-22 06:20:01 -04:00
parent 21cd99425b
commit e1c2ef03d7
7 changed files with 547 additions and 125 deletions
+2 -1
View File
@@ -34,7 +34,8 @@ templates_path = ["_templates"]
exclude_patterns = ["_build"]
html_theme = "alabaster"
html_title = ""
html_title = " "
html_short_title = " "
html_logo = "_static/logo.png"
html_static_path = ["_static"]
html_extra_path = ["CNAME"]
+132 -33
View File
@@ -1,19 +1,36 @@
Working with Chords
===================
Chords and Chord Charts
-----------------------
A **chord** is two or more tones sounding simultaneously. Chords are the
vertical dimension of music — while melody moves horizontally through
time, harmony stacks tones on top of each other.
PyTheory provides two chord-related classes:
Chord Construction
------------------
- :class:`~pytheory.chords.Chord` — a collection of tones played together
- :class:`~pytheory.charts.NamedChord` — a chord from the chart database with
fingering support
Chords are built by stacking **intervals** above a **root** note. The
most common chord type is the **triad** — three notes built from
alternating scale degrees (root, 3rd, 5th).
The four triad types::
Major root + major 3rd (4) + perfect 5th (7) Bright, stable
Minor root + minor 3rd (3) + perfect 5th (7) Dark, sad
Diminished root + minor 3rd (3) + diminished 5th (6) Tense, unstable
Augmented root + major 3rd (4) + augmented 5th (8) Eerie, unresolved
Adding a 7th creates a **seventh chord** — the foundation of jazz
harmony::
Dominant 7th root + 4 + 7 + 10 Bluesy, wants to resolve (G7)
Major 7th root + 4 + 7 + 11 Dreamy, sophisticated (Cmaj7)
Minor 7th root + 3 + 7 + 10 Warm, mellow (Am7)
Diminished 7th root + 3 + 6 + 9 Dramatic, symmetrical
Using the Chord Chart
---------------------
The built-in chart contains 144 chords (12 roots x 12 qualities):
PyTheory includes 144 pre-built chords (12 roots x 12 qualities):
.. code-block:: python
@@ -21,29 +38,37 @@ The built-in chart contains 144 chords (12 roots x 12 qualities):
chart = CHARTS["western"]
# Access a chord
c_major = chart["C"]
a_minor = chart["Am"]
g_seven = chart["G7"]
c_major = chart["C"] # C major (root position)
a_minor = chart["Am"] # A minor
g_seven = chart["G7"] # G dominant 7th
d_dim = chart["Ddim"] # D diminished
# Available qualities: "", "maj", "m", "5", "7", "9",
# "dim", "m6", "m7", "m9", "maj7", "maj9"
Available qualities:
Chord Tones
-----------
Each named chord knows which tones it contains:
============ ================ ================================
Quality Intervals Example tones (from C)
============ ================ ================================
``""`` 4, 7 C E G (major triad)
``"maj"`` 4, 7 C E G (explicit major)
``"m"`` 3, 7 C Eb G (minor triad)
``"5"`` 7 C G (power chord)
``"7"`` 4, 7, 10 C E G Bb (dominant 7th)
``"9"`` 4, 7, 10, 14 C E G Bb D (dominant 9th)
``"dim"`` 3, 6 C Eb Gb (diminished)
``"m6"`` 3, 7, 9 C Eb G A (minor 6th)
``"m7"`` 3, 7, 10 C Eb G Bb (minor 7th)
``"m9"`` 3, 7, 10, 14 C Eb G Bb D (minor 9th)
``"maj7"`` 4, 7, 11 C E G B (major 7th)
``"maj9"`` 4, 7, 11, 14 C E G B D (major 9th)
============ ================ ================================
.. code-block:: python
>>> chart["C"].acceptable_tone_names
('C', 'E', 'G')
>>> chart["Am"].acceptable_tone_names
('A', 'C', 'E')
>>> chart["G7"].acceptable_tone_names
('G', 'B', 'D', 'F')
>>> chart["Cm7"].acceptable_tone_names
('C', 'D#', 'G', 'A#') # Eb and Bb shown as sharps
Building Chords Manually
-------------------------
@@ -58,26 +83,100 @@ Building Chords Manually
Tone.from_string("G4", system="western"),
])
# Iteration
for tone in c_major:
print(tone)
len(c_major) # 3
"C" in c_major # True
Chord Properties
----------------
Intervals
---------
The ``intervals`` property returns semitone distances between adjacent
tones — these are musically meaningful and octave-invariant:
.. code-block:: python
# Frequency intervals between adjacent tones (Hz)
c_major.intervals
>>> c_major.intervals
[4, 3] # major 3rd (4) + minor 3rd (3) = major triad
# Harmony score (higher = more consonant intervals)
c_major.harmony
>>> Chord(tones=[C4, Eb4, G4]).intervals
[3, 4] # minor 3rd + major 3rd = minor triad
# Dissonance score (higher = wider intervals)
c_major.dissonance
Consonance and Dissonance
-------------------------
# Beat frequency between closest tone pair
c_major.beat_pulse
**Consonance** is the perception of stability and "pleasantness" when
tones sound together. **Dissonance** is the perception of tension and
roughness. Neither is inherently good or bad — music needs both.
Harmony Score
~~~~~~~~~~~~~
The ``harmony`` property measures consonance using **frequency ratio
simplicity**. The insight dates back to Pythagoras (6th century BC):
intervals whose frequencies form simple integer ratios sound consonant.
=========== ===== ====================
Interval Ratio Why it sounds "good"
=========== ===== ====================
Octave 2:1 Every 2nd wave aligns
Perfect 5th 3:2 Every 3rd wave aligns
Perfect 4th 4:3 Every 4th wave aligns
Major 3rd 5:4 Every 5th wave aligns
Minor 3rd 6:5 Every 6th wave aligns
Tritone 45:32 Waves rarely align
=========== ===== ====================
.. code-block:: python
fifth = Chord([C4, G4])
tritone = Chord([C4, F_sharp_4])
fifth.harmony > tritone.harmony # True
# The perfect fifth's 3:2 ratio scores higher
Dissonance Score
~~~~~~~~~~~~~~~~
The ``dissonance`` property uses the **Plomp-Levelt roughness model**
(1965). When two frequencies are close together, their sound waves
interfere and produce rapid amplitude fluctuations called **beating**.
This beating is perceived as roughness — the physiological basis of
dissonance.
The roughness depends on the frequency difference relative to the
**critical bandwidth** of the human ear (~25% of the frequency at
that register). Maximum roughness occurs when the difference equals
the critical bandwidth.
.. code-block:: python
# Octave: frequencies far apart → low roughness
octave = Chord([C4, C5])
# Major 3rd: closer frequencies → higher roughness
third = Chord([C4, E4])
octave.dissonance < third.dissonance # True
Beat Frequencies
~~~~~~~~~~~~~~~~
When two tones with slightly different frequencies are played together,
you hear a pulsing at the **beat frequency**: ``|f1 - f2|`` Hz.
- **< 1 Hz**: Slow pulsing, used for tuning instruments
- **115 Hz**: Audible rhythmic beating
- **1530 Hz**: Perceived as buzzing/roughness
- **> 30 Hz**: No longer beating — becomes part of the timbre
.. code-block:: python
chord = Chord(tones=[A4, E5, A5])
# All pairwise beat frequencies, sorted ascending
chord.beat_frequencies
# [(A4, E5, 189.6), (E5, A5, 220.0), (A4, A5, 440.0)]
# The slowest (most perceptible) beat
chord.beat_pulse # 189.6 Hz
+84 -14
View File
@@ -4,6 +4,26 @@ Fretboard and Fingerings
The :class:`~pytheory.chords.Fretboard` class represents a fretted instrument's
tuning and generates chord fingerings.
How Frets Work
--------------
Each fret on a guitar (or any fretted instrument) raises the pitch by
exactly **one semitone**. The open string is fret 0; fret 1 is one
semitone up, fret 2 is two semitones up, and so on.
Standard guitar tuning (high to low)::
String 1: E4 (highest)
String 2: B3
String 3: G3
String 4: D3
String 5: A2
String 6: E2 (lowest)
This tuning uses intervals of a perfect 4th (5 semitones) between most
strings, except between G and B which is a major 3rd (4 semitones). This
asymmetry is why guitar chord shapes shift when they cross the G-B pair.
Preset Tunings
--------------
@@ -11,48 +31,98 @@ Preset Tunings
from pytheory import Fretboard
guitar = Fretboard.guitar() # E4 B3 G3 D3 A2 E2
bass = Fretboard.bass() # G2 D2 A1 E1
ukulele = Fretboard.ukulele() # A4 E4 C4 G4
guitar = Fretboard.guitar() # Standard EADGBE
bass = Fretboard.bass() # Standard EADG
bass5 = Fretboard.bass(five_string=True) # 5-string BEADG
ukulele = Fretboard.ukulele() # GCEA (re-entrant)
Custom Tunings
--------------
Alternate Guitar Tunings
~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: python
# Built-in alternate tunings
drop_d = Fretboard.guitar("drop d") # DADGBE — heavy riffs
open_g = Fretboard.guitar("open g") # DGDGBD — slide guitar, Keith Richards
open_d = Fretboard.guitar("open d") # DADF#AD — slide, folk
open_e = Fretboard.guitar("open e") # EBEG#BE — slide blues
open_a = Fretboard.guitar("open a") # EAC#EAE
dadgad = Fretboard.guitar("dadgad") # DADGAD — Celtic, fingerstyle
half_down = Fretboard.guitar("half step down") # Eb standard — Hendrix, SRV
# Custom tuning with any notes
custom = Fretboard.guitar(("D4", "A3", "F#3", "D3", "A2", "D2"))
Custom Instruments
------------------
Any fretted instrument can be modeled:
.. code-block:: python
from pytheory import Tone, Fretboard
# Open D tuning
open_d = Fretboard(tones=[
# Banjo (open G tuning)
banjo = Fretboard(tones=[
Tone.from_string("D4"),
Tone.from_string("A3"),
Tone.from_string("F#3"),
Tone.from_string("B3"),
Tone.from_string("G3"),
Tone.from_string("D3"),
Tone.from_string("A2"),
Tone.from_string("D2"),
Tone.from_string("G4"), # 5th string (high drone)
])
# Mandolin
mandolin = Fretboard(tones=[
Tone.from_string("E5"),
Tone.from_string("A4"),
Tone.from_string("D4"),
Tone.from_string("G3"),
])
Getting Fingerings
------------------
The fingering algorithm finds the most playable voicing for any chord on
any fretboard. It scores each possibility by:
1. Preferring **open strings** (fret 0) — they ring freely
2. Preferring **ascending** fret patterns — easier hand position
3. Minimizing the number of **fingers needed**
.. code-block:: python
from pytheory import Fretboard, CHARTS
fb = Fretboard.guitar()
# Best fingering for a chord
c = CHARTS["western"]["C"]
# Best single fingering
print(c.fingering(fretboard=fb))
# (0, 1, 0, 2, 3, 0)
# String: E4=0 B3=1 G3=0 D3=2 A2=3 E2=0
# All possible fingerings
# All equally-scored fingerings
all_c = c.fingering(fretboard=fb, multiple=True)
# Muted strings appear as None
f = CHARTS["western"]["F"]
print(f.fingering(fretboard=fb))
Reading Fingerings
~~~~~~~~~~~~~~~~~~
The tuple ``(0, 1, 0, 2, 3, 0)`` reads from the highest string to the
lowest::
e|--0-- (open — E)
B|--1-- (fret 1 — C)
G|--0-- (open — G)
D|--2-- (fret 2 — E)
A|--3-- (fret 3 — C)
E|--0-- (open — E)
A value of ``None`` means the string is muted (not played).
Generating Full Charts
----------------------
+28 -8
View File
@@ -1,7 +1,8 @@
Audio Playback
==============
PyTheory can synthesize and play tones and chords through your speakers.
PyTheory can synthesize and play tones and chords through your speakers
using basic waveform synthesis.
.. note::
@@ -36,7 +37,21 @@ Playing a Chord
Waveform Types
--------------
Choose between sine, sawtooth, and triangle wave synthesis:
The waveform shape determines the **timbre** (tonal color) of the sound.
Different waveforms contain different combinations of **harmonics**
integer multiples of the fundamental frequency.
- **Sine wave** — the purest tone. Contains only the fundamental
frequency with no harmonics. Sounds smooth, clear, and "electronic."
This is the building block of all other waveforms (Fourier's theorem).
- **Sawtooth wave** — contains all harmonics (both odd and even),
each at amplitude 1/n. Sounds bright, buzzy, and aggressive.
Named for its shape. Used extensively in analog synthesizers.
- **Triangle wave** — contains only odd harmonics, each at amplitude
1/n². Sounds softer and more mellow than sawtooth — somewhere between
sine and sawtooth. Often described as "woody" or "hollow."
.. code-block:: python
@@ -44,17 +59,22 @@ Choose between sine, sawtooth, and triangle wave synthesis:
tone = Tone.from_string("C4", system="western")
play(tone, synth=Synth.SINE) # Smooth, pure tone
play(tone, synth=Synth.SINE) # Pure, clean
play(tone, synth=Synth.SAW) # Bright, buzzy
play(tone, synth=Synth.TRIANGLE) # Softer than sawtooth
play(tone, synth=Synth.TRIANGLE) # Mellow, hollow
Temperaments
------------
Play in different tuning systems:
Hear the difference between tuning systems:
.. code-block:: python
play(tone, temperament="equal") # Default, modern tuning
play(tone, temperament="pythagorean") # Ancient Greek tuning
play(tone, temperament="meantone") # Renaissance tuning
play(tone, temperament="equal") # Modern standard (since ~1917)
play(tone, temperament="pythagorean") # Pure fifths, wolf intervals
play(tone, temperament="meantone") # Pure thirds, Renaissance sound
Try playing a C major chord in each temperament — you'll hear subtle
differences in the "color" of the major third. Equal temperament is
a compromise; the other systems sacrifice some keys to make the good
keys sound better.
+24 -18
View File
@@ -17,28 +17,28 @@ Create tones, build scales, and explore music theory:
from pytheory import Tone, TonedScale, Fretboard, CHARTS
# Create a tone
c4 = Tone.from_string("C4")
print(c4) # C4
print(c4.frequency) # 261.63 Hz
# Create a tone — A4 is the tuning standard (440 Hz)
a4 = Tone.from_string("A4", system="western")
print(a4.frequency) # 440.0
# Tone arithmetic
e4 = c4 + 4 # Major third up
g4 = c4 + 7 # Perfect fifth up
print(e4, g4) # E4 G4
# Tone arithmetic — add semitones to move up the chromatic scale
c4 = Tone.from_string("C4", system="western")
e4 = c4 + 4 # Major third up (4 semitones)
g4 = c4 + 7 # Perfect fifth up (7 semitones)
print(e4, g4) # E4 G4
# Measure intervals
print(g4 - c4) # 7 (semitones)
# Measure intervals between tones
print(g4 - c4) # 7 (semitones — a perfect fifth)
# Build a scale
# Build a C major scale
c_major = TonedScale(tonic="C4")["major"]
print(c_major.note_names)
# ['C', 'D', 'E', 'F', 'G', 'A', 'B', 'C']
# Build chords from the scale
I = c_major.triad(0) # C major
IV = c_major.triad(3) # F major
V = c_major.triad(4) # G major
# Build diatonic triads from the scale
I = c_major.triad(0) # C E G (C major)
IV = c_major.triad(3) # F A C (F major)
V = c_major.triad(4) # G B D (G major)
# Guitar chord fingerings
fb = Fretboard.guitar()
@@ -48,9 +48,15 @@ Create tones, build scales, and explore music theory:
What's Included
---------------
- **12-tone Western system** with all chromatic notes
- **Scales**: major, minor, harmonic minor, and all 7 modes
- **6 musical systems**: Western, Indian (Hindustani), Arabic (Maqam),
Japanese, Blues/Pentatonic, Javanese Gamelan
- **40+ scales**: major, minor, harmonic minor, 7 modes, 10 thaats,
10 maqamat, 6 Japanese pentatonic scales, blues, pentatonic,
slendro, pelog, and more
- **Pitch calculation** in equal, Pythagorean, and meantone temperaments
- **Chord charts** with 144 pre-built chords (12 roots x 12 qualities)
- **Fingering generation** for any fretted instrument
- **Chord analysis**: consonance scoring, Plomp-Levelt dissonance,
beat frequency calculation
- **Fingering generation** for guitar (8 tunings), bass, ukulele, or
any custom fretted instrument
- **Audio playback** with sine, sawtooth, and triangle wave synthesis
+146 -39
View File
@@ -1,7 +1,29 @@
Working with Scales
===================
Scales are sequences of tones following a specific interval pattern.
A **scale** is an ordered set of tones spanning an octave, defined by a
pattern of intervals. Scales are the foundation of melody and harmony —
they determine which notes "belong" in a piece of music and shape its
emotional character.
Scale Construction
------------------
Every scale is defined by its **interval pattern** — the sequence of
whole steps (W = 2 semitones) and half steps (H = 1 semitone) between
consecutive tones.
The major scale::
W W H W W W H
C D E F G A B C
2 2 1 2 2 2 1 ← semitones between each note
The natural minor scale::
W H W W H W W
C D Eb F G Ab Bb C
2 1 2 2 1 2 2
Building Scales
---------------
@@ -14,7 +36,6 @@ Use :class:`~pytheory.scales.TonedScale` to generate scales in any key:
c = TonedScale(tonic="C4")
# Access scales by name
major = c["major"]
minor = c["minor"]
harmonic_minor = c["harmonic minor"]
@@ -22,62 +43,117 @@ Use :class:`~pytheory.scales.TonedScale` to generate scales in any key:
print(major.note_names)
# ['C', 'D', 'E', 'F', 'G', 'A', 'B', 'C']
Available Scales
----------------
Major and Minor
---------------
The **major scale** (Ionian mode) is the foundation of Western tonal
music. Its pattern of whole and half steps creates a bright, resolved
sound. Every major key has a **relative minor** that shares the same
notes but starts from the 6th degree:
- C major → A minor (both use only white keys)
- G major → E minor (both have one sharp: F#)
- F major → D minor (both have one flat: Bb)
.. code-block:: python
>>> c = TonedScale(tonic="C4")
>>> c.scales
('chromatic', 'major', 'minor', 'harmonic minor',
'ionian', 'dorian', 'phrygian', 'lydian',
'mixolydian', 'aeolian', 'locrian')
c_major = TonedScale(tonic="C4")["major"]
a_minor = TonedScale(tonic="A4")["minor"]
# Same notes, different starting point
set(c_major.note_names) == set(a_minor.note_names) # True
The **harmonic minor** raises the 7th degree of the natural minor,
creating an augmented 2nd interval (3 semitones) between the 6th and
7th degrees. This gives it a distinctive "Middle Eastern" or "classical"
sound and provides the leading tone needed for dominant harmony::
Natural minor: C D Eb F G Ab Bb C
Harmonic minor: C D Eb F G Ab B C
↑ raised 7th
Modes
-----
All seven modes of the major scale are supported:
The seven **modes** of the major scale are rotations of the same interval
pattern, each starting from a different degree. Each mode has a distinct
emotional character:
.. code-block:: python
c = TonedScale(tonic="C4")
c["ionian"] # Same as major: C D E F G A B C
c["dorian"] # C D Eb F G A Bb C
c["phrygian"] # C Db Eb F G Ab Bb C
c["lydian"] # C D E F# G A B C
c["mixolydian"] # C D E F G A Bb C
c["aeolian"] # Same as minor: C D Eb F G Ab Bb C
c["locrian"] # C Db Eb F Gb Ab Bb C
**Ionian** (I) — the major scale itself. Bright, happy, resolved::
Accessing Degrees
-----------------
c["ionian"] # C D E F G A B C
Scale tones can be accessed by index, Roman numeral, or degree name:
**Dorian** (ii) — minor with a raised 6th. Jazzy, soulful (So What,
Scarborough Fair)::
c["dorian"] # C D Eb F G A Bb C
**Phrygian** (iii) — minor with a flat 2nd. Spanish, flamenco, dark
(White Rabbit)::
c["phrygian"] # C Db Eb F G Ab Bb C
**Lydian** (IV) — major with a raised 4th. Dreamy, floating, ethereal
(The Simpsons theme, Flying by ET)::
c["lydian"] # C D E F# G A B C
**Mixolydian** (V) — major with a flat 7th. Bluesy, rock, dominant
(Norwegian Wood, Sweet Home Alabama)::
c["mixolydian"] # C D E F G A Bb C
**Aeolian** (vi) — the natural minor scale. Sad, dark, introspective
(Stairway to Heaven, Losing My Religion)::
c["aeolian"] # C D Eb F G Ab Bb C
**Locrian** (vii) — minor with flat 2nd and flat 5th. Unstable,
rarely used as a home key (used in metal and jazz over diminished
chords)::
c["locrian"] # C Db Eb F Gb Ab Bb C
Scale Degrees
-------------
Each note in a scale has a **degree name** that describes its function:
=========== ====== =======================================
Degree Number Function
=========== ====== =======================================
Tonic I Home base — the key center
Supertonic II One step above tonic
Mediant III Halfway between tonic and dominant
Subdominant IV A fifth below tonic (or fourth above)
Dominant V The strongest pull back to tonic
Submediant VI Root of the relative minor (or major)
Leading Tone VII One semitone below tonic — pulls upward
=========== ====== =======================================
Access degrees by index, Roman numeral, or name:
.. code-block:: python
major = TonedScale(tonic="C4")["major"]
# By index
major[0] # C4
major[4] # G4
major[0] # C4 (by index)
major["I"] # C4 (by Roman numeral)
major["tonic"] # C4 (by degree name)
# By Roman numeral
major["I"] # C4
major["V"] # G4
# By degree name
major["tonic"] # C4
major["V"] # G4 (dominant)
major["dominant"] # G4
# Slicing
major[0:3] # (C4, D4, E4)
major[0:3] # (C4, D4, E4) — slicing works too
Iteration
---------
Scales are iterable:
Scales are iterable and support ``len()`` and ``in``:
.. code-block:: python
@@ -91,16 +167,47 @@ Scales are iterable:
Building Chords from Scales
----------------------------
Build chords directly from scale degrees:
**Diatonic harmony** builds chords by stacking every other note of the
scale. A **triad** takes the 1st, 3rd, and 5th; a **seventh chord** adds
the 7th.
In the C major scale, the diatonic triads are::
I C E G = C major
ii D F A = D minor
iii E G B = E minor
IV F A C = F major
V G B D = G major
vi A C E = A minor
vii° B D F = B diminished
Notice the pattern: **major** triads on I, IV, V; **minor** triads on
ii, iii, vi; **diminished** on vii°. This pattern holds for every major
key.
.. code-block:: python
major = TonedScale(tonic="C4")["major"]
# Build a triad (root, 3rd, 5th)
I = major.triad(0) # C E G (C major)
ii = major.triad(1) # D F A (D minor)
V = major.triad(4) # G B D (G major)
# Build diatonic triads
I = major.triad(0) # C E G (C major)
ii = major.triad(1) # D F A (D minor)
iii = major.triad(2) # E G B (E minor)
IV = major.triad(3) # F A C (F major)
V = major.triad(4) # G B D (G major)
vi = major.triad(5) # A C E (A minor)
# Custom chord voicings
cmaj7 = major.chord(0, 2, 4, 6) # C E G B
# Build seventh chords
Imaj7 = major.chord(0, 2, 4, 6) # C E G B = Cmaj7
V7 = major.chord(4, 6, 8, 10) # G B D F = G7 (dominant 7th)
Common Progressions
~~~~~~~~~~~~~~~~~~~
Some of the most-used chord progressions in Western music:
- **IIVVI** — the foundation of blues, rock, country, folk
- **IVviIV** — the "pop progression" (Let It Be, No Woman No Cry,
With or Without You)
- **iiVI** — the backbone of jazz harmony
- **IviIVV** — the "50s progression" (Stand By Me, Every Breath You Take)
+131 -12
View File
@@ -2,7 +2,40 @@ Working with Tones
==================
A :class:`~pytheory.tones.Tone` represents a single musical note, optionally
with an octave number (scientific pitch notation).
with an octave number in scientific pitch notation (e.g. C4 = middle C).
What is a Tone?
---------------
A musical tone is a sound with a definite pitch — a periodic vibration at
a specific frequency. In the Western 12-tone system, the octave (a 2:1
frequency ratio) is divided into 12 equal steps called **semitones** or
**half steps**. Two semitones make a **whole step** (whole tone).
The 12 chromatic tones are::
C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B
Notes with two names (like C# and Db) are **enharmonic equivalents**
different names for the same pitch. Whether you call it C# or Db depends
on the musical context (key signature, harmonic function).
Scientific Pitch Notation
-------------------------
Each tone can be assigned an octave number. The standard is **scientific
pitch notation**, where the octave number increments at C::
... B3 C4 C#4 D4 ... A4 B4 C5 C#5 ...
^ ^
middle C one octave up
Key reference points:
- **A4 = 440 Hz** — the international tuning standard (ISO 16)
- **C4 = 261.63 Hz** — middle C on the piano
- **A0 = 27.5 Hz** — the lowest A on a standard piano
- **C8 = 4186 Hz** — the highest C on a standard piano
Creating Tones
--------------
@@ -11,7 +44,7 @@ Creating Tones
from pytheory import Tone
# From a string
# From a string (most common)
c4 = Tone.from_string("C4")
cs4 = Tone.from_string("C#4")
@@ -39,24 +72,87 @@ Properties
Pitch and Frequency
-------------------
Every tone vibrates at a specific frequency measured in Hertz (Hz —
cycles per second). The relationship between pitch and frequency is
**logarithmic**: each octave doubles the frequency, and each semitone
multiplies by the 12th root of 2 (~1.05946).
.. code-block:: python
>>> a4 = Tone.from_string("A4", system="western")
>>> a4.frequency
440.0
>>> a4.pitch()
440.0
# Different temperaments
>>> Tone.from_string("A3", system="western").frequency
220.0 # One octave down = half the frequency
>>> Tone.from_string("C4", system="western").frequency
261.63 # Middle C
Temperament
~~~~~~~~~~~
**Temperament** is the system used to tune the intervals between notes.
Different temperaments produce slightly different frequencies for the
same note name:
- **Equal temperament** (default): Every semitone has an identical
frequency ratio of 2^(1/12). This is the modern standard — it allows
free modulation between all keys but no interval is acoustically
"pure" except the octave.
- **Pythagorean temperament**: Built entirely from pure perfect fifths
(3:2 ratio). Produces beatless fifths but introduces the "Pythagorean
comma" — a small discrepancy when 12 fifths don't quite equal 7
octaves. Used in medieval European music.
- **Quarter-comma meantone**: Tunes major thirds to the pure ratio of
5:4, distributing the resulting error across the fifths. Dominant in
Renaissance and Baroque music (15th18th century). Sounds beautiful
in closely related keys but "wolf intervals" make distant keys
unusable.
.. code-block:: python
>>> a4.pitch(temperament="equal")
440.0
>>> a4.pitch(temperament="pythagorean")
440.0
440.0 # A4 is always 440 (it's the reference)
# Symbolic (SymPy expression)
>>> c5 = Tone.from_string("C5", system="western")
>>> c5.pitch(temperament="equal")
523.25
>>> c5.pitch(temperament="pythagorean")
521.48 # Slightly different!
# Symbolic output (SymPy expression)
>>> a4.pitch(symbolic=True)
440
Arithmetic
----------
Intervals and Arithmetic
-------------------------
An **interval** is the distance between two pitches, measured in
semitones. Intervals have both a **quantity** (number of scale steps)
and a **quality** (perfect, major, minor, augmented, diminished).
Common intervals::
Semitones Name Sound
───────── ──── ─────
0 Unison Same note
1 Minor 2nd Tense, dissonant (Jaws theme)
2 Major 2nd A whole step (Do-Re)
3 Minor 3rd Sad, dark (Greensleeves)
4 Major 3rd Happy, bright (Kumbaya)
5 Perfect 4th Open, hollow (Here Comes the Bride)
6 Tritone Unstable, tense (The Simpsons)
7 Perfect 5th Strong, stable (Star Wars)
8 Minor 6th Bittersweet
9 Major 6th Warm (My Bonnie)
10 Minor 7th Bluesy (Star Trek TOS)
11 Major 7th Dreamy, yearning
12 Octave Same note, higher
Tones support ``+`` and ``-`` operators for semitone math:
@@ -75,13 +171,17 @@ Subtracting two tones gives the semitone distance:
.. code-block:: python
>>> g4 = Tone.from_string("G4", system="western")
>>> g4 - c4 # Semitone distance
>>> g4 - c4 # Perfect fifth = 7 semitones
7
>>> c5 = Tone.from_string("C5", system="western")
>>> c5 - c4 # Octave = 12 semitones
12
Comparison and Sorting
----------------------
Tones can be compared and sorted by pitch:
Tones can be compared and sorted by pitch frequency:
.. code-block:: python
@@ -94,7 +194,26 @@ Equality checks note name and octave:
.. code-block:: python
>>> c4 == "C" # Compare with string
>>> c4 == "C" # Compare with string (name only)
True
>>> c4 == Tone(name="C", octave=4)
True
The Circle of Fifths
--------------------
The **circle of fifths** is the most important diagram in Western music
theory. Starting from any note and ascending by perfect fifths (7
semitones), you pass through all 12 chromatic tones before returning
to the starting note:
.. code-block:: python
>>> t = Tone.from_string("C4", system="western")
>>> for i in range(12):
... print(t.name, end=" ")
... t = t + 7
C G D A E B F# C# G# D# A# F
Each step clockwise adds one sharp to the key signature; each step
counter-clockwise (ascending by fourths = 5 semitones) adds one flat.