Skip to content

Commit 60131cc

Browse files
committed
update to v0.8
1 parent da92a9a commit 60131cc

File tree

8 files changed

+912
-258
lines changed

8 files changed

+912
-258
lines changed

ports/esp32/boards/MICROHYDRA/launcher/launcher.py

Lines changed: 103 additions & 195 deletions
Large diffs are not rendered by default.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
"""
2+
/*
3+
* ----------------------------------------------------------------------------
4+
* "THE BEER-WARE LICENSE" (Revision 42 modified):
5+
* <[email protected]> wrote this file. As long as you retain this notice and
6+
* my credit somewhere you can do whatever you want with this stuff. If we
7+
* meet some day, and you think this stuff is worth it, you can buy me a beer
8+
* in return.
9+
* ----------------------------------------------------------------------------
10+
*/
11+
"""
12+
13+
from machine import Pin, I2S
14+
import time
15+
16+
_PERIODS = ( # c0 thru a0 - how much to advance a sample pointer per frame for each note
17+
b'\x01\x00\x00\x00\x00\x00\x00\x00',
18+
b'\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00',
19+
b'\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00',
20+
b'\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00',
21+
b'\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00',
22+
b'\x01\x00\x00\x00\x00\x00',
23+
b'\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00',
24+
b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00',
25+
b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00',
26+
b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00',
27+
b'\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00',
28+
b'\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00'
29+
)
30+
31+
_MIN_VOLUME = const(0)
32+
_MAX_VOLUME = const(15)
33+
@micropython.native
34+
def _volume(volume):
35+
return 15 - (0 if volume < 0 else 15 if volume > 15 else volume)
36+
37+
@micropython.viper
38+
def _vipmod(a:uint, b:uint) -> uint:
39+
while a >= b:
40+
a -= b
41+
return a
42+
43+
class Register:
44+
def __init__(self, buf_start=0, sample=None, sample_len=0, pointer=0, note=0, period=1, period_mult=4, loop=False, volume=0):
45+
self.buf_start = buf_start
46+
self.sample = sample
47+
self.pointer = pointer
48+
self.period = period
49+
self.note = note
50+
self.period_mult = period_mult
51+
self.sample_len = sample_len
52+
self.loop = loop
53+
self.volume = volume
54+
55+
def copy(self):
56+
registers = Register()
57+
registers.buf_start = self.buf_start
58+
registers.sample = self.sample
59+
registers.pointer = self.pointer
60+
registers.period = self.period
61+
registers.note = self.note
62+
registers.period_mult = self.period_mult
63+
registers.sample_len = self.sample_len
64+
registers.loop = self.loop
65+
registers.volume = self.volume
66+
return registers
67+
68+
def __str__(self):
69+
return f"{self.buf_start}: {self.sample} v:{self.volume} n:{self.note}"
70+
71+
class M5Sound:
72+
def __init__(self, buf_size=2048, rate=11025, channels=4, sck=41, ws=43, sd=42):
73+
self._output = I2S(
74+
1,
75+
sck=Pin(sck),
76+
ws=Pin(ws),
77+
sd=Pin(sd),
78+
mode=I2S.TX,
79+
bits=16,
80+
format=I2S.STEREO,
81+
rate=rate,
82+
ibuf=buf_size
83+
)
84+
85+
self._rate = rate
86+
self._buf_size:int = buf_size
87+
self._buffer = bytearray(buf_size*2) # twice for stereo
88+
self.channels = channels
89+
self._registers = [Register() for _ in range(channels)]
90+
self._queues = [[] for _ in range(channels)]
91+
self._last_tick = 0
92+
self._output.irq(self._process_buffer)
93+
self._process_buffer(None)
94+
95+
def __del__(self):
96+
self._output.deinit()
97+
98+
# @micropython.native
99+
def _gen_buf_start(self):
100+
return int((time.ticks_diff(time.ticks_us(), self._last_tick) // (1000000 / self._rate)) * 2) # stereo
101+
102+
# @micropython.native
103+
def play(self, sample, note=0, octave=4, volume=15, channel=0, loop=False):
104+
registers = Register(
105+
buf_start = self._gen_buf_start(),
106+
sample = sample,
107+
sample_len = len(sample) // 2,
108+
loop = loop,
109+
note = note % 12,
110+
period_mult = 2 ** (octave + (note // 12)),
111+
volume = volume
112+
)
113+
self._queues[channel].append(registers)
114+
115+
# @micropython.native
116+
def stop(self, channel=0):
117+
registers = Register() # default has empty sample
118+
registers.buf_start = self._gen_buf_start()
119+
self._queues[channel].append(registers)
120+
121+
# @micropython.native
122+
def setvolume(self, volume, channel=0):
123+
if len(self._queues[channel]) > 0:
124+
registers = self._queues[channel][-1].copy()
125+
else:
126+
registers = self._registers[channel].copy()
127+
registers.buf_start = self._gen_buf_start()
128+
registers.volume = volume
129+
self._queues[channel].append(registers)
130+
131+
@micropython.viper
132+
def _clear_buffer(self):
133+
buf = ptr16(self._buffer)
134+
for i in range(0, int(self._buf_size)):
135+
buf[i] = 0
136+
137+
@micropython.viper
138+
def _fill_buffer(self, registers, end:int) -> bool:
139+
buf = ptr16(self._buffer)
140+
start = 1 + int(registers.buf_start)
141+
smp = ptr16(registers.sample)
142+
slen = uint(registers.sample_len)
143+
ptr = uint(registers.pointer)
144+
per = ptr8(_PERIODS[registers.note])
145+
perlen = uint(len(_PERIODS[registers.note]))
146+
perptr = uint(registers.period)
147+
permult = int(registers.period_mult)
148+
vol = uint(_volume(registers.volume))
149+
loop = bool(registers.loop)
150+
for i in range(start, end, 2): # odd word: right channel only
151+
if ptr >= slen: # sample ended
152+
if not loop: # stop playing
153+
return False
154+
ptr = uint(_vipmod(ptr, slen)) # or loop
155+
bsmp = smp[ptr]
156+
# ladies and gentlemen, the two's complement
157+
bsmp = (bsmp & 0b1000000000000000) | ((bsmp & 0b0111111111111111) >> vol)
158+
if (bsmp & 0b1000000000000000) != 0:
159+
bsmp |= (0b111111111111111 << 15-vol)
160+
buf[i] += bsmp
161+
for _ in range(permult): # add together frame periods for different octaves
162+
ptr += per[perptr]
163+
perptr += uint(1)
164+
if perptr >= perlen:
165+
perptr = uint(0)
166+
registers.buf_start = 0
167+
registers.pointer = ptr
168+
registers.period = perptr
169+
return True
170+
171+
# @micropython.native
172+
def _process_buffer(self, arg):
173+
self._last_tick = time.ticks_us()
174+
self._output.write(self._buffer)
175+
self._clear_buffer()
176+
177+
for ch in range(0, int(self.channels)):
178+
playing = True
179+
while playing:
180+
registers = self._registers[ch]
181+
182+
end = self._buf_size
183+
if len(self._queues[ch]) > 0:
184+
if self._queues[ch][0].buf_start >= self._buf_size:
185+
self._queues[ch][0].buf_start -= self._buf_size
186+
else:
187+
end = self._queues[ch][0].buf_start
188+
self._registers[ch] = self._queues[ch].pop(0)
189+
else:
190+
playing = False
191+
192+
if registers.sample:
193+
if not self._fill_buffer(registers, end):
194+
registers.sample = None
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import machine
2+
3+
4+
5+
# CONSTANTS:
6+
# vbat has a voltage divider of 1/2
7+
_MIN_VALUE = const(1575000) # 3.15v
8+
_MAX_VALUE = const(2100000) # 4.2v
9+
10+
_LOW_THRESH = const(_MIN_VALUE + ((_MAX_VALUE - _MIN_VALUE) // 3))
11+
_HIGH_THRESH = const(_LOW_THRESH + ((_MAX_VALUE - _MIN_VALUE) // 3))
12+
13+
14+
15+
# CLASS Battery:
16+
class Battery:
17+
def __init__(self):
18+
#init the ADC for the battery
19+
self.adc = machine.ADC(10)
20+
self.adc.atten(machine.ADC.ATTN_11DB) # needed to get apropriate range
21+
22+
def read_pct(self):
23+
"""
24+
Return an approximate battery level as a percentage
25+
"""
26+
raw_value = self.adc.read_uv()
27+
28+
if raw_value <= _MIN_VALUE:
29+
return 0
30+
elif raw_value >= _MAX_VALUE:
31+
return 100
32+
33+
delta_value = raw_value - _MIN_VALUE # shift range down
34+
delta_max = _MAX_VALUE - _MIN_VALUE # shift range down
35+
pct_value = int((delta_value / delta_max) * 100)
36+
return (pct_value)
37+
38+
def read_level(self):
39+
"""
40+
Read approx battery level on the adc and return as int range 0 (low) to 3 (high)
41+
This is reccomended, as the readings are not very accurate,
42+
and a percentage could therefore be misleading.
43+
"""
44+
raw_value = self.adc.read_uv()
45+
if raw_value < _MIN_VALUE:
46+
return 0
47+
if raw_value < _LOW_THRESH:
48+
return 1
49+
if raw_value < _HIGH_THRESH:
50+
return 2
51+
return 3
52+
53+
if __name__ == "__main__":
54+
from lib import st7789fbuf, keyboard
55+
from lib import microhydra as mh
56+
from launcher.icons import battery
57+
import time
58+
from font import vga2_16x32 as font
59+
from machine import SPI, Pin, PWM, reset, ADC
60+
61+
tft = st7789fbuf.ST7789(
62+
SPI(1, baudrate=40000000, sck=Pin(36), mosi=Pin(35), miso=None),
63+
135,
64+
240,
65+
reset=Pin(33, Pin.OUT),
66+
cs=Pin(37, Pin.OUT),
67+
dc=Pin(34, Pin.OUT),
68+
backlight=Pin(38, Pin.OUT),
69+
rotation=1,
70+
color_order=st7789fbuf.BGR
71+
)
72+
batt = Battery()
73+
74+
while True:
75+
time.sleep(1)
76+
tft.fill(0)
77+
tft.bitmap_text(font, f"Batt level: {batt.read_level()}", 10,10, 65535)
78+
tft.bitmap_text(font, f"pct: {batt.read_pct()}%", 10,50, 65535)
79+
tft.show()
80+

ports/esp32/boards/MICROHYDRA/lib/beeper.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
from machine import I2S, Pin
22
import math
33

4-
fast_sin_len = const(320)
5-
fast_sin_hz = const(25)
6-
SCK_PIN = const(41)
7-
WS_PIN = const(43)
8-
SD_PIN = const(42)
9-
I2S_ID = const(1)
10-
BUFFER_LENGTH_IN_BYTES = const(2100)
11-
SAMPLE_SIZE_IN_BITS = const(16)
12-
FORMAT = I2S.STEREO
13-
SAMPLE_RATE_IN_HZ = const(16000)
4+
_SCK_PIN = const(41)
5+
_WS_PIN = const(43)
6+
_SD_PIN = const(42)
7+
_I2S_ID = const(1)
8+
_BUFFER_LENGTH_IN_BYTES = const(2048)
9+
_SAMPLE_SIZE_IN_BITS = const(16)
10+
_FORMAT = I2S.STEREO
11+
_SAMPLE_RATE_IN_HZ = const(16000)
1412

1513
volume_map = {0:1,1:4,2:10,3:16,4:20,5:28,6:36,7:50,8:60,9:80,10:127}
1614
tone_map = {
@@ -56,15 +54,15 @@ class Beeper:
5654
def __init__(self, buf_size=4000):
5755

5856
self._output = I2S(
59-
I2S_ID,
60-
sck=Pin(SCK_PIN),
61-
ws=Pin(WS_PIN),
62-
sd=Pin(SD_PIN),
57+
_I2S_ID,
58+
sck=Pin(_SCK_PIN),
59+
ws=Pin(_WS_PIN),
60+
sd=Pin(_SD_PIN),
6361
mode=I2S.TX,
64-
bits=SAMPLE_SIZE_IN_BITS,
65-
format=FORMAT,
66-
rate=SAMPLE_RATE_IN_HZ,
67-
ibuf=BUFFER_LENGTH_IN_BYTES)
62+
bits=_SAMPLE_SIZE_IN_BITS,
63+
format=_FORMAT,
64+
rate=_SAMPLE_RATE_IN_HZ,
65+
ibuf=_BUFFER_LENGTH_IN_BYTES)
6866

6967
self._current_notes = []
7068

0 commit comments

Comments
 (0)