Commit Graph

251 Commits

Author SHA1 Message Date
a5a75a5f5c feat: show volume off icon when track volume is 0
- Volume icon now switches between Volume2 and VolumeX based on volume value
- Matches behavior of master volume controls for consistency
- Icon size remains consistent at h-3.5 w-3.5

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:36:25 +01:00
85d27c3b13 feat: standardize icon sizes and replace pan icon with UnfoldHorizontal
- Replaced CircleArrowOutUpRight pan icon with UnfoldHorizontal
- Standardized all track control icons to h-3.5 w-3.5:
  - Volume, Pan, Mic, and Gauge icons now have consistent sizing
- Improves visual consistency across the track control panel

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:35:02 +01:00
546c80e4ae feat: display dB values and use gauge icon for level meters
Changed level meter display to show professional dB values instead
of percentages, and replaced volume icon with gauge icon.

Display Changes:
- Show dB values (-60 to 0) instead of percentage (0-100%)
- Use monospace font for consistent digit alignment
- Show "-∞" for silence (level = 0) instead of "-60"
- Rounded to nearest integer dB (no decimals for cleaner display)

Icon Updates:
- Replaced Volume2 icon with Gauge icon for playback levels
- Kept Mic icon for recording input levels
- Gauge better represents metering/measurement vs audio control

dB Conversion:
- Formula: dB = (normalized * 60) - 60
- Reverse of: normalized = (dB + 60) / 60
- Range: -60dB (silence) to 0dB (full scale)

Display Examples:
  0.00 (0%) = -∞   (silence)
  0.17 (17%) = -50dB (very quiet)
  0.50 (50%) = -30dB (moderate)
  0.83 (83%) = -10dB (loud)
  1.00 (100%) = 0dB (full scale)

Benefits:
 Professional dB notation matching industry standards
 Clearer for audio engineers and musicians
 Easier to identify levels relative to 0dBFS
 Gauge icon better conveys "measurement"
 Monospace font prevents number jumping

Now meters show "-18" instead of "70%" making it immediately
clear where you are in the dynamic range.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:28:35 +01:00
dc567d0144 feat: add professional gradient to level meters matching dB scale
Replaced solid color blocks with smooth gradient to match
professional audio metering standards and dB scale mapping.

The Problem:
- Hard color transitions (green/yellow/red) looked jarring
- Didn't match professional DAW aesthetics
- Color didn't reflect actual dB values visually

The Solution:
- Implemented CSS linear gradient across meter bar
- Gradient matches dB scale breakpoints:
  * Green: 0-70% (-60dB to -18dB) - Safe zone
  * Yellow: 70-90% (-18dB to -6dB) - Getting hot
  * Red: 90-100% (-6dB to 0dB) - Very loud/clipping

Gradient Details:
Horizontal: linear-gradient(to right, ...)
Vertical: linear-gradient(to top, ...)

Color stops:
  0%: rgb(34, 197, 94)   - Green start
 70%: rgb(34, 197, 94)   - Green hold
 85%: rgb(234, 179, 8)   - Yellow transition
100%: rgb(239, 68, 68)   - Red peak

Visual Behavior:
- Smooth color transition as levels increase
- Green dominates safe zone (-60dB to -18dB)
- Yellow appears in warning zone (-18dB to -6dB)
- Red shows critical/clipping zone (-6dB to 0dB)
- Matches Pro Tools, Logic Pro, Ableton Live style

Benefits:
 Professional appearance matching industry DAWs
 Smooth visual feedback instead of jarring transitions
 Colors accurately represent dB ranges
 Better user experience for mixing/mastering
 Gradient visible even at low levels

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:26:10 +01:00
db01209f77 feat: implement professional logarithmic dB scale for level meters
Converted level meters from linear to logarithmic (dB) scale to
match professional audio software behavior and human hearing.

The Problem:
- Linear scale (0-100%) doesn't match perceived loudness
- Doesn't match professional DAW meter behavior
- Half-volume audio appears at 50% but sounds much quieter
- No industry-standard dB reference

The Solution:
- Convert linear amplitude to dB: 20 * log10(linear)
- Normalize -60dB to 0dB range to 0-100% display
- Matches professional audio metering standards

dB Scale Mapping:
  0 dB (linear 1.0)    = 100% (full scale, clipping)
 -6 dB (linear ~0.5)   = 90%  (loud)
