audiobook-creation-exchange 0.1.0

ACX-compliant audio post-processing: normalisation, limiting, gating, LUFS measurement, and spectral analysis for AI-generated speech audio.
Documentation
use crate::analyse::{db_to_linear, rms_db};

/// Maximum amplification allowed — prevents blowing up near-silent tracks.
const MAX_GAIN_DB: f32 = 24.0;

/// Apply a single linear gain scalar to land the track's RMS at `target_rms_db`.
///
/// The gain is clamped to ±`MAX_GAIN_DB` so near-silence segments
/// don't get amplified into noise.
pub fn normalise(samples: &mut [i16], target_rms_db: f32) {
    let measured = rms_db(samples);

    // If already silent, nothing to do.
    if measured <= -144.0 {
        return;
    }

    let gain_db = (target_rms_db - measured).clamp(-MAX_GAIN_DB, MAX_GAIN_DB);
    let gain = db_to_linear(gain_db);

    for s in samples.iter_mut() {
        let scaled = (*s as f32 * gain)
            .round()
            .clamp(i16::MIN as f32, i16::MAX as f32);
        *s = scaled as i16;
    }
}