Select Git revision
__init__.py

rorist authored
__init__.py 6.61 KiB
import bl00mbox
import captouch
import leds
import time
# TODO:
# - custom time between samples
# - remove delay for input detection (reset for instance)
# - light when seq plays
# - multiple channels
# - velocity support
from st3m.application import Application, ApplicationContext
from st3m.input import InputState
from st3m.ui import colours
from ctx import Context
class EndlessSequencer(Application):
def __init__(self, app_ctx: ApplicationContext) -> None:
super().__init__(app_ctx)
self.DEBUG = False
self.is_loading = True
self.loading_text = 'Loading'
self.blm = bl00mbox.Channel("Endless Sequencer")
self.kick = None
self.notes = []
self.samples = []
self.leds_ids = list(range(40))
self.sample_names = [
'kick.wav',
'snare.wav',
'hihat.wav',
'close.wav',
'open.wav',
'crash.wav',
'bark.wav',
'nya.wav',
]
self.sample_names = [
'close.wav' ]
self.current_sample = None
self.current_note = 0
self.startTime = time.ticks_ms()
self.bpm = 120
#self.sample_names = ['kick.wav', 'snare.wav', 'cowbell.wav', 'hihat.wav', 'silence.wav']
#self.app_path = '/flash/sys/apps/seq/'
def draw(self, ctx: Context) -> None:
ctx.rgb(*colours.BLACK)
ctx.rectangle(
-120.0,
-120.0,
240.0,
240.0,
).fill()
ctx.save()
ctx.move_to(0, -10)
ctx.text_baseline = ctx.MIDDLE
ctx.text_align = ctx.CENTER
ctx.rgb(*colours.GO_GREEN)
ctx.font = "Camp Font 1"
ctx.font_size = 30
ctx.text("ENDLESS SEQ")
if self.is_loading:
# Loading UI
ctx.move_to(0, 40)
ctx.rgb(*colours.RED)
ctx.font_size = 20
ctx.text('{} ... {}/{}'.format(self.loading_text,
len(self.samples),
len(self.sample_names)))
else:
# Main UI
ctx.rgb(*colours.WHITE)
# Buttons
ctx.move_to(0, -80)
ctx.font_size = 80
ctx.text("^")
ctx.move_to(0, -80)
ctx.font_size = 18
ctx.text("rec")
ctx.rotate(-0.45)
ctx.move_to(-20, -85)
ctx.font_size = 80
ctx.text("^")
ctx.move_to(-15, -85)
ctx.font_size = 18
ctx.text("reset")
ctx.rotate(0.45)
# CURRENT SAMPLE
if self.current_sample != None and self.current_sample < len(self.sample_names):
ctx.move_to(0, 25)
ctx.rgb(*colours.RED)
ctx.font_size = 20
ctx.text(self.sample_names[self.current_sample])
# BPM
ctx.move_to(0, 60)
ctx.rgb(*colours.WHITE)
ctx.font_size = 24
ctx.text("BPM: {}".format(self.bpm))
ctx.move_to(0, 80)
ctx.font_size = 14
ctx.text("left btn to adjust")
ctx.restore()
def think(self, ins: InputState, delta_ms: int) -> None:
super().think(ins, delta_ms)
# Load samples
if len(self.sample_names) != len(self.samples) and self.is_loading:
next = len(self.samples)
spl = self.sample_names[next]
if self.DEBUG:
print("Loading {}".format(spl))
sample = self.blm.new(bl00mbox.patches.sampler, spl)
sample.signals.output = self.blm.mixer
self.samples.append(sample)
else:
#if self.DEBUG:
# print("Loading finished.")
self.is_loading = False
ct = captouch.read()
# Input command
btn = self.input.buttons.app
if btn.left.repeated or btn.left.pressed:
self.bpm -= 1
if btn.right.repeated or btn.right.pressed:
self.bpm += 1
if ct.petals[9].pressed: #reset
if self.DEBUG:
print("CLEAR SEQ")
self.notes = []
if ct.petals[0].pressed: #record
if self.DEBUG:
print("REC SEQ")
# Get sequence
for i in range(1, 9):
sample_id = i-1
if ct.petals[i].pressed and sample_id < len(self.sample_names):
if self.DEBUG:
print(' seq {}'.format(self.sample_names[sample_id]))
self.notes.append(sample_id)
self.play_sample(sample_id)
time.sleep(0.2)
# Light petal
for i in range(10):
led_id = i*4
if ct.petals[i].pressed:
leds.set_all_rgb(0, 0, 0)
if i == 0: range_from = self.leds_ids[led_id-3:]
else: range_from = self.leds_ids[led_id-3:led_id]
leds_range = range_from+self.leds_ids[led_id:led_id+4]
if self.DEBUG:
print("light petal {}".format(i))
print(" light leds {}".format(leds_range))
for led in leds_range:
# Action boutons
if i not in [0, 9]:
leds.set_rgb(led, 0, 200, 0)
else:
leds.set_rgb(led, 200, 0, 0)
leds.update()
# Play sequence if nothing is pressed
if len(self.notes) > 0 and not ct.petals[0].pressed:
self.play_seq()
def next_bpm(self):
# taken from binarybrain code
beatTime = 60.0 * 1000.0 / self.bpm
curRelTime = time.ticks_diff(time.ticks_ms(), self.startTime)
return curRelTime / beatTime > 1
def play_sample(self, i):
self.current_sample = i
if i < len(self.samples):
if self.DEBUG and i in self.sample_names:
print (self.sample_names[i])
self.samples[i].signals.trigger.start()
def play_seq(self):
if self.DEBUG:
print("PLAY SEQ")
if self.next_bpm():
self.startTime = time.ticks_ms()
if self.current_note == len(self.notes): self.current_note = 0
if self.DEBUG:
print(" play note {}".format(i))
self.play_sample(self.notes[self.current_note])
self.current_note += 1
else:
if self.DEBUG:
print(" wait")
if __name__ == "__main__":
import st3m.run
st3m.run.run_view(EndlessSequencer(ApplicationContext()))