Skip to content
Snippets Groups Projects
Select Git revision
  • ea20912cf51b079bf9c20026d2fef61c92168051
  • master default protected
2 results

__init__.py

Blame
  • rorist's avatar
    rorist authored
    ea20912c
    History
    __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()))