Commit Graph

15 Commits

Author SHA1 Message Date
74879a42cf feat: implement multi-track waveform selection and editing with undo/redo
Added comprehensive selection and editing capabilities to multi-track editor:
- Visual selection overlay with Shift+drag interaction on waveforms
- Multi-track edit commands (cut, copy, paste, delete, duplicate)
- Full keyboard shortcut support (Ctrl+X/C/V/D, Delete, Ctrl+Z/Y)
- Complete undo/redo integration via command pattern
- Per-track selection state with localStorage persistence
- Audio buffer manipulation utilities (extract, insert, delete, duplicate segments)
- Toast notifications for all edit operations
- Red playhead to distinguish from blue selection overlay

All edit operations are fully undoable and integrated with the existing
history manager system.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 13:05:05 +01:00
beb7085c89 feat: complete Phase 7.4 - real-time track effects system
Implemented comprehensive real-time effect processing for multi-track audio:

Core Features:
- Per-track effect chains with drag-and-drop reordering
- Effect bypass/enable toggle per effect
- Real-time parameter updates (filters, dynamics, time-based, distortion, bitcrusher, pitch, timestretch)
- Add/remove effects during playback without interruption
- Effect chain persistence via localStorage
- Automatic playback stop when tracks are deleted

Technical Implementation:
- Effect processor with dry/wet routing for bypass functionality
- Real-time effect parameter updates using AudioParam setValueAtTime
- Structure change detection for add/remove/reorder operations
- Stale closure fix using refs for latest track state
- ScriptProcessorNode for bitcrusher, pitch shifter, and time stretch
- Dual-tap delay line for pitch shifting
- Overlap-add synthesis for time stretching

UI Components:
- EffectBrowser dialog with categorized effects
- EffectDevice component with parameter controls
- EffectParameters for all 19 real-time effect types
- Device rack with horizontal scrolling (Ableton-style)

Removed offline-only effects (normalize, fadeIn, fadeOut, reverse) as they don't fit the real-time processing model.

Completed all items in Phase 7.4:
- [x] Per-track effect chain
- [x] Effect rack UI
- [x] Effect bypass per track
- [x] Real-time effect processing during playback
- [x] Add/remove effects during playback
- [x] Real-time parameter updates
- [x] Effect chain persistence

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 12:08:33 +01:00
f640f2f9d4 feat: implement per-track and master effect chains (Option 3)
Architecture:
- Each track now has its own effect chain stored in track.effectChain
- Separate master effect chain for the final mix output
- SidePanel has 3 tabs: Tracks, Track FX, Master FX

Changes:
- types/track.ts: Add effectChain field to Track interface
- lib/audio/track-utils.ts: Initialize effect chain when creating tracks
- lib/hooks/useMultiTrack.ts: Exclude effectChain from localStorage, recreate on load
- components/editor/AudioEditor.tsx:
  - Add master effect chain state using useEffectChain hook
  - Add handlers for per-track effect chain manipulation
  - Pass both track and master effect chains to SidePanel
- components/layout/SidePanel.tsx:
  - Update to 3-tab interface (Tracks | Track FX | Master FX)
  - Track FX tab shows effects for currently selected track
  - Master FX tab shows master bus effects with preset management
  - Different icons for track vs master effects tabs

Note: Effect processing in Web Audio API not yet implemented.
This commit sets up the data structures and UI.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:30:46 +01:00
cf1358e051 fix: ensure track name is always a string in createTrack
Added type checking to prevent event objects from being used as track names.
When onClick handlers pass events, we now explicitly check for string type.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 22:50:43 +01:00
3c950eeba7 feat: implement Phase 7.1-7.2 multi-track infrastructure
Added core multi-track support with track management and controls:

**Track Types & Utilities:**
- Track interface with audio buffer, controls (volume/pan/solo/mute)
- Track utility functions for creation, mixing, and gain calculation
- Track color system with 9 preset colors
- Configurable track heights (60-300px)

**Components:**
- TrackHeader: Collapsible track controls with inline name editing
  - Solo/Mute buttons with visual feedback
  - Volume slider (0-100%) and Pan control (L-C-R)
  - Track color indicator and remove button
