rill-digital-filters 0.4.0

Digital filters for Rill - Biquad, OnePole, StateVariable, etc.
Documentation
//! Basic filter example
//!
//! Run with: cargo run --example basic_filter

use rill_core::time::ClockTick;
use rill_core::traits::{ActionContext, Algorithm};
use rill_core_dsp::filters::FilterParams;
use rill_digital_filters::{BiquadExt, BiquadFilter, FilterType};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Basic Filter Example ===\n");

    // Create a low-pass filter at 1000 Hz with Q=0.707
    let params = FilterParams {
        filter_type: FilterType::LowPass,
        cutoff: 1000.0,
        q: 0.707,
        gain_db: 0.0,
    };
    let mut filter = BiquadFilter::new(params);
    filter.init(44100.0);

    println!("Filter type: LowPass");
    println!("Cutoff: {} Hz", filter.cutoff());
    println!("Q: {}", filter.q());

    // Generate a test signal (sine wave at 440 Hz and 2000 Hz)
    println!("\nProcessing test signal...");

    let num_samples = 4410; // 0.1 seconds
    let mut input_440 = Vec::with_capacity(num_samples);
    let mut input_2000 = Vec::with_capacity(num_samples);

    for i in 0..num_samples {
        let t = i as f32 / 44100.0;
        input_440.push((2.0 * std::f32::consts::PI * 440.0 * t).sin());
        input_2000.push((2.0 * std::f32::consts::PI * 2000.0 * t).sin());
    }

    let tick = ClockTick::default();
    let ctx = ActionContext::new(&tick);

    // Process 440 Hz (should pass through)
    let mut output_440 = vec![0.0; num_samples];
    filter.process(Some(&input_440), &mut output_440, &ctx)?;

    let max_440: f32 = output_440
        .iter()
        .map(|&x: &f32| x.abs())
        .fold(0.0f32, |a, b| a.max(b));
    println!("440 Hz output max: {:.3}", max_440);

    // Reset filter
    filter.reset();

    // Process 2000 Hz (should be attenuated)
    let mut output_2000 = vec![0.0; num_samples];
    filter.process(Some(&input_2000), &mut output_2000, &ctx)?;

    let max_2000: f32 = output_2000
        .iter()
        .map(|&x: &f32| x.abs())
        .fold(0.0f32, |a, b| a.max(b));
    println!("2000 Hz output max: {:.3}", max_2000);

    assert!(max_2000 < max_440, "High frequencies should be attenuated");

    println!("\n✅ Filter example completed");
    Ok(())
}