use quiver::prelude::*;
fn midi_to_voct(note: u8) -> f64 {
(note as f64 - 60.0) / 12.0
}
fn main() {
let sample_rate = 44100.0;
let mut patch = Patch::new(sample_rate);
let pattern = [
(48, true), (50, true), (0, false), (43, true), (48, true), (0, false), (52, true), (50, true), ];
let mut seq_module = StepSequencer::new();
for (i, (note, active)) in pattern.iter().enumerate() {
seq_module.set_step(i, midi_to_voct(*note), *active);
}
let seq = patch.add("seq", seq_module);
let clock = patch.add("clock", Clock::new(sample_rate));
let vco = patch.add("vco", Vco::new(sample_rate));
let vcf = patch.add("vcf", Svf::new(sample_rate));
let vca = patch.add("vca", Vca::new());
let env = patch.add("env", Adsr::new(sample_rate));
let output = patch.add("output", StereoOutput::new());
patch.connect(clock.out("out"), seq.in_("clock")).unwrap();
patch.connect(seq.out("cv"), vco.in_("voct")).unwrap();
patch.connect(seq.out("gate"), env.in_("gate")).unwrap();
patch.connect(vco.out("saw"), vcf.in_("in")).unwrap();
patch.connect(vcf.out("lp"), vca.in_("in")).unwrap();
patch.connect(vca.out("out"), output.in_("left")).unwrap();
patch.connect(vca.out("out"), output.in_("right")).unwrap();
patch.connect(env.out("env"), vcf.in_("cutoff")).unwrap();
patch.connect(env.out("env"), vca.in_("cv")).unwrap();
patch.set_output(output.id());
patch.compile().unwrap();
println!("=== Sequenced Bass Demo ===\n");
fn note_name(note: u8) -> &'static str {
match note % 12 {
0 => "C",
1 => "C#",
2 => "D",
3 => "D#",
4 => "E",
5 => "F",
6 => "F#",
7 => "G",
8 => "G#",
9 => "A",
10 => "A#",
11 => "B",
_ => "?",
}
}
println!("Bassline pattern (now actually programmed into the sequencer):");
for (i, (note, active)) in pattern.iter().enumerate() {
if *active {
let voct = midi_to_voct(*note);
let octave = (note / 12) - 1;
println!(
" Step {}: {}{} ({:.3}V)",
i + 1,
note_name(*note),
octave,
voct
);
} else {
println!(" Step {}: rest", i + 1);
}
}
let step_samples = (sample_rate * 0.5) as usize;
println!("\nRunning one pass through the pattern (4.0s)...\n");
for i in 0..pattern.len() {
let (note, active) = pattern[(i + 1) % pattern.len()];
let mut peak = 0.0_f64;
for _ in 0..step_samples {
let (left, _) = patch.tick();
peak = peak.max(left.abs());
}
let label = if active {
format!("{}{}", note_name(note), (note / 12) as i32 - 1)
} else {
"rest".to_string()
};
let bar = "█".repeat((peak * 2.0) as usize);
println!(
"Step {} ({:>4}): {:5.2}V |{}",
(i + 1) % pattern.len() + 1,
label,
peak,
bar
);
}
println!("\nThe sequencer cycles through the pattern,");
println!("triggering the envelope on each gated step and resting on the others.");
}