mirror of
https://github.com/kennethreitz/pytheory.git
synced 2026-06-21 15:00:57 +00:00
cd6f814049
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
513 lines
24 KiB
Markdown
513 lines
24 KiB
Markdown
# Changelog
|
||
|
||
All notable changes to PyTheory are documented here.
|
||
|
||
## 0.34.0
|
||
|
||
- **16 dedicated instrument synths** — physical modeling and specialized
|
||
synthesis for: piano (hammer + steel strings + soundboard), bass guitar
|
||
(thick KS + pickup), flute (breath + tube resonance), trumpet (lip buzz
|
||
+ bell), clarinet (odd harmonics + reed), oboe (double reed + conical
|
||
bore), marimba (inharmonic bar modes), harpsichord (quill pluck),
|
||
cello (deep bowed + body), harp (soft pluck + soundboard bloom),
|
||
upright bass (pizzicato + wooden body), acoustic guitar (KS + body
|
||
resonance), electric guitar (KS + pickup comb filter), sitar (jawari
|
||
+ chikari), plus organ and bowed strings
|
||
- **Speaker cabinet simulation** — tames distorted guitar fizz
|
||
- **Guitar strumming** — `Part.strum("Am")` with fretboard lookup
|
||
- **Analog oscillator drift** — subtle per-note pitch wobble on synth presets
|
||
- **World percussion:** dhol, dholak, mridangam, djembe, metal kit
|
||
with 22 new drum patterns
|
||
- **Piano improvements:** brightness scales with pitch, two-stage decay,
|
||
hammer impact with felt character
|
||
- **Vibrato tuning:** reduced across flute, oboe, trumpet, cello for
|
||
smoother ensemble sound
|
||
- 27 synth waveforms, 10 envelopes, 40+ instrument presets, 80+ drum patterns
|
||
|
||
## 0.33.1
|
||
|
||
- **Electric guitar synth** — Karplus-Strong with magnetic pickup comb filter
|
||
simulation (single-coil honk, proper sustain)
|
||
- **Speaker cabinet simulation** — steep rolloff above 4-5kHz with presence
|
||
bump. Makes distorted guitar sound warm instead of fizzy.
|
||
- **6 guitar presets:** electric_guitar, clean_guitar, crunch_guitar,
|
||
distorted_guitar, orange_crunch, metal_guitar — all with proper cab sim
|
||
- **Sitar synth** — Karplus-Strong with jawari bridge buzz, chikari
|
||
sympathetic strings, variable damping
|
||
- **Guitar strumming** — `Part.strum("Am", Duration.HALF)` with
|
||
fretboard fingering lookup, down/up direction, adjustable strum speed
|
||
- **World drums:** dhol (bhangra, chaal), dholak (qawwali, folk),
|
||
mridangam (adi talam, korvai), djembe (standard, kuku, soli)
|
||
— all with bandpass-filtered membrane noise for realistic drum head sound
|
||
- **Metal drum kit** — clicky kick, bright snare, tight hats
|
||
with 4 patterns (double kick, metal blast, metal groove, metal gallop)
|
||
- 15 synth waveforms, 10 envelopes, 40+ instrument presets
|
||
|
||
## 0.33.0
|
||
|
||
- **Non-12-TET support** — `TET(n)` factory creates any equal temperament
|
||
- **11 microtonal systems:**
|
||
- `"shruti"` (22-TET Indian, 10 thaats with proper shruti intervals)
|
||
- `"maqam"` (24-TET Arabic, quarter-tone Rast/Bayati/Hijaz + 7 more)
|
||
- `"slendro"` (5-TET gamelan), `"pelog"` (9-TET gamelan with 3 pathet)
|
||
- `"thai"` (7-TET, 171 cents/step)
|
||
- `"makam"` (53-TET Turkish Arel-Ezgi-Uzdilek, 9 makams)
|
||
- `"carnatic"` (72-TET, 10 melakartas)
|
||
- `"19-tet"`, `"31-tet"` (historical Western)
|
||
- `"bohlen-pierce"` (13 divisions of the tritave 3:1 — non-octave!)
|
||
- **Just intonation** — `temperament="just"` for pure 5-limit ratios
|
||
- **Historical pitch** — `Score(reference_pitch=415.0)` for Baroque A=415
|
||
- **`Score(system=, temperament=, reference_pitch=)`** flows through to all playback
|
||
- Per-system `c_index` and `period` replace hardcoded constants
|
||
- Fixed all hardcoded `12`s in tone arithmetic
|
||
- Song #22: Greensleeves (Renaissance lute, meantone, A=415)
|
||
- 22 new microtonal tests (819 total)
|
||
|
||
## 0.32.1
|
||
|
||
- `Tone("X")` now raises `ValueError` immediately instead of silently accepting invalid names (#39)
|
||
- Support enharmonic spellings: `Cb`, `Fb`, `E#`, `B#` resolve correctly (#40)
|
||
- Support double sharps (`C##`, `Fx`) and double flats (`Dbb`) via semitone arithmetic (#41)
|
||
- Accept unicode music symbols: `♯` `♭` `𝄪` `𝄫`
|
||
|
||
## 0.32.0
|
||
|
||
- **8 new synth engine features:**
|
||
- Filter envelope: per-note lowpass sweep (`filter_amount`, `filter_attack`, `filter_decay`, `filter_sustain`)
|
||
- Velocity → brightness: harder notes = brighter filter (`vel_to_filter`)
|
||
- Sub-oscillator: octave-below sine for bass weight (`sub_osc`)
|
||
- Tremolo: amplitude LFO modulation (`tremolo_depth`, `tremolo_rate`)
|
||
- Saturation: even-harmonic tape/tube warmth (`saturation`)
|
||
- Noise layer: per-note breath/air texture (`noise_mix`)
|
||
- Phaser: swept allpass filter chain (`phaser`, `phaser_rate`)
|
||
- Configurable FM: `fm_ratio` and `fm_index` params
|
||
- **Highpass filter** (12 dB/oct biquad) on any part
|
||
- **2 new envelopes:** `bowed` (bow attack with sustain), `mallet` (strike with ringing sustain)
|
||
- **Improved `strings_synth`:** additive synthesis with body resonance curve, per-harmonic phase randomization, delayed vibrato onset, bow pressure variation
|
||
- **Instrument preset overhaul:** every preset sanity-checked against real instrument behavior
|
||
- Mallet instruments (vibraphone, celesta, music box, glockenspiel, tubular bells) now ring properly
|
||
- Trumpet uses sustaining envelope instead of pluck
|
||
- Woodwinds have breath noise, brass has velocity brightness
|
||
- Bass instruments have sub-oscillators, synth presets have filter envelopes
|
||
- Piano has velocity-to-brightness and subtle hammer noise
|
||
- Signal chain: saturation → tremolo → distortion → chorus → phaser → highpass → lowpass → delay → reverb
|
||
- Song #21: Cinematic Showcase (Orchestral)
|
||
|
||
## 0.31.0
|
||
|
||
- 3 new synth engines: Karplus-Strong pluck, Hammond organ, string ensemble with body formants
|
||
- 38 instrument presets: `score.part("lead", instrument="violin")`
|
||
- Keys, strings, woodwinds, brass, plucked, synth, and mallet categories
|
||
- 13 total synth waveforms
|
||
|
||
## 0.30.0
|
||
|
||
- Drums are a real Part — same effects pipeline as any voice
|
||
- `score.drums("rock", split=True)` splits kit into kick/snare/hats/toms/cymbals/percussion Parts
|
||
- Each split Part gets independent effects (reverb on snare, LP on hats, etc.)
|
||
- `set_drum_effects()` applies to all drum Parts (split or not)
|
||
- Sidechain triggers on kick only — hats and snare don't duck the pad
|
||
- MIDI import via `Score.from_midi(path)`
|
||
|
||
## 0.29.3
|
||
|
||
- Drums are now a real Part — same effects pipeline as any other voice, zero code duplication
|
||
- `score.parts["drums"]` is a standard Part with reverb, delay, lowpass, etc.
|
||
- `set_drum_effects()` is sugar over the Part's attributes
|
||
|
||
## 0.29.2
|
||
|
||
- Add `score.set_drum_effects()` — reverb, delay, lowpass, distortion, chorus on the drum bus
|
||
- Same effects engine as parts, zero code duplication
|
||
|
||
## 0.29.1
|
||
|
||
- Rename song.py → songs.py
|
||
- Polish all 20 example songs with stereo, convolution reverb, humanize, detune, sidechain
|
||
|
||
## 0.29.0
|
||
|
||
- Add `Score.from_midi(path)` — import any Standard MIDI File into a Score
|
||
- Minimal zero-dependency MIDI parser (Type 0 and Type 1)
|
||
- Each channel becomes a named Part, channel 10 becomes drum hits
|
||
- Tempo, time signature, velocities, and note durations preserved
|
||
- Roundtrip: save_midi → from_midi works
|
||
|
||
## 0.28.3
|
||
|
||
- Rewrite `pytheory demo` — 8 moods with stereo, effects, humanize, convolution reverb, sidechain
|
||
- Added Dub and Temple moods
|
||
|
||
## 0.28.2
|
||
|
||
- Lower drum_humanize default to 0.15 — tighter, more professional feel
|
||
|
||
## 0.28.1
|
||
|
||
- Humanize drum hits — random timing jitter and velocity variation (default 0.3)
|
||
- Control via `Score(drum_humanize=0.5)` — 0.0 = quantized, 0.3 = natural, 0.5+ = loose
|
||
|
||
## 0.28.0
|
||
|
||
- Add figured bass notation: `Chord.figured_bass` and `Chord.analyze_figured()` for classical inversion symbols
|
||
- Add pitch class set theory: `pitch_classes`, `normal_form`, `prime_form`, `forte_number` on Chord
|
||
- Add `Scale.recommend()` — ranked scale suggestions for a set of notes
|
||
- Forte number catalog covers all trichords and tetrachords
|
||
|
||
## 0.27.1
|
||
|
||
- Tab completion in REPL — context-aware for commands, drum presets, synths, envelopes, chords, notes, systems
|
||
|
||
## 0.27.0
|
||
|
||
- Rewrite all 15 drum sounds for higher quality (inharmonic partials, proper transients, multi-mode resonance, saturation)
|
||
- 19 example songs including Dance Party at the Reitz House
|
||
|
||
## 0.26.3
|
||
|
||
- Stereo drum panning — each sound placed in the stereo field (hat right, crash left, toms spread, kick/snare center)
|
||
- Stereo convolution reverb — different IR per L/R channel for all 7 presets
|
||
- 2 new songs: Neon Grid (stereo acid), Glass and Silk (sine+triangle waltz)
|
||
|
||
## 0.26.2
|
||
|
||
- Stereo convolution reverb — different IR per L/R channel for all 7 presets
|
||
- Both algorithmic and convolution reverbs now output true stereo
|
||
|
||
## 0.26.1
|
||
|
||
- Stereo reverb — L and R channels get different early reflection patterns for natural width
|
||
- Effects chain now skips mono reverb in favor of stereo reverb in the mixer
|
||
|
||
## 0.26.0
|
||
|
||
- **Stereo output** — render_score() now returns stereo (N, 2) arrays
|
||
- Add `pan` parameter: -1.0 (left) to 1.0 (right), constant-power panning
|
||
- Add `spread` parameter: detuned oscillators spread across L/R channels
|
||
- Master bus compressor runs per-channel for stereo
|
||
- All playback functions handle stereo natively
|
||
|
||
## 0.25.7
|
||
|
||
- Add `detune` parameter — ±cents oscillator spread on any synth (3 oscillators per note)
|
||
- Swing now applies to drum hits (offbeats shift with the groove)
|
||
- Improved snare and hi-hat sounds (metallic harmonics, faster attack)
|
||
|
||
## 0.25.6
|
||
|
||
- Swing now applies to drum hits — offbeats shift with the groove, everything locks into the same pocket
|
||
- Improved snare: 220Hz body, transient click, tanh saturation
|
||
- Improved hi-hats: metallic harmonics (6k+8.5k+12k Hz), crisper attack, shorter decay
|
||
|
||
## 0.25.5
|
||
|
||
- Improved snare: 220Hz body, transient click, tanh saturation — snappier and more present
|
||
- Improved hi-hats: metallic harmonics (6k+8.5k+12k Hz), shorter decay, crisper attack
|
||
|
||
## 0.25.4
|
||
|
||
- Add master bus compressor/limiter — louder, punchier, more cohesive mixes
|
||
- Feed-forward compression with configurable threshold, ratio, attack, release
|
||
- Makeup gain restores loudness after compression
|
||
- Brick-wall limiter at 0.95 prevents clipping
|
||
- Replaces simple normalization in render_score()
|
||
|
||
## 0.25.3
|
||
|
||
- Add `pytheory repl` — interactive music theory scratchpad and composition tool
|
||
- Context-aware prompt shows key, bpm, drums, active part + effects
|
||
- Theory commands: key, chords, modes, scales, circle, interval, identify, system
|
||
- Composition: drums, part, add, rest, arp, prog, effects, automation, LFO
|
||
- Guitar: fingering, scale diagram
|
||
- 6 musical systems with correct default tonics
|
||
- REPL guide documentation
|
||
|
||
## 0.25.1
|
||
|
||
- Add `pytheory demo` CLI command — plays a randomly generated track, different every time
|
||
- Rewrite README to showcase the full feature set (composition, effects, drums, MIDI export)
|
||
|
||
## 0.25.0
|
||
|
||
- Add sidechain compression — kick ducks pad/bass for the classic EDM pump effect
|
||
- Add song structure: `score.section("verse")`, `score.section("chorus")`, `score.repeat("verse")`
|
||
- Punchier kick drum: 808-style with faster pitch sweep (200→45Hz), sub thump, and soft saturation
|
||
- Section repeat copies all part notes, drum hits, and automation with proper offset
|
||
|
||
## 0.24.1
|
||
|
||
- Add `humanize` parameter on Parts — random micro-timing and velocity variation
|
||
- Makes programmed parts feel like a real player (0.1 = subtle, 0.3 = natural, 0.5+ = loose)
|
||
|
||
## 0.24.0
|
||
|
||
- Add per-note velocity: `lead.add("C5", Duration.QUARTER, velocity=90)` — dynamics, accents, ghost notes
|
||
- Add swing/groove: `Score("4/4", bpm=120, swing=0.5)` — shuffles every other note for human feel
|
||
- Add tempo changes mid-song: `score.set_tempo(140)` — accelerando, ritardando, tempo drops
|
||
- Add `Part.fade_in(bars)` and `Part.fade_out(bars)` — volume envelopes over sections
|
||
- Arpeggiator supports velocity parameter
|
||
- Per-part swing override (set independently from score swing)
|
||
- Tempo map engine: beat-to-sample conversion handles variable BPM throughout a score
|
||
|
||
## 0.23.0
|
||
|
||
- Add convolution reverb with 7 synthetic impulse responses: Taj Mahal, cathedral, plate, spring, cave, parking garage, canyon
|
||
- Each IR models real acoustic properties: early reflections, frequency-dependent absorption, diffusion density, and modulation
|
||
- FFT-based convolution via `scipy.signal.fftconvolve` for fast processing even with long tails (12s Taj Mahal)
|
||
- Select via `reverb_type` parameter on `Score.part()` — drop-in alongside existing algorithmic reverb
|
||
- IR cache for zero-cost reuse across parts
|
||
- Automatable via `Part.set(reverb_type="cathedral")` mid-song
|
||
|
||
## 0.22.0
|
||
|
||
- Add `Part.lfo()` for automated parameter modulation (filter sweeps, tremolo, auto-wah)
|
||
- 4 LFO shapes: sine, triangle, saw, square
|
||
- Configurable rate (cycles per bar), min/max range, duration, and resolution
|
||
- Stack multiple LFOs on different parameters for complex modulation
|
||
|
||
## 0.21.0
|
||
|
||
- Add `Part.set()` for mid-song effect automation (filter sweeps, reverb swells, distortion kicks)
|
||
- Add chorus effect (LFO-modulated delay, Juno-style)
|
||
- Renderer segments audio at automation points for per-section effect processing
|
||
- Updated effect chain: distortion → chorus → lowpass → delay → reverb
|
||
- Document automation, chorus, and updated signal chain
|
||
|
||
## 0.20.0
|
||
|
||
- Add `Part.arpeggio()` — arpeggiator with up/down/updown/downup/random patterns, octave spanning
|
||
- Fix Roman numeral parser to handle flat/sharp degree prefixes (bVI, bVII, bIII, #IV)
|
||
- Add `song_showoff.py` — generative composition that's different every time, uses every feature
|
||
- 4 mood palettes (dark, bright, ethereal, aggressive) with matched keys, progressions, drums, and effects
|
||
|
||
## 0.19.1
|
||
|
||
- Add `Part.arpeggio()` — arpeggiator with up/down/updown/downup/random patterns, octave spanning, and division control
|
||
- Arpeggiator chains with legato + glide for classic acid/trance sequencer sound
|
||
- Rename rhythm docs to "Sequencing: Rhythm and Scores"
|
||
- Document arpeggiator, legato, and glide in rhythm guide
|
||
|
||
## 0.19.0
|
||
|
||
- Add legato mode for parts — continuous waveform without retriggering envelope per note
|
||
- Add glide/portamento — smooth pitch slides between consecutive notes (303-style)
|
||
- Legato renders entire phrase as one oscillator with phase-accumulating frequency changes
|
||
- Glide uses exponential interpolation for perceptually linear pitch slides
|
||
|
||
## 0.18.1
|
||
|
||
- Add distortion effect (tanh soft-clip waveshaping) with drive and mix controls
|
||
- 3 new example songs: Dub Delay Madness (separate delay snare), Liquid DnB (174bpm), Late Night Texts (Drake-style trap)
|
||
- 16 total songs in the song player
|
||
|
||
## 0.18.0
|
||
|
||
- Add per-part audio effects: reverb, delay, and lowpass filter
|
||
- Reverb: Schroeder algorithm with configurable mix and decay
|
||
- Delay: tempo-synced echoes with feedback control
|
||
- Lowpass: 12 dB/octave biquad filter with resonance (Q) control
|
||
- All effects set at part creation: `score.part("lead", reverb=0.3, delay=0.25, lowpass=2000, lowpass_q=1.5)`
|
||
- Effects applied per-part before mixing for independent processing
|
||
|
||
## 0.17.0
|
||
|
||
- Add 10 new groove presets: country, ska, dub, jungle, techno, gospel, swing, bolero, tango, flamenco (58 total)
|
||
- Add 10 new fill presets: reggae, afrobeat, bossa nova, house, trap, hip hop, disco, cumbia, highlife, second line (21 total)
|
||
- Every major genre family now has matching groove + fill presets
|
||
|
||
## 0.16.0
|
||
|
||
- Add drum fill system with 11 genre-specific presets: rock, rock crash, jazz, jazz brush, salsa, samba, funk, metal, blast, buildup, breakdown
|
||
- `Pattern.fill("rock")` returns a 1-bar fill pattern
|
||
- `Score.fill("rock")` inserts a fill at the current position
|
||
- `Score.drums("rock", repeats=8, fill="rock", fill_every=4)` auto-fills every Nth bar
|
||
- Without `fill_every`, fill replaces only the last bar
|
||
|
||
## 0.15.1
|
||
|
||
- Add `Synth.PWM_SLOW` and `Synth.PWM_FAST` — pulse width modulation with LFO sweep (Juno-style pads)
|
||
- Add `Score.drums()` shorthand for `score.add_pattern(Pattern.preset(...), repeats=...)`
|
||
- Update all docs to use `score.drums()` syntax and document all 10 synth waveforms
|
||
|
||
## 0.15.0
|
||
|
||
- Add 5 new synth waveforms: `Synth.SQUARE`, `Synth.PULSE`, `Synth.FM`, `Synth.NOISE`, `Synth.SUPERSAW`
|
||
- Square wave: classic chiptune / 8-bit sound (odd harmonics at 1/n)
|
||
- Pulse wave: variable duty cycle for NES-style timbres (25%, 12.5%)
|
||
- FM synthesis: DX7-style frequency modulation (electric piano, bells, brass, metallic)
|
||
- Noise: white noise for percussion textures and effects
|
||
- Supersaw: 7 detuned saw oscillators for trance/EDM pads
|
||
- All 8 synths available in both the API (`Synth.FM`) and Part strings (`synth="fm"`)
|
||
- CLI play command supports all 8 waveforms
|
||
|
||
## 0.14.0
|
||
|
||
- Add `Part` class for multi-voice Score arrangements (lead, bass, pads, etc.)
|
||
- `Score.part()` creates named parts with independent synth, envelope, and volume
|
||
- `Score.add_pattern()` for attaching drum patterns
|
||
- `render_score()` exported for headless buffer rendering
|
||
- Parts accept raw float beat values alongside `Duration` enums
|
||
- All 10 example songs rewritten with drums + chords + lead + bass parts
|
||
|
||
## 0.13.1
|
||
|
||
- Fix drum pattern repeats: hits now correctly offset across cycles instead of piling up on the first bar
|
||
|
||
## 0.13.0
|
||
|
||
- Add drum synthesizer with 27 individual instrument voices (kick, snare, hat, conga, timbale, etc.)
|
||
- Add `play_pattern()` for playing drum patterns through the speakers
|
||
- Add `play_score()` for playing mixed drum patterns + chord progressions together
|
||
- Every `DrumSound` has a dedicated synthesis algorithm (pitch sweeps, noise bursts, membrane resonance, metallic rings)
|
||
|
||
## 0.12.0
|
||
|
||
- Add rhythm module: `Duration`, `TimeSignature`, `Note`, `Rest`, `Score`
|
||
- `Duration` enum with 8 note lengths (whole through sixteenth, dotted, triplet)
|
||
- `TimeSignature` with string parsing ("4/4", "3/4", "6/8", "12/8") and beats_per_measure
|
||
- `Score` class with fluent `.add()` / `.rest()` chaining, measure counting, and `save_midi()` export
|
||
- Measure-aware MIDI export with proper time signature and tempo meta events
|
||
- Add `DrumSound` enum with 27 General MIDI percussion sounds
|
||
- Add `Pattern` class with 48 drum pattern presets covering:
|
||
- **Rock/Pop**: rock, half time, double time, disco, motown, train beat
|
||
- **Jazz**: jazz, bebop, shuffle, linear, paradiddle
|
||
- **Latin**: salsa, bossa nova, samba, cumbia, merengue, baiao, maracatu
|
||
- **Afro-Cuban**: son clave 3-2/2-3, rumba clave 3-2/2-3, cascara, guaguanco, mozambique, nanigo, bembe, 6/8 afro-cuban, tresillo, habanera
|
||
- **African**: afrobeat, highlife
|
||
- **Caribbean**: reggae, dancehall
|
||
- **Electronic**: house, trap, drum and bass, breakbeat
|
||
- **Metal/Punk**: metal, blast beat, punk
|
||
- **Other**: funk, hip hop, bo diddley, second line, new orleans, waltz, 12/8 blues
|
||
- `Pattern.to_score()` renders drum patterns to Score for MIDI export
|
||
|
||
## 0.11.0
|
||
|
||
- Add drop voicings: `Chord.close_voicing()`, `Chord.open_voicing()`, `Chord.drop2()`, `Chord.drop3()`
|
||
- Add `Key.modulation_path(target)` for chord-by-chord modulation suggestions via pivot chords
|
||
- Add `Scale.degree_name(n)` returning traditional names (tonic, dominant, leading tone, etc.)
|
||
- Add `Chord.extensions()` to suggest available 9th/11th/13th extensions
|
||
- Add `Tone.solfege` property for fixed-Do solfege syllables (Do, Re, Mi, Fi, etc.)
|
||
- Add CLI `identify` command for full chord analysis from a symbol
|
||
- Add CLI `midi` command for exporting progressions to Standard MIDI Files
|
||
- Expand documentation: solfege, Helmholtz, cents, slash chords, drop voicings, chord extensions, borrowed chord analysis, ADSR envelopes, MIDI export, new CLI commands
|
||
|
||
## 0.10.0
|
||
|
||
- Add `Scale.fitness()` to score how well a set of notes fits a scale (0.0–1.0)
|
||
- Add `Key.suggest_next(chord)` for chord progression suggestions based on functional harmony
|
||
- Add `Tone.helmholtz` and `Tone.scientific` properties for alternate pitch notation
|
||
- Add `Chord.slash(bass)` and `Chord.slash_name` for slash chord notation (C/G, Am/E)
|
||
- Add `save_midi()` for exporting tones, chords, and progressions as Standard MIDI Files
|
||
- Add chord tone highlighting in `Fretboard.scale_diagram()` — chord tones uppercase, passing tones lowercase
|
||
- Extend `Chord.analyze()` to recognize borrowed chords (bVI, bVII, bIII, etc.)
|
||
|
||
## 0.9.0
|
||
|
||
- Add ADSR envelope system with 8 presets: `Envelope.PIANO`, `ORGAN`, `PLUCK`, `PAD`, `STRINGS`, `BELL`, `STACCATO`, `NONE`
|
||
- Add `Chord.from_symbol()` parser — handles any standard chord symbol (e.g. "F#m7b5", "Bbmaj9", "Gsus4") without lookup tables
|
||
- Add `Key.pivot_chords(target)` for finding modulation pivot chords between two keys
|
||
- Add `Scale.parallel_modes()` to show all modes sharing the same notes (C major → D dorian, E phrygian, etc.)
|
||
- Add `Tone.cents_difference(other)` for measuring fine pitch differences in cents
|
||
- Add `--envelope` flag to CLI play command
|
||
- CLI play command now uses `Chord.from_symbol()` for broader chord parsing
|
||
- Replace hardcoded `c_index = 3` with named `C_INDEX` constant throughout
|
||
|
||
## 0.8.3
|
||
|
||
- Add `Chord.symbol` property for standard shorthand notation (Cmaj7, Dm, G7, m7b5, etc.)
|
||
- Add `Key.common_progressions()` to realize all named progressions in a key
|
||
- Add CLI commands: `modes`, `circle`, `progressions`
|
||
|
||
## 0.8.2
|
||
|
||
- Use flat spellings in CHARTS `acceptable_tone_names` (e.g. Bbm now shows Bb/Db/F instead of A#/C#/F)
|
||
|
||
## 0.8.1
|
||
|
||
- Use musically correct flat spellings in flat keys (F major gives Bb, not A#)
|
||
|
||
## 0.8.0
|
||
|
||
- Add `Fretboard.scale_diagram()` for visual scale layouts on any instrument
|
||
- Add `play_progression()` for sequential chord playback with gaps
|
||
- Add cookbook documentation page with practical recipes
|
||
- Curated guitar fingering overrides for common open chords
|
||
- Fingering memoization with bounded cache, barre detection, 4-fret span constraint
|
||
- API ergonomics: `Fretboard.chord()`, convenience constructors, slow test markers
|
||
|
||
## 0.7.0
|
||
|
||
- Add `Fretboard.chord()` method for named chord lookups
|
||
- Improve fingering algorithm with better voicing selection
|
||
- Rewrite all documentation in REPL style with verified output
|
||
|
||
## 0.6.1
|
||
|
||
- Fix sawtooth and triangle wave generation
|
||
- Add WAV export via `save()`
|
||
- Add CLI tests and play module tests
|
||
- Skip play module tests when PortAudio is not available
|
||
|
||
## 0.6.0
|
||
|
||
- Support flat note names (Db, Bb, Eb, etc.) throughout the system
|
||
- Add `Fingering` class for labeled chord fingerings
|
||
- Add `pytheory play` CLI command for playing notes and chords
|
||
- Add 12 example scripts showcasing pytheory features
|
||
- Expand documentation with undocumented features and CLI guide
|
||
|
||
## 0.4.1
|
||
|
||
- Add `--temperament` flag to CLI tone command
|
||
- Add Symbolic Pitch section to tones docs
|
||
|
||
## 0.4.0
|
||
|
||
- Add key signatures, scale diagrams, chord building, and progression analysis
|
||
- Add CLI tool (`pytheory tone`, `pytheory chord`, `pytheory key`, etc.)
|
||
- Add Jupyter notebook tutorial
|
||
- Improve test coverage from 93% to 97% (476 tests)
|
||
- Add type hints, docstrings, and property caching throughout
|
||
|
||
## 0.3.2
|
||
|
||
- Add type hints and docstrings throughout the library
|
||
|
||
## 0.3.1
|
||
|
||
- Add capo support, chord merging (`+`), tritone substitution
|
||
- Add secondary dominants, Nashville number system
|
||
- Add more common progressions (blues, jazz, flamenco, modal)
|
||
|
||
## 0.3.0
|
||
|
||
- Add interval naming (`Tone.interval_to()`)
|
||
- Add MIDI conversion (`Tone.midi`, `Tone.from_midi()`)
|
||
- Add `Tone.from_frequency()`, `Tone.transpose()`
|
||
- Add `Chord.root`, `Chord.quality` properties
|
||
- Add `Chord.from_name()`, `Chord.from_intervals()`, `Chord.from_midi_message()`
|
||
- Add `Interval` constants (MINOR_THIRD, PERFECT_FIFTH, etc.)
|
||
- Add `PROGRESSIONS` dict with common named progressions
|
||
- Add `Tone.enharmonic` property
|
||
- Add inversions, harmonize, and Roman numeral progressions
|
||
- Add `Key` class with detection, signatures, relative/parallel keys
|
||
- Add `Scale.detect()` and `Chord.from_tones()` convenience constructors
|
||
- Add 25 instrument presets (mandolin family, violin family, banjo, harp, world instruments, keyboard)
|
||
- Add `Tone.circle_of_fifths()` and `Tone.circle_of_fourths()`
|
||
- Add chord identification (17 types), voice leading, tension scoring
|
||
- Add beat frequencies, Plomp-Levelt dissonance model, harmony scoring
|
||
|
||
## 0.2.0
|
||
|
||
- Add `Fretboard` class for guitar fretboards
|
||
- Add `play()` function with sine, sawtooth, and triangle wave synthesis
|
||
- Add chord harmony and dissonance calculations
|
||
- Modernize project structure (pyproject.toml, sounddevice)
|
||
|
||
## 0.1.0
|
||
|
||
- Initial release
|
||
- Western 12-tone system with tones, scales, and basic chord support
|
||
- Temperament support (equal, Pythagorean, meantone)
|
||
- Indian (Hindustani), Arabic, Japanese, Blues, and Gamelan systems
|