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
|
|
|
'use client';
|
|
|
|
|
|
|
|
|
|
import * as React from 'react';
|
2025-11-18 07:46:27 +01:00
|
|
|
import { Music, Plus, Upload, Trash2 } from 'lucide-react';
|
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
|
|
|
import { PlaybackControls } from './PlaybackControls';
|
2025-11-17 20:03:40 +01:00
|
|
|
import { ThemeToggle } from '@/components/layout/ThemeToggle';
|
|
|
|
|
import { CommandPalette } from '@/components/ui/CommandPalette';
|
2025-11-18 07:46:27 +01:00
|
|
|
import { Button } from '@/components/ui/Button';
|
2025-11-17 20:03:40 +01:00
|
|
|
import type { CommandAction } from '@/components/ui/CommandPalette';
|
2025-11-17 21:57:31 +01:00
|
|
|
import { useMultiTrack } from '@/lib/hooks/useMultiTrack';
|
|
|
|
|
import { useMultiTrackPlayer } from '@/lib/hooks/useMultiTrackPlayer';
|
2025-11-17 22:17:09 +01:00
|
|
|
import { useEffectChain } from '@/lib/hooks/useEffectChain';
|
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
|
|
|
import { useToast } from '@/components/ui/Toast';
|
2025-11-17 21:57:31 +01:00
|
|
|
import { TrackList } from '@/components/tracks/TrackList';
|
|
|
|
|
import { ImportTrackDialog } from '@/components/tracks/ImportTrackDialog';
|
2025-11-17 22:17:09 +01:00
|
|
|
import { formatDuration } from '@/lib/audio/decoder';
|
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
|
|
|
|
|
|
|
|
export function AudioEditor() {
|
2025-11-17 21:57:31 +01:00
|
|
|
const [importDialogOpen, setImportDialogOpen] = React.useState(false);
|
2025-11-17 22:17:09 +01:00
|
|
|
const [selectedTrackId, setSelectedTrackId] = React.useState<string | null>(null);
|
2025-11-17 15:44:29 +01:00
|
|
|
const [zoom, setZoom] = React.useState(1);
|
2025-11-18 07:20:29 +01:00
|
|
|
const [masterVolume, setMasterVolume] = React.useState(0.8);
|
2025-11-17 20:03:40 +01:00
|
|
|
|
2025-11-17 22:17:09 +01:00
|
|
|
const { addToast } = useToast();
|
2025-11-17 20:03:40 +01:00
|
|
|
|
2025-11-17 22:17:09 +01:00
|
|
|
// Multi-track hooks
|
|
|
|
|
const {
|
|
|
|
|
tracks,
|
|
|
|
|
addTrack,
|
|
|
|
|
addTrackFromBuffer,
|
|
|
|
|
removeTrack,
|
|
|
|
|
updateTrack,
|
|
|
|
|
clearTracks,
|
|
|
|
|
} = useMultiTrack();
|
2025-11-17 17:08:31 +01:00
|
|
|
|
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
|
|
|
const {
|
2025-11-17 22:17:09 +01:00
|
|
|
isPlaying,
|
|
|
|
|
currentTime,
|
|
|
|
|
duration,
|
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
|
|
|
play,
|
|
|
|
|
pause,
|
|
|
|
|
stop,
|
|
|
|
|
seek,
|
2025-11-17 22:17:09 +01:00
|
|
|
togglePlayPause,
|
2025-11-18 07:20:29 +01:00
|
|
|
} = useMultiTrackPlayer(tracks, masterVolume);
|
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
|
|
|
|
2025-11-18 07:30:46 +01:00
|
|
|
// Master effect chain
|
2025-11-17 20:27:08 +01:00
|
|
|
const {
|
2025-11-18 07:30:46 +01:00
|
|
|
chain: masterEffectChain,
|
|
|
|
|
presets: masterEffectPresets,
|
|
|
|
|
toggleEffectEnabled: toggleMasterEffect,
|
|
|
|
|
removeEffect: removeMasterEffect,
|
|
|
|
|
reorder: reorderMasterEffects,
|
|
|
|
|
clearChain: clearMasterChain,
|
|
|
|
|
savePreset: saveMasterPreset,
|
|
|
|
|
loadPresetToChain: loadMasterPreset,
|
|
|
|
|
deletePreset: deleteMasterPreset,
|
2025-11-17 20:27:08 +01:00
|
|
|
} = useEffectChain();
|
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
|
|
|
|
2025-11-17 21:57:31 +01:00
|
|
|
// Multi-track handlers
|
|
|
|
|
const handleImportTracks = () => {
|
|
|
|
|
setImportDialogOpen(true);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleImportTrack = (buffer: AudioBuffer, name: string) => {
|
|
|
|
|
addTrackFromBuffer(buffer, name);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleClearTracks = () => {
|
|
|
|
|
clearTracks();
|
2025-11-17 22:17:09 +01:00
|
|
|
setSelectedTrackId(null);
|
2025-11-17 21:57:31 +01:00
|
|
|
addToast({
|
|
|
|
|
title: 'Tracks Cleared',
|
|
|
|
|
description: 'All tracks have been removed',
|
|
|
|
|
variant: 'info',
|
|
|
|
|
duration: 2000,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-17 22:17:09 +01:00
|
|
|
const handleRemoveTrack = (trackId: string) => {
|
|
|
|
|
removeTrack(trackId);
|
|
|
|
|
if (selectedTrackId === trackId) {
|
|
|
|
|
setSelectedTrackId(null);
|
2025-11-17 20:03:40 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-18 07:30:46 +01:00
|
|
|
// Per-track effect chain handlers
|
|
|
|
|
const handleToggleTrackEffect = (effectId: string) => {
|
|
|
|
|
if (!selectedTrack) return;
|
|
|
|
|
const updatedChain = {
|
|
|
|
|
...selectedTrack.effectChain,
|
|
|
|
|
effects: selectedTrack.effectChain.effects.map((e) =>
|
|
|
|
|
e.id === effectId ? { ...e, enabled: !e.enabled } : e
|
|
|
|
|
),
|
|
|
|
|
};
|
|
|
|
|
updateTrack(selectedTrack.id, { effectChain: updatedChain });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleRemoveTrackEffect = (effectId: string) => {
|
|
|
|
|
if (!selectedTrack) return;
|
|
|
|
|
const updatedChain = {
|
|
|
|
|
...selectedTrack.effectChain,
|
|
|
|
|
effects: selectedTrack.effectChain.effects.filter((e) => e.id !== effectId),
|
|
|
|
|
};
|
|
|
|
|
updateTrack(selectedTrack.id, { effectChain: updatedChain });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleReorderTrackEffects = (fromIndex: number, toIndex: number) => {
|
|
|
|
|
if (!selectedTrack) return;
|
|
|
|
|
const effects = [...selectedTrack.effectChain.effects];
|
|
|
|
|
const [removed] = effects.splice(fromIndex, 1);
|
|
|
|
|
effects.splice(toIndex, 0, removed);
|
|
|
|
|
const updatedChain = {
|
|
|
|
|
...selectedTrack.effectChain,
|
|
|
|
|
effects,
|
|
|
|
|
};
|
|
|
|
|
updateTrack(selectedTrack.id, { effectChain: updatedChain });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleClearTrackChain = () => {
|
|
|
|
|
if (!selectedTrack) return;
|
|
|
|
|
const updatedChain = {
|
|
|
|
|
...selectedTrack.effectChain,
|
|
|
|
|
effects: [],
|
|
|
|
|
};
|
|
|
|
|
updateTrack(selectedTrack.id, { effectChain: updatedChain });
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-17 15:44:29 +01:00
|
|
|
// Zoom controls
|
|
|
|
|
const handleZoomIn = () => {
|
|
|
|
|
setZoom((prev) => Math.min(20, prev + 1));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleZoomOut = () => {
|
|
|
|
|
setZoom((prev) => Math.max(1, prev - 1));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleFitToView = () => {
|
|
|
|
|
setZoom(1);
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-18 07:11:43 +01:00
|
|
|
// Keyboard shortcuts
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
|
const handleKeyDown = (e: KeyboardEvent) => {
|
2025-11-18 07:14:10 +01:00
|
|
|
// Spacebar for play/pause - only if not interacting with form elements
|
|
|
|
|
if (e.code === 'Space') {
|
|
|
|
|
const target = e.target as HTMLElement;
|
|
|
|
|
// Don't trigger if user is typing or interacting with buttons/form elements
|
|
|
|
|
if (
|
|
|
|
|
target instanceof HTMLInputElement ||
|
|
|
|
|
target instanceof HTMLTextAreaElement ||
|
|
|
|
|
target instanceof HTMLButtonElement ||
|
|
|
|
|
target.getAttribute('role') === 'button'
|
|
|
|
|
) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-11-18 07:11:43 +01:00
|
|
|
e.preventDefault();
|
|
|
|
|
togglePlayPause();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
|
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
|
|
|
}, [togglePlayPause]);
|
|
|
|
|
|
2025-11-17 22:17:09 +01:00
|
|
|
// Find selected track
|
|
|
|
|
const selectedTrack = tracks.find((t) => t.id === selectedTrackId);
|
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
|
|
|
|
2025-11-17 20:03:40 +01:00
|
|
|
// Command palette actions
|
|
|
|
|
const commandActions: CommandAction[] = React.useMemo(() => {
|
|
|
|
|
const actions: CommandAction[] = [
|
|
|
|
|
// Playback
|
|
|
|
|
{
|
|
|
|
|
id: 'play',
|
|
|
|
|
label: 'Play',
|
|
|
|
|
description: 'Start playback',
|
|
|
|
|
shortcut: 'Space',
|
|
|
|
|
category: 'playback',
|
|
|
|
|
action: play,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'pause',
|
|
|
|
|
label: 'Pause',
|
|
|
|
|
description: 'Pause playback',
|
|
|
|
|
shortcut: 'Space',
|
|
|
|
|
category: 'playback',
|
|
|
|
|
action: pause,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'stop',
|
|
|
|
|
label: 'Stop',
|
|
|
|
|
description: 'Stop playback',
|
|
|
|
|
category: 'playback',
|
|
|
|
|
action: stop,
|
|
|
|
|
},
|
|
|
|
|
// View
|
|
|
|
|
{
|
|
|
|
|
id: 'zoom-in',
|
|
|
|
|
label: 'Zoom In',
|
2025-11-17 22:17:09 +01:00
|
|
|
description: 'Zoom in on waveforms',
|
2025-11-17 20:03:40 +01:00
|
|
|
category: 'view',
|
|
|
|
|
action: handleZoomIn,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'zoom-out',
|
|
|
|
|
label: 'Zoom Out',
|
2025-11-17 22:17:09 +01:00
|
|
|
description: 'Zoom out on waveforms',
|
2025-11-17 20:03:40 +01:00
|
|
|
category: 'view',
|
|
|
|
|
action: handleZoomOut,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'fit-to-view',
|
|
|
|
|
label: 'Fit to View',
|
2025-11-17 22:17:09 +01:00
|
|
|
description: 'Reset zoom to fit all tracks',
|
2025-11-17 20:03:40 +01:00
|
|
|
category: 'view',
|
|
|
|
|
action: handleFitToView,
|
|
|
|
|
},
|
2025-11-17 22:17:09 +01:00
|
|
|
// Tracks
|
2025-11-17 20:03:40 +01:00
|
|
|
{
|
2025-11-17 22:17:09 +01:00
|
|
|
id: 'add-track',
|
|
|
|
|
label: 'Add Empty Track',
|
|
|
|
|
description: 'Create a new empty track',
|
|
|
|
|
category: 'tracks',
|
|
|
|
|
action: () => addTrack(),
|
2025-11-17 20:03:40 +01:00
|
|
|
},
|
|
|
|
|
{
|
2025-11-17 22:17:09 +01:00
|
|
|
id: 'import-tracks',
|
|
|
|
|
label: 'Import Audio Files',
|
|
|
|
|
description: 'Import multiple audio files as tracks',
|
|
|
|
|
category: 'tracks',
|
|
|
|
|
action: handleImportTracks,
|
2025-11-17 20:03:40 +01:00
|
|
|
},
|
|
|
|
|
{
|
2025-11-17 22:17:09 +01:00
|
|
|
id: 'clear-tracks',
|
|
|
|
|
label: 'Clear All Tracks',
|
|
|
|
|
description: 'Remove all tracks',
|
|
|
|
|
category: 'tracks',
|
|
|
|
|
action: handleClearTracks,
|
2025-11-17 20:03:40 +01:00
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
return actions;
|
2025-11-17 22:17:09 +01:00
|
|
|
}, [play, pause, stop, handleZoomIn, handleZoomOut, handleFitToView, handleImportTracks, handleClearTracks, addTrack]);
|
|
|
|
|
|
|
|
|
|
// Keyboard shortcuts
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
|
|
|
// Prevent shortcuts if typing in an input
|
|
|
|
|
const isTyping = e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement;
|
|
|
|
|
|
|
|
|
|
// Spacebar: Play/Pause (always, unless typing in an input)
|
|
|
|
|
if (e.code === 'Space' && !isTyping) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
togglePlayPause();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isTyping) return;
|
|
|
|
|
|
|
|
|
|
// Escape: Clear selection
|
|
|
|
|
if (e.key === 'Escape') {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
setSelectedTrackId(null);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
|
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
|
|
|
}, [togglePlayPause]);
|
2025-11-17 20:03:40 +01:00
|
|
|
|
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
|
|
|
return (
|
2025-11-17 20:03:40 +01:00
|
|
|
<>
|
|
|
|
|
{/* Compact Header */}
|
|
|
|
|
<header className="flex items-center justify-between px-4 py-2 border-b border-border bg-card flex-shrink-0 gap-4">
|
|
|
|
|
{/* Left: Logo */}
|
2025-11-18 07:46:27 +01:00
|
|
|
<div className="flex items-center gap-4 flex-shrink-0">
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<Music className="h-5 w-5 text-primary" />
|
|
|
|
|
<h1 className="text-lg font-bold text-foreground">Audio UI</h1>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Track Actions */}
|
|
|
|
|
<div className="flex items-center gap-2 border-l border-border pl-4">
|
|
|
|
|
<Button variant="outline" size="sm" onClick={addTrack}>
|
|
|
|
|
<Plus className="h-4 w-4 mr-1.5" />
|
|
|
|
|
Add Track
|
|
|
|
|
</Button>
|
|
|
|
|
<Button variant="outline" size="sm" onClick={handleImportTracks}>
|
|
|
|
|
<Upload className="h-4 w-4 mr-1.5" />
|
|
|
|
|
Import
|
|
|
|
|
</Button>
|
|
|
|
|
{tracks.length > 0 && (
|
|
|
|
|
<Button variant="outline" size="sm" onClick={handleClearTracks}>
|
|
|
|
|
<Trash2 className="h-4 w-4 mr-1.5 text-destructive" />
|
|
|
|
|
Clear All
|
|
|
|
|
</Button>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2025-11-17 20:03:40 +01:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Right: Command Palette + Theme Toggle */}
|
|
|
|
|
<div className="flex items-center gap-2 flex-shrink-0">
|
|
|
|
|
<CommandPalette actions={commandActions} />
|
|
|
|
|
<ThemeToggle />
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
{/* Main content area */}
|
|
|
|
|
<div className="flex flex-1 overflow-hidden">
|
|
|
|
|
{/* Main canvas area */}
|
|
|
|
|
<main className="flex-1 flex flex-col overflow-hidden bg-background">
|
2025-11-17 22:17:09 +01:00
|
|
|
{/* Multi-Track View */}
|
|
|
|
|
<div className="flex-1 flex flex-col overflow-hidden">
|
|
|
|
|
<TrackList
|
|
|
|
|
tracks={tracks}
|
|
|
|
|
zoom={zoom}
|
|
|
|
|
currentTime={currentTime}
|
|
|
|
|
duration={duration}
|
|
|
|
|
selectedTrackId={selectedTrackId}
|
|
|
|
|
onSelectTrack={setSelectedTrackId}
|
|
|
|
|
onAddTrack={addTrack}
|
|
|
|
|
onImportTrack={handleImportTrack}
|
|
|
|
|
onRemoveTrack={handleRemoveTrack}
|
|
|
|
|
onUpdateTrack={updateTrack}
|
|
|
|
|
onSeek={seek}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-17 20:03:40 +01:00
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-18 07:46:27 +01:00
|
|
|
{/* Transport Controls + Master Channel */}
|
|
|
|
|
<div className="border-t border-border bg-card">
|
|
|
|
|
{/* Transport Controls */}
|
|
|
|
|
<div className="p-3 flex justify-center border-b border-border">
|
|
|
|
|
<PlaybackControls
|
|
|
|
|
isPlaying={isPlaying}
|
|
|
|
|
isPaused={!isPlaying}
|
|
|
|
|
currentTime={currentTime}
|
|
|
|
|
duration={duration}
|
|
|
|
|
volume={masterVolume}
|
|
|
|
|
onPlay={play}
|
|
|
|
|
onPause={pause}
|
|
|
|
|
onStop={stop}
|
|
|
|
|
onSeek={seek}
|
|
|
|
|
onVolumeChange={setMasterVolume}
|
|
|
|
|
currentTimeFormatted={formatDuration(currentTime)}
|
|
|
|
|
durationFormatted={formatDuration(duration)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Master Track Strip */}
|
|
|
|
|
<div className="p-3">
|
|
|
|
|
<div className="flex items-center gap-2 mb-2">
|
|
|
|
|
<h3 className="text-sm font-semibold text-foreground">Master</h3>
|
|
|
|
|
<span className="text-xs text-muted-foreground">Final mix output</span>
|
|
|
|
|
</div>
|
|
|
|
|
{/* Master effects will go here */}
|
|
|
|
|
<div className="text-xs text-muted-foreground">
|
|
|
|
|
Master effects: {masterEffectChain.effects.length}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-17 21:57:31 +01:00
|
|
|
{/* Import Track Dialog */}
|
|
|
|
|
<ImportTrackDialog
|
|
|
|
|
open={importDialogOpen}
|
|
|
|
|
onClose={() => setImportDialogOpen(false)}
|
|
|
|
|
onImportTrack={handleImportTrack}
|
|
|
|
|
/>
|
2025-11-17 20:03:40 +01:00
|
|
|
</>
|
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
|
|
|
);
|
|
|
|
|
}
|