use quiver::prelude::*;
use std::sync::Arc;
fn main() {
let sample_rate = 44100.0;
let mut patch = Patch::new(sample_rate);
let gate_cv = Arc::new(AtomicF64::new(0.0));
let gate = patch.add("gate", ExternalInput::gate(Arc::clone(&gate_cv)));
let vco = patch.add("vco", Vco::new(sample_rate));
let env = patch.add("env", Adsr::new(sample_rate));
let vca = patch.add("vca", Vca::new());
let output = patch.add("output", StereoOutput::new());
let attack_cv = patch.add("attack_cv", Offset::new(0.62)); let decay_cv = patch.add("decay_cv", Offset::new(0.5)); let sustain_cv = patch.add("sustain_cv", Offset::new(0.5)); let release_cv = patch.add("release_cv", Offset::new(0.64));
patch.connect(gate.out("out"), env.in_("gate")).unwrap();
patch
.connect(attack_cv.out("out"), env.in_("attack"))
.unwrap();
patch
.connect(decay_cv.out("out"), env.in_("decay"))
.unwrap();
patch
.connect(sustain_cv.out("out"), env.in_("sustain"))
.unwrap();
patch
.connect(release_cv.out("out"), env.in_("release"))
.unwrap();
patch.connect(vco.out("saw"), vca.in_("in")).unwrap();
patch.connect(env.out("env"), vca.in_("cv")).unwrap();
patch.connect(vca.out("out"), output.in_("left")).unwrap();
patch.set_output(output.id());
patch.compile().unwrap();
println!("=== ADSR Envelope Demo ===\n");
fn run_samples(patch: &mut Patch, n: usize) -> f64 {
let mut peak = 0.0_f64;
for _ in 0..n {
let (left, _) = patch.tick();
peak = peak.max(left.abs());
}
peak
}
println!("Initial state (gate off):");
let level = run_samples(&mut patch, 100);
println!(" Envelope level: {:.3}V\n", level);
println!("Gate ON - Attack phase begins");
gate_cv.set(5.0);
for ms in [10, 25, 50, 100, 200] {
let samples = (sample_rate * ms as f64 / 1000.0) as usize;
let level = run_samples(&mut patch, samples);
println!(" {}ms: level = {:.2}V", ms, level);
}
println!("\nDecay → Sustain:");
let level = run_samples(&mut patch, (sample_rate * 0.5) as usize);
println!(" Sustain level: {:.2}V\n", level);
println!("Gate OFF - Release phase begins");
gate_cv.set(0.0);
for ms in [50, 100, 200, 500] {
let samples = (sample_rate * ms as f64 / 1000.0) as usize;
let level = run_samples(&mut patch, samples);
println!(" +{}ms: level = {:.3}V", ms, level);
}
println!("\nThe envelope has completed its cycle.");
println!("Attack→Decay→Sustain (while held) →Release (when released)");
}