-
Notifications
You must be signed in to change notification settings - Fork 12
/
Note.py
36 lines (31 loc) · 1.51 KB
/
Note.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
import numpy as np
from conversion import SAMPLES_PER_SECOND
from generators import generate_sine
from ADSR import ADSR
from pitches import FREQUENCY_FOR_NOTE_LABEL
class Note:
# freq of 0 is interpreted as rest
def __init__(self, frequency=880, duration_seconds=0.5, level=0.8, pan=0.5, attack_seconds=0.1, decay_seconds=0.1, sustain_level=0.8, release_seconds=0.01):
self.frequency = FREQUENCY_FOR_NOTE_LABEL[frequency] if frequency in FREQUENCY_FOR_NOTE_LABEL else frequency
if self.frequency == '0': # handle case where numpy changes 0s to '0's
self.frequency = 0
self.level = level
self.pan = pan
self.duration_samples = int(duration_seconds * SAMPLES_PER_SECOND)
if attack_seconds + decay_seconds >= duration_seconds:
remainder = attack_seconds + decay_seconds - duration_seconds
attack_seconds -= remainder / 2
decay_seconds -= remainder / 2
self.set_adsr(ADSR(attack_seconds, decay_seconds, sustain_level, release_seconds))
def set_adsr(self, adsr):
self.adsr = adsr
self.__update_samples()
def get_samples(self):
return self.samples
def __update_samples(self):
if self.frequency == 0:
self.samples = np.zeros(self.duration_samples + self.adsr.release_samples)
else:
self.samples = generate_sine(self.frequency, self.duration_samples + self.adsr.release_samples)
self.adsr.apply(self.samples)
self.samples *= self.level