Skip to content

Smart Volume: Studio-Quality Auto Gain Control#350

Closed
djbob2000 wants to merge 10 commits into
ronitsingh10:mainfrom
djbob2000:feature/smart-volume
Closed

Smart Volume: Studio-Quality Auto Gain Control#350
djbob2000 wants to merge 10 commits into
ronitsingh10:mainfrom
djbob2000:feature/smart-volume

Conversation

@djbob2000

Copy link
Copy Markdown

Overview

This PR significantly upgrades the dynamics engine in FineTune to resolve volume fluctuations, pumping artifacts, and bass loss, while introducing broadcasting-grade AGC controls. It addresses user feedback regarding dynamics stability by implementing a per-device Smart Volume feature and isolating legacy controls for future re-design.

This PR closes and resolves the following issues:

image

Key Improvements

1. Dual-Band AGC Architecture & Phase-Linear Crossover

  • Linkwitz-Riley Crossover: Replaced the single-band AGC with a dual-band structure (Bass and Master bands split at 150 Hz) using a custom 4th-order Linkwitz-Riley crossover (LinkwitzRileyCrossover.swift). This ensures flat magnitude summation (allpass reconstruction) and eliminates phase cancellations.
  • Bidirectional Bass-to-Master Coupling: Implemented a bidirectional $\pm$3.0 dB coupling clamp on the bass band gain relative to the master band (keeping bassBand.currentGainDb strictly within [masterBand.currentGainDb - 3.0, masterBand.currentGainDb + 3.0]). This prevents unnatural independent bass pumping (upper clamp) and excessive bass loss during heavy bass transients (lower clamp).

2. Proportional Ballistics, AGC Window & Level Protections

  • Proportional Ballistics: Attack/release speeds scale dynamically in proportion to the overshoot/deficit (normalized per sample and per dB of difference), producing smooth, organic level corrections.
  • AGC Window (Comfort Zone): Implemented a 4.5 dB window (agcWindowSizeDb) around the target level where the AGC holds its current gain to eliminate breathing and pumping during steady passages.
  • Sudden Drop Protection: Accelerates the release speed (using a 2.5x speedup factor) when the driven level drops more than 10 dB below the target, allowing the system to recover quickly from sudden quiet transitions.
  • Sudden Jump Protection: An instantaneous fast-attack override (5.0 ms time constant) that immediately pulls the gain down during massive volume spikes to prevent transient clipping.

3. Silence Gate, Idle Gain Fallback & Real-Time Gating Slowdown

  • Orban-Style Idle Gain Fallback: During silence, the AGC gain slowly and smoothly drifts to a configurable parked level (silenceGateIdleGainDb defaulting to -24.0 dB) with a fallback time constant of 9.0 seconds, avoiding sudden volume pops when audio resumes.
  • Soft-Gating Slowdown Zone: Implemented an exponential slowdown zone between -12.0 dB and -16.0 dB. The active release speed is scaled down as the signal drops toward the gate threshold. For real-time thread safety, this is optimized as exp(lnGateSlowdownFactor * (1.0 - gatingFactor)) using a factor of 0.086 tuned for conversational speech dynamics.

4. Custom Parametric Sidechain Filter

  • Replaced the standard ITU-R BS.1770 K-weighting in the active Equalizer sidechain with a custom 7-stage parametric sidechain filter (ParametricSidechainFilter.swift) mimicking Stereo Tool's sidechain parameters (38 Hz Butterworth High Pass + 6 peaking EQ bands).
  • SIMD4 Optimization: The filter is fully vectorized using SIMD4 to process the three sidechain signals (mono downmix, bass band, and master band) in parallel in a single pass, ensuring allocation-free execution on the real-time audio thread.
  • The legacy KWeightingFilter has been preserved and integrated into the test suite for behavior and frequency response comparison.

5. Dedicated 3-Band Post-AGC Compressor

  • Added a fast-acting, multi-band PostAgcCompressor.swift immediately after the Loudness Equalizer in the signal path to catch transient overshoots that the slower AGC envelope follower misses.
  • 3-Band Processing: Splits the audio path into three bands using cascaded LR4 (Linkwitz-Riley 4th-order) crossovers at 77 Hz and 200 Hz:
    • Band 1 (< 77 Hz): Fixed threshold offset of -8.9 dB, ratio 4.0, attack 67.0 ms, release 1080.0 ms.
    • Band 2 (77 Hz - 200 Hz): Fixed threshold offset of -6.0 dB, ratio 4.0, attack 52.0 ms, release 599.0 ms.
    • Band 3 (> 200 Hz): Maps to user settings (thresholdDb defaults to 0.0 dBFS, ratio defaults to 7.6, attackMs defaults to 2.9 ms, and releaseMs defaults to 11.6 ms).
  • Dynamics Adjustments: Features a soft knee (0.1 dB), a max release speed cap (0.50), and an exponential release factor (0.8) to slow down recovery as gain reduction approaches 0 dB.
  • Enforces a strict stereo-only (2 channels) processing contract on the audio thread to guarantee allocation-free, lock-free real-time safety.

6. UI & Settings Enhancements

  • Per-Device Smart Volume: Introduced a dedicated per-device Smart Volume toggle in the Device Detail panel (DeviceDetailSheet.swift) and Device list (DeviceRow.swift) to allow enabling dynamic range leveling independently for specific hardware outputs.
  • Isolated Legacy Controls: Removed the legacy global Loudness Equalization toggle and Loudness Compensation slider from the Settings panel (AudioTab.swift). Loudness Equalization/Compensation features will be redesigned and reintroduced globally in a separate, subsequent MR.
  • Settings Migration: Migrated legacy unifiedLoudnessEnabled settings transparently inside SettingsManager.swift to enable per-device Smart Volume defaults if the legacy feature was previously configured.
  • Automatic Re-application: Integrated applyLoudnessEqualizationToTap to all device switch, connection, and update event loops in AudioEngine.swift to ensure Smart Volume parameters are dynamically applied across routes.

@djbob2000

Copy link
Copy Markdown
Author

@ronitsingh10 waiting your review or comments

@djbob2000 djbob2000 closed this Jul 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant