summaryrefslogtreecommitdiff
path: root/klangfarbrs/src/adsr.rs
diff options
context:
space:
mode:
authorGrant Shangreaux <grant@unabridgedsoftware.com>2021-11-11 10:20:59 -0600
committerGrant Shangreaux <grant@unabridgedsoftware.com>2021-11-11 10:20:59 -0600
commita17829f5412ee0757574b34e34ce78b2975df1fe (patch)
treefb7e09aa7ee101bf48c824634f1e79428c0529ed /klangfarbrs/src/adsr.rs
parent2b22b39b08c499798efcb874db6e6268eef43a52 (diff)
Add: poorly implemented but working amplitude envelope
Diffstat (limited to 'klangfarbrs/src/adsr.rs')
-rw-r--r--klangfarbrs/src/adsr.rs54
1 files changed, 44 insertions, 10 deletions
diff --git a/klangfarbrs/src/adsr.rs b/klangfarbrs/src/adsr.rs
index 682cc8a..9d51ba3 100644
--- a/klangfarbrs/src/adsr.rs
+++ b/klangfarbrs/src/adsr.rs
@@ -1,16 +1,18 @@
-use crate::{Millisecond, Amplitude};
+use super::{Millisecond, Amplitude, SamplesPerSecond};
pub struct Envelope {
- attack: Vec<Amplitude>,
- decay: Vec<Amplitude>,
- release: Vec<Amplitude>,
+ pub attack: Vec<Amplitude>,
+ pub decay: Vec<Amplitude>,
+ pub release: Vec<Amplitude>,
}
impl Envelope {
- pub fn new(attack: Millisecond, decay: Millisecond, sustain: Amplitude, release: Millisecond) -> Self {
- let attack = vec![sustain; attack as usize];
- let decay = vec![sustain; decay as usize];
- let release = vec![sustain; release as usize];
+ pub fn new(
+ attack: Millisecond, decay: Millisecond, sustain: Amplitude, release: Millisecond, sample_rate: SamplesPerSecond
+ ) -> Self {
+ let attack = interpolate(0.0, 1.0, ms_to_samples(attack, sample_rate));
+ let decay = interpolate(1.0, sustain, ms_to_samples(decay, sample_rate));
+ let release = interpolate(sustain, 0.0, ms_to_samples(release, sample_rate));
Self{attack, decay, release}
}
@@ -20,13 +22,45 @@ impl Envelope {
}
}
+fn interpolate(start: Amplitude, end: Amplitude, milliseconds: Millisecond) -> Vec<Amplitude> {
+ let step_size = (end - start) / milliseconds as f32;
+ let mut amps = vec!();
+ let mut current_val = start + step_size;
+
+ for i in 0..=milliseconds {
+ if i == 0 {
+ amps.push(start)
+ } else if i == milliseconds {
+ amps.push(end)
+ } else {
+ amps.push(current_val);
+ current_val += step_size;
+ }
+ }
+
+ amps
+}
+
+fn ms_to_samples(ms: Millisecond, sample_rate: SamplesPerSecond) -> u32 {
+ let multiplier = sample_rate as u32 / 1000;
+ multiplier * ms
+}
+
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_has_expected_total_length() {
- let total = Envelope::new(10, 10, 1.0, 10).len();
- assert_eq! (30, total)
+ let expected = 3 + ms_to_samples(30, 48000.0) as usize;
+ let total = Envelope::new(10, 10, 1.0, 10, 48000.0).len();
+ assert_eq! (expected, total)
+ }
+
+ #[test]
+ fn interpolate_works() {
+ let expected = vec![0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
+ let result = interpolate(0.0, 1.0, 5);
+ assert_eq!(expected, result)
}
}