- Track: Waveform display component with canvas rendering
  - Click-to-seek on waveform
  - Playhead visualization
  - Support for collapsed state
- TrackList: Container managing multiple tracks
  - Scrollable track list with custom scrollbar
  - Add track button
  - Empty state UI

**State Management:**
- useMultiTrack hook with localStorage persistence
- Add/remove/update/reorder track operations
- Track buffer management

Features implemented:
-  Track creation and removal
-  Track naming (editable)
-  Track colors
-  Solo/Mute per track
-  Volume fader per track (0-100%)
-  Pan control per track (L-C-R)
-  Track collapse/expand
-  Track height configuration
-  Waveform visualization per track
-  Multi-track audio mixing utilities

Next: Integrate into AudioEditor and implement multi-track playback

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 20:59:36 +01:00
8a0bd46593 fix: correct FilterOptions import in effect chain
Fixed TypeScript build error by importing FilterOptions instead of
non-existent FilterParameters from filters module.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 20:34:38 +01:00
0986896756 feat: add Phase 6.6 Effect Chain Management system
Effect Chain System:
- Create comprehensive effect chain types and state management
- Implement EffectRack component with drag-and-drop reordering
- Add enable/disable toggle for individual effects
- Build PresetManager for save/load/import/export functionality
- Create useEffectChain hook with localStorage persistence

UI Integration:
- Add Chain tab to SidePanel with effect rack
- Integrate preset manager dialog
- Add chain management controls (clear, presets)
- Update SidePanel with chain props and handlers

Features:
- Drag-and-drop effect reordering with visual feedback
- Effect bypass/enable toggle with power icons
- Save effect chains as presets with descriptions
- Import/export presets as JSON files
- localStorage persistence for chains and presets
- Visual status indicators for enabled/disabled effects
- Preset timestamp and effect count display

Components Created:
- /lib/audio/effects/chain.ts - Effect chain types and utilities
- /components/effects/EffectRack.tsx - Visual effect chain component
- /components/effects/PresetManager.tsx - Preset management dialog
- /lib/hooks/useEffectChain.ts - Effect chain state hook

Updated PLAN.md:
- Mark Phase 6.6 as complete
- Update current status to Phase 6.6 Complete
- Add effect chain features to working features list
- Update Next Steps to show Phase 6 complete

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 20:27:08 +01:00
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
0d43d73014 fix: cleanup round - full width layout and paste operation bug
Fixed two issues:
1. Made audio editor full width by removing max-w-6xl wrapper
2. Fixed insertBufferSegment bug where paste operation had incorrect
   target buffer indexing causing corrupted audio after paste

Changes:
- app/page.tsx: Removed max-w-6xl constraint for full-width editor
- lib/audio/buffer-utils.ts: Fixed paste buffer copying logic
  * Corrected target index calculation in "copy after insert point" loop
  * Was: targetData[insertBuffer.length + i] = sourceData[i]
  * Now: targetData[insertSample + insertBuffer.length + (i - insertSample)] = sourceData[i]

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 17:13:25 +01:00
ed9ac0b24f feat: implement Phase 4 - selection and editing features
Added comprehensive audio editing capabilities:
- Region selection with Shift+drag on waveform
- Visual selection feedback with blue overlay and borders
- AudioBuffer manipulation utilities (cut, copy, paste, delete, trim)
- EditControls UI component with edit buttons
- Keyboard shortcuts (Ctrl+A, Ctrl+X, Ctrl+C, Ctrl+V, Delete, Escape)
- Clipboard management for cut/copy/paste operations
- Updated useAudioPlayer hook with loadBuffer method

New files:
- types/selection.ts - Selection and ClipboardData interfaces
- lib/audio/buffer-utils.ts - AudioBuffer manipulation utilities
- components/editor/EditControls.tsx - Edit controls UI

Modified files:
- components/editor/Waveform.tsx - Added selection support
- components/editor/AudioEditor.tsx - Integrated edit operations
- lib/hooks/useAudioPlayer.ts - Added loadBuffer method

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 15:50:42 +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