mirror of
https://github.com/kennethreitz/pytheory.git
synced 2026-06-05 23:00:20 +00:00
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:
+2
-1
@@ -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
@@ -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
|
||||
- **1–15 Hz**: Audible rhythmic beating
|
||||
- **15–30 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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
- **I–IV–V–I** — the foundation of blues, rock, country, folk
|
||||
- **I–V–vi–IV** — the "pop progression" (Let It Be, No Woman No Cry,
|
||||
With or Without You)
|
||||
- **ii–V–I** — the backbone of jazz harmony
|
||||
- **I–vi–IV–V** — the "50s progression" (Stand By Me, Every Breath You Take)
|
||||
|
||||
+131
-12
@@ -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 (15th–18th 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.
|
||||
|
||||
Reference in New Issue
Block a user