use crate::Signal;
use dasp_envelope as envelope;
pub trait SignalEnvelope: Signal {
fn detect_envelope<D>(
self,
detector: envelope::Detector<Self::Frame, D>,
) -> DetectEnvelope<Self, D>
where
Self: Sized,
D: envelope::Detect<Self::Frame>,
{
DetectEnvelope {
signal: self,
detector: detector,
}
}
}
#[derive(Clone)]
pub struct DetectEnvelope<S, D>
where
S: Signal,
D: envelope::Detect<S::Frame>,
{
signal: S,
detector: envelope::Detector<S::Frame, D>,
}
impl<S, D> DetectEnvelope<S, D>
where
S: Signal,
D: envelope::Detect<S::Frame>,
{
pub fn set_attack_frames(&mut self, frames: f32) {
self.detector.set_attack_frames(frames);
}
pub fn set_release_frames(&mut self, frames: f32) {
self.detector.set_release_frames(frames);
}
pub fn into_parts(self) -> (S, envelope::Detector<S::Frame, D>) {
let DetectEnvelope { signal, detector } = self;
(signal, detector)
}
}
impl<S, D> Signal for DetectEnvelope<S, D>
where
S: Signal,
D: envelope::Detect<S::Frame>,
{
type Frame = D::Output;
fn next(&mut self) -> Self::Frame {
self.detector.next(self.signal.next())
}
fn is_exhausted(&self) -> bool {
self.signal.is_exhausted()
}
}
impl<T> SignalEnvelope for T where T: Signal {}