Skip to content

Sound System Implementation and State Management Issues #72

@alienx5499

Description

@alienx5499

🎯 Bug Overview

Bug Title
Complete Sound System Overhaul - Button Functionality and State Management

Bug Category

  • 🐛 Bug Fix
  • 🔊 Audio System
  • 🔄 State Management
  • 🎨 UI/UX Enhancement
  • 🔧 Core Functionality

🔍 Problem Statement

Is your bug fix related to a problem? Please describe.
The sound system in SortVision has fundamental issues from basic functionality to complex state management:

Basic Functionality Issues:

  1. Sound toggle button doesn't reliably turn sound on/off on click
  2. Visual feedback (button state) doesn't always match actual sound state
  3. Initial sound state is inconsistent across page loads
  4. Sound button appears to work but doesn't actually affect sound output

State Management Issues:

  1. When starting with sound disabled and enabling it during sorting, the sound doesn't work properly
  2. Sound state gets out of sync between UI and audio engine
  3. Sound doesn't consistently work when toggled during active sorting operations
  4. Audio context state isn't properly managed during state transitions
  5. Sound preferences don't persist correctly between sessions

Known Edge Cases:

  1. Sound fails to initialize when initial state is false
  2. Multiple rapid clicks on sound button can break state
  3. Sound state becomes undefined after certain sorting operations
  4. Browser tab switching can break audio context

User Story
As a user of SortVision, I want:

  1. The sound button to reliably turn sound on/off with a single click
  2. Visual feedback that accurately reflects the sound state
  3. My sound preferences to persist between sessions
  4. The ability to toggle sound during sorting without issues

💡 Proposed Solution

Describe the solution you'd like
Implement a complete sound system overhaul with proper button functionality, state management, and persistence.

Key Features/Requirements:

  • Fix basic sound button toggle functionality
  • Implement proper button state visual feedback
  • Add reliable initial state handling
  • Implement proper audio context lifecycle management
  • Synchronize UI state with audio engine state
  • Add reliable sound state persistence
  • Handle audio context suspension/resumption
  • Add proper error handling for audio operations
  • Ensure sound works when enabled during sorting
  • Add sound state validation before playing sounds

Acceptance Criteria:

  • Sound button toggles sound on/off reliably with single click
  • Button visual state matches actual sound state
  • Sound works correctly with any initial state (true/false)
  • Sound works when enabled during active sorting
  • Sound state persists between sessions
  • Sound can be toggled reliably at any time
  • No audio context errors in console
  • Sound state stays in sync between UI and engine
  • Proper error handling and user feedback
  • Clean, semantic code following project standards

🔄 Alternative Solutions

Describe alternatives you've considered

  1. Use Web Audio API directly without abstraction (rejected - too complex)
  2. Use a third-party audio library (rejected - overkill for simple sounds)
  3. Use simple HTML5 Audio elements (rejected - less control over sound)
  4. Use React Context for state management (rejected - adds unnecessary complexity)

Why is this the best approach?
A custom audio engine with proper state management provides the perfect balance of control and simplicity while maintaining good performance.

🎨 Design & Implementation Ideas

Technical Considerations:

  • Button Component: Proper event handling and state management
  • Audio Context: Proper lifecycle management
  • State Management: Sync between UI and engine
  • Error Handling: Graceful fallbacks
  • Performance: Efficient sound playing
  • Browser Support: Web Audio API compatibility

Implementation Approach:

// Sound Button Component
const SoundButton = () => {
  const [isEnabled, setIsEnabled] = useState(() => {
    const saved = localStorage.getItem('soundEnabled');
    return saved !== null ? JSON.parse(saved) : false;
  });
  
  const handleToggle = useCallback(async () => {
    try {
      await audioEngine.toggleSound();
      setIsEnabled(prev => !prev);
      localStorage.setItem('soundEnabled', JSON.stringify(!isEnabled));
    } catch (error) {
      console.error('Failed to toggle sound:', error);
      // Handle error state
    }
  }, [isEnabled]);

  return (
    <button 
      onClick={handleToggle}
      className={`sound-button ${isEnabled ? 'enabled' : 'disabled'}`}
      aria-pressed={isEnabled}
    >
      {isEnabled ? 'Sound On' : 'Sound Off'}
    </button>
  );
};

// Audio Engine Class
class AudioEngine {
  constructor() {
    this.audioContext = null;
    this.masterGain = null;
    this.isEnabled = false;
    this.isInitialized = false;
  }

  async init() {
    if (!this.isInitialized) {
      try {
        this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
        this.masterGain = this.audioContext.createGain();
        this.masterGain.connect(this.audioContext.destination);
        this.isInitialized = true;
      } catch (error) {
        console.error('Failed to initialize audio context:', error);
        throw error;
      }
    }
  }

