use nam_rs::{Model, NamModel};
const BLOCK: usize = 128;
fn main() -> Result<(), nam_rs::Error> {
let path = std::env::args()
.nth(1)
.expect("usage: streaming <model.nam>");
let model = NamModel::from_file(&path)?;
let mut amp = Model::from_nam(&model)?;
let sr = model.expected_sample_rate();
const HOST_SAMPLE_RATE: f64 = 48_000.0;
if sr != HOST_SAMPLE_RATE {
eprintln!(
"warning: host runs at {HOST_SAMPLE_RATE} Hz but the model expects {sr} Hz — \
a real host would resample the I/O to {sr} Hz here, or the output is wrong"
);
}
let rf = amp.receptive_field();
let summary = if rf > 0 {
format!(
"receptive field {rf} samples (~{:.1} ms at {sr} Hz) — the startup \
transient before output settles",
rf as f64 / sr * 1000.0,
)
} else {
"recurrent — no warmup transient".to_owned()
};
println!("loaded {path}: {summary}");
let signal: Vec<f32> = (0..8 * BLOCK)
.map(|i| 0.5 * (i as f32 * 0.05).sin())
.collect();
let mut streamed = signal.clone();
for block in streamed.chunks_mut(BLOCK) {
amp.process_buffer(block);
}
amp.reset();
let mut oneshot = signal.clone();
amp.process_buffer(&mut oneshot);
let max_diff = streamed
.iter()
.zip(&oneshot)
.map(|(a, b)| (a - b).abs())
.fold(0.0_f32, f32::max);
println!(
"streamed {} samples in {}-sample blocks; max deviation from a single \
whole-buffer call: {max_diff:e}",
signal.len(),
BLOCK,
);
assert_eq!(max_diff, 0.0, "block size must not change the output");
Ok(())
}