{
"id": "294",
"prompt": "An EDITABLE step sequencer, not a preprogrammed one: 8 steps by 2 tracks (kick and hat) as two bitmask state slots, tapping a grid cell XORs its bit, and the playhead advances whenever a phase counter reaches the period slot - only THAT boundary frame fires host::audio (a 55 Hz sine kick, a noise(25) hat). Minus and plus buttons move the period by 2 inside 4..24, a yellow marker rides the sounding column, and the live steps-per-minute (3600/period) is printed.",
"solution_rl": "fn frame(t: i32) {\n host::display::clear(0x0c0d11);\n if host::display::state_get(6) == 0 {\n host::display::state_set(6, 1);\n host::display::state_set(1, 136);\n host::display::state_set(2, 170);\n host::display::state_set(3, 8);\n }\n let period: i32 = host::display::state_get(3);\n let mut phase: i32 = host::display::state_get(4) + 1;\n let mut step: i32 = host::display::state_get(5);\n if phase >= period {\n phase = 0;\n step = (step + 1) & 7;\n host::display::state_set(5, step);\n if ((host::display::state_get(1) >> step) & 1) == 1 {\n host::audio::tone(55, 120, 0);\n }\n if ((host::display::state_get(2) >> step) & 1) == 1 {\n host::audio::noise(25);\n }\n }\n host::display::state_set(4, phase);\n\n let down: i32 = host::display::pointer_down();\n let prev: i32 = host::display::state_get(0);\n host::display::state_set(0, down);\n if down == 1 && prev == 0 {\n let px: i32 = host::display::pointer_x();\n let py: i32 = host::display::pointer_y();\n if px >= 48 && px < 496 && py >= 120 && py < 250 {\n let col: i32 = (px - 48) / 56;\n if col < 8 {\n if py < 180 {\n host::display::state_set(1, host::display::state_get(1) ^ (1 << col));\n } else if py >= 190 {\n host::display::state_set(2, host::display::state_get(2) ^ (1 << col));\n }\n }\n }\n if py >= 300 && py < 344 {\n if px >= 48 && px < 108 && period < 24 {\n host::display::state_set(3, period + 2);\n }\n if px >= 140 && px < 200 && period > 4 {\n host::display::state_set(3, period - 2);\n }\n }\n }\n\n host::display::draw_string(48, 40, \"STEP SEQUENCER\", 0xffffff, 2);\n host::display::draw_string(48, 100, \"KICK\", 0xff8866, 1);\n host::display::draw_string(48, 174, \"HAT\", 0x66ddff, 1);\n let kick: i32 = host::display::state_get(1);\n let hat: i32 = host::display::state_get(2);\n let mut c: i32 = 0;\n while c < 8 {\n let x: i32 = 48 + c * 56;\n if c == step {\n host::display::fill_rect(x, 112, 48, 4, 0xffcc33);\n }\n let mut kcol: i32 = 0x1c212b;\n if ((kick >> c) & 1) == 1 {\n kcol = 0xcc5533;\n }\n host::display::fill_rect(x, 120, 48, 50, kcol);\n let mut hcol: i32 = 0x1c212b;\n if ((hat >> c) & 1) == 1 {\n hcol = 0x3399cc;\n }\n host::display::fill_rect(x, 190, 48, 50, hcol);\n c = c + 1;\n }\n host::display::fill_rect(48, 300, 60, 44, 0x232833);\n host::display::draw_char(72, 314, 45, 0xffffff, 2);\n host::display::fill_rect(140, 300, 60, 44, 0x232833);\n host::display::draw_char(164, 314, 43, 0xffffff, 2);\n host::display::draw_string(240, 306, \"STEPS PER MIN\", 0x556677, 1);\n host::display::draw_number(240, 322, 3600 / period, 0xffffff, 2);\n host::display::present();\n}\n",
"tags": [
"app",
"sequencer",
"audio",
"bitmask"
]
}