  async toggleSound() {
    try {
      if (!this.isInitialized) {
        await this.init();
      }
      
      this.isEnabled = !this.isEnabled;
      
      if (this.isEnabled) {
        await this.audioContext.resume();
        this.masterGain.gain.value = 1;
      } else {
        this.masterGain.gain.value = 0;
      }
      
      return this.isEnabled;
    } catch (error) {
      console.error('Failed to toggle sound:', error);
      throw error;
    }
  }

  // ... other methods
}

// React Hook
const useAudio = () => {
  const [isEnabled, setIsEnabled] = useState(() => {
    const saved = localStorage.getItem('soundEnabled');
    return saved !== null ? JSON.parse(saved) : false;
  });

  const [isReady, setIsReady] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const initAudio = async () => {
      try {
        await audioEngine.init();
        if (isEnabled) {
          await audioEngine.toggleSound();
        }
        setIsReady(true);
      } catch (error) {
        setError(error);
      }
    };

    initAudio();
  }, []);

  // ... rest of the hook
};

Files to Modify:

  1. src/components/settings/SettingsForm.jsx

    • Fix sound button component
    • Add proper state handling
    • Add error handling
    • Add visual feedback
  2. src/utils/audioEngine.js

    • Implement robust audio context management
    • Add proper state handling
    • Add error handling
    • Add initialization checks
  3. src/hooks/useAudio.js

    • Implement state synchronization
    • Add persistence logic
    • Add sound validation
    • Add error handling
  4. src/components/sortingVisualizer/SortingVisualizer.jsx

    • Update how audio is passed to algorithms
    • Add state validation
    • Improve error handling
    • Add sound state checks

📊 Impact Assessment

Priority/Importance

  • Priority:

    • 🔴 Critical (Affects core functionality)
  • Impact:

    • 🎯 High (Core feature of visualization)

Target Audience:

  • 👥 All SortVision users
  • 🎓 Students learning algorithms
  • 👨‍🏫 Educators demonstrating sorts
  • 🌐 Web accessibility users

🎯 SSOC Season 4 Information

Project Status:

  • 🎯 Open for SSOC Season 4 Contributors
  • 🔒 Reserved for Specific Contributor
  • ⏳ In Progress
  • ✅ Completed

Difficulty Level:

  • 🟢 Beginner (20 points)
  • 🟡 Intermediate (30 points)
  • 🔴 Advanced (40 points) - Complex state management, Web Audio API, Error Handling

Estimated Time: 8-10 hours

Skills Required:

  • Advanced React/JSX
  • Web Audio API knowledge
  • State management expertise
  • Error handling experience
  • Testing experience
  • Git workflow knowledge
  • Browser API understanding
  • Async/Await proficiency

Implementation Plan:

  1. Phase 1: Basic Button Functionality (2 hours)

    • Fix sound button component
    • Add proper event handling
    • Add visual feedback
    • Add basic error handling
  2. Phase 2: Audio Engine Refactor (2 hours)

    • Implement proper audio context management
    • Add state handling
    • Add error handling
    • Add initialization checks
  3. Phase 3: React Hook Updates (2 hours)

    • Implement state synchronization
    • Add persistence logic
    • Add sound validation
    • Add error handling
  4. Phase 4: Component Integration (2 hours)

    • Update settings form
    • Update sorting visualizer
    • Add error handling
    • Add state validation
  5. Phase 5: Testing & Documentation (2 hours)

    • Test all scenarios
    • Add error handling
    • Document changes
    • Write unit tests

📚 Additional Context

Use Cases/Scenarios:

  1. User clicks sound button multiple times rapidly
  2. User starts sorting with sound off, enables during sort
  3. User toggles sound multiple times during sorting
  4. User reloads page with different sound states
  5. User experiences audio context errors
  6. User switches tabs/windows during sorting
  7. User has slow internet connection
  8. User's browser restricts audio autoplay

Technical Challenges:

  • Managing audio context lifecycle
  • Handling button click events properly
  • Synchronizing multiple state sources
  • Handling edge cases in sorting
  • Ensuring consistent behavior
  • Managing browser limitations
  • Handling async operations
  • Managing error states

Testing Requirements:

  • Test basic button functionality
  • Test button visual feedback
  • Test all sound state transitions
  • Verify persistence behavior
  • Check error handling
  • Test during active sorting
  • Test across different browsers
  • Verify no performance impact
  • Test with different initial states
  • Test rapid state changes
  • Test browser tab switching
  • Test with network throttling

✅ Checklist

  • I have searched existing issues to ensure this is not a duplicate
  • I have provided a clear problem statement and solution
  • I have considered alternative approaches
  • I have assessed the impact and priority
  • I have included relevant technical details
  • I have outlined testing requirements

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions