-
Notifications
You must be signed in to change notification settings - Fork 0
/
beats.py
executable file
·67 lines (46 loc) · 1.35 KB
/
beats.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
from math import floor
from os import listdir
from pygame import mixer
# Smaller than default buffer size increases timing accuracy
mixer.init(buffer=1024)
bpm = 120 # 2 beats per second
tick = 32 # 32 ticks per second
tick_duration = 1 / tick
beat_duration = 60 / bpm
ticks_per_beat = beat_duration / tick_duration
score = []
position = 0
drums = {fn.rsplit('.', 1)[0]: mixer.Sound('kit/' + fn) for fn in listdir('kit')}
def beat(beats=1):
play('Snr-01', beats)
def play(drum, beats=1):
_score(lambda: drums[drum].play())
_score(lambda: None, floor(ticks_per_beat * beats) - 2)
# Stop the sound to prevent hogging channels
_score(lambda: drums[drum].stop())
def rest(beats=1):
_score(lambda: None, floor(ticks_per_beat * beats))
def together(*parts):
global position
startPos = position
for part in parts:
position = startPos
part()
def repeat(part, count):
for i in range(count):
part()
def _score(action, repeat=1):
global position
if position == len(score):
score.extend([action] * repeat)
position += repeat
elif repeat == 1:
also = score[position]
score[position] = lambda: _together(action, also)
position += 1
else:
_score(action, 1)
_score(action, repeat - 1)
def _together(*fns):
for fn in fns:
fn()