1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use envelope;
use pitch;
pub trait Frequency {
fn hz_at_playhead(&self, perc: f64) -> f64;
#[inline]
fn freq_perc_at_playhead(&self, perc: f64) -> f64 {
pitch::Hz(self.hz_at_playhead(perc) as f32).perc()
}
}
pub type Envelope = envelope::Envelope;
#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
pub enum Dynamic {
Envelope(Envelope),
Hz(f64),
}
impl Dynamic {
pub fn is_env(&self) -> bool {
if let Dynamic::Envelope(_) = *self { true } else { false }
}
pub fn to_env(&self) -> Dynamic {
use std::iter::once;
if let Dynamic::Hz(hz) = *self {
let perc = pitch::Hz(hz as f32).perc();
return Dynamic::Envelope({
once(envelope::Point::new(0.0, perc, 0.0))
.chain(once(envelope::Point::new(1.0, perc, 0.0)))
.collect()
})
}
self.clone()
}
pub fn to_hz(&self) -> Dynamic {
if let Dynamic::Envelope(ref env) = *self {
use pitch::{LetterOctave, Letter};
return match env.points.iter().nth(0) {
Some(point) => Dynamic::Hz(pitch::Perc(point.y).hz() as f64),
None => Dynamic::Hz(LetterOctave(Letter::C, 1).hz() as f64),
}
}
self.clone()
}
}
impl Frequency for f64 {
#[inline]
fn hz_at_playhead(&self, _perc: f64) -> f64 { *self }
}
impl Frequency for Envelope {
#[inline]
fn hz_at_playhead(&self, perc: f64) -> f64 {
pitch::Perc(self.freq_perc_at_playhead(perc)).hz() as f64
}
#[inline]
fn freq_perc_at_playhead(&self, perc: f64) -> f64 {
envelope::Trait::y(self, perc)
.expect("The given playhead position is out of range (0.0..1.0).")
}
}
impl Frequency for Dynamic {
#[inline]
fn hz_at_playhead(&self, perc: f64) -> f64 {
match *self {
Dynamic::Envelope(ref env) => env.hz_at_playhead(perc),
Dynamic::Hz(hz) => hz,
}
}
}