Commit Graph

6 Commits

Author SHA1 Message Date
ee48f9475f feat: add advanced audio effects and improve UI
Phase 6.5 Advanced Effects:
- Add Pitch Shifter with semitones and cents adjustment
- Add Time Stretch with pitch preservation using overlap-add
- Add Distortion with soft/hard/tube types and tone control
- Add Bitcrusher with bit depth and sample rate reduction
- Add AdvancedParameterDialog with real-time waveform visualization
- Add 4 professional presets per effect type

Improvements:
- Fix undefined parameter errors by adding nullish coalescing operators
- Add global custom scrollbar styling with color-mix transparency
- Add custom-scrollbar utility class for side panel
- Improve theme-aware scrollbar appearance in light/dark modes
- Fix parameter initialization when switching effect types

Integration:
- All advanced effects support undo/redo via EffectCommand
- Effects accessible via command palette and side panel
- Selection-based processing support
- Toast notifications for all effects

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 20:03:40 +01:00
f414573655 fix: seeking backwards no longer jumps to frame 0
Fixed critical bug where seeking backwards during playback would
jump to position 0 instead of the desired position.

Root cause:
- When stop() was called on a playing source node, it triggered
  the onended event callback
- The onended callback would set pauseTime = 0 (thinking playback
  naturally ended)
- This interfered with the seek operation which was trying to set
  a new position

Solution:
- Clear sourceNode.onended callback BEFORE calling stop()
- This prevents the ended event from firing when we manually stop
- Seeking now works correctly in all directions

The fix ensures clean state transitions during seeking operations.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:32:50 +01:00
10d2921147 fix: proper seeking behavior with optional auto-play
Complete rewrite of seeking logic to support both scrubbing and
click-to-play functionality with proper state management.

Changes:
1. Added autoPlay parameter to seek() methods across the stack
2. Waveform behavior:
   - Click and drag → scrubs WITHOUT auto-play during drag
   - Mouse up after drag → auto-plays from release position
   - This allows smooth scrubbing while dragging
3. Timeline slider behavior:
   - onChange → seeks WITHOUT auto-play (smooth dragging)
   - onMouseUp/onTouchEnd → auto-plays from final position
4. Transport button state now correctly syncs with playback state

Technical implementation:
- player.seek(time, autoPlay) - autoPlay defaults to false
- If autoPlay=true OR was already playing → continues playback
- If autoPlay=false AND wasn't playing → just seeks (isPaused=true)
- useAudioPlayer.seek() now reads actual player state after seeking

User experience:
✓ Click on waveform → music plays from that position
✓ Drag on waveform → scrubs smoothly, plays on release
✓ Drag timeline slider → scrubs smoothly, plays on release
✓ Transport buttons show correct state (Play/Pause)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:30:11 +01:00
19bf7dc68a fix: seek now auto-starts playback for intuitive interaction
Changed seek behavior to match user expectations:
- Clicking on waveform now immediately starts playing from that position
- Dragging timeline slider starts playback at the selected position
- No need to click Play button after seeking

Previous behavior:
- seek() only continued playback if music was already playing
- Otherwise it just set isPaused = true
- User had to seek AND THEN click play button

New behavior:
- seek() always starts playback automatically
- Click anywhere → music plays from that position
- Much more intuitive UX matching common audio editors

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:24:31 +01:00
958c6d6680 fix: playback starts from seeked position instead of beginning
Fixed critical bug where playback always started from 0:00 regardless
of seek position or pause state.

Root cause:
- play() method called stop() which reset pauseTime to 0
- Then it checked isPaused (now false) and pauseTime (now 0)
- Result: always played from beginning

Solution:
- Calculate offset BEFORE calling stop()
- Preserve the paused position or start offset
- Then stop and recreate source node with correct offset

Now playback correctly starts from:
- Seeked position (waveform click or timeline slider)
- Paused position (when resuming after pause)
- Specified start offset (when provided)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:21:10 +01:00
ebfb4d3fff feat: implement Phase 2 - Web Audio API engine and waveform visualization
Phase 2 Complete Features:
- Web Audio API context management with browser compatibility
- Audio file upload with drag-and-drop support
- Audio decoding for multiple formats (WAV, MP3, OGG, FLAC, AAC, M4A)
- AudioPlayer class with full playback control
- Waveform visualization using Canvas API
- Real-time waveform rendering with progress indicator
- Playback controls (play, pause, stop, seek)
- Volume control with mute/unmute
- Timeline scrubbing
- Audio file information display

Components:
- AudioEditor: Main editor container
- FileUpload: Drag-and-drop file upload component
- AudioInfo: Display audio file metadata
- Waveform: Canvas-based waveform visualization
- PlaybackControls: Transport controls with volume slider

Audio Engine:
- lib/audio/context.ts: AudioContext management
- lib/audio/decoder.ts: Audio file decoding utilities
- lib/audio/player.ts: AudioPlayer class for playback
- lib/waveform/peaks.ts: Waveform peak generation

Hooks:
- useAudioPlayer: Complete audio player state management

Types:
- types/audio.ts: TypeScript definitions for audio types

Features Working:
✓ Load audio files via drag-and-drop or file picker
✓ Display waveform with real-time progress
✓ Play/pause/stop controls
✓ Seek by clicking on waveform or using timeline slider
✓ Volume control with visual feedback
✓ Audio file metadata display (duration, sample rate, channels)
✓ Toast notifications for user feedback
✓ SSR-safe audio context initialization
✓ Dark/light theme support

Tech Stack:
- Web Audio API for playback
- Canvas API for waveform rendering
- React 19 hooks for state management
- TypeScript for type safety

Build verified and working ✓

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:32:00 +01:00