339 Commits

Author SHA1 Message Date
kennethreitz 70efb0ad40 v0.36.0: Banjo, mandolin, ukulele, cajón, vocal synth, granular
34 synth waveforms, 26 songs, vocal/formant synthesis with choir
preset, granular engine, banjo/mandolin/ukulele physical models,
cajón drum with 3 patterns, strum sweep on fretboard instruments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.36.0
2026-03-27 19:54:08 -04:00
kennethreitz bf6deaab64 Mandolin synth, cajón drums, Song #26 Acoustic Ensemble
- Mandolin: paired steel strings (natural chorus from doubled
  courses), bright body resonance (500/1000/2000Hz)
- Cajón: bass (woody box thump), slap (snare wire buzz), tap
  (ghost note). 3 patterns: cajon, cajon rumba, cajon folk
- Song #26: guitar + uke + mandolin + cajón — humanized strumming,
  stereo panned, plate reverb
- Mandola preset (mandolin with lowpass for darker tone)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:46:15 -04:00
kennethreitz 7c792c0a2a Ukulele synth + strum sweep on all fretboard instruments
- Ukulele: nylon string KS with small body resonance (350/700/1200Hz),
  faster decay than guitar, mid-heavy character
- Strum sweep: 2 quiet grace notes (25% vel) before the chord hit,
  gives audible strum feel without choppiness
- Default strum_time 0.08 → 0.05 for tighter feel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:36:29 -04:00
kennethreitz bf8d4b9a77 Epic Bhairav: musical polyrhythm section, fix reverb levels
Polyrhythm section uses musical phrases (ti-ra-ki-ta patterns)
in 5-groups, 7-groups, and 9-groups rather than mechanical grid
overlays. Reverb pulled back to 0.4 across the song.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:12:31 -04:00
kennethreitz d2d5115c8a Song #25: Epic Bhairav + vocal synth merged to master
Orchestral piece in 22-shruti JI with choir vowel pads, timpani
rolls, bansuri, cello, sitar, strings, harp, djembe→tabla→extended
tabla solo finale (whisper→ghosts→call/response→9-tuplets→32nd
triplet cascades→grand tihai→slam).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:25:05 -04:00
kennethreitz 3cdd98b158 Merge vocal/formant synth: LF glottal model, 5 formants, choir
Formant synthesis with LF glottal pulse, 5 Peterson & Barney
formant peaks, jitter/shimmer, consonant onsets, click-free
transitions. Presets: vocal, choir.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:22:36 -04:00
kennethreitz 751d5a49b8 Cleaner vocal synth: less static, click-free note transitions
- Jitter reduced (0.3% → 0.1%), shimmer reduced (2% → 0.8%)
- Breath noise halved (0.08 → 0.04), mix 85/15 → 92/8
- 10ms fade in/out on every vocal note prevents clicks
- Smoother syllable transitions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:17:12 -04:00
kennethreitz 6a836dd891 Overhaul vocal synth: LF glottal model, 5 formants, jitter/shimmer
- LF glottal pulse: asymmetric open/close phase (not sines)
- 5 parallel formant filters per vowel (Peterson & Barney data)
- Jitter (0.3% pitch irregularity) + shimmer (2% amplitude)
- Much more voice-like than previous version
- Consonant onsets preserved

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:13:50 -04:00
kennethreitz 1f888e2b21 Vocal/formant synth with choir preset
Formant synthesis: glottal buzz source through parallel bandpass
filters at vowel resonance frequencies. Supports 5 vowels (A E I O U)
with consonant onsets (plosives, sibilants, nasals, fricatives,
liquids, aspirates, glides). Per-note lyrics via Part.add(lyric=).

Best for choir pads — vowel sounds with cathedral reverb and detune.
Consonant synthesis is rudimentary (noise bursts, not real speech).

