pointillism/effects/
delay.rs

1//! TODO: missing docs
2
3use crate::prelude::*;
4
5/// Plays a signal back with a delay. Can have some optional feedback. For a dry/wet effect, you can
6/// add this to the original signal in different proportions.
7///
8/// ## Instanciation
9///
10/// The [`Delay`] type is quite generic. It allows for a buffer that might or might not be owned,
11/// and it lets the feedback function be essentially anything. However in most cases, you'll want an
12/// owned buffer, and you'll want one of the following three feedback behaviors, for which we make
13/// type aliases.
14///
15/// - No feedback: [`Pure`].
16/// - Exponential feedback: [`Exp`].
17/// - Exponential feedback + ping-pong: [`Flip`].
18#[derive(Clone, Debug)]
19pub struct Delay<
20    S: Signal<Sample = B::Item>,
21    B: buf::BufferMut,
22    F: Map<Input = B::Item, Output = B::Item>,
23> {
24    /// The played signal.
25    pub sgn: S,
26
27    /// The backing [`gen::LoopBuf`]. This contains the buffer, and an index controlling the current
28    /// position.
29    ///
30    /// The length of the buffer deterimes the length of the delay. Since buffers can only hold an
31    /// integral amount of samples, a delay might not be exact to the frame. This probably isn't a
32    /// problem unless you have a really long delay though.
33    pub loop_gen: gen::LoopBuf<B>,
34
35    /// A function that determines how a sample from the buffer is fed back into itself. This is
36    /// most often used to lower its volume, and flip the channels for a ping-pong effect.
37    ///
38    /// The zero signal should be mapped to zero, or you'll get all sorts of unexpected behavior.
39    pub feedback: F,
40}
41
42impl<S: Signal<Sample = B::Item>, B: buf::BufferMut, F: Map<Input = B::Item, Output = B::Item>>
43    Delay<S, B, F>
44{
45    /// Initializes a new delay.
46    ///    
47    /// To use an empty, owned buffer, see [`Self::new_owned`].
48    pub const fn new(sgn: S, buffer: B, feedback: F) -> Self {
49        Self {
50            sgn,
51            loop_gen: gen::LoopBuf::new(buffer),
52            feedback,
53        }
54    }
55
56    /// Returns a reference to the inner buffer.
57    pub const fn buffer(&self) -> &B {
58        &self.loop_gen.buffer
59    }
60
61    /// Returns a mutable reference to the inner buffer.
62    pub fn buffer_mut(&mut self) -> &mut B {
63        &mut self.loop_gen.buffer
64    }
65
66    /// Clears the inner buffer.
67    pub fn clear(&mut self) {
68        self.buffer_mut().clear();
69    }
70
71    /// Reads the current sample from the signal and advances the buffer position. The signal is not
72    /// advanced.
73    ///
74    /// You can use this if you're advancing the signal manually.
75    pub fn read_sgn(&mut self) {
76        // Computes the new signal.
77        let sgn = self.sgn.get();
78        let buf = self.loop_gen._get();
79        let new_sgn = sgn + self.feedback.eval(buf);
80
81        // Updates the buffer, advances its position.
82        let idx = self.loop_gen.index();
83        self.buffer_mut()[idx] = new_sgn;
84        self.loop_gen.advance();
85    }
86}
87
88impl<S: Signal, F: Map<Input = S::Sample, Output = S::Sample>> Delay<S, buf::Dyn<S::Sample>, F>
89where
90    S::Sample: Audio,
91{
92    /// Initializes a new delay that owns its buffer. The size of the buffer is determined by the
93    /// delay time.
94    pub fn new_owned(sgn: S, delay: unt::Time, feedback: F) -> Self {
95        Self::new(sgn, buf::Dyn::new_time(delay), feedback)
96    }
97}
98
99impl<S: Signal<Sample = B::Item>, B: buf::BufferMut, F: Map<Input = B::Item, Output = B::Item>>
100    Signal for Delay<S, B, F>
101{
102    type Sample = S::Sample;
103
104    fn get(&self) -> Self::Sample {
105        self.loop_gen._get()
106    }
107}
108
109impl<
110        S: SignalMut<Sample = B::Item>,
111        B: buf::BufferMut,
112        F: Map<Input = B::Item, Output = B::Item>,
113    > SignalMut for Delay<S, B, F>
114{
115    fn advance(&mut self) {
116        self.read_sgn();
117        self.sgn.advance();
118    }
119
120    fn retrigger(&mut self) {
121        // Retriggers the signals.
122        self.sgn.retrigger();
123        self.loop_gen.retrigger();
124
125        // Clears the buffer.
126        self.clear();
127    }
128}
129
130impl<
131        S: Frequency<Sample = B::Item>,
132        B: buf::BufferMut,
133        F: Map<Input = B::Item, Output = B::Item>,
134    > Frequency for Delay<S, B, F>
135{
136    fn freq(&self) -> unt::Freq {
137        self.sgn.freq()
138    }
139
140    fn freq_mut(&mut self) -> &mut unt::Freq {
141        self.sgn.freq_mut()
142    }
143}
144
145impl<S: Base<Sample = B::Item>, B: buf::BufferMut, F: Map<Input = B::Item, Output = B::Item>> Base
146    for Delay<S, B, F>
147{
148    type Base = S::Base;
149
150    fn base(&self) -> &S::Base {
151        self.sgn.base()
152    }
153
154    fn base_mut(&mut self) -> &mut S::Base {
155        self.sgn.base_mut()
156    }
157}
158
159impl<S: Stop<Sample = B::Item>, B: buf::BufferMut, F: Map<Input = B::Item, Output = B::Item>> Stop
160    for Delay<S, B, F>
161{
162    fn stop(&mut self) {
163        self.sgn.stop();
164    }
165}
166
167impl<S: Panic<Sample = B::Item>, B: buf::BufferMut, F: Map<Input = B::Item, Output = B::Item>> Panic
168    for Delay<S, B, F>
169{
170    fn panic(&mut self) {
171        self.sgn.panic();
172        self.clear();
173    }
174}
175
176/// A delay that only plays once.
177pub type Pure<S, B> = Delay<S, B, map::Zero<<S as Signal>::Sample, <S as Signal>::Sample>>;
178
179impl<S: Signal<Sample = B::Item>, B: buf::BufferMut> Pure<S, B> {
180    /// Initializes a delay that only plays once.
181    ///
182    /// To use an empty, owned buffer, see [`Self::new_pure_owned`].
183    pub const fn new_pure(sgn: S, buffer: B) -> Self {
184        Self::new(sgn, buffer, map::Zero::new())
185    }
186}
187
188impl<S: Signal> Pure<S, buf::Dyn<S::Sample>>
189where
190    S::Sample: Audio,
191{
192    /// Initializes a delay that only plays once and owns its buffer. The size of the buffer is
193    /// determined by the delay time.
194    pub fn new_pure_owned(sgn: S, delay: unt::Time) -> Self {
195        Self::new_owned(sgn, delay, map::Zero::new())
196    }
197}
198
199/// A delay that feeds back into itself with some gain factor.
200///
201/// This causes the signal to decay exponentially. You can set the volume to `1.0` for an infinite
202/// delay, but other than that, you'll probably want a value exclusively between `0.0` and `1.0`.
203pub type Exp<S, B> = Delay<S, B, map::Pw<<S as Signal>::Sample, unt::Vol>>;
204
205impl<S: Signal<Sample = B::Item>, B: buf::BufferMut> Exp<S, B> {
206    /// Initializes a new [`Exp`].
207    ///
208    /// To use an empty, owned buffer, see [`Self::new_exp_owned`].
209    pub const fn new_exp(sgn: S, buffer: B, vol: unt::Vol) -> Self {
210        Self::new(sgn, buffer, map::Pw::new(vol))
211    }
212
213    /// Returns the feedback volume.
214    pub const fn vol(&self) -> unt::Vol {
215        self.feedback.func
216    }
217
218    /// Returns a mutable reference to the feedback volume.
219    pub fn vol_mut(&mut self) -> &mut unt::Vol {
220        &mut self.feedback.func
221    }
222}
223
224impl<S: Signal> Exp<S, buf::Dyn<S::Sample>>
225where
226    S::Sample: Audio,
227{
228    /// Initializes a delay with exponential decay that owns its buffer. The size of the buffer is
229    /// determined by the delay time.
230    pub fn new_exp_owned(sgn: S, delay: unt::Time, vol: unt::Vol) -> Self {
231        Self::new_owned(sgn, delay, map::Pw::new(vol))
232    }
233}
234
235/// An exponential delay with a ping-pong effect.
236pub type Flip<S, B> = Delay<S, B, map::Comp<map::Pw<smp::Stereo, unt::Vol>, map::Flip>>;
237
238/// Simple auxiliary function.
239const fn comp_flip(vol: unt::Vol) -> map::Comp<map::Pw<smp::Stereo, unt::Vol>, map::Flip> {
240    map::Comp::new(map::Pw::new(vol), map::Flip)
241}
242
243impl<S: Signal<Sample = smp::Stereo>, B: buf::BufferMut<Item = smp::Stereo>> Flip<S, B> {
244    /// Initializes a new [`Flip`].
245    ///
246    /// You can set the volume to `1.0` for an infinite delay, but other than that, you'll probably
247    /// want a value exclusively between `0.0` and `1.0`.
248    pub const fn new_flip(sgn: S, buffer: B, vol: unt::Vol) -> Self {
249        Self::new(sgn, buffer, comp_flip(vol))
250    }
251
252    /// Returns the feedback volume.
253    pub const fn vol(&self) -> unt::Vol {
254        self.feedback.inner.func
255    }
256
257    /// Returns a mutable reference to the feedback volume.
258    pub fn vol_mut(&mut self) -> &mut unt::Vol {
259        &mut self.feedback.inner.func
260    }
261}
262
263impl<S: Signal<Sample = smp::Stereo>> Flip<S, buf::Dyn<S::Sample>> {
264    /// Initializes a ping-pong delay that owns its buffer. The size of the buffer is determined by
265    /// the delay time.
266    pub fn new_flip_owned(sgn: S, delay: unt::Time, vol: unt::Vol) -> Self {
267        Self::new_owned(sgn, delay, comp_flip(vol))
268    }
269}