-
Notifications
You must be signed in to change notification settings - Fork 1
/
adsr.py
47 lines (42 loc) · 1.85 KB
/
adsr.py
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
class ADSR(object):
def __init__(self, attack_ms, decay_ms, sustain_level, release_ms, samples_per_second):
self.attack_ms = attack_ms
self.decay_ms = decay_ms
self.sustain_level = sustain_level
self.release_ms = release_ms
self.samples_per_second = samples_per_second
self.samples_per_ms = samples_per_second / 1000.0
self.attack_samples = int(round(attack_ms * self.samples_per_ms))
self.decay_samples = int(round(decay_ms * self.samples_per_ms))
self.release_samples = int(round(release_ms * self.samples_per_ms))
def envelope(self, total_ms):
sustain_ms = max(0, total_ms - self.attack_ms - self.decay_ms - self.release_ms)
for level in self.attack_levels():
yield level
for level in self.decay_levels():
yield level
for level in self.sustain_levels(sustain_ms):
yield level
for level in self.release_levels():
yield level
def attack_levels(self):
add_incr = 1.0 / self.attack_samples
current_level = 0
for level in xrange(self.attack_samples):
current_level += add_incr
yield current_level
def decay_levels(self):
sub_incr = (1.0 - self.sustain_level) / self.decay_samples
current_level = 1.0
for level in xrange(self.decay_samples):
current_level -= sub_incr
yield current_level
def sustain_levels(self, sustain_ms):
for level in xrange(int(round(self.samples_per_ms * sustain_ms))):
yield self.sustain_level
def release_levels(self):
sub_incr = self.sustain_level / self.release_samples
current_level = self.sustain_level
for level in xrange(self.release_samples):
current_level -= sub_incr
yield current_level