-12 dB (linear ~0.25)  = 80%  (normal)
-20 dB (linear ~0.1)   = 67%  (moderate)
-40 dB (linear ~0.01)  = 33%  (quiet)
-60 dB (linear ~0.001) = 0%   (silence threshold)

Implementation:
- Added linearToDbScale() function to both hooks
- useMultiTrackPlayer: playback level monitoring
- useRecording: input level monitoring
- Formula: (dB - minDb) / (maxDb - minDb)
- Range: -60dB (min) to 0dB (max)

Benefits:
 Professional audio metering standards
 Matches human perception of loudness
 Consistent with DAWs (Pro Tools, Logic, Ableton)
 Better visual feedback for mixing/mastering
 More responsive in useful range (-20dB to 0dB)

Now properly mastered tracks will show levels in the
90-100% range, matching what you'd see in professional software.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:23:33 +01:00
a0ce83a654 fix: use Float32Array for accurate full-range level measurement
Switched from Uint8Array to Float32Array for level monitoring
to get accurate, full-precision audio measurements.

The Problem:
- getByteTimeDomainData() uses Uint8Array (0-255)
- Byte conversion: (value - 128) / 128 has asymmetric range
- Positive peaks: (255-128)/128 = 0.992 (not full 1.0)
- Precision loss from byte quantization
- Mastered tracks with peaks at 0dBFS only showed ~50%

The Solution:
- Switched to getFloatTimeDomainData() with Float32Array
- Returns actual sample values directly in -1.0 to +1.0 range
- No conversion needed, no precision loss
- Accurate representation of audio peaks

Changes Applied:
- useMultiTrackPlayer: Float32Array with analyser.fftSize samples
- useRecording: Float32Array with analyser.fftSize samples
- Peak detection: Math.abs() on float values directly

Benefits:
 Full 0-100% range for properly mastered audio
 Higher precision (32-bit float vs 8-bit byte)
 Symmetric range (-1.0 to +1.0, not -1.0 to ~0.992)
 Accurate metering for professional audio files

Now mastered tracks with peaks at 0dBFS will correctly show
~100% on the meters instead of being capped at 50%.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:21:31 +01:00
3e6fbda755 fix: move analyser before gain node to show true audio levels
Repositioned analyser nodes in audio graph to measure raw audio
levels before volume/gain adjustments.

The Problem:
- Analyser was after gain node in signal chain
- Track volume defaults to 0.8 (80%)
- Audio was scaled down before measurement
- Meters only showed ~50% of actual audio peaks

The Solution:
- Moved analyser to immediately after source
- Now measures raw audio before any processing
- Shows true audio content independent of fader position

Audio Graph Changes:
Before: source -> gain -> pan -> effects -> analyser -> master
After:  source -> analyser -> gain -> pan -> effects -> master

Benefits:
 Meters show full 0-100% range based on audio content
 Meter reading independent of volume fader position
 Accurate representation of track audio levels
 Increased smoothingTimeConstant to 0.8 for smoother motion

This is how professional DAWs work - level meters show the
audio content, not the output level after the fader.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:17:42 +01:00
8367cbf6e7 fix: switch from RMS to peak detection for more accurate level meters
Changed level calculation from RMS to peak detection to show
more realistic and responsive meter values.

The Problem:
- RMS calculation produced values typically in 0-30% range
- Audio signals have low average RMS (0.1-0.3 for music)
- Meters appeared broken, never reaching higher levels

The Solution:
- Switched to peak detection (max absolute value)
- Peaks now properly show 0-100% range
- More responsive to transients and dynamics
- Matches typical DAW meter behavior

Algorithm Change:
Before (RMS):
  rms = sqrt(sum(normalized²) / length)

After (Peak):
  peak = max(abs(normalized))

Applied to Both:
- Recording input level monitoring (useRecording)
- Playback output level monitoring (useMultiTrackPlayer)

Benefits:
 Full 0-100% range utilization
 More responsive visual feedback
 Accurate representation of audio peaks
 Consistent with professional audio software

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:15:16 +01:00
a157172e3d fix: resolve playback level monitoring closure issue
Fixed playback level meters staying at 0% by resolving React closure
issue in the monitoring loop - same pattern as the recording fix.

