SoundBoard

A web-based sound synthesizer and board management application built with React and the Web Audio API. Users can create multiple custom soundboards, synthesize sounds using oscillators with ADSR envelopes, record audio from their microphone, and trigger sounds via keyboard shortcuts or a 3x3 grid.

Key Decisions

DecisionRationaleOutcome
Synthesized sounds over audio filesEliminates asset management, enables real-time customizationGood — flexible and lightweight
Singleton AudioService patternSingle AudioContext, centralized buffer/node managementGood — efficient resource usage
ADSR envelope systemProfessional sound shaping, matches user expectationsGood — satisfying sound quality
Keyboard bindings 1-9Intuitive mapping, matches 3x3 grid layoutGood — fast user interactions
Web Audio API onlyNo external dependencies, full browser controlGood — no dependency bloat
React hooks for stateuseAudio and useKeyboard separation of concernsGood — maintainable and testable logic
Multiple boards with CRUDUsers can create, rename, and delete sound collectionsGood — scalable organization
SoundEditor for real-time tweakingSliders for frequency, waveform, duration, and ADSRGood — interactive sound design
RecordingService for mic inputMediaRecorder API with MIME type fallback chainGood — robust recording across browsers
Long press gesture for edit modeuseLongPress hook with progress feedback (2s threshold)Good — clean mobile-friendly UX
File upload for custom soundsAddSoundButton with hidden file input patternGood — flexible content sourcing
ErrorBoundary for crash resilienceClass component error boundary with reset capabilityGood — improved app stability

Patterns Established

PatternDescriptionReusable
AudioService singletonCentralized Web Audio context managementYes
SoundGenerator with presetsOscillator synthesis with ADSR envelopesYes
useAudio hookPlayback state management for ReactYes
useKeyboard hookKey binding to actions with repeat preventionYes
CSS co-locationComponent.tsx paired with Component.cssYes
RecordingService singletonMediaRecorder with MIME negotiationYes
useLongPress hookConfigurable threshold with progress stateYes
SliderControl componentReusable range input with label/value displayYes
Board management patternCRUD operations for named collectionsYes
fetchWithRetry utilityExponential backoff for HTTP requestsYes

Lessons Learned

LessonContextImpact
Browser autoplay policy requires user gestureCalling resumeContext() on first clickPrevents audio initialization failures
Web Audio rate/volume can’t change mid-playNeed to stop and restart sound to apply changesLimits real-time modulation without extra complexity
Oscillator presets are more flexible than filesCustomization and sound design are enabled at the code levelDramatically reduced app size
MediaRecorder MIME type browser varianceMust detect supported types at runtime via fallback chainReliable recording on Chrome, Safari, and Firefox
Long press needs both mouse and touchDesktop vs mobile input divergenceConsistent gesture behavior across devices

Technical Debt

ItemPriorityNotes
No persistence for custom soundsMediumBoard data is currently in-memory only; planned for v0.3
Dual type filesLowTypes exist in both types.ts and types/index.ts; consolidate
Volume slider UI-only for SystemSoundsLowAudioToolbox ignores app volume; migration to AVAudioPlayer needed