play_instrument/
play_instrument.rs1use tono_core::dsl::Adsr;
7use tono_core::instrument::{Instrument, InstrumentDesign, Note};
8use tono_core::patch::Patch;
9use tono_core::runtime::{AudioSource, Mixer};
10
11fn lead() -> Patch {
14 serde_json::from_str(
15 r#"{ "doc": { "name":"lead", "duration":1.0, "engine":2, "root": { "type":"chain", "stages": [
16 { "type":"super", "wave":"sawtooth", "freq":220, "voices":5, "detune_cents":14 },
17 { "type":"lowpass", "cutoff":2400, "q":0.9 } ] } },
18 "params": [ { "name":"pitch", "paths":["root.stages[0].freq"], "min":20, "max":8000, "default":220 } ] }"#,
19 )
20 .expect("valid patch")
21}
22
23fn peak(b: &[f32]) -> f32 {
24 b.iter().fold(0.0f32, |m, &x| m.max(x.abs()))
25}
26
27fn n(name: &str) -> Note {
28 Note::parse(name).unwrap()
29}
30
31fn main() {
32 let sr = 48_000;
33 let design = InstrumentDesign::new(lead()).with_amp(Adsr {
34 a: 0.01,
35 d: 0.15,
36 s: 0.6,
37 r: 0.25,
38 punch: 0.0,
39 });
40 let mut inst = Instrument::new(design, sr).expect("streamable instrument");
41
42 inst.note_on(n("C4"), 0.9);
44 inst.note_on(n("E4"), 0.8);
45 inst.note_on(n("G4"), 0.7);
46 println!("chord: {} voices", inst.active_voices());
47
48 let mut block = vec![0.0f32; 512 * 2];
49 let mut p = 0.0f32;
50 for _ in 0..40 {
51 inst.fill(&mut block);
52 p = p.max(peak(&block));
53 }
54 inst.all_notes_off();
55 for _ in 0..60 {
56 inst.fill(&mut block);
57 }
58 println!(
59 "after release: {} voices (chord peak {p:.3})",
60 inst.active_voices()
61 );
62
63 let mut mixer = Mixer::new(sr);
65 let lead_id = mixer.add(inst);
66 mixer.set_gain(lead_id, 0.8);
67
68 let melody = ["C4", "E4", "G4", "C5", "G4", "E4"];
69 let mut apeak = 0.0f32;
70 for name in melody {
71 let voice = mixer.get_mut::<Instrument>(lead_id).unwrap();
72 voice.note_on(n(name), 0.85);
73 for _ in 0..11 {
75 mixer.fill(&mut block);
76 apeak = apeak.max(peak(&block));
77 }
78 mixer
79 .get_mut::<Instrument>(lead_id)
80 .unwrap()
81 .note_off(n(name));
82 }
83 println!("melody through the mixer: peak {apeak:.3}");
84}