mcelp 1.0.1

Mitsubishi CELP speech codec: a 3.6 kbit/s speech encoder and decoder
Documentation
//! Filtering the search's shapes through the impulse response.
//!
//! Both encoder searches work against a signal that has already been through
//! the weighted synthesis filter, so rather than filtering every candidate they
//! convolve each shape with the impulse response once and combine the results.
//! This is that convolution; the searches themselves are in
//! [`crate::pitch_search`] and [`crate::pulses`].

use crate::fixed::{acc, hi, sat, shift};

/// Samples in a subframe, and taps in one pulse shape.
pub use crate::SUBFRAME;
pub const SHAPE: usize = 20;

/// Convolve one shape with the impulse response.
///
/// The shape's length is whatever the caller passes: the fixed codebook's
/// twenty-tap pulses, or the eighty samples of excitation history the closed
/// loop searches against.
pub fn filter(shape: &[i16], response: &[i16]) -> [i16; SUBFRAME] {
    let mut out = [0i16; SUBFRAME];
    for k in 0..SUBFRAME {
        let mut total = 0i64;
        for i in 0..=k.min(shape.len() - 1) {
            total = acc(total + (shape[i] as i64) * (response[k - i] as i64) * 2);
        }
        out[k] = hi(sat(shift(total, 3)));
    }
    out
}