Skip to content

Phase 22-23: Synthesis Engine, Extended Steps, Demo Sessions#15

Merged
adewale merged 37 commits intomainfrom
claude/display-roadmap-Osuh7
Dec 17, 2025
Merged

Phase 22-23: Synthesis Engine, Extended Steps, Demo Sessions#15
adewale merged 37 commits intomainfrom
claude/display-roadmap-Osuh7

Conversation

@adewale
Copy link
Owner

@adewale adewale commented Dec 15, 2025

Summary

This PR includes Phase 22 (Synthesis Engine) and Phase 23 (Polish) work:

  • 32 new synth presets across 4 engine types
  • Extended MAX_STEPS from 64 to 128 (8 bars at 16th note resolution)
  • Fixed mid-playback sampled instrument preloading (Bug Create new favicon for Keyboardia #8)
  • 17 demo sessions showcasing the full feature range
  • Comprehensive documentation audit for internal consistency
  • ~32,000 lines added across 148 files

Phase 22: Synthesis Engine

New Instruments (60+ total)

  • Web Audio Synths: 32 presets (bass, lead, pad, keys, ambient, electronic)
  • Tone.js Synths: 11 presets (FM, membrane, metal, pluck, duo, AM)
  • Advanced Synths: 8 presets (supersaw, thick-lead, wobble-bass, acid-bass)
  • Sampled Instruments: Piano with multi-velocity samples

Effects Chain

  • Reverb, Delay, Chorus, Distortion
  • Master bypass control
  • Per-track effects (future)

Phase 23: Extended Steps & Polish

Extended Step Sequencer

  • MAX_STEPS: 64 → 128 (8 bars at 16th notes)
  • STEP_COUNT_OPTIONS: [4, 8, 12, 16, 24, 32, 64, 96, 128]
  • Full test coverage for 128-step scenarios

Bug Fix #8: Mid-Playback Preloading

Problem: Piano tracks added during playback never loaded

Fix: SamplePicker now preloads sampled instruments immediately on selection

Demo Sessions (17 total)

Session Demonstrates
progressive-house-build 128-step evolving build
polyrhythmic-evolution Odd-length patterns (5, 7, 11, 13, 17, 19, 23)
edm-drop-section 8-bar pre-drop + drop
extended-afrobeat 96-step triplet groove
ambient-soundscape Pads, shimmer, evolving + high swing
synth-bass-showcase Reese, Hoover, Acid, Wobble, FM Bass
keys-and-piano Sampled piano, Rhodes, Wurli, Organ
electronic-leads Supersaw, Hypersaw, Advanced leads
gate-mode-demo Gate vs Oneshot playback
fx-and-percussion Tone.js drums, bells, stabs

Documentation Audit

Updated all references for consistency across:

  • CHANGELOG.md, ROADMAP.md, SPEC.md, STATUS.md
  • TUNING-CONSTANTS.md, types.ts, session-api.ts
  • worker/invariants.ts, worker/validation.ts

Test plan

  • Run full test suite (npm run test -- --run)
  • Verify 128-step patterns play correctly
  • Test adding piano track during playback
  • Load each demo session and verify playback
  • Check gate mode in gate-mode-demo session
  • Verify all synth types play correctly

🤖 Generated with Claude Code

claude and others added 30 commits December 15, 2025 08:37
Consolidates all remaining music synthesis requirements from roadmap Phase 25
into a detailed spec including:
- Dual oscillator architecture
- Filter modulation with envelope
- LFO system (vibrato, tremolo, filter sweeps)
- Effects chain (reverb, delay, chorus, distortion)
- Sampled instruments (piano, strings, brass)
- XY pad / macro controls
- FM synthesis

Includes full Tone.js analysis:
- Available synths (MonoSynth, DuoSynth, FMSynth, etc.)
- Effects suite (25+ built-in effects)
- Transport & scheduling capabilities
- Bundle size impact (~100-120KB gzipped)
- Browser compatibility

Recommends hybrid approach: keep custom scheduler (polymetric support),
integrate Tone.js for effects, sampler, and advanced synths.
Implements the hybrid approach from specs/SYNTHESIS-ENGINE.md:
- Keep existing scheduler (polymetric support)
- Add Tone.js for effects and advanced synths

New files:
- toneEffects.ts: Effects chain (Reverb, Delay, Chorus)
- toneSynths.ts: Advanced synths (FM, AM, Membrane, Metal, Pluck, Duo)
- Comprehensive test suites (60 new tests)

ToneEffectsChain features:
- Freeverb (instant ready, no async IR)
- FeedbackDelay with tempo-synced time ("8n", "4n")
- Chorus with LFO
- State serialization for multiplayer sync
- Proper disposal pattern

ToneSynthManager features:
- 11 presets: fm-epiano, fm-bass, fm-bell, am-bell, am-tremolo,
  membrane-kick, membrane-tom, metal-cymbal, metal-hihat,
  pluck-string, duo-lead
- Lazy synth instantiation
- Semitone to note/frequency conversion

AudioEngine integration:
- Async initialization (non-blocking)
- Full effects API (getEffectsState, applyEffectsState, etc.)
- playToneSynth() for advanced synth playback
- isToneSynthSample() for sample ID detection

Best practices applied (from spec Section 7):
- Singleton pattern for effects
- Deep copy for state (prevents mutation)
- Proper dispose() calls
- Value clamping for all parameters

All 597 tests pass.
This commit completes the Phase 25 synthesis features:

- Distortion effect with waveshaping in effects chain
- WebSocket integration for effects multiplayer sync
- Tone.Sampler for sampled instruments (piano, strings, brass, electric-piano)
- Advanced synth engine with dual oscillators, filter envelope, and LFO
- XY Pad / Macro controls for real-time parameter control

New presets: supersaw, sub-bass, wobble-bass, warm-pad, vibrato-lead,
tremolo-strings, acid-bass, thick-lead

All 716 tests passing.
Audit findings and fixes:
- Fix voice active flag never resetting (advancedSynth.ts)
- Add release timeout tracking and noteStartTime for voice stealing
- Add delay.time validation allowlist (live-session.ts)
- Clear loadPromise on error to allow retry (toneSampler.ts)
- Remove dead code: unused clamp function and voiceNotes Map
- Centralize C4_FREQUENCY and NOTE_NAMES in new constants.ts
- Fix getAllParameterValues return type (xyPad.ts)
- Reset state to defaults in toneEffects.ts dispose()
- Fix concurrent resume() race condition with promise locking (engine.ts)
- Add toneInitPromise for Tone.js initialization locking
- Fix fire-and-forget initAudio() with error handling (StepSequencer.tsx)
- Add audio context state check in Recorder.tsx handlePlaySlice

New tests for all fixes (752 tests passing):
- Voice release tracking and inactive state
- Voice stealing based on noteStartTime
- loadPromise error recovery
- toneEffects state reset on dispose
- constants.ts unit tests for delay time validation
Move the duplicate VALID_DELAY_TIMES constant from inline in
live-session.ts to worker/invariants.ts for better organization.
The constant is duplicated from audio/constants.ts because
workers bundle separately from browser code.
Implement dynamic import for the audio engine to improve initial page
load for users who are just viewing/sharing sessions without playing.

Feature flag: VITE_LAZY_AUDIO=true enables lazy loading (default: false)

Trigger classification (documented in lazyAudioLoader.ts):
- Tier 1 (MUST trigger): Play button, sample preview, recording, chromatic notes
- Tier 2 (SHOULD trigger): Step toggle, sample picker open, transpose change
- Tier 3 (SHOULD NOT): Page load, session name, QR/share, mute/solo

Components updated:
- StepSequencer.tsx: Play uses getAudioEngine(), step toggle uses ensureAudioLoaded()
- TrackRow.tsx: Preview handlers check isAudioLoaded() before playing
- SamplePicker.tsx: Preview on hover triggers ensureAudioLoaded()
- Recorder.tsx: Recording and playback use getAudioEngine()
- ChromaticGrid.tsx: Note clicks check isAudioLoaded() for preview

Roadmap updated with Phase 26: Performance optimization
- Named Tone.js imports (tree-shaking) - planned
- Code splitting for audio modules - planned
- Lazy audio engine loading - implemented

761 tests passing.
Per Web Audio API specs, mouseenter/mouseover are NOT valid user
gestures for unlocking AudioContext. Only click, touch, key events
qualify.

Changes:
- SamplePicker: Don't call initialize() on hover - just skip preview
- SamplePicker: Add ensureAudioLoaded() to handleSelect (click IS valid)

This fixes silent hover previews being confusing - now they're
intentionally silent until a valid gesture unlocks the AudioContext.
- Create audioTriggers.ts as single source of truth for audio decisions
- Define trigger tiers: Tier 1 (require), Tier 2 (preload), Preview
- Add 40 tests for gesture validation and trigger classification
- Update all components to use centralized trigger handlers
- Add window.__audioTriggers debug API in development mode
Comprehensive technical reference covering:
- Signal flow and component relationships
- All synth engines (Web Audio, Tone.js, Advanced)
- Effects chain and parameter ranges
- Lazy loading and trigger system
- Sample system and parameter locks
- Memory management and performance optimizations
The spec was missing concrete UI designs, violating the "Three Surfaces"
lesson: API, State, and UI must all align for a feature to be complete.

New section 9 adds:
- Effects panel wireframes and interaction model
- Sample picker updates for new synths
- Three surfaces alignment checklist
- Implementation priority (P0-P4)
- Mobile responsive design requirements
- Published session behavior
EffectsPanel (new):
- LED bar meters for wet/dry (10 segments, click to set)
- Effect-specific colors: Reverb=cyan, Delay=blue, Chorus=purple, Distortion=orange
- Hardware synth rack aesthetic with glow effects
- Responsive: 4-column desktop, 2-column tablet, 1-column mobile
- JetBrains Mono for values, LED-style display

SamplePicker updates:
- Add 11 Tone.js synths (FM, Membrane, Metal, AM, Pluck, Duo)
- Add 8 Advanced synths (Supersaw, Wobble, Acid 303, etc.)
- Distinct colors: Synth=pink, Tone=cyan, Advanced=purple
- Grouped by synthesis type (FM, Drum, Mod, Leads, Bass, Pads)
Section 9 refinements (based on UI philosophy analysis):
- Add mobile-first ASCII mockup (stacked vertical layout)
- Add visual design specification (slider styling, color coding)
- Add typography guidelines matching existing patterns
- Update desktop mockup for better readability

New Section 10: Musical Surface Area Expansion
- Before/after comparison (35→62 sounds, +77%)
- Genre coverage matrix (10 genres now possible)
- Sound design capabilities table

New Section 11: Example Sessions
- "Ambient Dreamscape" (reverb + pads)
- "Acid Warehouse" (distortion + 303)
- "Sunset Chillwave" (FM + chorus + delay)
- "Dubstep Drop" (wobble bass + effects)
- "Minimal Techno" (p-locks + effects)

Each session includes verification checklist.
Fixes:
- Remove unused type imports in advancedSynth.test.ts
- Export default constants with _ prefix in advancedSynth.ts
- Add getter for _noteFrequency to satisfy unused property check
- Fix return type in audioTriggers.ts tryGetEngineForPreview to properly allow null
- Widen Set type in constants.test.ts to allow checking arbitrary strings
- Remove unused vi import from lazyAudioLoader.test.ts
- Fix parameter property syntax in toneSynths.test.ts (TS1294)
- Add type assertions for config properties in toneSynths.test.ts
- Prefix unused loop variables with _ in test files
- Remove unused imports from Recorder.tsx

All 801 unit tests and 28 integration tests pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…ting

- Fix track deletion memory leak: call audioEngine.removeTrackGain() when
  deleting tracks to clean up orphaned GainNodes
- Fix SamplePicker preview parameter bugs for tone/advanced/sampled instruments
  with correct parameter ordering and readiness checks
- Add sampled: prefix routing in scheduler for piano and future sampled instruments
- Reorganize instruments by musical function (Drums, Bass, Keys, Leads, Pads, FX)
  instead of by engine type for intuitive browsing
- Add collapsible categories on mobile, always expanded on desktop
- Add minimum touch target sizes (44px mobile, 32px desktop) for instrument buttons
- Fix eslint errors: unused vars, function declaration order, dynamic imports

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Memory leak fixes:
- Engine.ts: Store unlock handler reference for proper cleanup
- useMultiplayer.ts: Restore original clock sync handler on cleanup
- App.tsx: Use useEffect for copied state timer instead of setTimeout in callback
- Recorder.tsx: Disconnect BufferSource on playback end
- StepSequencer.tsx: Use ref for copySource in keyboard listener to avoid recreating

Code deduplication:
- Extract clamp() to utils/math.ts (used by toneEffects, xyPad, grid reducers)
- Extract DELAY_TIME_OPTIONS to audio/delay-constants.ts (used by Transport, EffectsPanel)
- Create track-utils.ts with findTrackById, createStepsArray, createParameterLocksArray

All 1598 tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The chromatic/keyboard view was only being shown for tracks with 'synth:'
prefix, ignoring sampled instruments like 'sampled:piano'.

Added isMelodicInstrument() helper that correctly identifies all melodic
instruments that should show the keyboard view:
- synth: prefixed instruments (all melodic)
- advanced: prefixed instruments (all melodic)
- sampled: prefixed instruments (piano, etc.)
- tone: prefixed instruments (except drum synths like membrane-kick)

Regular samples (kick, snare, etc.) remain as percussive and don't show
the keyboard view.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests cover all instrument categories:
- synth: prefix instruments (melodic)
- advanced: prefix instruments (melodic)
- sampled: prefix instruments (melodic, including piano)
- tone: prefix instruments (mixed - melodic vs drums)
- Regular samples (percussive)
- Edge cases (empty string, unknown prefix, case sensitivity)

Also includes keyboard view requirement tests to prevent
regression of the piano keyboard display bug.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Documents all work from this branch:
- Memory leak fixes (16 confirmed leaks)
- Code deduplication (math.ts, delay-constants.ts, track-utils.ts)
- Keyboard view bug fix for sampled instruments
- 62 new tests for isMelodicInstrument
- Architecture audit findings (B+ grade)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This branch pulled forward and implemented most of Phase 25:
- Sampled piano with multi-sampling (C2-C5)
- Tone.js integration (FM, AM, Membrane, Metal, Pluck, Duo)
- Advanced dual-oscillator synth (863 lines)
- Effects chain (reverb, delay, chorus, distortion)
- XY Pad / macro controls (370 lines)
- Lazy audio loading
- 5,963 lines of audio tests
- 1,808-line synthesis spec

Also includes memory leak fixes, code deduplication, and
architecture audit from original scope.

Renumbered phases 23-33 to account for new Phase 22.
Marked Phase 25 as substantially complete.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Critical fixes:
- MIDI-EXPORT.md: Remove dead link to non-existent research file
- SESSION-LIFECYCLE.md: Fix "Project Phase 11" → "Phase 24" (Auth)
- SYNTHESIS-ENGINE.md: Update status to "Substantially Complete"
- SYNTHESIS-ENGINE.md: Fix success criteria checkboxes
- MUSICAL-FOUNDATIONS-SUMMARY.md: Note that effects implemented in Phase 22

Phase reference updates:
- Clarify Phase 22 (Synthesis Engine) vs Phase 25 (remaining work)
- Update related references across specs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added:
- Effects session persistence (Medium priority)
- Bundle size verification (Low priority)
- Critical note about effects sync requirement

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates to align code comments with ROADMAP.md:

Phase Reference Fixes:
- Phase 16 → Phase 26 for "Shared Sample Recording" (was incorrectly labeled)
- Phase 21A → Phase 22 for synthesis engine work (16 files)
- Phase 24 → Phase 21 for publishing features (was renumbered)
- Phase 25 → Phase 22 for Tone.js integration (was pulled forward)

Files Updated: 28 files across:
- app/src/audio/ (synthesis, scheduling, effects)
- app/src/components/ (UI components)
- app/src/hooks/ (React hooks)
- app/src/worker/ (Cloudflare worker)
- app/src/sync/ (multiplayer)
- app/src/*.css (styling comments)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 22: Implement per-player playback tracking to show which players
are currently playing in the multiplayer session.

Changes:
- Server: Replace session-wide isPlaying boolean with per-player Set
- Server: Include playingPlayerIds in snapshots for new/reconnecting clients
- Server: Broadcast playback_stopped when players disconnect while playing
- Client: Track playingPlayerIds in multiplayer state
- UI: Show pulsing play indicator on avatars of playing players
- Tests: Add 10 new tests for playback presence tracking

Key architectural decision: Each player independently controls their own
audio ("my ears, my control"), but we now show presence indicators so
others can see who's listening. Works in both regular and published sessions.

Also includes:
- Documentation cleanup (removed deferred items per user request)
- Spec consistency fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document the Phase 22 playback presence indicator feature:
- STATUS.md: Add to Phase 11 "Also Completed (Later)" section
- STATUS.md: Update file table descriptions
- ROADMAP.md: Add section 14 under Phase 22 with full implementation details

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused createMockToneNode helper in audio-context-safety.test.ts
- Add proper type casts for Tone.setContext mock calls
- Prefix unused loop variable with underscore (_name)
- Remove unused instrumentScheduleLoop import in playback-state-debug.test.ts
- Prefix unused error variables with underscore in analyze-bug-patterns.ts

All 1696 tests pass, build succeeds with no errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Removed unused modules identified in codebase audit:

- toneSampler.ts: R2-hosted sample approach, never integrated
  - Referenced non-existent /api/samples/ route
  - Superseded by sampled-instrument.ts with manifest-based loading

- tone-note-players.ts: Strategy pattern with fallback behavior
  - Contradicts explicit no-fallback policy
  - Current note-player.ts uses simpler NotePlayerRegistry

- Updated audio-context-safety.test.ts singleton audit:
  - Removed getSamplerManager() entry
  - Updated expected count from 4 to 3

Build passes, all 1676 tests pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Debugging Infrastructure:
- Add debug-coordinator.ts: Central hub that coordinates debug subsystems
  based on URL flags (?debug=1, ?trace=1, ?audio-debug=1, ?log=1)
- Add debug-tracer.ts: Structured observability with spans, correlation IDs,
  duration measurement, and performance statistics
- Add log-store.ts: IndexedDB-based persistent log storage with auto-cleanup,
  TTL-based retention, and export capabilities
- Add bug-patterns.ts: Registry of known bugs with symptoms, detection
  functions, and fix guidance
- Add playback-state-debug.ts: Scheduler state verification and invariant
  checking for audio playback debugging

CLI Tools:
- Add analyze-logs.ts: Log file analysis with error grouping, timeline view,
  and session breakdown
- Add post-fix-analysis.ts: Find similar bug patterns after fixing a bug
- Add bug-capture.ts: Interactive wizard for documenting bugs
- Add /post-fix Claude Code command for guided post-fix workflow

Documentation:
- Add DEBUGGING-LESSONS-LEARNED.md: Root cause analysis for fixed bugs
- Add DEBUGGING-WORKFLOW.md: Step-by-step debugging procedures
- Add AUDIO-CONTENT-TOOLS.md: Tools for audio content management
- Add HIDDEN-UI-FEATURES.md: Spec for hidden advanced UI features (XY Pad)
- Update development-tools.md: Comprehensive tool reference
- Update ROADMAP.md and MIDI-EXPORT.md with new phases

Audio Module Updates:
- Integrate debug instrumentation into engine.ts, scheduler.ts, synth.ts
- Add debug hooks to toneEffects.ts
- Initialize debug coordinator in main.tsx
- Enhance logger.ts with persistent storage and category support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The integration tests expected a session-wide `isPlaying` boolean, but
Phase 22 changed to per-player playback tracking. Updated tests to check
for `playingPlayerIds` and `playingPlayers` instead.

Changes:
- Check for `playingPlayerIds` array in debug endpoint
- Check for `playingCount` in debug endpoint
- Check for `playingPlayers` Set in runInDurableObject

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code cleanup based on branch audit:

- Unify semitoneToFrequency into single canonical implementation in constants.ts
  - synth.ts now re-exports from constants.ts
  - AdvancedSynthEngine uses imported function
  - Removed duplicate class methods from ToneSynthManager and AdvancedSynthEngine

- Remove orphaned VALID_DELAY_TIMES from constants.ts
  - Was only used in tests, duplicated worker/invariants.ts
  - UI uses delay-constants.ts, validation uses invariants.ts

- Fix HMR zombie scheduler issue
  - Add import.meta.hot.accept() to scheduler.ts
  - Without accept(), dispose() wasn't called on HMR updates

- Remove duplicate debug initialization from engine.ts
  - debug-coordinator.ts handles initialization
  - Removes redundant initDebugTracer/initPlaybackDebug/initBugPatterns calls

- Clean up singleton patterns in Tone.js modules
  - Remove cached singletons that caused AudioContext mismatch on HMR
  - toneEffects.ts, toneSynths.ts, advancedSynth.ts now use fresh instances

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
adewale and others added 5 commits December 16, 2025 23:19
Phase 23 UI Polish features:

Effects Master Bypass:
- Combined FX button with split click zones (bypass/panel toggle)
- CSS Grid centering for perfect vertical alignment
- Stable width via grid stacking (both states in DOM)
- Visual feedback: green (active), red (bypassed)

Playback Mode Toggle:
- SET_TRACK_PLAYBACK_MODE reducer action
- Desktop: button in TrackRow grid
- Mobile: toggle in InlineDrawer
- One-shot (plays to completion) vs Gate (cuts at step boundary)

XY Pad Component:
- Reusable 2D parameter control
- Touch and mouse support
- Integrated with reverb (wet/decay)
- External labels for clean sizing

LRU Sample Cache:
- O(1) get/set with doubly-linked list
- Reference counting prevents evicting in-use samples
- Size-based eviction (64MB default)
- 25 unit tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Completes Phase 23 with cache integration and lazy loading:

LRU Cache Integration:
- SampledInstrument now uses LRU cache for sample buffers
- Cache key format: `{instrumentId}:{note}` (e.g., piano:60)
- Cache checked before network fetch, populated after decode
- Reference counting API: acquireCacheReferences() / releaseCacheReferences()
- Engine exposes acquireInstrumentSamples() / releaseInstrumentSamples()

Lazy Loading:
- Removed eager preload at startup
- Instruments load on-demand via ensureLoaded() or load()
- Progressive loading preserved (C4 first, then remaining)
- Loading state API: getSampledInstrumentState(), onSampledInstrumentStateChange()

Test fix:
- Clear LRU cache in beforeEach to ensure predictable fetch behavior

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… abstraction

Critical bug fix:
- preloadInstrumentsForTracks now handles both synth:piano and sampled:piano formats
- Piano samples now correctly load before playback starts

New abstraction (instrument-types.ts):
- Centralized parseInstrumentId() for consistent prefix handling
- collectSampledInstruments() replaces duplicated logic across 15+ files
- Comprehensive tests (32 new tests)

ESLint fixes (8 warnings resolved):
- DebugOverlay: Made formatTimeAgo pure with state-based currentTime
- Recorder: Documented intentional setState in effects
- useMultiplayer: Added missing getStateForHash dependency
- useQRMode: Documented intentional isActive dependency
- useSession: Fixed mount-only effect and Date.now() purity

Tests: 1728 passing (38 new)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… audit docs

## Extended Step Sequencer (64 → 128 steps)
- MAX_STEPS now 128 (8 bars at 16th note resolution)
- STEP_COUNT_OPTIONS: [4, 8, 12, 16, 24, 32, 64, 96, 128]
- Added 128-step test coverage for polyrhythms and edge cases

## Bug Fix #8: Mid-playback sampled instrument preloading
- SamplePicker now preloads sampled instruments on selection
- Fixes piano not playing when added during playback
- Added 5 tests for preloading behavior
- Documented in DEBUGGING-LESSONS-LEARNED.md

## Demo Sessions (showcasing extended patterns)
- progressive-house-build.json (128-step evolving build)
- polyrhythmic-evolution.json (odd-length: 5, 7, 11, 13, 17, 19, 23 steps)
- edm-drop-section.json (8-bar pre-drop + drop)
- extended-afrobeat.json (96-step triplet groove)

## Documentation Audit (internal consistency)
- Updated all references from 64 to 128 steps
- Fixed CHANGELOG, ROADMAP, SPEC, STATUS, TUNING-CONSTANTS
- Updated validation in session-api.ts and worker/validation.ts
- Aligned types.ts comments with actual MAX_STEPS value

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## New Demo Sessions

1. **ambient-soundscape.json** — Atmospheric pads, shimmer, evolving, glass
   - High swing (45) for organic feel
   - Gate playback mode for sustained textures
   - Advanced synth: tremolo-strings

2. **synth-bass-showcase.json** — All bass varieties
   - Reese, Hoover, Acid 303, Wobble, FM Bass, Funk, Sub
   - Gate mode for wobble bass
   - Various patterns highlighting each bass character

3. **keys-and-piano.json** — Keyboard instruments
   - Sampled piano, Rhodes, Wurlitzer, Organ, FM Piano
   - E-Piano, Clavinet, Vibes
   - Jazz-influenced chord progression (swing: 35)

4. **electronic-leads.json** — EDM lead synths
   - Supersaw, Hypersaw, Advanced Supersaw
   - Thick Lead, Vibrato Lead, Duo Lead
   - Trance-style patterns at 138 BPM

5. **gate-mode-demo.json** — Playback mode comparison
   - Side-by-side GATE vs ONESHOT examples
   - Gated pads, strings, organ, bass, lead
   - Rhythmic chopping effects

6. **fx-and-percussion.json** — FX and synth drums
   - Tone.js drums: membrane kick/tom, metal cymbal/hihat
   - FM Bell, AM Bell, Synth Bell
   - Stab, Brass, Wobble, Growl

## Coverage Improvement

Before: 11 sessions using ~15% of instruments
After: 17 sessions using ~80% of instruments

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@adewale adewale changed the title Add comprehensive synthesis engine specification Phase 22-23: Synthesis Engine, Extended Steps, Demo Sessions Dec 17, 2025
adewale and others added 2 commits December 17, 2025 01:14
TypeScript strict mode requires explicit type annotation for prevNode
since it references self in initializer context.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The class name was changed during the SamplePicker refactor but
the E2E tests were not updated.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@adewale adewale merged commit 32b57a2 into main Dec 17, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants