Changed from single JSON file to ZIP archive format to avoid string
length limits when serializing large audio buffers.
New ZIP structure:
- project.json (metadata, track info, effects, automation)
- track_0.wav, track_1.wav, etc. (audio files in WAV format)
Benefits:
- No more RangeError: Invalid string length
- Smaller file sizes (WAV compression vs base64 JSON)
- Human-readable audio files in standard format
- Can extract and inspect individual tracks
- Easier to edit/debug project metadata
Added jszip dependency for ZIP file handling.
Changed file picker to accept .zip files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added full export/import functionality for projects:
Export Features:
- Export button for each project in Projects dialog
- Downloads project as JSON file with all data
- Includes tracks, audio buffers, effects, automation, settings
- Filename format: {project_name}_{timestamp}.json
Import Features:
- Import button in Projects dialog header
- File picker for .json files
- Automatically generates new project ID to avoid conflicts
- Appends "(Imported)" to project name
- Preserves all project data
This enables:
- Backup of projects outside the browser
- Sharing projects with collaborators
- Migration between computers/browsers
- Version snapshots at different stages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Modified handleSaveProject to accept showToast parameter (default: false)
- Auto-saves now run silently without toast notifications
- Added Ctrl+S / Cmd+S keyboard shortcut for manual save with toast
- Added "Save Project" and "Open Projects" to command palette
- Error toasts still shown for all save failures
This provides the best of both worlds:
- Automatic background saves don't interrupt the user
- Manual saves (Ctrl+S or command palette) provide confirmation
- Users can work without being constantly notified
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The handleSaveProject callback had currentTime in its dependencies, which
caused the callback to be recreated on every playback frame update. This
made the auto-save effect reset its timer constantly, preventing auto-save
from ever triggering.
Solution: Use a ref to capture the latest currentTime value without
including it in the callback dependencies. This keeps the callback stable
while still saving the correct currentTime.
Added debug logging to track auto-save scheduling and triggering.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Deep clone automation data using JSON.parse(JSON.stringify()) to remove
any functions before saving to IndexedDB. This prevents DataCloneError
when trying to store non-serializable data.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Effects contain non-serializable data like functions and audio nodes that
cannot be stored in IndexedDB. Added proper serialization.
Changes:
- Added serializeEffects function to strip non-serializable data
- Uses JSON parse/stringify to deep clone parameters
- Preserves effect type, name, enabled state, and parameters
- Fixes DataCloneError when saving projects with effects
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**useMultiTrack.ts:**
- Removed localStorage persistence (tracks, effects, automation)
- Now relies entirely on IndexedDB via project management system
- Simpler state management without dual persistence
**AudioEditor.tsx:**
- Store last project ID in localStorage when saving
- Auto-load last project on page mount
- Only runs once per session with hasAutoLoaded flag
- Falls back to empty state if project can't be loaded
**Benefits:**
- No more conflicts between localStorage and IndexedDB
- Effects and automation properly persisted
- Seamless experience - reload page and your project is ready
- Single source of truth (IndexedDB)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed auto-save from 30s interval to 3s debounce, and added
currentProjectName to dependencies so it saves when name changes.
**Changes:**
- Auto-save now triggers 3 seconds after ANY change (tracks or name)
- Added `currentProjectName` to auto-save effect dependencies
- Removed `onBlur` handler from input (auto-save handles it)
- Added tooltip "Click to edit project name"
- Faster feedback - saves 3s after typing stops instead of 30s
**User Experience:**
- Edit project name → auto-saves after 3s
- Add/modify tracks → auto-saves after 3s
- No need to manually save or wait 30 seconds
- Toast notification confirms save
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed project loading to restore all track properties and added inline
project name editing in header.
**AudioEditor.tsx:**
- Added `loadTracks` from useMultiTrack hook
- Fixed `handleLoadProject` to use `loadTracks()` instead of recreating tracks
- Now properly restores all track properties (effects, automation, volume, pan, etc.)
- Shows track count in success toast message
- Added editable project name input in header
- Positioned between logo and track actions
- Auto-sizes based on text length
- Saves on blur (triggers auto-save)
- Smooth hover/focus transitions
- Muted color that brightens on interaction
**useMultiTrack.ts:**
- Added `loadTracks()` method to replace all tracks at once
- Enables proper project loading with full state restoration
- Maintains all track properties during load
**Fixes:**
- Projects now load correctly with all tracks and their audio buffers
- Track properties (effects, automation, volume, pan, etc.) fully restored
- Project name can be edited inline in header
- Auto-save triggers when project name changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Integrated complete project management system with auto-save:
**AudioEditor.tsx - Full Integration:**
- Added "Projects" button in header toolbar (FolderOpen icon)
- Project state management (currentProjectId, currentProjectName, projects list)
- Comprehensive project handlers:
- `handleOpenProjectsDialog` - Opens dialog and loads project list
- `handleSaveProject` - Saves current project to IndexedDB
- `handleNewProject` - Creates new project with confirmation
- `handleLoadProject` - Loads project and restores all tracks/settings
- `handleDeleteProject` - Deletes project with cleanup
- `handleDuplicateProject` - Creates project copy
- Auto-save effect: Saves project every 30 seconds when tracks exist
- ProjectsDialog component integrated with all handlers
- Toast notifications for all operations
**lib/storage/projects.ts:**
- Re-exported ProjectMetadata type for easier importing
- Fixed type exports
**Key Features:**
- **Auto-save**: Automatically saves every 30 seconds
- **Project persistence**: Full track state, audio buffers, effects, automation
- **Smart loading**: Restores zoom, track order, and all track properties
- **Safety confirmations**: Warns before creating new project with unsaved changes
- **User feedback**: Toast messages for all operations (save, load, delete, duplicate)
- **Seamless workflow**: Projects → Import → Export in logical toolbar order
**User Flow:**
1. Click "Projects" to open project manager
2. Create new project or load existing
3. Work on tracks (auto-saves every 30s)
4. Switch between projects anytime
5. Duplicate projects for experimentation
6. Delete old projects to clean up
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added complete project save/load system using IndexedDB:
**New Files:**
- `lib/storage/db.ts` - IndexedDB database schema and operations
- ProjectMetadata interface for project metadata
- SerializedAudioBuffer and SerializedTrack for storage
- Database initialization with projects object store
- Audio buffer serialization/deserialization functions
- CRUD operations for projects
- `lib/storage/projects.ts` - High-level project management service
- Save/load project state with tracks and settings
- List all projects sorted by last updated
- Delete and duplicate project operations
- Track serialization with proper type conversions
- Audio buffer and effect chain handling
- `components/dialogs/ProjectsDialog.tsx` - Project list UI
- Grid view of all projects with metadata
- Project actions: Open, Duplicate, Delete
- Create new project button
- Empty state with call-to-action
- Confirmation dialog for deletions
**Key Features:**
- IndexedDB stores complete project state (tracks, audio buffers, settings)
- Efficient serialization of AudioBuffer channel data
- Preserves all track properties (effects, automation, volume, pan)
- Sample rate and duration tracking
- Created/updated timestamps
- Type-safe with full TypeScript support
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed the non-standard FLAC export option which was causing import issues:
**Problem:**
- "FLAC" export was actually a custom compressed WAV format
- Used fflate (DEFLATE compression) instead of real FLAC encoding
- Files couldn't be imported back or opened in other software
- No browser-compatible FLAC encoder library exists
**Changes:**
- Removed FLAC from export format options (WAV and MP3 only)
- Removed FLAC quality slider from ExportDialog
- Removed audioBufferToFlac function reference
- Updated ExportSettings interface to only include 'wav' | 'mp3'
- Simplified bit depth selector (WAV only instead of WAV/FLAC)
- Updated format descriptions to clarify lossy vs lossless
**Export formats now:**
- ✅ WAV - Lossless, Uncompressed (16/24/32-bit)
- ✅ MP3 - Lossy, Compressed (128/192/256/320 kbps)
Users can now successfully export and re-import their audio!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Now when users upload an audio file, they see the ImportDialog with options:
**User Flow:**
1. User selects audio file (click or drag-drop)
2. File is pre-decoded to extract metadata (sample rate, channels)
3. ImportDialog shows with file info and import options:
- Convert to Mono (if stereo/multi-channel)
- Resample Audio (44.1kHz - 192kHz)
- Normalize on Import
4. User clicks Import (or Cancel)
5. File is imported with selected transformations applied
6. Track name auto-updates to filename
**Track.tsx Changes:**
- Added import dialog state (showImportDialog, pendingFile, fileMetadata)
- Updated handleFileChange to show dialog instead of direct import
- Added handleImport to process file with user-selected options
- Added handleImportCancel to dismiss dialog
- Renders ImportDialog when showImportDialog is true
- Logs imported audio metadata to console
Now users can see and control all import transformations!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Switched from low-level Lame API to Mp3Encoder class which:
- Properly initializes all required modules (Lame, BitStream, etc.)
- Handles module dependencies via setModules() calls
- Provides a simpler encodeBuffer/flush API
- Resolves "init_bit_stream_w is not defined" error
Updated TypeScript declarations to export Mp3Encoder and WavHeader
from lamejs/src/js/index.js
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed MP3 export by importing lamejs modules directly from source:
- Import MPEGMode, Lame, and BitStream from individual source files
- Use Lame API directly instead of Mp3Encoder wrapper
- Updated TypeScript declarations for each module
- Resolves "MPEGMode is not defined" error
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Switched from npm package to GitHub repo (github:zhuker/lamejs) which
includes the proper browser build. Reverted to simple dynamic import.
Fixes MP3 export MPEGMode reference error.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed MP3 export to dynamically load the pre-built lame.min.js
bundle from node_modules instead of trying to import the CommonJS
module. The browser bundle properly bundles all dependencies including
MPEGMode and exposes a global lamejs object.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed MP3 export error by handling both default and named exports
from lamejs module to support CommonJS/ESM interop.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated documentation to reflect export regions implementation:
- Marked Phase 11.3 (Export Regions) as complete
- Updated progress overview to show Phase 11.1-11.3 complete
- Added export scope details to Working Features
- Listed all three export modes: project, selection, tracks
- Updated phase status summary
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented Phase 11.3 - Export Regions:
- Added export scope selector in ExportDialog
- Entire Project: Mix all tracks into single file
- Selected Region: Export only the selected region (disabled if no selection)
- Individual Tracks: Export each track as separate file
- Updated ExportSettings interface with scope property
- Refactored handleExport to support all three export modes:
- Project mode: Mix all tracks (existing behavior)
- Selection mode: Extract selection from all tracks and mix
- Tracks mode: Loop through tracks and export separately with sanitized filenames
- Added hasSelection prop to ExportDialog to enable/disable selection option
- Created helper function convertAndDownload to reduce code duplication
- Selection mode uses extractBufferSegment for precise region extraction
- Track names are sanitized for filenames (remove special characters)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated documentation to reflect completed export features:
- Marked Phase 11.1 (Export Formats) as complete
- Marked Phase 11.2 (Export Settings) as complete
- Added technical implementation details for MP3 and FLAC
- Updated progress overview status
- Added Export Features section to Working Features list
- Updated Analysis Tools section to reflect Phase 10 completion
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented Phase 11.1 export format support:
- Added MP3 export using lamejs library
- Added FLAC export using fflate DEFLATE compression
- Updated ExportDialog with format selector and format-specific options
- MP3: bitrate selector (128/192/256/320 kbps)
- FLAC: compression quality slider (0-9)
- WAV: bit depth selector (16/24/32-bit)
- Updated AudioEditor to route export based on selected format
- Created TypeScript declarations for lamejs
- Fixed AudioStatistics to use audioBuffer instead of buffer property
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
All Phase 10 items now complete:
- ✅ Frequency Analyzer & Spectrogram
- ✅ Phase Correlation Meter
- ✅ LUFS Loudness Meter
- ✅ Audio Statistics with full metrics
Updated status to Phase 11 (Export & Import) in progress.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Marked completed items in Phase 10:
- ✅ Frequency Analyzer (10.1) with real-time FFT display
- ✅ Spectrogram (10.2) with time-frequency visualization
- ✅ Peak/RMS metering (10.3) already complete
- ✅ Clip indicator (10.3) for master channel
Added Analysis Tools section to Working Features.
Updated Current Status and Next Steps.
Remaining Phase 10 items:
- Phase correlation meter
- LUFS loudness meter
- Audio statistics display
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed several TypeScript issues:
- Changed 'formatter' to 'formatValue' in CircularKnob props
- Added explicit type annotations for formatValue functions
- Initialized animationFrameRef with undefined value
- Removed unused Waveform import from TrackControls
All type checks now pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed spectrogram to use transparency for low values
instead of interpolating from background color:
- Low signal values (0-64) fade from transparent to blue
- Background color shows through transparent areas
- Now matches FrequencyAnalyzer theme behavior
- Both analyzers use bg-muted/30 wrapper for consistent theming
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated both FrequencyAnalyzer and Spectrogram to use
light gray background (bg-muted/30) that adapts to the theme:
- Wrapped canvas in bg-muted/30 container
- FrequencyAnalyzer reads parent background color for canvas fill
- Spectrogram interpolates from background color to blue for low values
- Both analyzers now work properly in light and dark themes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Increased analyzer dimensions from 160px to 192px width
and from 300px to 360px minimum height for better visibility.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Constrained analyzer components to 160px width to match
the MasterControls card width, creating better visual alignment
in the master column.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added real-time audio analysis visualizations to master column:
- FrequencyAnalyzer component with FFT bar display
- Canvas-based rendering with requestAnimationFrame
- Color gradient from cyan to green based on frequency
- Frequency axis labels (20Hz, 1kHz, 20kHz)
- Spectrogram component with time-frequency waterfall display
- Scrolling visualization with ImageData pixel manipulation
- Color mapping: black → blue → cyan → green → yellow → red
- Vertical frequency axis with labels
- Master column redesign
- Fixed width layout (280px)
- Toggle buttons to switch between FFT and Spectrum views
- Integrated above master controls with 300px minimum height
- Exposed masterAnalyser from useMultiTrackPlayer hook
- Analyser node now accessible to visualization components
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed button dimensions from h-8 w-full to h-12 w-12 for a
square/quadratic shape matching the design of track buttons.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed master mute button from Button component to match track style:
- Native button element with rounded-md styling
- Blue background when muted (bg-blue-500) with shadow
- Card background when unmuted with hover state
- Text-based "M" label instead of icons
- Larger size (h-8, text-[11px]) compared to track (h-5, text-[9px])
- Removed unused Volume2/VolumeX icon imports
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added comprehensive touch event handling for mobile/tablet support:
CircularKnob.tsx:
- Added handleTouchStart, handleTouchMove, handleTouchEnd handlers
- Touch events use same drag logic as mouse events
- Prevents default to avoid scrolling while adjusting
TrackFader.tsx:
- Added touch event handlers for vertical fader control
- Integrated with existing onTouchStart/onTouchEnd callbacks
- Supports touch-based automation recording
MasterFader.tsx:
- Added touch event handlers matching TrackFader
- Complete touch support for master volume control
All components now work seamlessly on touch-enabled devices.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Reverted track heights to original values:
- DEFAULT_TRACK_HEIGHT: 360px → 340px
- MIN_TRACK_HEIGHT: 260px → 240px
Increased bottom padding of TrackControls from py-2 to pt-2 pb-4
for better spacing at the bottom of the control card.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Raised MIN_TRACK_HEIGHT to ensure proper spacing for all track
controls with the new border styling.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Increased DEFAULT_TRACK_HEIGHT to provide more vertical space for
track controls and waveform viewing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed background from bg-card to bg-card/50 for both TrackControls
and MasterControls to make the border more prominent.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Increased opacity for both TrackControls and MasterControls:
- bg-muted/10 → bg-muted/20 (background)
- border-accent/30 → border-accent/50 (border)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Shifted faders to the right for better visual alignment:
- TrackFader: 8px margin-left
- MasterFader: 12px margin-left
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed back from .toFixed(2) to .toFixed(1) while keeping the fixed
widths to prevent component movement.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>