Quickstart

PyTheory works at two levels — pick the one that fits what you need:

  1. Music theory — explore scales, chords, keys, intervals, and harmony. No audio required. Works anywhere Python runs.

  2. Composition — build multi-part arrangements with drums, synths, effects, and export to MIDI. Needs PortAudio for live playback.

Both are first-class. You can use PyTheory purely as a theory reference and never touch the audio side, or you can jump straight into composing. This guide covers both paths.

Installation

$ pip install pytheory

(Don’t want to install anything yet? Try PyTheory in your browser at the playground.)

For audio playback through your speakers, you’ll also need PortAudio:

  • macOS: brew install portaudio

  • Ubuntu: apt install libportaudio2

  • Windows: included with the sounddevice package

PortAudio is only needed for live playback. MIDI export, WAV export, and all theory functions work without it.

Two optional extras unlock the performance features:

$ pip install "pytheory[live]"   # MIDI input (python-rtmidi)
$ pip install "pytheory[link]"   # Ableton Link sync (LinkPython-extern)

[live] lets the live engine take input from a MIDI keyboard or controller; [link] lets it lock tempo and beat grid to an Ableton Link session (Ableton Live, most iOS music apps). They’re independent — install either or both. [link] compiles Ableton’s C++ Link library on first install, so expect the install to take a minute. See Live Performance for what they unlock.

Hear Something Immediately

$ pytheory demo

This generates and plays a random track — different every time. It’s the fastest way to hear what PyTheory can do.

Explore Music Theory

The theory layer is where most people start. No audio setup needed — this works everywhere Python runs. Every concept in Western music theory — and fifteen other tuning systems — has a clean Python API.

Tones and intervals:

>>> from pytheory import Tone

>>> c4 = Tone.from_string("C4", system="western")
>>> c4.frequency
261.6255653005986
>>> c4.midi
60

>>> c4 + 7
<Tone G4>
>>> c4.interval_to(c4 + 7)
'perfect 5th'

>>> Tone.from_frequency(440)
<Tone A4>
>>> Tone.from_midi(69)
<Tone A4>

Keys, scales, and chords:

>>> from pytheory import Key, Chord

>>> key = Key("C", "major")
>>> key.chords
['C major', 'D minor', 'E minor', 'F major', 'G major', 'A minor', 'B diminished']

>>> [c.symbol for c in key.progression("I", "V", "vi", "IV")]
['C', 'G', 'Am', 'F']

>>> key.signature
{'sharps': 0, 'flats': 0, 'accidentals': []}

>>> Key("F", "major").signature
{'sharps': 0, 'flats': 1, 'accidentals': ['Bb']}

>>> Chord.from_symbol("Am7").identify()
'A minor 7th'

>>> Chord.from_tones("G", "B", "D", "F").analyze("C")
'V7'

Harmonic analysis and modulation:

>>> Key("C", "major").pivot_chords(Key("G", "major"))
['A minor', 'C major', 'E minor', 'G major']

>>> Key("C", "major").relative
<Key A minor>

>>> key.suggest_next(key.triad(4))  # what follows V?
[<Chord C major>, <Chord A minor>, <Chord F major>]

Scales across 16 tuning systems:

>>> from pytheory import TonedScale

>>> TonedScale(tonic="Sa4", system="indian")["bhairav"].note_names
['Sa', 'komal Re', 'Ga', 'Ma', 'Pa', 'komal Dha', 'Ni', 'Sa']

>>> TonedScale(tonic="Do4", system="arabic")["hijaz"].note_names
['Do', 'Reb', 'Mi', 'Fa', 'Sol', 'Solb', 'Sib', 'Do']

>>> TonedScale(tonic="C4", system="japanese")["hirajoshi"].note_names
['C', 'D', 'Eb', 'G', 'Ab', 'C']

Those TonedScale spellings are 12-tone-equal-tempered approximations. For the real thing — just-intonation Indian ragas and quarter-tone Arabic maqamat with their authentic tunings — reach for the dedicated Raga and Maqam classes (see Musical Systems):

>>> from pytheory import Raga, Maqam

>>> Raga.get("yaman").note_names(sa="C")
['C', 'D', 'E', 'F#', 'G', 'A', 'B']

>>> Maqam.get("rast").degree_names()  # the down arrow marks a quarter-flat
['Do', 'Re', 'Mi↓', 'Fa', 'Sol', 'La', 'Si↓']