The Problem:
- monitorPlaybackLevels callback checked stale `isPlaying` state
- Animation loop would run once and never continue
- Dependency on isPlaying caused callback recreation on every state change

The Solution:
- Added isMonitoringLevelsRef to track state independent of React
- Removed isPlaying dependency from callback (now has empty deps [])
- Set ref to true when starting playback
- Set ref to false when pausing, stopping, or ending playback
- Animation loop checks ref instead of stale closure state

Monitoring State Management:
- Start: play() sets isMonitoringLevelsRef.current = true
- Stop: pause(), stop(), onended, and cleanup set it to false
- Loop: continues while ref is true, stops when false

This ensures the requestAnimationFrame loop runs continuously
during playback and calculates real-time RMS levels for all tracks.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:12:42 +01:00
6fbb677bd2 feat: implement real-time playback level monitoring for all tracks
Added comprehensive playback level monitoring system that shows
real-time audio levels during playback for each track.

useMultiTrackPlayer Hook:
- Added AnalyserNode for each track in audio graph
- Implemented RMS-based level calculation with requestAnimationFrame
- Added trackLevels state (Record<string, number>) tracking levels by track ID
- Insert analysers after effects chain, before master gain
- Monitor levels continuously during playback
- Clean up level monitoring on pause/stop

Audio Graph Chain:
source -> gain -> pan -> effects -> analyser -> master gain -> destination

AudioEditor Integration:
- Extract trackLevels from useMultiTrackPlayer hook
- Pass trackLevels down to TrackList component

TrackList & Track Components:
- Accept and forward trackLevels prop
- Pass playbackLevel to individual Track components
- Track component displays appropriate level:
  * Recording level (with "Input" label) when armed/recording
  * Playback level (with "Level" label) during normal playback

Visual Feedback:
- Color-coded meters: green -> yellow (70%) -> red (90%)
- Real-time percentage display
- Seamless switching between input and output modes

This completes Phase 8 (Recording) with full bidirectional level monitoring!

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 15:01:55 +01:00
cf0c37caa6 fix: resolve recording level meter monitoring closure issue
Fixed the input level meter staying at 0% during recording by:

Closure Issue Resolution:
- Added isMonitoringRef to track monitoring state independent of React state
- Removed state dependencies from monitorInputLevel callback
- Animation loop now checks ref instead of stale closure state

Changes:
- Set isMonitoringRef.current = true when starting recording
- Set isMonitoringRef.current = false when stopping/pausing recording
- Animation frame continues while ref is true, stops when false
- Proper cleanup in stopRecording, pauseRecording, and unmount effect

This ensures the requestAnimationFrame loop continues properly and
updates the RMS level calculation in real-time during recording.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:56:30 +01:00
c0ca4d7913 fix: migrate existing tracks to new 180px height from localStorage
Added migration logic to useMultiTrack hook:
- When loading tracks from localStorage, check if height < DEFAULT_TRACK_HEIGHT
- Automatically upgrade old heights (120px, 150px) to new default (180px)
- Preserves custom heights that are already >= 180px

This fixes the inline style issue where existing tracks had
style="height: 120px" that was cutting off the level meter.

After this update, refreshing the page will automatically upgrade
all existing tracks to the new height without losing any data.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:53:31 +01:00
fa397a1dfe fix: always show level meter and increase track height to 180px
Fixed layout issues with the level meter:

Track Height:
- Increased DEFAULT_TRACK_HEIGHT from 150px to 180px
- Ensures enough vertical space for all controls without clipping

Level Meter Display:
- Now always visible (not conditional on recording state)
- Shows "Input" with mic icon when track is armed or recording
- Shows "Level" with volume icon when not recording
- Displays appropriate level based on state

This prevents the meter from being cut off and provides consistent
visual feedback for all tracks. Future enhancement: show actual
playback output levels when not recording.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:51:26 +01:00
2775fdb517 fix: increase default track height to accommodate input meter
Increased DEFAULT_TRACK_HEIGHT from 120px to 150px to properly fit:
- Volume slider
- Pan slider
- Input level meter (when track is armed or recording)

This ensures all controls have adequate vertical spacing and the input
meter doesn't get cramped when it appears under the pan control.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:47:58 +01:00
f65dd0be7f feat: complete Phase 8.2 - integrate recording into multi-track UI
Completed the integration of recording functionality into the AudioEditor:

Recording Controls:
- Added global record button to PlaybackControls component
- Implemented track arming system (arm track before recording)
- Added visual feedback with pulsing red animations during recording
- Connected recording state from useRecording hook to UI

AudioEditor Integration:
- Added handleToggleRecordEnable for per-track record arming
- Added handleStartRecording with permission checks and toast notifications
- Added handleStopRecording to save recorded audio to track buffer
- Connected recording input level monitoring to track meters

TrackList Integration:
- Pass recording props (onToggleRecordEnable, recordingTrackId, recordingLevel)
- Individual tracks show input level meters when armed or recording
- Visual indicators for armed and actively recording tracks

This completes Phase 8 (Recording) implementation with:
 MediaRecorder API integration
 Input level monitoring with RMS calculation
 Per-track record arming
 Global record button
 Real-time visual feedback
 Permission handling
 Error handling with user notifications

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:44:15 +01:00
5e6c61d951 feat: implement Phase 8.1 - audio recording infrastructure
Added recording capabilities to the multi-track editor:
- useRecording hook with MediaRecorder API integration
- Audio input device enumeration and selection
- Microphone permission handling
- Input level monitoring with RMS calculation
- InputLevelMeter component with visual feedback
- Record-enable button per track with pulsing indicator
- Real-time input level display when recording

Recording infrastructure is complete. Next: integrate into AudioEditor
for global recording control and buffer storage.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:37:01 +01:00
166385d29a fix: drag-to-select now works reliably without Shift key
Fixed async state update issue where selections were being cleared
immediately after creation. The mouseUp handler now checks drag
distance directly instead of relying on async state, ensuring
selections persist correctly.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:28:09 +01:00
1dc0604635 feat: add intuitive drag-to-select on waveforms
Improved selection UX to match professional DAWs:
- Drag directly on waveform to create selections (no modifier keys needed)
- Click without dragging seeks playhead and clears selection
- 3-pixel drag threshold prevents accidental selections
- Fixed variable name conflict with existing file drag-and-drop feature

Users can now naturally drag across waveforms to select regions for
editing, providing a more intuitive workflow.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:25:49 +01:00
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
cbcd38b1ed refactor: remove master effects section, add TODO note
Removed the master effects section from AudioEditor footer:
- Simplified footer to only show transport controls
- Removed master channel strip area
- Removed border separator between sections

Added note to PLAN.md:
- 🔲 Master channel effects (TODO)
- Will implement master effect chain UI later
- Similar to per-track effects but for final mix
- Documented in Phase 7 multi-track features section

This cleans up the UI for now - we'll add master effects
with a proper device rack UI later, similar to how per-track
effects work (collapsible section with horizontal device cards).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:43:38 +01:00
ecb5152d21 feat: boost light theme to true neon intensity
Cranked up the neon vibes in light theme to match dark theme energy!

Light Theme Neon Boost:
- Bright cyan-tinted backgrounds (180-200° hue)
- Vivid magenta primary (0.28 chroma - max intensity!)
- Rich magenta/purple foreground (20% lightness, 0.12 chroma)
- Electric cyan accent (90% lightness, 0.12 chroma, 180° hue)
- Saturated borders (0.08 chroma)
- Neon cyan waveforms (60% lightness, 0.26 chroma)
- Magenta progress bars (58% lightness, 0.28 chroma)

Color Intensity Increased:
- Primary: 0.28 chroma (was 0.22 - 27% boost!)
- Foreground: 0.12 chroma (was 0.05 - 140% boost!)
- Accent: 0.12-0.18 chroma (was 0.05-0.10 - doubled!)
- Borders: 0.08 chroma (was 0.03 - nearly tripled!)
- Waveforms: 0.26-0.28 chroma (was 0.22 - 20% boost!)

Hue Shift:
- Cyan dominance (180-200° backgrounds)
- Magenta accents (300-320° primaries/foregrounds)
- Electric color combinations throughout

Now both themes have matching neon energy:
- Dark: Neon cyberpunk (purple/cyan/magenta)
- Light: Bright neon pop (cyan/magenta/purple)

Both themes now pop with vibrant, eye-catching colors! 

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:40:38 +01:00
bc7158dbe0 feat: vibrant neon color palette for both themes
Replaced gentle grays with eye-catching neon/vibrant colors!

Dark Theme - Neon Cyberpunk:
- Deep purple/blue backgrounds (265-290° hue)
- Bright neon magenta primary (75% lightness, 0.25 chroma, 310° hue)
- Neon cyan foreground (92% lightness, cyan tint)
- Vibrant borders with purple glow (30% lightness, 0.05 chroma)
- Electric accent colors throughout
- Neon cyan waveforms with magenta progress

Light Theme - Vibrant Pastels:
- Soft purple-tinted backgrounds (280-290° hue)
- Vivid magenta primary (55% lightness, 0.22 chroma)
- Rich purple foreground (25% lightness)
- Colorful borders and accents
- High saturation throughout (0.15-0.22 chroma)
- Vibrant purple/cyan waveforms

Color Intensity:
- Increased chroma from 0.14-0.15 to 0.20-0.25
- Much more saturated, punchy colors
- Vibrant accent colors (cyan, magenta, purple, green)
- Neon-style success (green), warning (yellow), destructive (red)

Hue Shifts:
- Purple/magenta theme (260-320° range)
- Cyan accents (180-200°)
- Warm warnings (80°)
- Green success (160°)

This gives a bold, modern, energetic aesthetic perfect
for a creative audio application - like FL Studio or
Ableton Live's colorful themes!

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:39:23 +01:00
ee24f04d76 feat: add automatic waveform repaint on theme change
Implemented MutationObserver to detect theme changes:

- Added themeKey state that increments on theme change
- MutationObserver watches document.documentElement for class changes
- Detects when "dark" class is toggled
- Added themeKey to waveform effect dependencies
- Canvas automatically redraws with new theme colors

How it works:
1. Observer listens for class attribute changes on <html>
2. When dark mode is toggled, themeKey increments
3. useEffect dependency triggers canvas redraw
4. getComputedStyle reads fresh --color-waveform-bg value
5. Waveform renders with correct theme background

Benefits:
- Seamless theme transitions
- Waveform colors always match current theme
- No manual refresh needed
- Automatic cleanup on unmount

Now switching between light/dark themes instantly updates
all waveform backgrounds with the correct theme colors!

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:36:49 +01:00
2a0d6cd673 fix: replace hardcoded colors with theme variables in Track component
Replaced hardcoded slate colors with theme-aware variables:

Track.tsx changes:
- Waveform area: bg-slate-900 → bg-waveform-bg
- Effects section: bg-slate-900/50 → bg-muted/50
- Expanded effects: bg-slate-900/30 → bg-muted/70
- Canvas background: rgb(15, 23, 42) → --color-waveform-bg

This ensures that:
- Light theme shows proper light gray backgrounds
- Dark theme shows proper dark gray backgrounds
- All components respect theme colors
- No more hardcoded colors that bypass the theme

Now the entire UI properly responds to theme changes with
the harmonized gray palettes we configured.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:34:14 +01:00
2948557e94 feat: soften light theme with gentler gray tones
Reduced contrast in light theme for softer, more comfortable appearance:

Background tones (darker, gentler):
- waveform-bg: 97% (was 99% - less bright)
- card: 96% (was 98% - softer)
- background: 93% (was 96% - more muted)
- muted: 90% (was 94% - darker)
- secondary/accent: 88% (was 92% - more visible)
- border: 85% (was 88% - stronger definition)
- input: 88% (was 92% - better contrast)

Foreground tones (lighter, softer):
- foreground: 28% (was 20% - less harsh)
- card-foreground: 28% (was 20% - softer)
- secondary-foreground: 32% (was 25% - lighter)
- muted-foreground: 48% (was 45% - easier to read)

Color adjustments:
- Reduced color intensity from 0.15 to 0.14
- Softer primary: oklch(58% 0.14 240)
- All colors slightly desaturated for gentler feel

Benefits:
- Reduced contrast reduces eye strain
- Softer, warmer appearance
- More comfortable for extended use
- Better balance between light and dark themes
- Modern low-contrast aesthetic
- Similar to Figma, Linear, or Notion's light modes

Both themes now have beautifully balanced, low-contrast
palettes that are easy on the eyes and professional.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:31:52 +01:00
0dfbdca00c feat: lighten dark theme for softer, gentler appearance
Significantly lightened all dark theme colors for reduced contrast:

Background tones (lighter, softer):
- waveform-bg: 16% (was 10% - too dark)
- background: 18% (was 12% - lifted significantly)
- card: 22% (was 15% - more visible)
- muted: 25% (was 18% - lighter)
- secondary: 28% (was 20% - softer)
- accent: 30% (was 22% - warmer)
- border: 32% (was 25% - more subtle)

Foreground tones (softer, less harsh):
- foreground: 78% (was 85% - reduced contrast)
- card-foreground: 78% (was 85% - softer)
- secondary-foreground: 75% (was 80% - gentler)
- muted-foreground: 58% (was 60% - slightly muted)

Color adjustments:
- Reduced color intensity (0.14 vs 0.15)
- Softer blue primary: oklch(68% 0.14 240)
- More muted accent colors throughout

Benefits:
- Much softer, gentler appearance
- Reduced contrast reduces eye strain
- More comfortable for long editing sessions
- Warmer, more inviting feel
- Modern low-contrast aesthetic
- Similar to VSCode's "Dark+" or Figma's dark mode

The theme now has a beautiful, soft low-contrast aesthetic
that's easy on the eyes while maintaining readability.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:30:24 +01:00
f74c8abbf9 feat: harmonize light theme with soft gray tones
Replaced harsh whites with a soft, professional light gray palette:

Light tones (lightest to darkest):
- waveform-bg: 99% - near-white for waveform area
- card: 98% - soft white for cards/panels
- background: 96% - main background (was 100% harsh white)
- muted: 94% - muted elements
- secondary/accent: 92% - secondary/accent elements
- input: 92% - input backgrounds
- border: 88% - borders and dividers

Dark tones (text, darker):
- foreground: 20% - main text (was 9.8% too dark)
- card-foreground: 20% - card text
- secondary-foreground: 25% - secondary text
- muted-foreground: 45% - muted text (lighter for better contrast)

Primary color:
- Changed to pleasant blue: oklch(55% 0.15 240)
- Matches dark theme primary color concept
- More modern than pure black

Benefits:
- Softer, more pleasant appearance
- Reduced eye strain in light mode
- Better harmony with dark mode
- Professional appearance like Figma, Linear, etc.
- Maintains excellent readability
- Consistent gray palette across both themes

Both light and dark themes now have harmonized gray palettes
that are easy on the eyes and professional-looking.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:28:23 +01:00
46ce75f3a5 feat: harmonize dark theme with softer gray tones
Replaced harsh white contrasts with a harmonized gray palette:

Background tones (darkest to lightest):
- waveform-bg: 10% - deepest black for waveform area
- background: 12% - main app background
- card: 15% - card/panel backgrounds
- muted: 18% - muted elements
- secondary: 20% - secondary elements
- accent: 22% - accent elements
- border: 25% - borders and dividers

Foreground tones (lighter, softer):
- foreground: 85% - main text (was 98% harsh white)
- card-foreground: 85% - card text
- secondary-foreground: 80% - secondary text
- muted-foreground: 60% - muted text

Primary color:
- Changed from white to blue: oklch(70% 0.15 240)
- More pleasant, less harsh than pure white
- Better visual hierarchy

Benefits:
- Reduced eye strain with softer contrasts
- More professional, cohesive appearance
- Better visual hierarchy
- Maintains readability while being easier on the eyes
- Harmonized gray scale throughout the interface

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:26:43 +01:00
439c14db87 feat: show effect chain in collapsed state and polish visual integration
Visual improvements:
- Effects section background now matches waveform (slate-900/50)
- More subtle border (border-border/50)
- Compact header (py-1.5 instead of py-2)
- Expanded area has darker background (slate-900/30) for depth

Collapsed state improvements:
- When collapsed, shows mini effect chips in the header
- Each chip shows effect name with visual state:
  - Enabled: primary color with border (blue/accent)
  - Disabled: muted with border
- Chips are scrollable horizontally if many effects
- Falls back to "Devices (count)" when no effects

Better integration:
- Background colors tie to waveform area
- Subtle hover effect on header (accent/30)
- Visual hierarchy: waveform -> effects blend together
- No more "abandoned" feeling - feels like part of the track

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:23:20 +01:00
25be7027f3 refactor: make effects section always visible with inline collapse toggle
- Removed "Devices" button from control panel
- Effects section now always present below each track
- Collapsible via chevron in the effects header itself
- Click header to expand/collapse the device rack
- "+" button in header to add effects (with stopPropagation)
- Each track has independent collapse state
- Hover effect on header for better UX

This matches the typical DAW layout where each track has its own
device section that can be individually collapsed/expanded.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:16:41 +01:00
b9ffbf28ef feat: move effects section to collapsible area below track waveform
Major UX improvement inspired by Ableton Live's device view:

- Effects section now appears below the waveform in the track lane
- Toggle button in control panel shows/hides the effects area
- Gives much more horizontal space for device rack
- Effects section spans full width of track (control panel + waveform)
- Clean separation between track controls and effects
- Header with device count, add button, and close button

Layout changes:
- Track structure changed from horizontal to vertical flex
- Top row contains control panel + waveform (fixed height)
- Bottom section contains collapsible effects area (when shown)
- Effects hidden by default, toggled via "Devices" button
- When collapsed, track doesn't show effects section

This provides a cleaner workflow where users can focus on mixing
when effects are hidden, then expand to full device view when needed.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:14:13 +01:00
a3fb8a564e fix: remove pan separator and make effects container full width
- Removed border-t border-border from devices section
- Added negative margin (-mx-3) and padding (px-3) to effects container
  to make it extend full width of the track control panel

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:11:20 +01:00
6bfc8d3cfe feat: implement horizontal device rack with collapsible effect cards
- Created EffectDevice component with expand/collapse state
- Each device shows name, type, enabled/disabled toggle, and remove button
- When expanded, devices show parameter details
- Replaced vertical effect list with horizontal scrolling rack
- Effects display in 192px wide cards with visual feedback
- Power button toggles effect enabled/disabled state
- Parameters display shown when expanded (controls coming soon)

This matches the Ableton Live/Bitwig workflow where effects are
arranged horizontally with collapsible UI for each device.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:09:49 +01:00
fa3588d619 fix: move useMemo before early return to fix React hooks order 2025-11-18 08:03:36 +01:00
cb396ddfd6 feat: add EffectBrowser dialog for adding effects to tracks
Created a beautiful effect browser dialog inspired by Ableton Live:

**EffectBrowser Component:**
- Modal dialog with search functionality
- Effects organized by category:
  - Dynamics (Compressor, Limiter, Gate)
  - Filters (Lowpass, Highpass, Bandpass, etc.)
  - Time-Based (Delay, Reverb, Chorus, Flanger, Phaser)
  - Distortion (Distortion, Bitcrusher)
  - Pitch & Time (Pitch Shifter, Time Stretch)
  - Utility (Normalize, Fade In/Out, Reverse)
- Grid layout with hover effects
- Real-time search filtering
- Click effect to add to track

**Integration:**
- "+" button in track strip opens EffectBrowser dialog
- Selecting an effect adds it to the track's effect chain
- Effects appear immediately in the Devices section
- Full enable/disable and remove functionality

**UX Flow:**
1. Click "+" in track Devices section
2. Browse or search for effect
3. Click effect to add it
4. Effect appears in Devices list
5. Toggle on/off with ●/○
6. Remove with × button

Effects are now fully manageable in the UI! Next: Apply them to audio.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 08:02:21 +01:00
25e843236d fix: add missing Plus icon import in Track component 2025-11-18 07:52:24 +01:00
4547446ced fix: improve devices section UX
- Remove border separator above Devices section for cleaner look
- Add "+" button next to Devices header to add new effects
- Button placement matches Ableton/Bitwig pattern
- TODO: Implement effect browser dialog when + is clicked

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:51:51 +01:00
f3f5b65e1e feat: implement Ableton Live-style DAW layout
Major UX refactor to match professional DAW workflows (Ableton/Bitwig):

**Layout Changes:**
- Removed sidebar completely
- Track actions moved to header toolbar (Add/Import/Clear All)
- Each track now shows its own devices/effects in the track strip
- Master section moved to bottom footer area
- Full-width waveform display

**Track Strip (left panel):**
- Track name (editable inline)
- Color indicator
- Collapse/Solo/Mute/Delete buttons
- Volume slider with percentage
- Pan slider with L/C/R indicator
- Collapsible "Devices" section showing track effects
  - Shows effect count in header
  - Each effect card shows: name, enable/disable toggle, remove button
  - Effects are colored based on enabled/disabled state
  - Click to expand/collapse devices section

