rosa 0.1.0

Audio feature extraction library matching librosa output
Documentation
//! Pre-emphasis and de-emphasis filters matching `librosa.effects`.

/// Apply pre-emphasis filter to an audio signal.
///
/// Matches `librosa.effects.preemphasis(y, coef=coef)`.
///
/// Implements: `y_out[n] = y[n] - coef * y[n-1]`
/// with initial state `zi = 2*y[0] - y[1]` (linear extrapolation).
///
/// Using scipy's direct form II transposed convention:
/// `y_out[0] = y[0] + zi`, `y_out[n] = y[n] - coef * y[n-1]` for n >= 1.
///
/// # Examples
///
/// ```
/// let signal = vec![1.0, 2.0, 3.0, 4.0];
/// let filtered = rosa::effects::preemphasis(&signal, 0.97);
/// assert_eq!(filtered.len(), 4);
/// ```
pub fn preemphasis(y: &[f64], coef: f64) -> Vec<f64> {
    let n = y.len();
    if n == 0 {
        return Vec::new();
    }
    if n == 1 {
        return vec![y[0]];
    }

    let mut result = Vec::with_capacity(n);

    // Initial state: zi = 2*y[0] - y[1] (linear extrapolation)
    // First output via direct form II transposed: y_out[0] = b[0]*y[0] + zi
    let zi = 2.0 * y[0] - y[1];
    result.push(y[0] + zi); // = 3*y[0] - y[1]

    // Subsequent samples: standard FIR y_out[n] = y[n] - coef * y[n-1]
    for i in 1..n {
        result.push(y[i] - coef * y[i - 1]);
    }

    result
}

/// Apply de-emphasis filter to an audio signal.
///
/// Matches `librosa.effects.deemphasis(y, coef=coef)`.
///
/// This is the inverse of `preemphasis`. If `y_pre = preemphasis(x, coef)`,
/// then `deemphasis(y_pre, coef) ≈ x`.
///
/// Algorithm:
/// 1. IIR filter: `x[n] = y[n] + coef * x[n-1]` with `x[-1] = 0`
/// 2. Subtract correction: `((2-coef)*y[0] - y[1]) / (3-coef) * coef^n`
pub fn deemphasis(y: &[f64], coef: f64) -> Vec<f64> {
    let n = y.len();
    if n == 0 {
        return Vec::new();
    }
    if n == 1 {
        return vec![y[0]];
    }

    // Step 1: IIR filter with zi=0: x[n] = y[n] + coef * x[n-1]
    let mut iir = Vec::with_capacity(n);
    iir.push(y[0]);
    for i in 1..n {
        iir.push(y[i] + coef * iir[i - 1]);
    }

    // Step 2: Subtract correction factor
    // correction[n] = ((2-coef)*y[0] - y[1]) / (3-coef) * coef^n
    let corr_base = ((2.0 - coef) * y[0] - y[1]) / (3.0 - coef);
    let mut coef_pow = 1.0;
    for i in 0..n {
        iir[i] -= corr_base * coef_pow;
        coef_pow *= coef;
    }

    iir
}