From 3e6fbda755e98aa38630c31f9541a0547438d992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Tue, 18 Nov 2025 15:17:42 +0100 Subject: [PATCH] fix: move analyser before gain node to show true audio levels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Repositioned analyser nodes in audio graph to measure raw audio levels before volume/gain adjustments. The Problem: - Analyser was after gain node in signal chain - Track volume defaults to 0.8 (80%) - Audio was scaled down before measurement - Meters only showed ~50% of actual audio peaks The Solution: - Moved analyser to immediately after source - Now measures raw audio before any processing - Shows true audio content independent of fader position Audio Graph Changes: Before: source -> gain -> pan -> effects -> analyser -> master After: source -> analyser -> gain -> pan -> effects -> master Benefits: ✅ Meters show full 0-100% range based on audio content ✅ Meter reading independent of volume fader position ✅ Accurate representation of track audio levels ✅ Increased smoothingTimeConstant to 0.8 for smoother motion This is how professional DAWs work - level meters show the audio content, not the output level after the fader. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- lib/hooks/useMultiTrackPlayer.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/hooks/useMultiTrackPlayer.ts b/lib/hooks/useMultiTrackPlayer.ts index 3399a80..ba41797 100644 --- a/lib/hooks/useMultiTrackPlayer.ts +++ b/lib/hooks/useMultiTrackPlayer.ts @@ -152,7 +152,7 @@ export function useMultiTrackPlayer(tracks: Track[], masterVolume: number = 1) { const panNode = audioContext.createStereoPanner(); const analyserNode = audioContext.createAnalyser(); analyserNode.fftSize = 256; - analyserNode.smoothingTimeConstant = 0.3; + analyserNode.smoothingTimeConstant = 0.8; // Set gain based on track volume and solo/mute state const trackGain = getTrackGain(track, tracks); @@ -161,8 +161,10 @@ export function useMultiTrackPlayer(tracks: Track[], masterVolume: number = 1) { // Set pan panNode.pan.setValueAtTime(track.pan, audioContext.currentTime); - // Connect: source -> gain -> pan -> effects -> analyser -> master gain -> destination - source.connect(gainNode); + // Connect: source -> analyser -> gain -> pan -> effects -> master gain -> destination + // Analyser is before gain so it shows raw audio levels independent of volume fader + source.connect(analyserNode); + analyserNode.connect(gainNode); gainNode.connect(panNode); // Apply effect chain @@ -173,9 +175,8 @@ export function useMultiTrackPlayer(tracks: Track[], masterVolume: number = 1) { console.log('[MultiTrackPlayer] Effects:', track.effectChain.effects); const { outputNode, effectNodes } = applyEffectChain(audioContext, panNode, track.effectChain); - // Insert analyser after effects, before master gain - outputNode.connect(analyserNode); - analyserNode.connect(masterGain); + // Connect to master gain + outputNode.connect(masterGain); console.log('[MultiTrackPlayer] Effect output connected with', effectNodes.length, 'effect nodes'); // Start playback from current position @@ -404,7 +405,7 @@ export function useMultiTrackPlayer(tracks: Track[], masterVolume: number = 1) { const panNode = audioContext.createStereoPanner(); const analyserNode = audioContext.createAnalyser(); analyserNode.fftSize = 256; - analyserNode.smoothingTimeConstant = 0.3; + analyserNode.smoothingTimeConstant = 0.8; // Set gain based on track volume and solo/mute state const trackGain = getTrackGain(track, latestTracks); @@ -413,14 +414,15 @@ export function useMultiTrackPlayer(tracks: Track[], masterVolume: number = 1) { // Set pan panNode.pan.setValueAtTime(track.pan, audioContext.currentTime); - // Connect: source -> gain -> pan -> effects -> analyser -> master gain -> destination - source.connect(gainNode); + // Connect: source -> analyser -> gain -> pan -> effects -> master gain -> destination + // Analyser is before gain so it shows raw audio levels independent of volume fader + source.connect(analyserNode); + analyserNode.connect(gainNode); gainNode.connect(panNode); // Apply effect chain const { outputNode, effectNodes } = applyEffectChain(audioContext, panNode, track.effectChain); - outputNode.connect(analyserNode); - analyserNode.connect(masterGain); + outputNode.connect(masterGain); // Start playback from current position source.start(0, pausedAtRef.current);