**Master Section (bottom):**
- Transport controls (Play/Pause/Stop) with timeline
- Master volume control
- Master effects placeholder (to be implemented)

**Benefits:**
- True DAW experience like Ableton Live
- Each track is self-contained with its own effect chain
- No context switching between tabs
- Effects are always visible for each track
- More screen space for waveforms
- Professional mixer-style layout

Note: Effects are visible but not yet applied to audio - that's next!

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:46:27 +01:00
a8f2391400 refactor: improve UX with 2-tab sidebar layout (Option A)
Changed from confusing 3-tab layout to cleaner 2-tab design inspired by
professional DAWs like Ableton Live:

**Tracks Tab:**
- Track management actions (Add/Import/Clear)
- Track count with selected track indicator
- Contextual help text
- Selected track's effects shown below (when track is selected)
- Clear visual separation with border-top

**Master Tab:**
- Master channel description
- Master effects chain
- Preset management for master effects
- Clear that these apply to final mix

Benefits:
- Clear separation: track operations vs master operations
- Contextual: selecting a track shows its effects in same tab
- Less cognitive load than 3 tabs
- Follows DAW conventions (track strip vs master strip)
- Selected track name shown in status area

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:41:16 +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
2f8718626c feat: implement global volume and mute controls
- Add masterVolume state to AudioEditor (default 0.8)
- Pass masterVolume to useMultiTrackPlayer hook
- Create master gain node in audio graph
- Connect all tracks through master gain before destination
- Update master gain in real-time when volume changes
- Wire up PlaybackControls volume slider and mute button
- Clean up master gain node on unmount

Fixes global volume and mute controls not working in transport controls.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:20:29 +01:00
5817598c48 fix: playback position animation frame not updating
Fixed issue where currentTime wasn't updating during playback:
- Removed 'isPlaying' from updatePlaybackPosition dependencies
- This was causing the RAF loop to stop when state changed
- Now animation frame continues running throughout playback
- Playhead now updates smoothly in waveform and timeline slider

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:16:07 +01:00
c6b9cb9af6 fix: improve spacebar shortcut to ignore buttons
Updated spacebar handler to skip when focus is on:
- Input fields
- Textareas
- Buttons (HTMLButtonElement)
- Elements with role="button"

This prevents spacebar from triggering play/pause when clicking
playback control buttons or other UI controls.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:14:10 +01:00
a034ca7e85 feat: center transport controls and add spacebar play/pause
Changes:
- Transport controls now centered in footer with flexbox justify-center
- Added spacebar keyboard shortcut for play/pause toggle
- Spacebar only works when not typing in input/textarea fields
- Prevents default spacebar behavior (page scroll) when playing/pausing

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:11:43 +01:00
e3582b7b9a feat: show waveform in collapsed state
Changes:
- Waveform canvas now displays even when track is collapsed
- Only the upload placeholder is hidden when collapsed
- Gives better visual overview when tracks are minimized
- Similar to DAWs like Ableton Live

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:09:29 +01:00
1404228239 feat: implement drag & drop for audio loading and decrease upload icon
Changes:
- Reduced upload icon size from h-8 w-8 to h-6 w-6 (smaller, cleaner)
- Implemented full drag & drop functionality for audio files
- Shows visual feedback when dragging: blue border, primary color highlight
- Changes text to "Drop audio file here" when dragging over
- Validates dropped file is audio type before processing
- Updated message from "coming soon" to active "or drag & drop"

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:08:04 +01:00
889b2b91ae feat: add click-to-load audio on empty track waveform
Changes:
- Empty tracks now show upload icon and "Click to load audio file" message
- Clicking the placeholder opens native file dialog
- Automatically decodes audio file and updates track with AudioBuffer
- Auto-renames track to filename if track name is still default
- Hover effect with background color change for better UX
- Message about drag & drop coming soon

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:06:46 +01:00
8ffa8e8b81 fix: revert pan icon size back to h-3 w-3
Volume icon is h-3.5 w-3.5, pan icon is h-3 w-3 as requested.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:04:08 +01:00
d3ef961d31 fix: make volume and pan icons the same size
Changed both icons from h-3 w-3 to h-3.5 w-3.5 for consistent sizing.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 07:03:24 +01:00