Presets: vocal (solo), choir (detuned ensemble).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:10:54 -04:00
kennethreitz fb923f6c76 v0.35.1: Granular synthesis engine
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.35.1
2026-03-27 11:50:32 -04:00
kennethreitz 59e3338892 Granular synthesis engine with presets
Grain cloud synthesis: source waveform chopped into tiny overlapping
grains (40ms, 50/sec) with Hanning windows, random scatter, and
per-grain pitch variation. Creates textures impossible with other
synthesis. Two presets: granular_pad, granular_texture.
30 synth waveforms total.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:47:52 -04:00
kennethreitz 8cf4145c15 Docs: timpani, saxophone, Part.roll(), update waveform counts
- Add timpani and saxophone synth sections to synths.rst
- Add rolls section to sequencing.rst with examples
- Update waveform count: 27 → 29

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:38:46 -04:00
kennethreitz b3885b2c15 v0.35.0: JI ratios, 8.5x faster import, timpani, saxophone, rolls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.35.0
2026-03-27 11:34:34 -04:00
kennethreitz ae04fa60cc Reduce vibrato across all instruments to 0.001
Strings, cello, trumpet, clarinet, oboe all cut to 0.001 depth.
Much subtler in ensemble context.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:29:48 -04:00
kennethreitz 6c411e43f8 Part.roll() for crescendo/decrescendo rolls, reedier sax, timpani reverb
- roll(tone, duration, velocity_start, velocity_end, speed) — rapid
  repeated notes with velocity ramp. Works on any instrument.
- Saxophone reed noise boosted and bandpass filtered for more bite
- Timpani preset: cathedral reverb at 0.4

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:26:28 -04:00
kennethreitz e0427af3cc Timpani and saxophone synths, 4 sax presets
- Timpani: inharmonic membrane modes (1.0, 1.5, 1.99, 2.44),
  felt mallet attack, copper kettle resonance, two-stage decay
- Saxophone: conical bore (all harmonics), strong mids, reed buzz,
  brass body warmth. 4 presets: saxophone, alto_sax, tenor_sax, bari_sax
