Skip to main content

oscen/
instruments.rs

1use super::{
2    envelopes::Adsr,
3    filters::Lpf,
4    operators::{Delay, Mixer, Product},
5    signal::{mk_tag, ArcMutex, Builder, In, Link, Rack, Real, Signal, Tag, Gate},
6};
7use crate::{as_any_mut, std_signal, gate};
8use std::any::Any;
9
10#[derive(Clone)]
11pub struct WaveGuide {
12    tag: Tag,
13    burst: Tag,
14    hz: In,
15    cutoff_freq: In,
16    wet_decay: In,
17    input: ArcMutex<Link>,
18    gate: ArcMutex<Adsr>,
19    lpf: ArcMutex<Lpf>,
20    delay: ArcMutex<Delay>,
21    mixer: ArcMutex<Mixer>,
22    rack: Rack,
23}
24
25impl WaveGuide {
26    pub fn new(burst: Tag) -> Self {
27        let mut rack = Rack::new(vec![]);
28
29        let input = Link::new().wrap();
30        rack.append(input.clone());
31
32        // Adsr
33        let gate = Adsr::new(0.2, 0.2, 0.2)
34            .attack(0.001)
35            .decay(0)
36            .sustain(0)
37            .release(0.001)
38            .wrap();
39        rack.append(gate.clone());
40
41        // Exciter: gated noise
42        let exciter = Product::new(vec![input.tag(), gate.tag()]).wrap();
43        rack.append(exciter.clone());
44
45        // Feedback loop
46        let mut mixer = Mixer::new(vec![]).build();
47        let delay = Delay::new(mixer.tag(), (0.02).into()).wrap();
48
49        let cutoff_freq = 2000;
50        let lpf = Lpf::new(delay.tag()).cutoff_freq(cutoff_freq).wrap();
51
52        let wet_decay = 0.95;
53        let mixer = mixer
54            .waves(vec![exciter.tag(), lpf.tag()])
55            .levels(vec![1.0, wet_decay])
56            .wrap();
57
58        rack.append(lpf.clone());
59        rack.append(delay.clone());
60        rack.append(mixer.clone());
61
62        WaveGuide {
63            tag: mk_tag(),
64            burst,
65            hz: 440.into(),
66            cutoff_freq: cutoff_freq.into(),
67            wet_decay: wet_decay.into(),
68            input,
69            gate,
70            lpf,
71            delay,
72            mixer,
73            rack,
74        }
75    }
76
77    pub fn hz<T: Into<In>>(&mut self, arg: T) -> &mut Self {
78        self.hz = arg.into();
79        self
80    }
81
82    pub fn on(&mut self) {
83        self.gate.lock().unwrap().on();
84    }
85
86    pub fn off(&mut self) {
87        self.gate.lock().unwrap().off();
88    }
89
90    pub fn attack<T: Into<In>>(&mut self, arg: T) -> &mut Self {
91        self.gate.lock().unwrap().attack(arg);
92        self
93    }
94
95    pub fn decay<T: Into<In>>(&mut self, arg: T) -> &mut Self {
96        self.gate.lock().unwrap().decay(arg);
97        self
98    }
99
100    pub fn sustain<T: Into<In>>(&mut self, arg: T) -> &mut Self {
101        self.gate.lock().unwrap().sustain(arg);
102        self
103    }
104
105    pub fn release<T: Into<In>>(&mut self, arg: T) -> &mut Self {
106        self.gate.lock().unwrap().release(arg);
107        self
108    }
109
110    pub fn cutoff_freq<T: Into<In>>(&mut self, arg: T) -> &mut Self {
111        self.lpf.lock().unwrap().cutoff_freq(arg);
112        self
113    }
114
115    pub fn wet_decay<T: Into<In>>(&mut self, arg: T) -> &mut Self {
116        self.mixer.lock().unwrap().level_nth(1, arg.into());
117        self
118    }
119}
120
121impl Builder for WaveGuide {}
122
123gate!(WaveGuide);
124
125impl Signal for WaveGuide {
126    std_signal!();
127    fn signal(&mut self, rack: &Rack, sample_rate: Real) -> Real {
128        let input = rack.output(self.burst);
129        self.input.lock().unwrap().value(input);
130        let dt = 1.0 / f64::max(1.0, In::val(&rack, self.hz));
131        self.delay.lock().unwrap().delay_time(dt);
132        self.rack.signal(sample_rate)
133    }
134}
135