use crate::prelude::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ArStage {
Attack,
Release,
Done,
}
#[derive(Clone, Copy, Debug)]
pub struct Ar {
pub attack: unt::Time,
pub release: unt::Time,
stage: ArStage,
release_vol: unt::Vol,
phase_time: unt::Time,
}
impl Ar {
#[must_use]
pub fn new(attack: unt::Time, release: unt::Time) -> Self {
let mut ar = Self {
attack,
release,
stage: ArStage::Attack,
phase_time: unt::Time::ZERO,
release_vol: unt::Vol::ZERO,
};
ar.set_stage();
ar
}
#[must_use]
pub fn stage(&self) -> ArStage {
self.stage
}
fn set_stage(&mut self) {
if self.stage == ArStage::Attack && self.phase_time >= self.attack {
self.stage = ArStage::Release;
self.release_vol = unt::Vol::FULL;
self.phase_time -= self.attack;
}
if self.stage == ArStage::Release && self.phase_time >= self.release {
self.stage = ArStage::Done;
}
}
}
impl Signal for Ar {
type Sample = smp::Env;
fn get(&self) -> smp::Env {
smp::Env(match self.stage() {
ArStage::Attack => self.phase_time / self.attack,
ArStage::Release => self.release_vol.gain * (1.0 - self.phase_time / self.release),
ArStage::Done => 0.0,
})
}
}
impl SignalMut for Ar {
fn advance(&mut self) {
self.phase_time.advance();
self.set_stage();
}
fn retrigger(&mut self) {
self.stage = ArStage::Attack;
self.phase_time = unt::Time::ZERO;
}
}
impl Done for Ar {
fn is_done(&self) -> bool {
self.stage == ArStage::Done
}
}
impl Stop for Ar {
fn stop(&mut self) {
self.release_vol = unt::Vol::new(self.get().0);
self.phase_time = unt::Time::ZERO;
self.stage = ArStage::Release;
}
}
impl Panic for Ar {
fn panic(&mut self) {
self.stage = ArStage::Done;
}
}
pub type ArEnv<S> = eff::StopTremolo<S, Ar>;
impl<S: SignalMut> ArEnv<S> {
pub fn new_ar(sgn: S, ar: Ar) -> Self {
Self::new(sgn, ar)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AdsrStage {
Attack,
Decay,
Sustain,
Release,
Done,
}
impl From<ArStage> for AdsrStage {
fn from(value: ArStage) -> Self {
match value {
ArStage::Attack => Self::Attack,
ArStage::Release => Self::Release,
ArStage::Done => Self::Done,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct Adsr {
pub attack: unt::Time,
pub decay: unt::Time,
pub sustain: unt::Vol,
pub release: unt::Time,
stage: AdsrStage,
release_vol: unt::Vol,
phase_time: unt::Time,
}
impl Adsr {
#[must_use]
pub fn new(attack: unt::Time, decay: unt::Time, sustain: unt::Vol, release: unt::Time) -> Self {
let mut adsr = Self {
attack,
decay,
sustain,
release,
stage: AdsrStage::Attack,
phase_time: unt::Time::ZERO,
release_vol: unt::Vol::ZERO,
};
adsr.set_stage();
adsr
}
#[must_use]
pub fn stage(&self) -> AdsrStage {
self.stage
}
fn set_stage(&mut self) {
if self.stage == AdsrStage::Attack && self.phase_time >= self.attack {
self.stage = AdsrStage::Decay;
self.phase_time -= self.attack;
}
if self.stage == AdsrStage::Decay && self.phase_time >= self.decay {
self.stage = AdsrStage::Sustain;
self.phase_time -= self.decay;
}
if self.stage == AdsrStage::Release && self.phase_time >= self.release {
self.stage = AdsrStage::Done;
}
}
}
impl Signal for Adsr {
type Sample = smp::Env;
fn get(&self) -> smp::Env {
smp::Env(match self.stage() {
AdsrStage::Attack => self.phase_time / self.attack,
AdsrStage::Decay => 1.0 + (self.sustain.gain - 1.0) * (self.phase_time / self.decay),
AdsrStage::Sustain => self.sustain.gain,
AdsrStage::Release => self.release_vol.gain * (1.0 - self.phase_time / self.release),
AdsrStage::Done => 0.0,
})
}
}
impl SignalMut for Adsr {
fn advance(&mut self) {
self.phase_time.advance();
self.set_stage();
}
fn retrigger(&mut self) {
self.stage = AdsrStage::Attack;
self.phase_time = unt::Time::ZERO;
}
}
impl Done for Adsr {
fn is_done(&self) -> bool {
self.stage == AdsrStage::Done
}
}
impl Stop for Adsr {
fn stop(&mut self) {
self.release_vol = unt::Vol::new(self.get().0);
self.phase_time = unt::Time::ZERO;
self.stage = AdsrStage::Release;
}
}
impl Panic for Adsr {
fn panic(&mut self) {
self.stage = AdsrStage::Done;
}
}
pub type AdsrEnv<S> = eff::StopTremolo<S, Adsr>;
impl<S: SignalMut> AdsrEnv<S> {
pub fn new_adsr(sgn: S, adsr: Adsr) -> Self {
Self::new(sgn, adsr)
}
}