Guitar fingerings:

>>> from pytheory import Fretboard

>>> fb = Fretboard.guitar()
>>> fb.chord("Am")
Fingering(E=x, A=0, D=2, G=2, B=1, e=0)

All of the above works without PortAudio, without sounddevice, without any audio setup at all. It’s pure Python music theory.

Compose a Track

This is where it gets fun. A Score is your arrangement — drums, chords, melody, bass, each with their own synth and effects:

from pytheory import Score, Key, Duration, play_score

score = Score("4/4", bpm=120)
score.drums("rock", repeats=8, fill="rock", fill_every=4)

piano = score.part("piano", instrument="piano", reverb=0.3)
lead = score.part("lead", synth="saw", envelope="pluck",
                  delay=0.2, reverb=0.2, lowpass=4000)
bass = score.part("bass", synth="triangle", lowpass=900)

for chord in Key("G", "major").progression("I", "V", "vi", "IV") * 2:
    piano.add(chord, Duration.WHOLE)

lead.add("D5", 1).add("B4", 0.5).add("D5", 0.5)
lead.add("G5", 1).add("E5", 1)
lead.add("D5", 0.5).add("B4", 0.5).add("A4", 1)
lead.add("G4", 2).rest(2)

for n in ["G2", "G2", "D2", "D2", "E2", "E2", "C2", "C2"] * 2:
    bass.add(n, Duration.HALF)

play_score(score)

Export to Your DAW

The whole point: sketch in Python, finish in Logic / Ableton / Reaper.

score.save_midi("my_sketch.mid")

Open that file in any DAW and you’ll see all the notes laid out on the timeline, ready to assign to real instruments and mix.

You can also save rendered audio:

from pytheory import save, Chord
save(Chord.from_symbol("Am7"), "am7.wav", t=2_000)

Prefer sheet music? Export the same arrangement to notation — ABC, LilyPond, or MusicXML — and open it in MuseScore, Frescobaldi, or any engraver:

with open("my_sketch.musicxml", "w") as f:
    f.write(score.to_musicxml(title="My Sketch"))

See Playback and Export for the full export story, and Listening — Microphone In to go the other way — transcribe a recording straight back into a Score.

What’s in the Box

Theory — tones, scales (40+ across 16 tuning systems, including just-intonation Indian ragas and quarter-tone Arabic maqamat), chords (19 types, Roman numeral analysis with secondary dominants, figured bass, tension scoring, voice leading, pitch class sets with Forte numbers), keys (detection, signatures, modulation paths, borrowed chords), cadence detection, reharmonization, and scale recommendation.

Sequencing — Score, Part, Duration, TimeSignature. Arpeggiator with 5 patterns. Legato with pitch glide. Per-note velocity. Swing. Tempo changes. Fade in/out. Song sections with repeat. Humanize.

Synthesis — 56 waveforms, from the classic four (sine, saw, square, triangle) through FM, supersaw, pulse, and wavefolding to 39 dedicated instrument synths modeled from scratch — plus 83 ready-to-play instrument presets that bundle a synth, envelope, and effects. 10 ADSR envelopes. Detune. Stereo pan and spread.

Effects — distortion, chorus, lowpass filter (with resonance), delay, reverb (algorithmic + 7 stereo convolution presets including Taj Mahal with 12-second tail). All per-part with automation and LFO modulation. Sidechain compression. Master bus compressor/limiter.

Drums — 100 pattern presets (rock, jazz, salsa, bossa nova, afrobeat, house, trap, and 90+ more). 37 fill presets. 74 synthesized drum voices with stereo panning.

Instruments — 25 fretted and bowed string instruments (guitar with 8 tunings, bass, ukulele, mandolin family, violin family, banjo, harp, oud, sitar, erhu, and more) with chord-fingering generation, ASCII tab, and SVG/PNG fretboard diagrams.

Output — stereo playback, WAV export, MIDI import/export, and notation export to ABC, LilyPond, and MusicXML. Plus audio-to-score transcription: drop in a recording and get the notes back.

Interface — REPL with tab completion (pytheory repl) and a CLI with 24 commands: pytheory demo, pytheory key, pytheory chord, pytheory identify, pytheory midi, pytheory play, pytheory raga, pytheory maqam, pytheory tune, and more.

Where to Go Next