diff --git a/components/bl00mbox/bl00mbox_user.c b/components/bl00mbox/bl00mbox_user.c
index 584b01cb02ce554f849d6639371ec808945a2358..3c31abad16e7f5f277c92d68fb1ea5cd5b8e4524 100644
--- a/components/bl00mbox/bl00mbox_user.c
+++ b/components/bl00mbox/bl00mbox_user.c
@@ -750,10 +750,10 @@ int16_t * bl00mbox_channel_bud_get_table_pointer(uint8_t channel, uint32_t bud_i
     return bud->plugin->plugin_table;
 }
 
-int16_t bl00mbox_channel_bud_get_table_len(uint8_t channel, uint32_t bud_index){
+uint32_t bl00mbox_channel_bud_get_table_len(uint8_t channel, uint32_t bud_index){
     bl00mbox_channel_t * chan = bl00mbox_get_channel(channel);
-    if(chan == NULL) return false;
+    if(chan == NULL) return 0;
     bl00mbox_bud_t * bud = bl00mbox_channel_get_bud_by_index(channel, bud_index);
-    if(bud == NULL) return false;
+    if(bud == NULL) return 0;
     return bud->plugin->plugin_table_len;
 }
diff --git a/components/bl00mbox/include/bl00mbox_user.h b/components/bl00mbox/include/bl00mbox_user.h
index 745d27607c7a449fb5d5eda9d0954d8128c509dc..9239408ff87f6b3541e54ac6855caeef180fe867 100644
--- a/components/bl00mbox/include/bl00mbox_user.h
+++ b/components/bl00mbox/include/bl00mbox_user.h
@@ -52,5 +52,5 @@ uint16_t bl00mbox_channel_get_source_signal(uint8_t channel, uint64_t bud_index,
 
 bool bl00mbox_channel_bud_set_table_value(uint8_t channel, uint32_t bud_index, uint32_t table_index, int16_t value);
 int16_t bl00mbox_channel_bud_get_table_value(uint8_t channel, uint32_t bud_index, uint32_t table_index);
-int16_t bl00mbox_channel_bud_get_table_len(uint8_t channel, uint32_t bud_index);
+uint32_t bl00mbox_channel_bud_get_table_len(uint8_t channel, uint32_t bud_index);
 int16_t * bl00mbox_channel_bud_get_table_pointer(uint8_t channel, uint32_t bud_index);
diff --git a/components/bl00mbox/plugins/sequencer.c b/components/bl00mbox/plugins/sequencer.c
index c137271430281f5430c86c4c32ee020d54df9766..5345e2d96e2b0d1d58b54880066147ecb25d1680 100644
--- a/components/bl00mbox/plugins/sequencer.c
+++ b/components/bl00mbox/plugins/sequencer.c
@@ -11,14 +11,17 @@ radspa_descriptor_t sequencer_desc = {
     .destroy_plugin_instance = radspa_standard_plugin_destroy
 };
 
-#define SEQUENCER_NUM_SIGNALS 6
+#define SEQUENCER_NUM_SIGNALS 7
 #define SEQUENCER_STEP 0
-#define SEQUENCER_STEP_LEN 1
-#define SEQUENCER_SYNC_OUT 2
-#define SEQUENCER_SYNC_IN 3
-#define SEQUENCER_BPM 4
-#define SEQUENCER_BEAT_DIV 5
-#define SEQUENCER_OUTPUT 6
+#define SEQUENCER_SYNC_OUT 1
+#define SEQUENCER_SYNC_IN 2
+#define SEQUENCER_START_STEP 3
+#define SEQUENCER_END_STEP 4
+#define SEQUENCER_BPM 5
+#define SEQUENCER_BEAT_DIV 6
+
+// mpx'd
+#define SEQUENCER_OUTPUT 7
 
 static uint64_t target(uint64_t step_len, uint64_t bpm, uint64_t beat_div){
         if(bpm == 0) return 0;
@@ -37,20 +40,22 @@ void sequencer_run(radspa_t * sequencer, uint16_t num_samples, uint32_t render_p
 
     radspa_signal_t * step_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_STEP);
     if(step_sig->buffer != NULL) output_request = true;
-    radspa_signal_t * step_len_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_STEP_LEN);
     radspa_signal_t * sync_out_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_SYNC_OUT);
     if(sync_out_sig->buffer != NULL) output_request = true;
     if(!output_request) return;
 
     radspa_signal_t * sync_in_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_SYNC_IN);
+    radspa_signal_t * start_step_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_START_STEP);
+    radspa_signal_t * end_step_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_END_STEP);
     radspa_signal_t * bpm_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_BPM);
     radspa_signal_t * beat_div_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_BEAT_DIV);
 
     int16_t * table = sequencer->plugin_table;
 
-    int16_t s1 = radspa_signal_get_value(step_len_sig, 0, num_samples, render_pass_id);
-    int16_t s2 = data->track_step_len;
-    data->step_target = s1 > 0 ? (s1 > s2 ? s2 : s1) : 1;
+    int16_t s1 = radspa_signal_get_value(end_step_sig, 0, num_samples, render_pass_id);
+    int16_t s2 = data->track_step_len - 1;
+    data->step_end = s1 > 0 ? (s1 > s2 ? s2 : s1) : 1;
+    data->step_start = radspa_signal_get_value(start_step_sig, 0, num_samples, render_pass_id);
 
     int16_t bpm = bpm_sig->get_value(bpm_sig, 0, num_samples, render_pass_id);
     int16_t beat_div = beat_div_sig->get_value(beat_div_sig, 0, num_samples, render_pass_id);
