From 0f3d59b1641df6ad33bafe225d94678f2dab71a2 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Jan 2026 03:09:07 +0000 Subject: [PATCH] fix: Tie native bridge monitoring to arm state for DAW-like behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The native bridge's audio monitoring was not checking the track's armed state, causing inconsistent behavior when arming/disarming tracks. In the browser's TrackAudioProcessor, monitoring is properly tied to arm state (shouldMonitor = isArmed && monitoringEnabled). However, the native bridge only checked monitoring_enabled and is_muted, ignoring is_armed. This caused the bug where: 1. Start audio with track armed → audio works 2. Disarm track → audio stops (expected for DAW) 3. Re-arm track → no audio (bug) The fix adds is_armed to the should_monitor check in process_input(), making native bridge monitoring behave like a traditional DAW: - Monitoring requires: armed AND monitoring enabled AND not muted - Disarming a track now properly stops input monitoring - Re-arming restores monitoring as expected --- native-bridge/src/audio/engine.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/native-bridge/src/audio/engine.rs b/native-bridge/src/audio/engine.rs index f028477..4202d80 100644 --- a/native-bridge/src/audio/engine.rs +++ b/native-bridge/src/audio/engine.rs @@ -1083,15 +1083,21 @@ impl AudioEngine { // Get monitoring state - use atomic flag for monitoring_enabled (never fails!) let mon_vol = f32::from_bits(monitoring_volume.load(Ordering::Relaxed)); let monitoring_enabled = is_monitoring.load(Ordering::Relaxed); - let is_muted = if let Ok(state) = processing_state.try_read() { - state.track_state.is_muted + // Read arm and mute state from processing_state + // Both affect whether we should monitor: must be armed AND not muted + let (is_armed, is_muted) = if let Ok(state) = processing_state.try_read() { + (state.track_state.is_armed, state.track_state.is_muted) } else { - false // Default to not muted - let audio through + // Default: armed=true (let audio through), muted=false (let audio through) + // This prevents audio dropout if lock is briefly contested + (true, false) }; // Local monitoring: apply volume, pan, and push to output // Note: Effects were already applied above (before browser stream) - let should_monitor = monitoring_enabled && !is_muted; + // Monitoring requires: armed AND monitoring enabled AND not muted + // This matches DAW behavior where disarming a track stops input monitoring + let should_monitor = is_armed && monitoring_enabled && !is_muted; if should_monitor { // Apply volume and pan for local monitoring