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>
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>
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>
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>
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>