use aether_core::{node::DspNode, param::ParamBlock, BUFFER_SIZE, MAX_INPUTS};
use aether_nodes::filter::StateVariableFilter;
use hound::{WavSpec, WavWriter};
use rand::Rng;
const SAMPLE_RATE: u32 = 48000;
const DURATION_SECS: f32 = 4.0;
const NUM_SAMPLES: usize = (SAMPLE_RATE as f32 * DURATION_SECS) as usize;
const FILTER_MODE_LOWPASS: f32 = 0.0;
fn main() {
println!("=== Filter Cutoff Sweep Rendering ===\n");
let spec = WavSpec {
channels: 1,
sample_rate: SAMPLE_RATE,
bits_per_sample: 16,
sample_format: hound::SampleFormat::Int,
};
println!("Generating white noise...");
let mut rng = rand::thread_rng();
let mut noise_samples = Vec::with_capacity(NUM_SAMPLES);
for _ in 0..NUM_SAMPLES {
noise_samples.push(rng.gen_range(-0.3..0.3));
}
println!("Rendering unfiltered noise to filter_sweep_before.wav...");
let mut writer_before = WavWriter::create("filter_sweep_before.wav", spec).unwrap();
for &sample in &noise_samples {
let amplitude = (sample * i16::MAX as f32) as i16;
writer_before.write_sample(amplitude).unwrap();
}
writer_before.finalize().unwrap();
println!("✓ Rendered unfiltered");
println!("Rendering filtered with cutoff sweep to filter_sweep_after.wav...");
let mut writer_after = WavWriter::create("filter_sweep_after.wav", spec).unwrap();
let mut filter = StateVariableFilter::new();
let mut params = ParamBlock::new();
params.add(200.0); params.add(0.7); params.add(FILTER_MODE_LOWPASS);
let mut sample_idx = 0;
let mut input_buffer = [0.0f32; BUFFER_SIZE];
while sample_idx < NUM_SAMPLES {
for i in 0..BUFFER_SIZE {
if sample_idx + i < NUM_SAMPLES {
input_buffer[i] = noise_samples[sample_idx + i];
} else {
input_buffer[i] = 0.0;
}
}
let progress = sample_idx as f32 / NUM_SAMPLES as f32;
let cutoff = 200.0 + progress * 7800.0;
params.get_mut(0).set_target(cutoff, 0);
let inputs = [Some(&input_buffer); MAX_INPUTS];
let mut output = [0.0f32; BUFFER_SIZE];
filter.process(&inputs, &mut output, &mut params, SAMPLE_RATE as f32);
for &sample in &output {
if sample_idx >= NUM_SAMPLES {
break;
}
let amplitude = (sample * i16::MAX as f32) as i16;
writer_after.write_sample(amplitude).unwrap();
sample_idx += 1;
}
}
writer_after.finalize().unwrap();
println!("✓ Rendered filtered with sweep");
println!("\n✓ Filter sweep rendered successfully!");
println!("Compare: ffplay filter_sweep_before.wav");
println!(" ffplay filter_sweep_after.wav");
}