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>
This commit is contained in:
2025-11-18 15:01:55 +01:00
parent cf0c37caa6
commit 6fbb677bd2
4 changed files with 82 additions and 8 deletions

View File

@@ -35,6 +35,7 @@ export interface TrackProps {
onToggleRecordEnable?: () => void;
isRecording?: boolean;
recordingLevel?: number;
playbackLevel?: number;
}
export function Track({
@@ -61,6 +62,7 @@ export function Track({
onToggleRecordEnable,
isRecording = false,
recordingLevel = 0,
playbackLevel = 0,
}: TrackProps) {
const canvasRef = React.useRef<HTMLCanvasElement>(null);
const containerRef = React.useRef<HTMLDivElement>(null);
@@ -564,12 +566,12 @@ export function Track({
</label>
<div className="flex-1">
<InputLevelMeter
level={track.recordEnabled || isRecording ? recordingLevel : 0}
level={track.recordEnabled || isRecording ? recordingLevel : playbackLevel}
orientation="horizontal"
/>
</div>
<span className="text-xs text-muted-foreground w-10 text-right flex-shrink-0">
{Math.round((track.recordEnabled || isRecording ? recordingLevel : 0) * 100)}%
{Math.round((track.recordEnabled || isRecording ? recordingLevel : playbackLevel) * 100)}%
</span>
</div>
</>