-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtune.py
executable file
·128 lines (97 loc) · 2.92 KB
/
tune.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
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/python3
import enum
import os
import time
import repeat_mode as rm
class PitchLabel(enum.Enum):
DO = "DO"
RE = "RE"
MI = "MI"
FA = "FA"
SOL = "SOL"
LA = "LA"
SI = "SI"
class PitchAccidental(enum.Enum):
NATURAL = ""
SHARP = "#"
FLAT = "b"
PitchLabelDict = {
"A" : PitchLabel.LA,
"B" : PitchLabel.SI,
"C" : PitchLabel.DO,
"D" : PitchLabel.RE,
"E" : PitchLabel.MI,
"F" : PitchLabel.FA,
"G" : PitchLabel.SOL,
"DO" : PitchLabel.DO,
"RE" : PitchLabel.RE,
"MI" : PitchLabel.MI,
"FA" : PitchLabel.FA,
"SOL" : PitchLabel.SOL,
"LA" : PitchLabel.LA,
"SI" : PitchLabel.SI,
}
#Intervals to LA3
interval_dict = {
PitchLabel.DO : -9,
PitchLabel.RE : -7,
PitchLabel.MI : -5,
PitchLabel.FA : -4,
PitchLabel.SOL : -2,
PitchLabel.LA : 0,
PitchLabel.SI : 2
}
class AbstractTune():
def play(self, tempo=1):
raise NotImplementedError()
class Pattern(AbstractTune):
def __init__(self, tunes=None, repeat_mode=None):
if tunes is None:
tunes = []
self.tunes = tunes
if repeat_mode is None:
self.repeat_mode = rm.SimpleRepeatMode()
def add_tune(self, tune):
self.tunes.append(tune)
def set_repeat_mode(self, repeat_mode):
self.repeat_mode = repeat_mode
def play(self, tempo=1):
for _ in range(self.repeat_mode.get_repeat_number()):
for tune in self.tunes:
tune.play(tempo=tempo)
class Pitch():
def __init__(self, pitch_label, octave, pitch_accidental=PitchAccidental.NATURAL):
self.pitch_label = pitch_label
self.octave = octave
self.pitch_accidental = pitch_accidental
self.freq = self._compute_freq()
SEMITONE_FREQ = 1.05946
LA3_FREQ = 440
def _compute_freq(self):
accidenter = 0
if self.pitch_accidental == PitchAccidental.SHARP:
accidenter = 1
if self.pitch_accidental == PitchAccidental.FLAT:
accidenter = -1
accidented_octave = self.octave-3
la3_interval = accidented_octave*12 + interval_dict[self.pitch_label] + accidenter
return Pitch.LA3_FREQ * (Pitch.SEMITONE_FREQ**la3_interval)
def get_freq(self):
return self.freq
def __str__(self):
return self.pitch_label.value + self.pitch_accidental.value + str(self.octave)
class Note(AbstractTune):
def __init__(self, pitch, duration):
self.pitch = pitch
self.duration = duration
def play(self, tempo=1):
os.system("beep -f {} -l {}".format(self.pitch.get_freq(), self.duration*tempo))
def __str__(self):
return str(self.pitch) + " " + str(self.duration)
class Silence(AbstractTune):
def __init__(self, duration):
self.duration = duration
def play(self, tempo=1):
time.sleep(self.duration*tempo)
def __str__(self):
return "s", str(self.duration)