@@ -65,8 +70,8 @@ void sequencer_run(radspa_t * sequencer, uint16_t num_samples, uint32_t render_p
             if(data->counter >= data->counter_target){
                 data->counter = 0;
                 data->step++;
-                if(data->step >= data->step_target){
-                    data->step = 0;
+                if(data->step > data->step_end){
+                    data->step = data->step_start;
                     data->sync_out = -data->sync_out;
                 }
             }
@@ -74,7 +79,7 @@ void sequencer_run(radspa_t * sequencer, uint16_t num_samples, uint32_t render_p
             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->step = data->step_start;
                 data->sync_out = -data->sync_out;
             }
             data->sync_in_prev = sync_in;
@@ -131,9 +136,10 @@ radspa_t * sequencer_create(uint32_t init_var){
     data->beat_div_prev = 16;
     data->counter_target = target(data->track_step_len, data->bpm_prev, data->beat_div_prev);
     radspa_signal_set(sequencer, SEQUENCER_STEP, "step", RADSPA_SIGNAL_HINT_OUTPUT, 0);
-    radspa_signal_set(sequencer, SEQUENCER_STEP_LEN, "step_len", RADSPA_SIGNAL_HINT_INPUT, num_pixels);
     radspa_signal_set(sequencer, SEQUENCER_SYNC_OUT, "sync_out", RADSPA_SIGNAL_HINT_OUTPUT, 0);
     radspa_signal_set(sequencer, SEQUENCER_SYNC_IN, "sync_in", RADSPA_SIGNAL_HINT_INPUT | RADSPA_SIGNAL_HINT_TRIGGER, 0);
+    radspa_signal_set(sequencer, SEQUENCER_START_STEP, "step_start", RADSPA_SIGNAL_HINT_INPUT, 0);
+    radspa_signal_set(sequencer, SEQUENCER_END_STEP, "step_end", RADSPA_SIGNAL_HINT_INPUT, num_pixels-1);
     radspa_signal_set(sequencer, SEQUENCER_BPM, "bpm", RADSPA_SIGNAL_HINT_INPUT, data->bpm_prev);
     radspa_signal_set(sequencer, SEQUENCER_BEAT_DIV, "beat_div", RADSPA_SIGNAL_HINT_INPUT, data->beat_div_prev);
     radspa_signal_set_group(sequencer, data->num_tracks, 1, SEQUENCER_OUTPUT, "track",
diff --git a/components/bl00mbox/plugins/sequencer.h b/components/bl00mbox/plugins/sequencer.h
index bed48c15a79788bbb53ff5dc9ce8c24df14ba9ee..57b478896be9da1869c5a18e0f093c4d05e58ca3 100644
--- a/components/bl00mbox/plugins/sequencer.h
+++ b/components/bl00mbox/plugins/sequencer.h
@@ -11,7 +11,8 @@ typedef struct {
 typedef struct {
     uint8_t num_tracks;
     uint16_t track_step_len;
-    uint8_t step_target;
+    uint8_t step_end;
+    uint8_t step_start;
     uint8_t step;
     uint64_t counter;
     uint64_t counter_target;
diff --git a/python_payload/apps/gay_drums/__init__.py b/python_payload/apps/gay_drums/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..9e5b9b08b8804cef09db7cec710f8abbeea53447
--- /dev/null
+++ b/python_payload/apps/gay_drums/__init__.py
@@ -0,0 +1,458 @@
+import bl00mbox
+import captouch
+import leds
+
+from st3m.application import Application, ApplicationContext
+from st3m.input import InputState
+from st3m.goose import Tuple, Iterator, Optional, Callable, List, Any, TYPE_CHECKING
+from ctx import Context
+from st3m.ui.view import View, ViewManager
+
+if TYPE_CHECKING:
+    Number = float | int
+    Color = Tuple[Number, Number, Number]
+    ColorLeds = Tuple[int, int, int]
+    Rendee = Callable[[Context, Any], None]
+else:
+    Number = Color = ColorLeds = Rendee = None
+
+
+class GayDrums(Application):
+    def __init__(self, app_ctx: ApplicationContext) -> None:
+        super().__init__(app_ctx)
+        self.blm = bl00mbox.Channel("gay drums")
+        self.num_samplers = 6
+        self.seq = self.blm.new(bl00mbox.patches.sequencer, num_tracks=8, num_steps=32)
+        self.bar = self.seq.signals.step.value // 16
+        self.set_bar_mode(0)
+
+        self.kick: Optional[bl00mbox.patches._Patch] = None
+        self.hat: Optional[bl00mbox.patches._Patch] = None
+        self.close: Optional[bl00mbox.patches._Patch] = None
+        self.open: Optional[bl00mbox.patches._Patch] = None
+        self.crash: Optional[bl00mbox.patches._Patch] = None
+        self.snare: Optional[bl00mbox.patches._Patch] = None
+
+        self.seq.signals.bpm.value = 80
+
+        self.track_names = ["kick", "hihat", "snare", "crash", "nya", "woof"]
+        self.ct_prev = captouch.read()
+        self.track = 1
+        self.blm.background_mute_override = True
+        self.tap_tempo_press_counter = 0
+        self.track_back_press_counter = 0
+        self.delta_acc = 0
+        self.stopped = False
+        self.track_back = False
+        self.bpm = self.seq.signals.bpm.value
+
+        self.samples_loaded = 0
+        self.samples_total = len(self.track_names)
+        self.loading_text = ""
+        self.init_complete = False
+        self.load_iter = self.iterate_loading()
+        self._render_list_2: List[Tuple[Rendee, Any]] = []
+        self._render_list_1: List[Tuple[Rendee, Any]] = []
+
+        self._group_highlight_on = [False] * 4
+        self._group_highlight_redraw = [False] * 4
+        self._redraw_background = 2
+        self._group_gap = 5
+        self.background_col: Color = (0, 0, 0)
+        self.highlight_col: Color = (0.15, 0.15, 0.15)
+
+    def set_bar_mode(self, mode: int) -> None:
+        # TODO: figure out how to speed up re-render
+        if mode == 0:
+            self.seq.signals.step_start = 0
+            self.seq.signals.step_end = 15
+        if mode == 1:
+            self.seq.signals.step_start = 16
+            self.seq.signals.step_end = 31
+        if mode == 2:
+            self.seq.signals.step_start = 0
+            self.seq.signals.step_end = 31
+
+    def iterate_loading(self) -> Iterator[Tuple[int, str]]:
+        yield 0, "kick.wav"
+        self.nya = self.blm.new(bl00mbox.patches.sampler, "nya.wav")
+        self.nya.signals.output = self.blm.mixer
+        self.nya.signals.trigger = self.seq.plugins.seq.signals.track6
+        self.kick = self.blm.new(bl00mbox.patches.sampler, "kick.wav")
+        self.kick.signals.output = self.blm.mixer
+        self.kick.signals.trigger = self.seq.plugins.seq.signals.track0
+        yield 1, "hihat.wav"
+        self.woof = self.blm.new(bl00mbox.patches.sampler, "bark.wav")
+        self.woof.signals.output = self.blm.mixer
+        self.woof.signals.trigger = self.seq.plugins.seq.signals.track7
+        self.hat = self.blm.new(bl00mbox.patches.sampler, "hihat.wav")
+        self.hat.signals.output = self.blm.mixer
+        self.hat.signals.trigger = self.seq.plugins.seq.signals.track1
+        yield 2, "close.wav"
+        self.close = self.blm.new(bl00mbox.patches.sampler, "close.wav")
+        self.close.signals.output = self.blm.mixer
+        self.close.signals.trigger = self.seq.plugins.seq.signals.track2
+        yield 3, "open.wav"
+        self.open = self.blm.new(bl00mbox.patches.sampler, "open.wav")
+        self.open.signals.output = self.blm.mixer
+        self.open.signals.trigger = self.seq.plugins.seq.signals.track3
+        yield 4, "snare.wav"
+        self.snare = self.blm.new(bl00mbox.patches.sampler, "snare.wav")
+        self.snare.signals.output = self.blm.mixer
+        self.snare.signals.trigger = self.seq.plugins.seq.signals.track4
+        yield 5, "crash.wav"
+        self.crash = self.blm.new(bl00mbox.patches.sampler, "crash.wav")
+        self.crash.signals.output = self.blm.mixer
+        self.crash.signals.trigger = self.seq.plugins.seq.signals.track5
+        yield 6, ""
+
+    def _highlight_petal(self, num: int, r: int, g: int, b: int) -> None:
+        for i in range(5):
+            leds.set_rgb((4 * num - i + 2) % 40, r, g, b)
+
+    def _track_col(self, track: int) -> ColorLeds:
+        rgb = (20, 20, 20)
+        if track == 0:
+            rgb = (120, 0, 137)
+        elif track == 1:
+            rgb = (0, 75, 255)
+        elif track == 2:
+            rgb = (0, 130, 27)
+        elif track == 3:
+            rgb = (255, 239, 0)
+        elif track == 4:
+            rgb = (255, 142, 0)
+        elif track == 5:
+            rgb = (230, 0, 0)
+        return rgb
+
+    def draw_background(self, ctx: Context, data: None) -> None:
+        ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill()
+
+        # group bars
+        bar_len = 10 * (1 + self.num_samplers)
+        bar_pos = 4 * 12 + self._group_gap
+        self.ctx_draw_centered_rect(ctx, 0, 0, 1, bar_len, (0.5, 0.5, 0.5))
+        self.ctx_draw_centered_rect(ctx, bar_pos, 0, 1, bar_len, (0.5, 0.5, 0.5))
+        self.ctx_draw_centered_rect(ctx, -bar_pos, 0, 1, bar_len, (0.5, 0.5, 0.5))
+
+        ctx.font = ctx.get_font_name(1)
+
+        ctx.font_size = 15
+        ctx.rgb(0.6, 0.6, 0.6)
+
+        ctx.move_to(0, -85)
+        ctx.text("(hold) stop")
+
+        ctx.move_to(0, -100)
+        ctx.text("tap tempo")
+
+        self.draw_track_name(ctx, None)
+        self.draw_bpm(ctx, None)
+
+        for track in range(self.num_samplers):
+            for step in range(16):
+                self.draw_track_step_marker(ctx, (track, step))
+
+    def track_get_state(self, track: int, step: int) -> int:
+        sequencer_track = track
+        if track > 1:
+            sequencer_track += 2
+        if track == 1:
+            if self.seq.trigger_state(1, step):
+                return 1
+            elif self.seq.trigger_state(2, step):
+                return 2
+            elif self.seq.trigger_state(3, step):
+                return 3
+            else:
+                return 0
+        else:
+            state = self.seq.trigger_state(sequencer_track, step)
+            if state == 0:
+                return 0
+            elif state == 32767:
+                return 3
+            elif state < 16384:
+                return 1
+            else:
+                return 2
+
+    def track_incr_state(self, track: int, step: int) -> None:
+        sequencer_track = track
+        if track > 1:
+            sequencer_track += 2
+        if track == 1:
+            state = self.track_get_state(track, step)
+            if state == 0:
+                self.seq.trigger_start(1, step)
+                self.seq.trigger_clear(2, step)
+                self.seq.trigger_clear(3, step)
+            if state == 1:
+                self.seq.trigger_clear(1, step)
+                self.seq.trigger_start(2, step)
+                self.seq.trigger_clear(3, step)
+            if state == 2:
+                self.seq.trigger_clear(1, step)
+                self.seq.trigger_clear(2, step)
+                self.seq.trigger_start(3, step)
+            if state == 3:
+                self.seq.trigger_clear(1, step)
+                self.seq.trigger_clear(2, step)
+                self.seq.trigger_clear(3, step)
+        else:
+            state = self.seq.trigger_state(sequencer_track, step)
+            if state == 0:
+                new_state = 16000
+            elif state == 32767:
+                new_state = 0
+            else:
+                new_state = 32767
+            self.seq.trigger_start(sequencer_track, step, new_state)
+
+    def draw_track_step_marker(self, ctx: Context, data: Tuple[int, int]) -> None:
+        track, step = data
+        self._group_gap = 4
+        rgb = self._track_col(track)
+        rgbf = (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
+        y = -int(12 * (track - (self.num_samplers - 1) / 2))
+        trigger_state = self.track_get_state(track, step)
+        size = 2
+        x = 12 * (7.5 - step)
+        x += self._group_gap * (1.5 - (step // 4))
+        x = int(-x)
+        group = step // 4
+        bg = self.background_col
+        if self._group_highlight_on[group]:
+            bg = self.highlight_col
+        if trigger_state == 3:
+            self.ctx_draw_centered_rect(ctx, x, y, 8, 8, rgbf)
+        elif trigger_state == 2:
+            self.ctx_draw_centered_rect(ctx, x, y, 8, 8, bg)
+            self.ctx_draw_centered_rect(ctx, x, y - 2, 8, 4, rgbf)
+        elif trigger_state == 1:
+            self.ctx_draw_centered_rect(ctx, x, y, 8, 8, bg)
+            self.ctx_draw_centered_rect(ctx, x, y + 2, 8, 4, rgbf)
+        elif trigger_state == 0:
+            self.ctx_draw_centered_rect(ctx, x, y, 8, 8, bg)
+            self.ctx_draw_centered_rect(ctx, x, y, 2, 2, rgbf)
+
+    def ctx_draw_centered_rect(
+        self, ctx: Context, posx: int, posy: int, sizex: int, sizey: int, col: Color
+    ) -> None:
+        ctx.rgb(*col)
+        nosx = int(posx - (sizex / 2))
+        nosy = int(posy - (sizey / 2))
+        ctx.rectangle(nosx, nosy, int(sizex), int(sizey)).fill()
+
+    def draw_group_highlight(self, ctx: Context, data: int) -> None:
+        i = data
+        col = self.background_col
+        if self._group_highlight_on[i]:
+            col = self.highlight_col
+        sizex = 48 + self._group_gap - 2
+        sizey = 10 * (1 + self.num_samplers)
+        posx = -int((12 * 4 + 1 + self._group_gap) * (1.5 - i))
+        posy = 0
+        self.ctx_draw_centered_rect(ctx, posx, posy, sizex, sizey, col)
+
+        for x in range(self.num_samplers):
+            for y in range(4):
+                self.draw_track_step_marker(ctx, (x, y + 4 * i))
+
+    def draw_bpm(self, ctx: Context, data: None) -> None:
+        self.ctx_draw_centered_rect(ctx, 0, -65, 200, 22, (0, 0, 0))
+        bpm = self.seq.signals.bpm.value
+        ctx.font = ctx.get_font_name(1)
+        ctx.font_size = 20
+
+        ctx.move_to(0, -65)
+        ctx.rgb(255, 255, 255)
+        ctx.text(str(bpm) + " bpm")
+
+    def draw(self, ctx: Context) -> None:
+        if not self.init_complete:
+            ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill()
+
+            ctx.font = ctx.get_font_name(0)
+            ctx.font_size = 24
+            ctx.move_to(0, -10)
+            ctx.rgb(0.8, 0.8, 0.8)
+            if self.samples_loaded == self.samples_total:
+                ctx.text("Loading complete")
+            else:
+                ctx.text("Loading samples...")
+
+            ctx.font_size = 16
+            ctx.move_to(0, 10)
+            ctx.text(self.loading_text)
+
+            progress = self.samples_loaded / self.samples_total
+            bar_len = 120 / self.samples_total
+            for x in range(self.samples_loaded):
+                rgb = self._track_col(x)
+                rgbf = (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
+                ctx.rgb(*rgbf)
+                ctx.rectangle(x * bar_len - 60, 30, bar_len, 10).fill()
+            return
+
+        for i in range(4):
+            if self._group_highlight_redraw[i]:
+                self._group_highlight_redraw[i] = False
+                self._render_list_1 += [(self.draw_group_highlight, i)]
+
+        for rendee in self._render_list_1:
+            fun, param = rendee
+            fun(ctx, param)
+        for rendee in self._render_list_2:
+            fun, param = rendee
+            fun(ctx, param)
+        self._render_list_2 = self._render_list_1.copy()
+        self._render_list_1 = []
+
+        size = 4
+
+        st = self.seq.signals.step.value
+
+        stepx = -12 * (7.5 - st)
+        stepx -= self._group_gap * (1.5 - (st // 4))
+        stepy = -12 - 5 * self.num_samplers
+
+        trigger_state = self.track_get_state(self.track, st)
+        dotsize = 1
+        if trigger_state:
+            dotsize = 4
+        self.ctx_draw_centered_rect(ctx, 0, stepy, 200, 4, self.background_col)
+        self.ctx_draw_centered_rect(ctx, stepx, stepy, dotsize, dotsize, (1, 1, 1))
+
+    def draw_track_name(self, ctx: Context, data: None) -> None:
+        self.ctx_draw_centered_rect(ctx, 0, 60, 200, 30, self.background_col)
+        ctx.font = ctx.get_font_name(1)
+
+        ctx.font_size = 20
+        ctx.rgb(1, 1, 1)
+
+        ctx.move_to(45, 60)
+        ctx.text(">")
+
+        ctx.move_to(-45, 60)
+        ctx.text(">")
+
+        ctx.font_size = 15
+        ctx.rgb(0.6, 0.6, 0.6)
+        ctx.move_to(-45, 75)
+        ctx.text("(hold)")
+
+        ctx.font_size = 28
+
+        track = self.track
+        ctx.move_to(0, 60)
+        col = [x / 255 for x in self._track_col(track)]
+        ctx.rgb(*col)
+        ctx.text(self.track_names[track])
+
+        ctx.font_size = 15
+
+        track = (track - 1) % self.num_samplers
+        ctx.move_to(75, 60)
+        col = [x / 255 for x in self._track_col(track)]
+        ctx.rgb(*col)
+        ctx.text(self.track_names[track])
+
+        track = (track + 2) % self.num_samplers
+        ctx.move_to(-75, 60)
+        col = [x / 255 for x in self._track_col(track)]
+        ctx.rgb(*col)
+        ctx.text(self.track_names[track])
+
+    def think(self, ins: InputState, delta_ms: int) -> None:
+        super().think(ins, delta_ms)
+
+        if not self.init_complete:
+            try:
+                self.samples_loaded, self.loading_text = next(self.load_iter)
+            except StopIteration:
+                self.init_complete = True
+                self._render_list_1 += [(self.draw_background, None)]
+            return
+
+        st = self.seq.signals.step.value
+        rgb = self._track_col(self.track)
+        leds.set_all_rgb(0, 0, 0)
+        self._highlight_petal(10 - (4 - (st // 4)), *rgb)
+        self._highlight_petal(10 - (6 + (st % 4)), *rgb)
+        leds.update()
+
+        if self.bar != (st // 16):
+            self.bar = st // 16
+            self._group_highlight_redraw = [True] * 4
+
+        ct = captouch.read()
+        for i in range(4):
+            if ct.petals[4 - i].pressed:
+                if not self._group_highlight_on[i]:
+                    self._group_highlight_redraw[i] = True
+                self._group_highlight_on[i] = True
+                for j in range(4):
+                    if ct.petals[6 + j].pressed and not (
+                        self.ct_prev.petals[6 + j].pressed
+                    ):
+                        self.track_incr_state(self.track, self.bar * 16 + i * 4 + j)
+
+                        self._render_list_1 += [
+                            (self.draw_track_step_marker, (self.track, i * 4 + j))
+                        ]
+            else:
+                if self._group_highlight_on[i]:
+                    self._group_highlight_redraw[i] = True
+                self._group_highlight_on[i] = False
+
+        if not ct.petals[5].pressed and (self.ct_prev.petals[5].pressed):
+            if self.track_back:
+                self.track_back = False
+            else:
+                self.track = (self.track - 1) % self.num_samplers
+                self._render_list_1 += [(self.draw_track_name, None)]
+
+        if ct.petals[0].pressed and not (self.ct_prev.petals[0].pressed):
+            if self.stopped:
+                self.seq.signals.bpm = self.bpm
+                self._render_list_1 += [(self.draw_bpm, None)]
+                self.blm.background_mute_override = True
+                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.signals.bpm = bpm
+                    self._render_list_1 += [(self.draw_bpm, None)]
+                    self.bpm = bpm
+            self.delta_acc = 0
+
+        if ct.petals[0].pressed:
+            if self.tap_tempo_press_counter > 500:
+                self.seq.signals.bpm = 0
+                self._render_list_1 += [(self.draw_bpm, None)]
+                self.stopped = True
+                self.blm.background_mute_override = False
+            else:
+                self.tap_tempo_press_counter += delta_ms
+        else:
+            self.tap_tempo_press_counter = 0
+
+        if ct.petals[5].pressed:
+            if (self.track_back_press_counter > 500) and not self.track_back:
+                self.track = (self.track + 1) % self.num_samplers
+                self._render_list_1 += [(self.draw_track_name, None)]
+                self.track_back = True
+            else:
+                self.track_back_press_counter += delta_ms
+        else:
+            self.track_back_press_counter = 0
+
+        if self.delta_acc < 3000:
+            self.delta_acc += delta_ms
+        self.ct_prev = ct
+
+    def on_enter(self, vm: Optional[ViewManager]) -> None:
+        self._render_list_1 += [(self.draw_background, None)]
+        self._render_list_1 += [(self.draw_background, None)]  # nice
diff --git a/python_payload/apps/simple_drums/flow3r.toml b/python_payload/apps/gay_drums/flow3r.toml
similarity index 78%
rename from python_payload/apps/simple_drums/flow3r.toml
rename to python_payload/apps/gay_drums/flow3r.toml
index 6d2308c5ddaa060695b701b3384fac7529c02779..278293587e166f382c7f495c04b1be52af045e98 100644
--- a/python_payload/apps/simple_drums/flow3r.toml
+++ b/python_payload/apps/gay_drums/flow3r.toml
@@ -1,9 +1,9 @@
 [app]
-name = "Simple Drums"
+name = "gay drums"
 menu = "Music"
 
 [entry]
-class = "SimpleDrums"
+class = "GayDrums"
 
 [metadata]
 author = "Flow3r Badge Authors"
diff --git a/python_payload/apps/simple_drums/__init__.py b/python_payload/apps/simple_drums/__init__.py
deleted file mode 100644
index 6ee84938b2286aefb44a52dc744698980fcfb64d..0000000000000000000000000000000000000000
--- a/python_payload/apps/simple_drums/__init__.py
+++ /dev/null
@@ -1,210 +0,0 @@
-import bl00mbox
-import captouch
-import leds
-
-from st3m.application import Application, ApplicationContext
-from st3m.input import InputState
-from st3m.goose import Tuple
-from ctx import Context
-
-
-class Dot:
-    def __init__(
-        self,
-        sizex: float,
-        sizey: float,
-        imag: float,
-        real: float,
-        col: Tuple[float, float, float],
-    ) -> None:
-        self.sizex = sizex
-        self.sizey = sizey
-        self.imag = imag
-        self.real = real
-        self.col = col
-
-    def draw(self, i: int, ctx: Context) -> None:
-        imag = self.imag
-        real = self.real
-        sizex = self.sizex
-        sizey = self.sizey
-        col = self.col
-
-        ctx.rgb(*col).rectangle(
-            -int(imag + (sizex / 2)), -int(real + (sizey / 2)), sizex, sizey
-        ).fill()
-
-
-class SimpleDrums(Application):
-    def __init__(self, app_ctx: ApplicationContext) -> None:
-        super().__init__(app_ctx)
-        # ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill()
-        self.blm = bl00mbox.Channel("simple drums")
-        self.seq = self.blm.new(bl00mbox.patches.sequencer)
-        self.hat = self.blm.new(bl00mbox.patches.sampler, "hihat.wav")
-        # Dot(10, 10, -30, 0, self._track_col(0)).draw(0,ctx)
-        self.kick = self.blm.new(bl00mbox.patches.sampler, "kick.wav")
-        # Dot(20, 20, 0, 40, self._track_col(1)).draw(0,ctx)
-        self.snare = self.blm.new(bl00mbox.patches.sampler, "snare.wav")
-        # Dot(30, 30, 2, -20, self._track_col(2)).draw(0,ctx)
-        self.kick.signals.output = self.blm.mixer
-        self.snare.signals.output = self.blm.mixer
-        self.hat.signals.output = self.blm.mixer
-        self.kick.signals.trigger = self.seq.plugins.seq.signals.track0
-        self.hat.signals.trigger = self.seq.plugins.seq.signals.track1
-        self.snare.signals.trigger = self.seq.plugins.seq.signals.track2
-        self.seq.signals.bpm.value = 80
-
-        self.track_names = ["kick", "hihat", "snare"]
-        self.track = 0
-        self.blm.background_mute_override = True
-        self.tap_tempo_press_counter = 0
-        self.delta_acc = 0
-        self.stopped = False
-        self.bpm = self.seq.signals.bpm.value
-
-        # True if a given group should be highlighted, when a corresponding
-        # petal is pressed.
-        self._group_highlight = [False for _ in range(4)]
-
-        # Disable repeat functionality as we want to detect long holds.
-        for i in range(10):
-            self.input.captouch.petals[i].whole.repeat_disable()
-
-    def _highlight_petal(self, num: int, r: int, g: int, b: int) -> None:
-        for i in range(5):
-            leds.set_rgb((4 * num - i + 2) % 40, r, g, b)
-
-    def _track_col(self, track: int) -> Tuple[int, int, int]:
-        rgb = (20, 20, 20)
-        if track == 0:
-            rgb = (0, 255, 0)
-        elif track == 1:
-            rgb = (0, 0, 255)
-        elif track == 2:
-            rgb = (255, 0, 0)
-        return rgb
-
-    def draw(self, ctx: Context) -> None:
-        dots = []
-        groupgap = 4
-        for i in range(4):
-            if self._group_highlight[i]:
-                dots.append(
-                    Dot(
-                        48 + groupgap,
-                        40,
-                        int((12 * 4 + groupgap) * (1.5 - i)),
-                        0,
-                        (0.15, 0.15, 0.15),
-                    )
-                )
-        st = self.seq.signals.step.value
-
-        for track in range(3):
-            rgb = self._track_col(track)
-            rgbf = (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
-            y = 12 * (track - 1)
-            for i in range(16):
-                trigger_state = self.seq.trigger_state(track, i)
-                size = 2
-                if trigger_state:
-                    size = 8
-                x = 12 * (7.5 - i)
-                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)))
-        dots.append(Dot(1, 40, -4 * 12 - groupgap, 0, (0.5, 0.5, 0.5)))
-
-        ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill()
-        for i, dot in enumerate(dots):
-            dot.draw(i, ctx)
-
-        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.signals.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.signals.step.value
-        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(10 - (4 - (st // 4)), *rgb)
-        self._highlight_petal(10 - (6 + (st % 4)), *rgb)
-        leds.update()
-
-        petals = self.input.captouch.petals
-
-        self._group_highlight = [False for _ in range(4)]
-        for i in range(4):
-            if petals[4 - i].whole.down:
-                self._group_highlight[i] = True
-                for j in range(4):
-                    if petals[6 + j].whole.pressed:
-                        self.seq.trigger_toggle(self.track, i * 4 + j)
-        if petals[5].whole.pressed:
-            self.track = (self.track - 1) % 3
-        if petals[0].whole.pressed:
-            if self.stopped:
-                self.seq.signals.bpm = self.bpm
-                self.blm.background_mute_override = True
-                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.signals.bpm = bpm
-                    self.bpm = bpm
-            self.delta_acc = 0
-
-        if petals[0].whole.down:
-            if self.tap_tempo_press_counter > 500:
-                self.seq.signals.bpm = 0
-                self.stopped = True
-                self.blm.background_mute_override = False
-            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
diff --git a/python_payload/bl00mbox/_patches.py b/python_payload/bl00mbox/_patches.py
index be8affe4ba906eab06a13ce889b721fc8888b2f7..0a03d9660b6b4e89b78d5a4e0f187ce288a11ee6 100644
--- a/python_payload/bl00mbox/_patches.py
+++ b/python_payload/bl00mbox/_patches.py
@@ -1,12 +1,7 @@
 # SPDX-License-Identifier: CC0-1.0
 import math
-
 import bl00mbox
-
-try:
-    import cpython.wave as wave
-except ImportError:
-    wave = None
+import cpython.wave as wave
 
 
 class _Patch:
@@ -105,15 +100,15 @@ class tinysynth_fm(tinysynth):
 
 class sampler(_Patch):
     """
-    needs a wave file with path relative to /flash/sys/samples/
+    requires a wave file. default path: /sys/samples/
     """
 
     def __init__(self, chan, filename):
         super().__init__(chan)
-        if wave is None:
-            pass
-            # raise Bl00mboxError("wave library not found")
-        f = wave.open("/flash/sys/samples/" + filename, "r")
+        if filename.startswith("/"):
+            f = wave.open("/flash/" + filename, "r")
+        else:
+            f = wave.open("/flash/sys/samples/" + filename, "r")
 
         self.len_frames = f.getnframes()
         self.plugins.sampler = chan.new(bl00mbox.plugins._sampler_ram, self.len_frames)
@@ -146,23 +141,21 @@ class sampler(_Patch):
 
 
 class sequencer(_Patch):
-    def __init__(self, chan, num=4):
+    def __init__(self, chan, num_tracks, num_steps):
         super().__init__(chan)
-        if num > 32:
-            num = 32
-        if num < 0:
-            num = 0
-        self.seqs = []
-        prev_seq = None
-        self.num_pixels = 16
-        self.num_tracks = num
-        init_var = (self.num_pixels * 256) + (self.num_tracks)  # magic
+        self.num_steps = num_steps
+        self.num_tracks = num_tracks
+        init_var = (self.num_steps * 256) + (self.num_tracks)  # magic
+
         self.plugins.seq = chan.new(bl00mbox.plugins._sequencer, init_var)
         self.signals.bpm = self.plugins.seq.signals.bpm
         self.signals.beat_div = self.plugins.seq.signals.beat_div
         self.signals.step = self.plugins.seq.signals.step
-        self.signals.step_len = self.plugins.seq.signals.step_len
-        tracktable = [-32767] + ([0] * self.num_pixels)
+        self.signals.step_end = self.plugins.seq.signals.step_end
+        self.signals.step_start = self.plugins.seq.signals.step_start
+        self.signals.step_start = self.plugins.seq.signals.step_start
+
+        tracktable = [-32767] + ([0] * self.num_steps)
         self.plugins.seq.table = tracktable * self.num_tracks
 
     def __repr__(self):
@@ -193,14 +186,19 @@ class sequencer(_Patch):
         return ret
 
     def _get_table_index(self, track, step):
-        return step + 1 + track * (self.num_pixels + 1)
+        return step + 1 + track * (self.num_steps + 1)
+
+    def trigger_start(self, track, step, val=32767):
+        a = self.plugins.seq.table
+        a[self._get_table_index(track, step)] = val
+        self.plugins.seq.table = a
 
-    def trigger_start(self, track, step):
+    def trigger_stop(self, track, step, val=32767):
         a = self.plugins.seq.table
-        a[self._get_table_index(track, step)] = 32767
+        a[self._get_table_index(track, step)] = -1
         self.plugins.seq.table = a
 
-    def trigger_stop(self, track, step):
+    def trigger_clear(self, track, step):
         a = self.plugins.seq.table
         a[self._get_table_index(track, step)] = 0
         self.plugins.seq.table = a
@@ -213,7 +211,7 @@ class sequencer(_Patch):
         if self.trigger_state(track, step) == 0:
             self.trigger_start(track, step)
         else:
-            self.trigger_stop(track, step)
+            self.trigger_clear(track, step)
 
 
 class fuzz(_Patch):
diff --git a/python_payload/bl00mbox/_user.py b/python_payload/bl00mbox/_user.py
index b9c9bf9aaa441b6addae046ea222d1f59b348f19..72150e0b1b0e368a1e20fd58f588d299acdfb457 100644
--- a/python_payload/bl00mbox/_user.py
+++ b/python_payload/bl00mbox/_user.py
@@ -517,12 +517,6 @@ class Channel:
             plugin = Plugin(self, thing, plugin_init_var)
         return plugin
 
-    def _new_patch(self, patch, init_var=None):
-        if init_var == None:
-            return patch(self)
-        else:
-            return patch(self, init_var)
-
     @staticmethod
     def print_overview():
         ret = []
@@ -540,13 +534,13 @@ class Channel:
         for plugin in self.plugins:
             print(repr(plugin))
 
-    def new(self, thing, init_var=None):
+    def new(self, thing, *args, **kwargs):
         self.free = False
         if type(thing) == type:
             if issubclass(thing, bl00mbox.patches._Patch):
-                return self._new_patch(thing, init_var)
+                return thing(self, *args, **kwargs)
         if isinstance(thing, bl00mbox._plugins._Plugin) or (type(thing) == int):
-            return self._new_plugin(thing, init_var)
+            return self._new_plugin(thing, *args, **kwargs)
 
     @property
     def plugins(self):
diff --git a/python_payload/mypystubs/bl00mbox/_patches.pyi b/python_payload/mypystubs/bl00mbox/_patches.pyi
index 8ae4f41df8e1a2d9b4ffd5682a1a3519b6913768..596aea53f4a891b1fecaa4f9b5ce9ff958559b94 100644
--- a/python_payload/mypystubs/bl00mbox/_patches.pyi
+++ b/python_payload/mypystubs/bl00mbox/_patches.pyi
@@ -28,8 +28,11 @@ class tinysynth_fm(tinysynth): ...
 class sequencer(_Patch):
     bpm: int
 
-    def trigger_state(self, track: int, i: int) -> bool: ...
-    def trigger_toggle(self, track: int, i: int) -> None: ...
+    def trigger_start(self, track: int, step: int, val: int = 32767) -> None: ...
+    def trigger_stop(self, track: int, step: int, val: int = 32767) -> None: ...
+    def trigger_clear(self, track: int, step: int) -> None: ...
+    def trigger_state(self, track: int, step: int) -> int: ...
+    def trigger_toggle(self, track: int, step: int) -> None: ...
 
 class sampler(_Patch): ...
 
diff --git a/python_payload/mypystubs/bl00mbox/_user.pyi b/python_payload/mypystubs/bl00mbox/_user.pyi
index 054bb681cba785d1f423051efb5d208163932cf2..d10d4db5b901f1a214b64b22e15f1ffb4cae0e32 100644
--- a/python_payload/mypystubs/bl00mbox/_user.pyi
+++ b/python_payload/mypystubs/bl00mbox/_user.pyi
@@ -50,14 +50,13 @@ class Channel:
 
     def __init__(self, name: str): ...
     def clear(self) -> None: ...
-    def _new_patch(self, patch: Type[T], init_var: Optional[Any] = None) -> T: ...
     def _new_plugin(
         self,
         thing: bl00mbox._plugins._Plugin | int,
         init_var: Optional[int | float] = None,
     ) -> Plugin: ...
     @overload
-    def new(self, thing: Type[P], init_var: Optional[Any] = None) -> P: ...
+    def new(self, thing: Type[P], *args: Any, **kwargs: Any) -> P: ...
     @overload
     def new(
         self,
diff --git a/python_payload/samples/README.md b/python_payload/samples/README.md
index ad43546b016fb477a237328c7729492d21589035..46c4c5f88a89ef967242f1d25fc9ff5ae850dded 100644
--- a/python_payload/samples/README.md
+++ b/python_payload/samples/README.md
@@ -2,3 +2,8 @@ Credits:
 https://freesound.org/people/sandyrb/sounds/35633/
 https://freesound.org/people/kaonaya/sounds/131363/
 https://freesound.org/people/Vrezerino/sounds/16709/
+https://freesound.org/people/collinb1000/sounds/634854/
+https://freesound.org/people/exotonestudio/sounds/416249/
+https://freesound.org/people/TheEndOfACycle/sounds/674293/
+https://freesound.org/people/KurireeVA/sounds/476588/
+https://freesound.org/people/boop_7/sounds/684369/
diff --git a/python_payload/samples/bark.wav b/python_payload/samples/bark.wav
new file mode 100644
index 0000000000000000000000000000000000000000..a041d36cb105b7858559582ac02bdb5056d1466d
Binary files /dev/null and b/python_payload/samples/bark.wav differ
diff --git a/python_payload/samples/close.wav b/python_payload/samples/close.wav
new file mode 100644
index 0000000000000000000000000000000000000000..5ddb60e4096528298b9f89e1abfe344276376d68
Binary files /dev/null and b/python_payload/samples/close.wav differ
diff --git a/python_payload/samples/crash.wav b/python_payload/samples/crash.wav
new file mode 100644
index 0000000000000000000000000000000000000000..55e79b487ac8c4773f8bbf4d2e8f7d92425ef367
Binary files /dev/null and b/python_payload/samples/crash.wav differ
diff --git a/python_payload/samples/kick.wav b/python_payload/samples/kick.wav
index 47232f348dfc7f21bd8f6179ae4281d6c4b42bfa..cf33913a55a20dfc97c3277eadc1ef325b713156 100644
Binary files a/python_payload/samples/kick.wav and b/python_payload/samples/kick.wav differ
diff --git a/python_payload/samples/nya.wav b/python_payload/samples/nya.wav
new file mode 100644
index 0000000000000000000000000000000000000000..a9a38f9d4575e7e7d23bacb48e92c38693eba7fc
Binary files /dev/null and b/python_payload/samples/nya.wav differ
diff --git a/python_payload/samples/open.wav b/python_payload/samples/open.wav
new file mode 100644
index 0000000000000000000000000000000000000000..4b4640dff73767e473e88030ada9b3f5e2833504
Binary files /dev/null and b/python_payload/samples/open.wav differ
diff --git a/python_payload/samples/snare.wav b/python_payload/samples/snare.wav
index 696c806a22ae191e82d418fb43a9a99dbda7bc2c..b3fad121ed8fc2221ef3d2bd47af20356ecbd6f8 100644
Binary files a/python_payload/samples/snare.wav and b/python_payload/samples/snare.wav differ
diff --git a/python_payload/st3m/goose.py b/python_payload/st3m/goose.py
index 51b32bf5c3d21123e10a8d613ebf5872c867da06..f9ee01f20dd577d440b147baa590f6cce2090422 100644
--- a/python_payload/st3m/goose.py
+++ b/python_payload/st3m/goose.py
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
     class ABCBase(metaclass=ABCMeta):
         pass
 
-    from typing import List, Optional, Tuple, Dict, Any, Callable
+    from typing import List, Optional, Tuple, Dict, Any, Callable, Iterator
     from enum import Enum
 else:
     # We're in CPython or Micropython.
@@ -31,7 +31,7 @@ else:
         return _fail
 
     try:
-        from typing import List, Optional, Tuple, Dict, Any, Callable
+        from typing import List, Optional, Tuple, Dict, Any, Callable, Iterator
         from enum import Enum
     except ImportError:
         # We're in Micropython.
@@ -41,6 +41,7 @@ else:
         Dict = None
         Any = None
         Callable = None
+        Iterator = None
 
         class Enum:
             pass
@@ -57,4 +58,5 @@ __all__ = [
     "Dict",
     "Any",
     "Callable",
+    "Iterator",
 ]