--- phase: 04-polish-audio plan: 01 subsystem: audio tags: [web-audio-api, web-speech-api, audiocontext, speech-synthesis, mute-button] # Dependency graph requires: - phase: 03-gameplay-loop provides: Settings store with audioEnabled, IndexedDB persistence provides: - Web Audio API sound effects module (playCorrectSound, playRewardSound, playForestElementSound) - Web Speech API text-to-speech module (speakText) - Mute button UI with persisted toggle state - AudioContext lazy initialization on first user interaction affects: [04-02, 04-03, 04-04] # Tech tracking tech-stack: added: [Web Audio API, Web Speech API] patterns: [lazy AudioContext initialization, settings-gated audio playback] key-files: created: - src/audio/sounds.ts - src/audio/speech.ts modified: - src/types.ts - index.html - src/styles/main.css - src/main.ts - src/api/gemini.ts - src/storage/db.test.ts - src/ui/parent.ts key-decisions: - "speechEnabled defaults to false (opt-in feature, not opt-out)" - "AudioContext created lazily on first click/keydown for autoplay policy compliance" - "All sound functions use try/catch with silent fallback (never throw)" patterns-established: - "Audio gating: every sound/speech function checks Settings before playing" - "Lazy AudioContext: initAudioOnInteraction() called from user event handlers" requirements-completed: [AUDI-01, AUDI-02, AUDI-03, AUDI-04, AUDI-05] # Metrics duration: 4min completed: 2026-03-29 --- # Phase 04 Plan 01: Audio System Summary **Web Audio API procedural sounds (correct/reward/forest) and Web Speech API German TTS with mute button and Settings persistence** ## Performance - **Duration:** 4 min - **Started:** 2026-03-29T16:14:40Z - **Completed:** 2026-03-29T16:18:48Z - **Tasks:** 2 - **Files modified:** 9 ## Accomplishments - Three procedural Web Audio API sounds: correct keystroke beep (800Hz), ascending reward melody (C5-E5-G5-C6), filtered white noise for forest elements - German text-to-speech via Web Speech API with async voice loading and settings gate - Mute button with fixed-position circular UI, toggle persistence in IndexedDB, and visual state feedback ## Task Commits Each task was committed atomically: 1. **Task 1: Audio module + Speech module + Settings extension** - `c19b7fe` (feat) 2. **Task 2: Mute button in HTML + CSS + wiring in main.ts** - `52596c5` (feat) ## Files Created/Modified - `src/audio/sounds.ts` - Web Audio API sound effects with AudioContext lazy init - `src/audio/speech.ts` - Web Speech API speakText with German voice detection - `src/types.ts` - Added speechEnabled to Settings interface - `index.html` - Added mute-btn element outside all screen sections - `src/styles/main.css` - Mute button fixed-position styles - `src/main.ts` - Wired mute button toggle and AudioContext init on first interaction - `src/api/gemini.ts` - Added speechEnabled default to getDefaultSettings - `src/storage/db.test.ts` - Added speechEnabled to test Settings fixture - `src/ui/parent.ts` - Added speechEnabled defaults in inline Settings initializers ## Decisions Made - speechEnabled defaults to false (opt-in) while audioEnabled defaults to true (opt-out) -- speech is more intrusive than sound effects - AudioContext is created lazily on first user interaction (click or keydown) to comply with browser autoplay policies - All audio functions wrap in try/catch and never throw to callers -- silent degradation preferred ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 2 - Missing Critical] Added speechEnabled defaults to all Settings initializers** - **Found during:** Task 1 (Settings extension) - **Issue:** Plan only mentioned adding speechEnabled to the types.ts interface, but several files create default Settings objects inline (gemini.ts, parent.ts, db.test.ts) that would fail type checking - **Fix:** Added speechEnabled: false to all inline Settings object literals across the codebase - **Files modified:** src/api/gemini.ts, src/storage/db.test.ts, src/ui/parent.ts - **Verification:** npx tsc --noEmit passes - **Committed in:** c19b7fe (Task 1 commit) --- **Total deviations:** 1 auto-fixed (1 missing critical) **Impact on plan:** Essential for type safety. No scope creep. ## Issues Encountered None ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - Audio system ready to be wired into lesson/reward/forest screens (Plan 04-02+) - Mute button functional and persisting state across reloads - speakText ready for companion dialogue integration ## Self-Check: PASSED All created files exist, all commit hashes verified. --- *Phase: 04-polish-audio* *Completed: 2026-03-29*