Skip to content

Commit 80dfd91

Browse files
authored
Merge pull request #38 from feat/add-sound-effects
Feat: add sound effects system (#21)
2 parents a4a5eb9 + e48cfa0 commit 80dfd91

13 files changed

Lines changed: 3162 additions & 2258 deletions

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,15 @@
3838
- **Autoplay**: Automatic step-by-step animation with play/pause/stop controls
3939
- **Interactive Controls**: Play, pause, step forward/backward through algorithm execution
4040
- **Mobile Swipe Gestures**: Swipe left/right on mobile devices to navigate steps in manual mode with an attractive tutorial overlay
41+
- **Audio Feedback**: Optional sound effects for algorithm operations and UI interactions
42+
- **Sorting**: Distinct sounds for comparing, swapping, pivot selection, and completion
43+
- **Pathfinding**: Audio cues for node exploration and path discovery
44+
- **UI Sounds**: Click feedback and array generation sounds
4145
- **Customizable Settings**:
4246
- Switch between Sorting and Pathfinding modes
4347
- Choose between Manual (default) and Autoplay control modes
4448
- Adjust animation speed (Slow, Medium, Fast, Very Fast)
49+
- Toggle sound effects on/off
4550
- **Algorithm Analysis**: Interactive complexity panel with Big-O notation and performance graphs
4651
- **Python Code Examples**: View Python implementations
4752
- **Responsive Design**: Works seamlessly on desktop and mobile devices
@@ -54,6 +59,7 @@
5459

5560
- Node.js (v18 or higher)
5661
- pnpm (v8 or higher)
62+
- Modern browser with Web Audio API support (for sound effects)
5763

5864
If you don't have pnpm installed:
5965

@@ -176,7 +182,8 @@ bayan-flow/
176182
│ │ ├── arrayHelpers.js
177183
│ │ ├── arrayHelpers.test.js
178184
│ │ ├── gridHelpers.js
179-
│ │ └── gridHelpers.test.js
185+
│ │ ├── gridHelpers.test.js
186+
│ │ └── soundManager.js
180187
│ ├── constants/ # App constants
181188
│ │ └── index.js
182189
│ ├── test/ # Test configuration

docs/ARCHITECTURE.md

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ This document provides an in-depth explanation of the Bayan Flow architecture, d
99
3. [Data Flow](#data-flow)
1010
4. [Algorithm Implementation](#algorithm-implementation)
1111
5. [Animation System](#animation-system)
12-
6. [State Management](#state-management)
13-
7. [Testing Strategy](#testing-strategy)
14-
8. [Performance Optimizations](#performance-optimizations)
12+
6. [Audio System](#audio-system)
13+
7. [State Management](#state-management)
14+
8. [Testing Strategy](#testing-strategy)
15+
9. [Performance Optimizations](#performance-optimizations)
1516

1617
## System Architecture
1718

@@ -220,6 +221,60 @@ for (let step of steps) {
220221
}
221222
```
222223

224+
## Audio System
225+
226+
### SoundManager Architecture
227+
228+
The audio system uses **Tone.js** for Web Audio API abstraction and provides contextual sound feedback for algorithm operations.
229+
230+
**Core Design:**
231+
```javascript
232+
class SoundManager {
233+
constructor() {
234+
this.isEnabled = false;
235+
this.softSynth = new Tone.Synth({...}); // UI sounds
236+
this.pluckSynth = new Tone.PluckSynth({...}); // Compare sounds
237+
this.metallicSynth = new Tone.MetalSynth({...}); // Swap sounds
238+
this.polySynth = new Tone.PolySynth({...}); // Chord sounds
239+
}
240+
}
241+
```
242+
243+
### Sound Mapping Strategy
244+
245+
**Sorting Operations:**
246+
- **Compare**: Pluck synth with frequency mapped to element value (150-350Hz)
247+
- **Swap**: Metallic synth for distinct swap feedback
248+
- **Pivot**: Soft synth with lower frequency range (100-200Hz)
249+
- **Sorted**: Major chord (C-E-G) for completion celebration
250+
251+
**Pathfinding Operations:**
252+
- **Node Visit**: Soft synth at 220Hz (A3 note)
253+
- **Path Found**: Extended chord (C3-E3-G3-C4) for success
254+
- **UI Interactions**: Brief G4 note for clicks
255+
256+
### Integration Pattern
257+
258+
**Hook Integration:**
259+
```javascript
260+
const executeStep = useCallback((step) => {
261+
// Update visual state
262+
setArray(step.array);
263+
setStates(step.states);
264+
265+
// Trigger contextual audio
266+
if (step.states.includes(ELEMENT_STATES.SWAPPING)) {
267+
soundManager.playSwap(step.array[swapIndex]);
268+
}
269+
}, []);
270+
```
271+
272+
**Benefits:**
273+
- **Non-blocking**: Audio failures don't affect visualization
274+
- **User-controlled**: Easy enable/disable toggle
275+
- **Performance**: Early returns when disabled
276+
- **Contextual**: Sounds match visual operations
277+
223278
## State Management
224279

225280
### Custom Hook: useSortingVisualization

docs/DEVELOPMENT.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,54 @@ const debouncedSize = useDebounce(arraySize, 300);
398398
### Issue: Types Not Working
399399
**Solution:** Restart TypeScript server
400400

401+
### Issue: Audio Not Working
402+
**Solution:** Check browser autoplay policy, ensure user interaction before enabling
403+
404+
## Sound System Integration
405+
406+
### Adding Sound to New Algorithms
407+
408+
**Step 1: Identify Sound Events**
409+
```javascript
410+
// In your algorithm implementation
411+
if (hasSwapping) {
412+
soundManager.playSwap(elementValue);
413+
} else if (hasComparing) {
414+
soundManager.playCompare(elementValue);
415+
}
416+
```
417+
418+
**Step 2: Update Hook Integration**
419+
```javascript
420+
const executeStep = useCallback((step) => {
421+
// Update visual state
422+
setArray(step.array);
423+
setStates(step.states);
424+
425+
// Add sound logic
426+
const hasNewState = step.states.includes(NEW_STATE);
427+
if (hasNewState) {
428+
soundManager.playNewSound();
429+
}
430+
}, []);
431+
```
432+
433+
**Step 3: Add New Sound Methods**
434+
```javascript
435+
// In soundManager.js
436+
playNewSound() {
437+
if (!this.isEnabled) return;
438+
this.synth.triggerAttackRelease('C4', '8n');
439+
}
440+
```
441+
442+
### Sound Design Guidelines
443+
444+
- **Frequency Mapping**: Map element values to frequencies for intuitive audio feedback
445+
- **Duration**: Keep sounds brief (64n to 8n note values) to avoid overlap
446+
- **Volume**: Use moderate levels to prevent fatigue
447+
- **Fallback**: Always check `isEnabled` before playing sounds
448+
401449
## Conclusion
402450

403451
This project follows modern React best practices:
@@ -407,5 +455,6 @@ This project follows modern React best practices:
407455
- Test-driven development
408456
- Performance optimization
409457
- Clean code principles
458+
- Accessible audio feedback
410459

411460
All contributions are welcome!

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
"@octokit/rest": "^22.0.0",
5353
"lucide-react": "^0.544.0",
5454
"react": "^19.1.1",
55-
"react-dom": "^19.1.1"
55+
"react-dom": "^19.1.1",
56+
"tone": "^15.1.22"
5657
},
5758
"devDependencies": {
5859
"@eslint/js": "^9.36.0",

0 commit comments

Comments
 (0)