diff --git a/components/bl00mbox/plugins/sequencer.c b/components/bl00mbox/plugins/sequencer.c index 0d13d377acf206de274d2c4db97a4d7411d4adb1..6bdaefb2aadabd7215b3699571957ea5ca317cbf 100644 --- a/components/bl00mbox/plugins/sequencer.c +++ b/components/bl00mbox/plugins/sequencer.c @@ -18,6 +18,7 @@ radspa_descriptor_t sequencer_desc = { #define SEQUENCER_OUTPUT 6 static uint64_t target(uint64_t step_len, uint64_t bpm, uint64_t beat_div){ + if(bpm == 0) return 0; return (48000ULL * 60 * 4) / (bpm * beat_div); } @@ -95,43 +96,43 @@ void sequencer_run(radspa_t * sequencer, uint16_t num_samples, uint32_t render_p data->bpm_prev = bpm; data->beat_div_prev = beat_div; } - - for(uint16_t i = 0; i < num_samples; i++){ + if(data->counter_target){ + for(uint16_t i = 0; i < num_samples; i++){ + data->counter++; + if(data->counter >= data->counter_target){ + data->counter = 0; + data->step++; + if(data->step >= data->step_target){ + data->step = 0; + data->sync_out = -data->sync_out; + } + } - data->counter++; - if(data->counter >= data->counter_target){ - data->counter = 0; - data->step++; - if(data->step >= data->step_target){ + int16_t sync_in = sync_in_sig->get_value(sync_in_sig, i, num_samples, render_pass_id); + if(((sync_in > 0) && (data->sync_in_prev <= 0)) || ((sync_in > 0) && (data->sync_in_prev <= 0))){ + data->counter = 0; data->step = 0; data->sync_out = -data->sync_out; } - } - - int16_t sync_in = sync_in_sig->get_value(sync_in_sig, i, num_samples, render_pass_id); - if(((sync_in > 0) && (data->sync_in_prev <= 0)) || ((sync_in > 0) && (data->sync_in_prev <= 0))){ - data->counter = 0; - data->step = 0; - data->sync_out = -data->sync_out; - } - data->sync_in_prev = sync_in; - - if(!data->counter){ //event just happened - for(uint8_t track = 0; track < data->num_tracks; track++){ - int16_t type = table[track*data->track_step_len]; - int16_t stage_val = table[data->step + 1 + data->track_step_len * track]; - if(type == 32767){ - data->track_fill[track] = stage_val; - } else if(type == -32767){ - if(stage_val > 0) data->track_fill[track] = radspa_trigger_start(stage_val, &(data->trigger_hist[track])); - if(stage_val < 0) data->track_fill[track] = radspa_trigger_stop(&(data->trigger_hist[track])); + data->sync_in_prev = sync_in; + + if(!data->counter){ //event just happened + for(uint8_t track = 0; track < data->num_tracks; track++){ + int16_t type = table[track*data->track_step_len]; + int16_t stage_val = table[data->step + 1 + data->track_step_len * track]; + if(type == 32767){ + data->track_fill[track] = stage_val; + } else if(type == -32767){ + if(stage_val > 0) data->track_fill[track] = radspa_trigger_start(stage_val, &(data->trigger_hist[track])); + if(stage_val < 0) data->track_fill[track] = radspa_trigger_stop(&(data->trigger_hist[track])); + } } } + + if(output_sig->buffer != NULL) (output_sig->buffer)[i] = data->track_fill[0]; + if(sync_out_sig->buffer != NULL) (sync_out_sig->buffer)[i] = data->sync_out; + if(step_sig->buffer != NULL) (step_sig->buffer)[i] = data->step; } - - if(output_sig->buffer != NULL) (output_sig->buffer)[i] = data->track_fill[0]; - if(sync_out_sig->buffer != NULL) (sync_out_sig->buffer)[i] = data->sync_out; - if(step_sig->buffer != NULL) (step_sig->buffer)[i] = data->step; } sync_out_sig->value = data->sync_out; output_sig->value = data->track_fill[0]; diff --git a/python_payload/apps/simple_drums/__init__.py b/python_payload/apps/simple_drums/__init__.py index c5f7a1ef1d7c8ef76b7975ac7b97a8650b15f64b..96896c2dcbe207e7fc7a27578c10fecb1293e5d6 100644 --- a/python_payload/apps/simple_drums/__init__.py +++ b/python_payload/apps/simple_drums/__init__.py @@ -51,10 +51,15 @@ class SimpleDrums(Application): self.kick.sampler.signals.trigger = self.seq.seqs[0].signals.output self.hat.sampler.signals.trigger = self.seq.seqs[1].signals.output self.snare.sampler.signals.trigger = self.seq.seqs[2].signals.output + self.track_names = ["kick", "hihat", "snare"] self.ct_prev = captouch.read() self.track = 0 self.seq.bpm = 80 self.blm.background_mute_override = True + self.tap_tempo_press_counter = 0 + self.delta_acc = 0 + self.stopped = False + self.bpm = self.seq.bpm def _highlight_petal(self, num: int, r: int, g: int, b: int) -> None: for i in range(5): @@ -81,9 +86,10 @@ class SimpleDrums(Application): 40, int((12 * 4 + groupgap) * (1.5 - i)), 0, - (0.1, 0.1, 0.1), + (0.15, 0.15, 0.15), ) ) + st = self.seq.seqs[0].signals.step.value for track in range(3): rgb = self._track_col(track) @@ -98,6 +104,8 @@ class SimpleDrums(Application): x += groupgap * (1.5 - (i // 4)) x = int(x) dots.append(Dot(size, size, x, y, rgbf)) + if (i == st) and (track == 0): + dots.append(Dot(size / 2, size / 2, x, 24, (1, 1, 1))) dots.append(Dot(1, 40, 0, 0, (0.5, 0.5, 0.5))) dots.append(Dot(1, 40, 4 * 12 + groupgap, 0, (0.5, 0.5, 0.5))) @@ -106,13 +114,51 @@ class SimpleDrums(Application): ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill() for i, dot in enumerate(dots): dot.draw(i, ctx) - return + + ctx.font = ctx.get_font_name(4) + ctx.font_size = 30 + + ctx.move_to(0, 65) + col = [x / 255 for x in self._track_col(self.track)] + ctx.rgb(*col) + ctx.text(self.track_names[self.track]) + + ctx.font_size = 18 + + ctx.move_to(0, 102) + next_track = (self.track + 1) % 3 + col = [x / 255 for x in self._track_col(next_track)] + ctx.rgb(*col) + ctx.text(self.track_names[next_track]) + + ctx.font = ctx.get_font_name(1) + ctx.font_size = 20 + + ctx.move_to(0, -65) + ctx.rgb(255, 255, 255) + ctx.text(str(self.seq.bpm) + " bpm") + + ctx.font_size = 15 + + ctx.move_to(0, -85) + + ctx.rgb(0.6, 0.6, 0.6) + ctx.text("(hold) stop") + + ctx.move_to(0, -100) + ctx.text("tap tempo") + + ctx.move_to(0, 85) + ctx.text("next:") def think(self, ins: InputState, delta_ms: int) -> None: super().think(ins, delta_ms) st = self.seq.seqs[0].signals.step.value - leds.set_all_rgb(0, 0, 0) rgb = self._track_col(self.track) + if st == 0: + leds.set_all_rgb(*[int(x / 4) for x in rgb]) + else: + leds.set_all_rgb(0, 0, 0) self._highlight_petal(4 - (st // 4), *rgb) self._highlight_petal(6 + (st % 4), *rgb) leds.update() @@ -127,5 +173,25 @@ class SimpleDrums(Application): if ct.petals[5].pressed and not (self.ct_prev.petals[5].pressed): self.track = (self.track + 1) % 3 if ct.petals[0].pressed and not (self.ct_prev.petals[0].pressed): - self.track = (self.track + 1) % 3 + if self.stopped: + self.seq.bpm = self.bpm + self.stopped = False + elif self.delta_acc < 3000 and self.delta_acc > 10: + bpm = int(60000 / self.delta_acc) + if bpm > 40 and bpm < 500: + self.seq.bpm = bpm + self.bpm = bpm + self.delta_acc = 0 + + if ct.petals[0].pressed: + if self.tap_tempo_press_counter > 500: + self.seq.bpm = 0 + self.stopped = True + else: + self.tap_tempo_press_counter += delta_ms + else: + self.tap_tempo_press_counter = 0 + + if self.delta_acc < 3000: + self.delta_acc += delta_ms self.ct_prev = ct