- 29 synth waveforms total

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:22:47 -04:00
kennethreitz 552836ae5b Drop pytuning/sympy, lazy-load scipy: import 0.48s → 0.05s (fixes #44)
- Replace pytuning with 30-line native implementations of EDO,
  Pythagorean, and quarter-comma meantone scale generators
- Lazy-load scipy.signal (337ms) — only imported when audio rendering
  is actually used, not on theory-only imports
- Removes pytuning and sympy from dependencies entirely

Import time: 0.479s → 0.056s (8.5x faster)

Closes #44

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:17:52 -04:00
kennethreitz 0fe53fcdeb Merge pull request #46 from kennethreitz/fix/accidental-octave-wrap
Fix B#/Cb octave boundary crossing
2026-03-27 11:11:43 -04:00
kennethreitz f6fb2a2cd6 Fix B#/Cb octave boundary crossing (fixes #45)
B#4 now correctly resolves to C5 (523.25 Hz), not C4 (261.63 Hz).
Cb4 now correctly resolves to B3 (246.94 Hz), not B4 (493.88 Hz).

When an accidental crosses the B/C octave boundary, the octave is
adjusted: sharps crossing B→C increment, flats crossing C→B decrement.
Also handles double sharps (B##→C#5) and double flats (Cbb→Bb3).

Closes #45

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:11:08 -04:00
kennethreitz 70d6e6b8ce Reduce flute vibrato further (0.0015 → 0.0008)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:05:55 -04:00
kennethreitz aec9a999cb Arabic maqam JI ratios: Zalzalian neutral third (27/22)
Maqam system now uses just intonation ratios instead of 24-TET:
- Quarter-tone positions use Zalzalian (11-limit) ratios
- Mi↓ (the defining Rast note) is exactly 27/22 from Do
- Standard JI intervals for chromatic positions
- Septimal ratios (7-limit) for other quarter-tone positions

Research confirmed: Turkish 53-TET and Thai 7-TET are already
correct as equal temperaments. Gamelan has no universal ratios
(each ensemble is unique), so TET remains the best default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:00:16 -04:00
kennethreitz 3acde86028 Int tone names, wrapping, System.tone(), proper shruti JI ratios
- Tone(0, system=edo22) works alongside Tone("0", ...)
- Tone(22, system=edo22) wraps to tone 0, octave+1
- Tone(-1) wraps to last tone, octave-1
- System.tone(name, octave) convenience method
- Shruti system now uses 5-limit just intonation ratios instead
  of 22-TET approximation. Based on Pythagorean/harmonic ratios
  from traditional Indian musicology. Pa is a pure 3/2, Ga is a
  pure 5/4.
- System.ratios attribute overrides equal temperament when set

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:54:28 -04:00
kennethreitz aa405702a9 Fix Journey: EDM parts start after tabla solo ends
Calculated edm_start from actual section lengths so pad/sub/sitar2
don't bleed into the tabla solo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:44:42 -04:00
kennethreitz b7c018fb94 Expanded tabla solo: 4 sections, 9-tuplets, polyrhythm, grand tihai
Solo now has 4 distinct parts:
1. Whisper — single hits with space, breath
2. Ghosts emerge — 16th note ghost fills between accents
3. Call and response — dayan vs bayan, 9-tuplet break
4. Blazing — 32nd triplet cascades, rapid alternating hands,
   9-against-4 polyrhythm, grand tihai (3x, each louder), slam

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 03:06:59 -04:00
kennethreitz 07a52a3a25 Add tabla solo section to Journey, louder sitar in EDM drop
Tabla solo with ghost notes, 32nd triplet cascade, tihai, then
slams into house beat. Sitar volume 0.22 → 0.4 in EDM section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 03:03:57 -04:00
kennethreitz e12cb9003b Song #24: Journey (Piano → World → Sitar EDM)
Single score, one reverb space (Taj Mahal), tanpura drone throughout.
Piano arpeggios alone → cello joins → harp/oboe/flute with djembe →
sitar over tabla → EDM section with sitar, synth pad, 808 sub, house
drums. 28 bars, 5 movements.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 03:01:36 -04:00
kennethreitz 28968a1b5c Docs: strumming, pitch bends, tuning systems, fix instrument count
- Add guitar strumming section to sequencing.rst
- Add pitch bends section with three bend types
- Add tuning systems section (temperament, reference_pitch, TET)
- Fix index.rst: 25 → 49 instrument presets

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:49:24 -04:00
kennethreitz 8a4a2df1aa Song #23: Tabla Solo in Raga Yaman (22-shruti)
Tanpura drone intro, quiet sitar Yaman phrases, tabla solo building
from gentle theka through ghost notes to blazing tiri kita with
bayan pitch bends, tihai, dramatic silence, slam finish. Taj Mahal
reverb throughout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:37:34 -04:00
kennethreitz f4a90637db Note choking: new hits fade out previous tails on same sound
Drums and melodic notes now choke previous resonance with a quick
fade when a new hit/note starts. Prevents muddy buildup at fast
tempos. Added bayan pitch bend drum sound (TABLA_GE_BEND).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:32:34 -04:00
kennethreitz 90a1a31049 Fix pitch bends: resampling preserves instrument timbre
Render at base pitch using the actual synth, then variable-rate
resample to shift pitch over time. No more sine wave fallback or
retriggering artifacts. Three bend types: smooth (log), linear, late.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:22:03 -04:00
kennethreitz 33b2e82594 v0.34.1: Pitch bends, updated docs and songs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.34.1
2026-03-27 02:15:32 -04:00
kennethreitz 9f8dd0006d Pitch bends, updated docs, songs with new instruments
- Pitch bend: part.add("C4", bend=2, bend_type="smooth") bends up
  a whole step. Three types: smooth (log/perceptual), linear, late
  (hold then bend — blues style).
- Updated songs.py: use dedicated instrument synths (piano_synth,
  flute_synth, trumpet_synth, etc.) instead of generic waveforms
- Updated docs: synths.rst (27 waveforms, instrument synths section),
  effects.rst (cabinet sim, analog drift, updated signal chain),
  drums.rst (world percussion: tabla, dhol, dholak, mridangam,
  djembe, metal kit), index.rst (feature counts)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:14:45 -04:00
kennethreitz 417f7f74a3 19 new tests: instrument synths, cabinet, analog, strumming, world drums
Tests for: all 14 dedicated synth waveforms, piano brightness scaling,
cabinet sim frequency reduction, analog drift rendering, strum with/
without fretboard, strum direction, all 6 tabla sounds, dhol/mridangam/
djembe/metal kit sounds, 20 world drum pattern presets, guitar preset
cabinet sim. 838 tests total.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:11:48 -04:00
kennethreitz cd6f814049 Update changelog with vibrato tuning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:08:37 -04:00
kennethreitz 83fcdb0a09 Reduce vibrato depth on flute, oboe, trumpet, cello
All cut from 0.003-0.004 to 0.0015-0.002 — less wobbly in
ensemble context, more natural.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:08:17 -04:00
kennethreitz aa21bf0f2a v0.34.0: 27 synth waveforms, world drums, guitar strumming
16 dedicated instrument synths, speaker cab sim, analog drift,
strumming with fretboard lookup, dhol/dholak/mridangam/djembe/
metal kit with 22 patterns, 5 new demo moods.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.34.0
2026-03-27 02:00:57 -04:00
kennethreitz e7e35ad4e4 5 more dedicated synths: oboe, harpsichord, cello, harp, upright bass
- Oboe: double reed buzz + conical bore (all harmonics, peaked 3-5)
- Harpsichord: KS with quill chiff, bright metallic pluck
- Cello: deep bowed string with 250/500Hz body resonance
- Harp: soft KS pluck with large soundboard bloom
- Upright bass: thick string pizzicato with wooden body resonance
- 27 synth waveforms total

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:59:20 -04:00
kennethreitz 503dbce937 6 dedicated instrument synths: piano, bass, flute, trumpet, clarinet, marimba
- Piano: hammer strike + detuned strings + inharmonicity + soundboard
- Bass guitar: heavy KS with thick string damping + low-mid pickup
- Flute: breath noise + tube resonance + developing vibrato
- Trumpet: lip buzz harmonics + brass bell resonance + vibrato
- Clarinet: odd harmonics (cylindrical bore) + reed noise
- Marimba: inharmonic bar modes (1x, 4x, 9.2x) + resonator tube
- 22 synth waveforms total

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:44:00 -04:00
kennethreitz c6bbfae7e6 Acoustic guitar synth with body resonance, fix strum
- New acoustic_guitar_synth: Karplus-Strong with wooden body
  resonance (3 formant peaks at 110/250/500 Hz), warmer initial
  noise, gentle rolloff. Sounds woody, not harsh.
- Strum renders as a single chord hit — no more exposed grace
  notes that sounded digital. Clean, full chord sound.
- 16 synth waveforms total

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:38:35 -04:00
kennethreitz 64ef7f0803 Add analog oscillator drift for synth warmth
Per-note random pitch wobble (gaussian, ±cents scaled by analog param)
simulates analog oscillator instability. Applied to synth_lead (0.3),
synth_pad (0.4), synth_bass (0.2), acid_bass (0.3), electric_piano
(0.2), organ (0.15). Subtle enough to add life without sounding
out of tune.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:32:03 -04:00
kennethreitz 406e5d7e54 Electric guitar synth, cab sim, strumming, world drums, metal kit
- Electric guitar: Karplus-Strong + magnetic pickup comb filter
- Cabinet simulation: speaker rolloff + presence bump (tames fizz)
- 6 guitar presets: clean, crunch, distorted, orange, metal
- Part.strum(): fretboard fingering lookup with down/up strumming
- Sitar synth: jawari buzz + chikari sympathetic strings
- Dhol, dholak, mridangam, djembe synthesis (membrane noise)
- Metal drum kit (kick click, bright snare, tight hats)
- 11 world patterns + 4 metal patterns + 7 tabla patterns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:25:53 -04:00
kennethreitz 267b7284ba Add dhol, dholak, mridangam, djembe drums + 11 world patterns
Drum synthesis:
- Dhol: dagga (heavy bass), tilli (treble crack), both
- Dholak: ge (bass palm), na (treble fingers), tit (light tap)
- Mridangam: tham (clay body bass), nam (rich overtone ring),
  din (both heads), tha (muted)
- Djembe: bass (center palm), tone (edge ring), slap (sharp crack)
All with bandpass-filtered membrane noise for drum head character.

Patterns:
- Dhol: bhangra, dhol chaal
- Dholak: qawwali, dholak folk
- Mridangam: adi talam, mridangam korvai
- Djembe: djembe (standard), kuku, soli

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:59:27 -04:00
kennethreitz 9b62b56120 Sitar synth, tabla drums with wood/metal shells, 7 tabla patterns
- Sitar synth: Karplus-Strong with gentle jawari bridge buzz,
  variable damping (bright attack fades to warm sustain), chikari
  sympathetic string shimmer
- Tabla: 6 synthesized strokes (Na, Tin, Ge, Dha, Tit, Ke) with
  goatskin membrane noise (bandpass filtered), wooden shell resonance
  on dayan, copper/metal shell resonance on bayan
- 7 tabla patterns: teental (16 beats), jhaptaal (10), rupak (7),
  dadra (6), keherwa (8), tabla solo, tiri kita (fast 16th-note)
- Sitar instrument preset with proper lowpass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:54:19 -04:00
kennethreitz 4fe7771d83 v0.33.0: Microtonal systems, historical tuning, Bohlen-Pierce
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.33.0
2026-03-27 00:34:59 -04:00
kennethreitz 57079a43ac Merge feature/non-12-tet: microtonal systems, historical tuning
11 microtonal systems, Bohlen-Pierce tritave, just intonation,
reference pitch, Score(system=, temperament=, reference_pitch=).
TET(n) factory for any equal temperament. 819 tests passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:34:12 -04:00
kennethreitz 1d07b06968 Add Greensleeves (Renaissance lute, meantone A=415) to songs.py
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:33:50 -04:00
kennethreitz 9887b59cfb Add reference_pitch to Score and playback pipeline
Score(reference_pitch=415.0, temperament="meantone") renders an
entire piece at Baroque pitch with historical tuning. Flows through
to all .pitch() calls in both normal and legato renderers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:32:11 -04:00
kennethreitz 9850a8016e Bohlen-Pierce, just intonation, temperament in Score/playback
- Bohlen-Pierce (13-TET tritave): period=3.0 support in pitch(),
  System, and TET factory. 13 equal divisions of the 3:1 ratio.
- Just intonation temperament: 5-limit JI ratios (pure 3/2 fifths,
  5/4 thirds). Use temperament="just" anywhere.
- Score(temperament="just") flows through to playback — all .pitch()
  calls in the render pipeline use the Score's temperament.
- Carnatic 72-TET system with 10 melakartas.
- Fix c_index for Indian, Arabic, and Gamelan 12-TET systems.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:24:03 -04:00
kennethreitz 35f5f35dc5 Carnatic 72-TET, Score system param, 22 microtonal tests
- Carnatic (72-TET): 10 melakartas including shankarabharanam,
  kalyani, mayamalavagowla, kharaharapriya, etc.
- Score(system=) param passes tuning system to all parts, so
  Part.add("Sa") resolves through the correct system
- 22 new tests covering all microtonal systems: TET factory,
  19/31-TET, shruti, maqam, slendro, pelog, thai, makam,
  carnatic, circle of fifths, from_frequency, Score integration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:18:09 -04:00
kennethreitz 47ca94111f Add gamelan slendro/pelog, Thai 7-TET, Turkish 53-TET makam
- Slendro (5-TET): true equal 5-tone gamelan tuning, 240 cents/step
- Pelog (9-TET): 7-of-9 gamelan tuning with pathet nem/lima/barang
- Thai classical (7-TET): 7 equal divisions (~171 cents each)
- Turkish makam (53-TET): Arel-Ezgi-Uzdilek system with 9 makams
  (rast, hicaz, ussak, nihavend, huseyni, kurdi, segah, saba, huzzam)
- Fix octave parser to only match trailing digits (not "Mib+3")
- Fix _index to use _name_to_index (avoid creating Tone objects)
- Fix _math to use per-system c_index

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:11:19 -04:00