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>
This commit is contained in:
@@ -64,14 +64,16 @@ export function useMultiTrackPlayer(tracks: Track[], masterVolume: number = 1) {
|
||||
const dataArray = new Uint8Array(analyser.frequencyBinCount);
|
||||
analyser.getByteTimeDomainData(dataArray);
|
||||
|
||||
// Calculate RMS level
|
||||
let sum = 0;
|
||||
// Calculate peak level (more responsive than RMS for visual meters)
|
||||
let peak = 0;
|
||||
for (let i = 0; i < dataArray.length; i++) {
|
||||
const normalized = (dataArray[i] - 128) / 128;
|
||||
sum += normalized * normalized;
|
||||
const normalized = Math.abs((dataArray[i] - 128) / 128);
|
||||
if (normalized > peak) {
|
||||
peak = normalized;
|
||||
}
|
||||
}
|
||||
const rms = Math.sqrt(sum / dataArray.length);
|
||||
levels[track.id] = rms;
|
||||
|
||||
levels[track.id] = peak;
|
||||
});
|
||||
|
||||
setTrackLevels(levels);
|
||||
|
||||
@@ -78,15 +78,16 @@ export function useRecording(): UseRecordingReturn {
|
||||
|
||||
analyser.getByteTimeDomainData(dataArray);
|
||||
|
||||
// Calculate RMS level
|
||||
let sum = 0;
|
||||
// Calculate peak level (more responsive than RMS for visual meters)
|
||||
let peak = 0;
|
||||
for (let i = 0; i < dataArray.length; i++) {
|
||||
const normalized = (dataArray[i] - 128) / 128;
|
||||
sum += normalized * normalized;
|
||||
const normalized = Math.abs((dataArray[i] - 128) / 128);
|
||||
if (normalized > peak) {
|
||||
peak = normalized;
|
||||
}
|
||||
}
|
||||
const rms = Math.sqrt(sum / dataArray.length);
|
||||
|
||||
setState((prev) => ({ ...prev, inputLevel: rms }));
|
||||
setState((prev) => ({ ...prev, inputLevel: peak }));
|
||||
|
||||
animationFrameRef.current = requestAnimationFrame(updateLevel);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user