Something went wrong. Try again.
YAML-based live configuration of MicroFreak datyoma.tngl.io/mfctl
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778use super::value::Percent;use super::value::time_control;use mfctl_derive::author;
#[author]#[serde(default, rename_all = "camelCase", deny_unknown_fields)]pub struct Envelope { #[garde(skip)] /// true lets the main envelope shape loudness; false switches sound on and off with the gate. pub amp_mod: bool, /// Time for the main envelope to reach its peak, in milliseconds. pub attack_ms: AttackMs, /// Decay and release time, in milliseconds. pub decay_release_ms: DecayReleaseMs, /// Main envelope sustain level (0–100%). pub sustain: Percent, #[garde(skip)] /// true prevents envelope retriggering when notes overlap. pub legato: bool, #[garde(skip)] /// true sharpens the envelope's decay. pub snap: bool,}
impl Default for Envelope { fn default() -> Self { Self { amp_mod: true, attack_ms: AttackMs(0), decay_release_ms: DecayReleaseMs(1663), sustain: Percent(100.0), legato: false, snap: false, } }}
time_control!( AttackMs, 10000, [0, 25, 75, 200, 470, 940, 1830, 3100, 5700, 10000]);
time_control!( DecayReleaseMs, 25000, [0, 900, 1400, 2200, 3200, 4900, 6800, 10200, 15400, 25000]);
#[cfg(test)]mod tests { use super::*; use crate::parameter::{RegisterCodec, StoredValue}; use crate::patch::value::tests::check_time_control;
#[test] fn attack_follows_firmware_knots() { check_time_control!( AttackMs, [0, 25, 75, 200, 470, 940, 1830, 3100, 5700, 10000] ); }
#[test] fn decay_release_follows_firmware_knots() { check_time_control!( DecayReleaseMs, [0, 900, 1400, 2200, 3200, 4900, 6800, 10200, 15400, 25000] ); }
#[test] fn attack_interpolates_between_knots() { assert_eq!(AttackMs(50).encode(), StoredValue(5460)); assert_eq!(AttackMs::decode(StoredValue(5460)).unwrap(), AttackMs(50)); }}