diff --git a/docs/guide/chords.rst b/docs/guide/chords.rst index 241a605..74ded04 100644 --- a/docs/guide/chords.rst +++ b/docs/guide/chords.rst @@ -322,6 +322,14 @@ against 17 known chord types (triads, 7ths, 9ths, sus, power chords). >>> Chord.from_tones("Bb", "D", "F").identify() 'Bb major' +Enharmonic spellings are fully supported — Cb, Fb, E#, B#, double +sharps/flats, and unicode symbols (see :doc:`tones` for details): + +.. code-block:: pycon + + >>> Chord.from_tones("Cb", "Eb", "Gb").identify() + 'B minor' + You can also access the root and quality separately: .. code-block:: pycon diff --git a/docs/guide/drums.rst b/docs/guide/drums.rst index 96eda2b..977b32a 100644 --- a/docs/guide/drums.rst +++ b/docs/guide/drums.rst @@ -9,7 +9,7 @@ in Atlanta. Over a dancehall pattern, you're in Kingston. The drums ARE the genre -- they tell the listener's body how to move before a single melodic note is played. -PyTheory includes a complete drum system -- 27 synthesized percussion +PyTheory includes a complete drum system -- 51 synthesized percussion sounds, 80+ pattern presets across dozens of genres, and 21 fill presets. Every sound is generated from waveforms; no samples needed. @@ -91,7 +91,7 @@ The ``DrumSound`` enum maps to General MIDI percussion note numbers: >>> DrumSound.CLOSED_HAT.value 42 -All 27 sounds, organized by type: +All 51 sounds, organized by type: **Kicks:** KICK (36) @@ -106,7 +106,24 @@ All 27 sounds, organized by type: **Percussion:** COWBELL (56), CLAVE (75), SHAKER (70), TAMBOURINE (54), CONGA_HIGH (63), CONGA_LOW (64), BONGO_HIGH (60), BONGO_LOW (61), TIMBALE_HIGH (65), TIMBALE_LOW (66), AGOGO_HIGH (67), AGOGO_LOW (68), -GUIRO (73), MARACAS (70) +GUIRO (73) + +**Tabla:** TABLA_NA (86), TABLA_TIN (87), TABLA_GE (88), TABLA_DHA (89), +TABLA_TIT (90), TABLA_KE (91), TABLA_GE_BEND (108 -- bayan with upward +pitch bend from palm pressing into the head) + +**Dhol:** DHOL_DAGGA (92), DHOL_TILLI (93), DHOL_BOTH (94) + +**Dholak:** DHOLAK_GE (95), DHOLAK_NA (96), DHOLAK_TIT (97) + +**Mridangam:** MRIDANGAM_THAM (98), MRIDANGAM_NAM (99), MRIDANGAM_DIN (100), +MRIDANGAM_THA (101) + +**Djembe:** DJEMBE_BASS (102), DJEMBE_TONE (103), DJEMBE_SLAP (104) + +**Cajón:** CAJON_SLAP (109), CAJON_TAP (110) + +**Metal Kit:** METAL_KICK (105), METAL_SNARE (106), METAL_HAT (107) Drum Synthesis -------------- @@ -200,8 +217,8 @@ everything to its essentials. The metal kit adds 3 dedicated sounds (double kick, china cymbal, stack) and 4 patterns for extreme metal subgenres. -**World Percussion:** tabla, dhol, dholak, mridangam, djembe -- Deep -traditions from across the globe, each with authentic sound sets and +**World Percussion:** tabla, dhol, dholak, mridangam, djembe, cajón -- +Deep traditions from across the globe, each with authentic sound sets and idiomatic patterns. See the World Percussion section below for details. **Other:** funk, hip hop, bo diddley, second line, new orleans, waltz, @@ -330,8 +347,10 @@ most expressive percussion instruments ever created. A single tabla player can produce an astonishing range of tones by varying finger placement, pressure, and striking technique. -**6 sounds** -- covering the primary tabla strokes (na, tin, tun, ge, -ke, and ti-ra-ki-ta combinations). +**7 sounds** -- covering the primary tabla strokes (na, tin, tun, ge, +dha, ke, tit) plus a bayan pitch bend sound (TABLA_GE_BEND) that +models the technique of pressing the palm into the bayan head to bend +the pitch upward. **7 patterns:** teental (16 beats, the most common taal), jhaptaal (10 beats), rupak (7 beats), dadra (6 beats), keherwa (8 beats, folk @@ -433,6 +452,23 @@ classic triplet-feel gallop rhythm). score = Score("4/4", bpm=200) score.drums("metal blast", repeats=4) +Cajón +~~~~~ + +The cajón is a box-shaped percussion instrument from Peru, now +ubiquitous in acoustic and unplugged settings worldwide. Players sit +on the box and strike the front face with their hands. + +**2 sounds** -- slap (sharp, snare-like) and tap (bass-like). + +**3 patterns:** cajon (basic groove), cajon rumba (flamenco-style rumba), +and cajon folk (folk/acoustic pattern). + +.. code-block:: python + + score = Score("4/4", bpm=100) + score.drums("cajon", repeats=4) + MIDI Export ----------- diff --git a/docs/guide/effects.rst b/docs/guide/effects.rst index 2d8559d..7a60fda 100644 --- a/docs/guide/effects.rst +++ b/docs/guide/effects.rst @@ -841,9 +841,11 @@ processes each section independently: lead.arpeggio("Gm", bars=4, pattern="updown", octaves=2) Any parameter can be automated: ``lowpass``, ``lowpass_q``, ``highpass``, -``reverb``, ``reverb_decay``, ``delay``, ``delay_time``, ``delay_feedback``, -``distortion``, ``distortion_drive``, ``chorus``, ``phaser``, ``phaser_rate``, -``saturation``, ``tremolo_depth``, ``tremolo_rate``, ``volume``. +``reverb``, ``reverb_decay``, ``reverb_type``, ``delay``, ``delay_time``, +``delay_feedback``, ``distortion``, ``distortion_drive``, ``chorus``, +``phaser``, ``phaser_rate``, ``saturation``, ``tremolo_depth``, +``tremolo_rate``, ``cabinet``, ``cabinet_brightness``, ``analog_drift``, +``volume``. LFO Automation -------------- diff --git a/docs/guide/playback.rst b/docs/guide/playback.rst index a5aee76..a409cd0 100644 --- a/docs/guide/playback.rst +++ b/docs/guide/playback.rst @@ -66,6 +66,17 @@ the mix louder and punchier: chords.add(Chord.from_symbol(sym), Duration.WHOLE) play_score(score) +The render pipeline respects the Score's ``temperament`` and +``reference_pitch`` settings, so Baroque or microtonal scores play back +at the correct tuning: + +.. code-block:: python + + score = Score("4/4", bpm=80, temperament="meantone", reference_pitch=415.0) + +Press **Ctrl+C** at any time during playback to stop — PyTheory catches +``KeyboardInterrupt`` and stops audio cleanly. + See :doc:`sequencing` for how to build scores and parts. render_score() -- Headless Rendering @@ -153,7 +164,7 @@ Play a drum pattern through the speakers: play_pattern(Pattern.preset("rock"), repeats=4, bpm=120) play_pattern(Pattern.preset("bossa nova"), repeats=4, bpm=140) -See :doc:`drums` for the full list of 58 presets and 21 fills. +See :doc:`drums` for the full list of 80+ presets and 21 fills. play_progression() -- Quick Chord Playback ------------------------------------------ diff --git a/docs/guide/sequencing.rst b/docs/guide/sequencing.rst index f61f697..bb7e0fc 100644 --- a/docs/guide/sequencing.rst +++ b/docs/guide/sequencing.rst @@ -667,8 +667,16 @@ A Score can use any tuning system and temperament: # Just intonation — pure intervals score = Score("4/4", bpm=90, temperament="just") -Temperaments: ``"equal"`` (default), ``"pythagorean"``, ``"meantone"``, -``"just"``. +The Score constructor accepts these tuning parameters: + +- ``system``: Musical system name (default ``"western"``). Any system + from :doc:`systems` works — ``"indian"``, ``"shruti"``, ``"maqam"``, + ``"carnatic"``, etc. Note strings in ``Part.add()`` are parsed against + this system. +- ``temperament``: Tuning temperament — ``"equal"`` (default), + ``"pythagorean"``, ``"meantone"``, ``"just"``. +- ``reference_pitch``: Concert pitch in Hz (default 440.0). Use 415.0 + for Baroque tuning, 432.0 for "Verdi tuning", etc. Custom equal temperaments via the ``TET()`` factory: diff --git a/docs/guide/synths.rst b/docs/guide/synths.rst index c91f7c6..dd9b019 100644 --- a/docs/guide/synths.rst +++ b/docs/guide/synths.rst @@ -390,7 +390,7 @@ Dedicated Instrument Synths -------------------------- Beyond the classic and physical modeling waveforms, PyTheory includes -24 dedicated instrument synths. Each one uses tailored synthesis +31 dedicated instrument synths. Each one uses tailored synthesis techniques -- additive harmonics, formant shaping, body resonance modeling, and specialized envelopes -- to capture the character of a specific acoustic instrument. These are the waveforms that bring the @@ -715,7 +715,7 @@ Instrument Presets ------------------ Instead of choosing synth + envelope + effects manually, use an -instrument preset — 40+ predefined combinations that approximate real +instrument preset — 60+ predefined combinations that approximate real instruments: .. code-block:: python @@ -728,20 +728,28 @@ instruments: Available instruments: -**Keys**: piano, electric_piano, organ, harpsichord, celesta, music_box +**Keys**: piano, electric_piano, organ, harpsichord, celesta, music_box, +accordion **Strings**: violin, viola, cello, contrabass, string_ensemble -**Woodwinds**: flute, clarinet, oboe, bassoon +**Woodwinds**: flute, clarinet, oboe, bassoon, saxophone, alto_sax, +tenor_sax, bari_sax **Brass**: trumpet, trombone, french_horn, tuba, brass_ensemble -**Plucked**: acoustic_guitar, electric_guitar, distorted_guitar, -bass_guitar, upright_bass, harp, sitar, koto +**Plucked**: acoustic_guitar, electric_guitar, clean_guitar, crunch_guitar, +distorted_guitar, orange_crunch, metal_guitar, bass_guitar, upright_bass, +harp, sitar, koto, banjo, mandolin, mandola, ukulele -**Synth**: synth_lead, synth_pad, synth_bass, acid_bass, 808_bass +**World/Exotic**: pedal_steel, theremin, kalimba, steel_drum, didgeridoo, +bagpipe -**Percussion**: vibraphone, marimba, xylophone, glockenspiel, tubular_bells +**Synth**: synth_lead, synth_pad, synth_bass, acid_bass, 808_bass, +granular_pad, granular_texture, vocal, choir + +**Percussion**: vibraphone, marimba, xylophone, glockenspiel, tubular_bells, +timpani Explicit kwargs override preset defaults: diff --git a/docs/guide/systems.rst b/docs/guide/systems.rst index 9ffa06e..9770d90 100644 --- a/docs/guide/systems.rst +++ b/docs/guide/systems.rst @@ -1,10 +1,11 @@ Musical Systems =============== -PyTheory supports **six musical systems**, each with its own tone names, -scale patterns, and centuries of tradition behind them. Every system -maps onto the same 12-tone equal temperament backbone, so you can -compare scales across cultures and even combine them in your own music. +PyTheory supports **16 musical systems** — 6 core systems mapped onto +12-tone equal temperament, plus 10 microtonal systems with their own +native tunings. The core systems let you compare scales across cultures; +the microtonal systems go beyond 12-TET into genuinely different pitch +universes. Western ------- @@ -271,4 +272,117 @@ produce the same pitches: >>> do4.frequency 261.6255653005986 +Microtonal Systems +------------------ + +Beyond the six 12-TET core systems, PyTheory includes 10 microtonal +systems that use their own native tunings — more notes per octave, +just intonation ratios, or entirely alien pitch structures. + +Shruti (22 tones per octave) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Indian 22-shruti system divides the octave into 22 unequal steps +using just intonation ratios. These microtonal inflections are what +give classical Indian music its characteristic expressiveness — pitches +that fall "between the cracks" of the piano. + +.. code-block:: python + + score = Score("4/4", bpm=75, system="shruti") + +Maqam (24 tones per octave) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Arabic 24-tone system adds Zalzalian quarter-tone intervals +(derived from just intonation ratios of 11 and 13) to the standard +12 tones. These "neutral" intervals — halfway between major and minor — +are the soul of maqam music. + +.. code-block:: python + + score = Score("4/4", bpm=90, system="maqam") + +Slendro (5-TET) +~~~~~~~~~~~~~~~~ + +The Javanese slendro scale — 5 equal divisions of the octave. Each +step is 240 cents, wider than any Western interval. Ethereal and +floating. + +Pelog (9-TET) +~~~~~~~~~~~~~ + +Approximation of the Javanese pelog tuning as 9 equal divisions of +the octave. + +Thai (7-TET) +~~~~~~~~~~~~~ + +Thai classical music divides the octave into 7 equal steps of ~171 +cents each — every interval is the same size. + +Makam (53-TET) +~~~~~~~~~~~~~~ + +Turkish makam music uses 53 equal divisions of the octave — fine +enough to approximate virtually any just interval. The system that +underlies Ottoman classical music. + +Carnatic (72-TET) +~~~~~~~~~~~~~~~~~ + +South Indian Carnatic music theory describes 72 melakarta ragas. +The 72-TET system provides enough resolution to represent all the +microtonal inflections of Carnatic practice. + +19-TET and 31-TET +~~~~~~~~~~~~~~~~~~ + +Extended equal temperaments that offer better approximations of +just intonation intervals than 12-TET. 19-TET has excellent major +thirds; 31-TET closely matches quarter-comma meantone. + +.. code-block:: python + + score = Score("4/4", bpm=100, system="19-tet") + +Bohlen-Pierce (13 equal divisions of the tritave) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A genuinely alien tuning system — 13 equal divisions of the +**tritave** (3:1 ratio) instead of the octave (2:1). No octaves, no +fifths, built on 3:5:7 harmonics. Used by experimental composers. + +.. code-block:: python + + score = Score("4/4", bpm=100, system="bohlen-pierce") + +The TET() Factory +~~~~~~~~~~~~~~~~~ + +Create any equal temperament on the fly with the ``TET()`` factory: + +.. code-block:: python + + from pytheory import TET + + edo19 = TET(19) # 19-tone equal temperament + edo31 = TET(31) # 31-tone equal temperament + score = Score("4/4", bpm=100, system=edo19) + +Tone names in custom TET systems are integers (0, 1, 2, ..., n-1). + +System.tone() Method +~~~~~~~~~~~~~~~~~~~~ + +Any system can create a Tone directly: + +.. code-block:: python + + from pytheory import SYSTEMS + + western = SYSTEMS["western"] + c4 = western.tone("C", octave=4) + Music is universal, but every culture hears it differently. These systems are different maps of the same territory -- explore one you've never played in before and see what you find. diff --git a/docs/guide/tones.rst b/docs/guide/tones.rst index 64fee0e..a01633c 100644 --- a/docs/guide/tones.rst +++ b/docs/guide/tones.rst @@ -357,6 +357,45 @@ every tone knows its enharmonic spelling: >>> Tone.from_string("C4", system="western").enharmonic is None True +Extended Enharmonics +~~~~~~~~~~~~~~~~~~~~ + +PyTheory supports the full range of enharmonic spellings used in real +music theory: + +- **Cb** and **Fb** — musically valid flats (Cb = B, Fb = E) +- **E#** and **B#** — musically valid sharps (E# = F, B# = C) +- **Double sharps** (``##`` or ``x``) — e.g. F## = G +- **Double flats** (``bb``) — e.g. Dbb = C +- **Unicode symbols** — ``♯`` (sharp), ``♭`` (flat), ``𝄪`` (double sharp), + ``𝄫`` (double flat) are all recognized and normalized to ASCII + +.. code-block:: pycon + + >>> Tone.from_string("Cb4") # resolves to B3 (octave boundary fix) + + >>> Tone.from_string("B#4") # resolves to C5 (octave boundary fix) + + >>> Tone.from_string("E#4") # resolves to F4 + + >>> Tone.from_string("Fb4") # resolves to E4 + + +The octave boundary is correctly handled: B# crosses up to the next +octave (B#4 = C5), and Cb crosses down (Cb4 = B3), matching standard +scientific pitch notation where the octave number increments at C. + +Tone Validation +~~~~~~~~~~~~~~~ + +Tones are validated on construction — if a tone name is not recognized +in its system, a ``ValueError`` is raised: + +.. code-block:: pycon + + >>> Tone.from_string("X4") # not a valid tone name + ValueError: ... + The Circle of Fifths -------------------- diff --git a/docs/index.rst b/docs/index.rst index fedaf3f..6764f58 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,8 +18,8 @@ Theory ------ The theory layer works everywhere Python runs — no audio setup needed. -Tones, scales, chords, keys, intervals, harmony, 6 musical systems, -25 instruments: +Tones, scales, chords, keys, intervals, harmony, 16 musical systems, +60+ instruments: .. code-block:: pycon @@ -72,25 +72,29 @@ every time:: What's Inside ------------- -- **Theory** — tones, scales (40+ across 6 systems), chords (17 types), +- **Theory** — tones, scales (40+ across 16 systems), chords (17 types), keys, Roman numeral analysis, figured bass, pitch class sets (Forte - numbers), scale recommendation, modulation, voice leading + numbers), scale recommendation, modulation, voice leading, enharmonic + support (Cb, Fb, E#, B#, double sharps/flats, unicode symbols) - **Sequencing** — Score, Parts, arpeggiator, legato/glide, velocity, - swing, humanize, tempo changes, song sections with repeat + swing, humanize, tempo changes, song sections with repeat, strumming, + pitch bends (3 types), rolls, tuning systems (TET factory, 4 + temperaments, reference_pitch) - **Synthesis** — 41 waveforms (including Karplus-Strong pluck, Hammond organ, - bowed string, and 14 dedicated instrument synths), 10 envelopes, 40+ - instrument presets, configurable FM, sub-oscillator, noise layer, filter - envelope, velocity-to-brightness, analog oscillator drift, detune, stereo - pan/spread, strumming, 80+ drum patterns (stereo panned, including world - percussion), 21 fills + bowed string, granular, vocal/formant, and 31 dedicated instrument synths), + 10 envelopes, 60+ instrument presets, configurable FM, sub-oscillator, + noise layer, filter envelope, velocity-to-brightness, analog oscillator + drift, detune, stereo pan/spread, 80+ drum patterns (stereo panned, + including world percussion and cajón), 21 fills, 11 microtonal systems - **Effects** — reverb (algorithmic + 7 convolution IRs, stereo), delay, - lowpass/highpass (with resonance), distortion, cabinet simulation, + lowpass/highpass (with resonance), distortion, guitar cabinet simulation, saturation, chorus, phaser, tremolo, analog drift, sidechain compression, automation, LFOs. Master bus compressor/limiter -- **Instruments** — 49 presets with fingering generation, guitar strumming, - pitch bends +- **Instruments** — 60+ presets with fingering generation, guitar strumming, + pitch bends, note choking - **Output** — stereo playback, WAV export, MIDI import/export -- **Interface** — REPL with tab completion, CLI (15 commands), ``pytheory demo`` +- **Interface** — REPL with tab completion, CLI (15 commands), ``pytheory demo``, + KeyboardInterrupt handling for clean stop - **AI-friendly** — Claude Code can compose and play music through PyTheory from natural language