diff options
author | Bad Diode <bd@badd10de.dev> | 2023-08-24 18:38:46 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-08-24 18:38:46 +0200 |
commit | cf9912cd61c9499fc60a839042fcae1ac556e044 (patch) | |
tree | 47d396da1f5515038080adcd8c947e593a205b21 /src | |
parent | 84f7dd59c87506a29f534a2f6a558799db38d256 (diff) | |
download | stepper-cf9912cd61c9499fc60a839042fcae1ac556e044.tar.gz stepper-cf9912cd61c9499fc60a839042fcae1ac556e044.zip |
Add visual feedback and control for scale roots
Diffstat (limited to 'src')
-rw-r--r-- | src/drawing.c | 60 | ||||
-rw-r--r-- | src/main.c | 20 | ||||
-rw-r--r-- | src/scale.c | 2 | ||||
-rw-r--r-- | src/sequencer.c | 40 |
4 files changed, 73 insertions, 49 deletions
diff --git a/src/drawing.c b/src/drawing.c index a432285..f3115c5 100644 --- a/src/drawing.c +++ b/src/drawing.c | |||
@@ -393,12 +393,16 @@ draw_bpm() { | |||
393 | draw_rect(x, y, x + R_COL_W - 2, y + BPM_H - 3, COL_FG); | 393 | draw_rect(x, y, x + R_COL_W - 2, y + BPM_H - 3, COL_FG); |
394 | txt_drawf_small("BPM", x + 7, y - 10, COL_FG); | 394 | txt_drawf_small("BPM", x + 7, y - 10, COL_FG); |
395 | 395 | ||
396 | // Make sure its horizontally centered if only 2 digits | 396 | if (settings.sync == SYNC_IN_LINK) { |
397 | int bpm = patterns[pattern_selection_loc].bpm; | 397 | txt_drawf("SYNC", x + 2, y + 2, COL_FG); |
398 | if (bpm >= 100) { | ||
399 | txt_drawf("%d", x + 5, y + 2, COL_FG, bpm); | ||
400 | } else { | 398 | } else { |
401 | txt_drawf("%d", x + 8, y + 2, COL_FG, bpm); | 399 | // Make sure its horizontally centered if only 2 digits |
400 | int bpm = patterns[pattern_selection_loc].bpm; | ||
401 | if (bpm >= 100) { | ||
402 | txt_drawf("%d", x + 5, y + 2, COL_FG, bpm); | ||
403 | } else { | ||
404 | txt_drawf("%d", x + 8, y + 2, COL_FG, bpm); | ||
405 | } | ||
402 | } | 406 | } |
403 | } | 407 | } |
404 | 408 | ||
@@ -531,16 +535,18 @@ draw_note(u8 note, u8 clr) { | |||
531 | draw_filled_rect(x0, y0, x1, y1, clr); | 535 | draw_filled_rect(x0, y0, x1, y1, clr); |
532 | } break; | 536 | } break; |
533 | default: { | 537 | default: { |
534 | if (clr == COL_FG) { | 538 | // NOTE: Decide if this looks better or nah. Also, not the right |
535 | clr = COL_BG; | 539 | // place for it... |
536 | } | 540 | // if (clr == COL_FG) { |
541 | // clr = COL_BG; | ||
542 | // } | ||
537 | y0 = base_y0; | 543 | y0 = base_y0; |
538 | y1 = base_y1 + PIANO_BLACK_H - 2; | 544 | y1 = base_y1 + PIANO_BLACK_H - 2; |
539 | switch (value) { | 545 | switch (value) { |
540 | case 1: { x0 = base_x + octave * 28 + 3; } break; | 546 | case 1: { x0 = base_x + octave * 28 + 3; } break; |
541 | case 3: { x0 = base_x + octave * 28 + 7; } break; | 547 | case 3: { x0 = base_x + octave * 28 + 7; } break; |
542 | case 6: { x0 = base_x + octave * 28 + 15; } break; | 548 | case 6: { x0 = base_x + octave * 28 + 15; } break; |
543 | case 8: { x0 = base_x + octave * 28 + 19; } break; | 549 | case 8: { x0 = base_x + octave * 28 + 19; } break; |
544 | case 10: { x0 = base_x + octave * 28 + 23; } break; | 550 | case 10: { x0 = base_x + octave * 28 + 23; } break; |
545 | } | 551 | } |
546 | x1 = x0; | 552 | x1 = x0; |
@@ -557,7 +563,24 @@ draw_piano(void) { | |||
557 | size_t y1 = PIANO_START_Y + PIANO_H; | 563 | size_t y1 = PIANO_START_Y + PIANO_H; |
558 | draw_rect(x0, y0, x1, y1, COL_FG); | 564 | draw_rect(x0, y0, x1, y1, COL_FG); |
559 | for (size_t i = 0; i < 12 * 6; i++) { | 565 | for (size_t i = 0; i < 12 * 6; i++) { |
560 | draw_note(i, COL_FG); | 566 | u8 clr = COL_FG; |
567 | if (input_handler == handle_right_col_selection && | ||
568 | right_col_selection_loc == R_COL_SCALE) { | ||
569 | s8 pos = i % 12; | ||
570 | if (pos == current_scale_root) { | ||
571 | clr = COL_ACC_1; | ||
572 | } else { | ||
573 | s8 scale_pos = (pos - current_scale_root) % 12; | ||
574 | if (scale_pos < 0) { | ||
575 | scale_pos *= -1; | ||
576 | scale_pos = 12 - scale_pos; | ||
577 | } | ||
578 | if (scales[current_scale][scale_pos] == 1) { | ||
579 | clr = COL_ACC_0; | ||
580 | } | ||
581 | } | ||
582 | } | ||
583 | draw_note(i, clr); | ||
561 | } | 584 | } |
562 | } | 585 | } |
563 | 586 | ||
@@ -1314,7 +1337,9 @@ draw_piano_notes(void) { | |||
1314 | // Show last/current played notes in all channels. | 1337 | // Show last/current played notes in all channels. |
1315 | if (play_status == 1) { | 1338 | if (play_status == 1) { |
1316 | Pattern *pat = &patterns[current_pattern]; | 1339 | Pattern *pat = &patterns[current_pattern]; |
1317 | if (pat->empty || play_status == 0) { | 1340 | if (pat->empty || |
1341 | play_status == 0 || | ||
1342 | input_handler == handle_right_col_selection) { | ||
1318 | return; | 1343 | return; |
1319 | } | 1344 | } |
1320 | u8 step = step_counter % 16; | 1345 | u8 step = step_counter % 16; |
@@ -1681,7 +1706,12 @@ draw_notif_bar() { | |||
1681 | txt_drawf_small("SETTINGS", x0 + 2, y0 + 1, color); | 1706 | txt_drawf_small("SETTINGS", x0 + 2, y0 + 1, color); |
1682 | } break; | 1707 | } break; |
1683 | case R_COL_SCALE: { | 1708 | case R_COL_SCALE: { |
1684 | txt_drawf_small("SCALE: %s", x0 + 2, y0 + 1, color, scale_long[current_scale]); | 1709 | const char *roots[12] = { |
1710 | "C ", "C#", "D ", "D#", "E ", "F ", | ||
1711 | "F#", "G ", "G#", "A ", "A#", "B ", | ||
1712 | }; | ||
1713 | txt_drawf_small("ROOT: %s SCALE: %s", x0 + 2, y0 + 1, color, | ||
1714 | roots[current_scale_root], scale_long[current_scale]); | ||
1685 | } break; | 1715 | } break; |
1686 | case R_COL_BPM: { | 1716 | case R_COL_BPM: { |
1687 | txt_drawf_small("TEMPO: %d bpm", x0 + 2, y0 + 1, color, patterns[pattern_selection_loc].bpm); | 1717 | txt_drawf_small("TEMPO: %d bpm", x0 + 2, y0 + 1, color, patterns[pattern_selection_loc].bpm); |
@@ -36,6 +36,7 @@ WITH REGARD TO THIS SOFTWARE. | |||
36 | // - Per-channel N steps to create polymeters? | 36 | // - Per-channel N steps to create polymeters? |
37 | // - Channel params should show if there are some already on all triggers and | 37 | // - Channel params should show if there are some already on all triggers and |
38 | // modify only the selected parameter, not all of them. | 38 | // modify only the selected parameter, not all of them. |
39 | // - Should scale mode be toggleable? | ||
39 | // | 40 | // |
40 | // WIP (1.7) | 41 | // WIP (1.7) |
41 | // + Improve "grey" cursor with dithering instead. | 42 | // + Improve "grey" cursor with dithering instead. |
@@ -52,20 +53,20 @@ WITH REGARD TO THIS SOFTWARE. | |||
52 | // + Fix stop button behaviour. | 53 | // + Fix stop button behaviour. |
53 | // + Scale mode for entering notes. | 54 | // + Scale mode for entering notes. |
54 | // + Make sure bank switching is queued like patterns. | 55 | // + Make sure bank switching is queued like patterns. |
55 | // - Should scale mode be toggleable? | 56 | // + If we are on sync in, BPM should display SYNC |
57 | // + Visual feedback for scale/root note adjustment. | ||
56 | // - Shortcut to quickly exit/enter chain mode. | 58 | // - Shortcut to quickly exit/enter chain mode. |
57 | // - If we are on sync in, BPM should display SYNC | 59 | // - Add CREDITS to the documentation for now, should probably be a menu item |
60 | // later. | ||
61 | // - Settings page overhaul. | ||
62 | // - Remove thin cursor option and make the fat one default, it's just better. | ||
58 | // | 63 | // |
59 | // - Improve SRAM saving to make room for longer patterns and/or more banks. | 64 | // - Improve SRAM saving to make room for longer patterns and/or more banks. |
60 | // - Higher resolution clock to allow for microtiming and more accurate tempo. | 65 | // - Higher resolution clock to allow for microtiming and more accurate tempo. |
61 | // - Add settings for "performance mode" in which banks are not saved by | 66 | // - Add settings for "performance mode" in which banks are not saved by |
62 | // default while changing patterns. | 67 | // default while changing patterns. |
63 | // - Make sure sync works with the same cable for in/out. | 68 | // - Make sure sync works with the same cable for in/out. |
64 | // - Remove thin cursor option and make the fat one default, it's just better. | ||
65 | // - Settings page overhaul. | ||
66 | // - Study more improvements for a "performance mode". | 69 | // - Study more improvements for a "performance mode". |
67 | // - Add CREDITS to the documentation for now, should probably be a menu item | ||
68 | // later. | ||
69 | 70 | ||
70 | #include "gba/gba.h" | 71 | #include "gba/gba.h" |
71 | 72 | ||
@@ -111,10 +112,6 @@ render_sequencer(void) { | |||
111 | PROF(draw_scale(), draw_btn_cycles); | 112 | PROF(draw_scale(), draw_btn_cycles); |
112 | redraw_scale = false; | 113 | redraw_scale = false; |
113 | } | 114 | } |
114 | if (redraw_piano_note) { | ||
115 | PROF(draw_piano_notes(), draw_piano_cycles); | ||
116 | redraw_piano_note = false; | ||
117 | } | ||
118 | if (redraw_params) { | 115 | if (redraw_params) { |
119 | PROF(draw_parameters(), draw_param_cycles); | 116 | PROF(draw_parameters(), draw_param_cycles); |
120 | redraw_params = false; | 117 | redraw_params = false; |
@@ -125,8 +122,8 @@ render_sequencer(void) { | |||
125 | draw_pattern_chain(); | 122 | draw_pattern_chain(); |
126 | } | 123 | } |
127 | 124 | ||
128 | // TODO: redraw_notif? | ||
129 | draw_notif_bar(); | 125 | draw_notif_bar(); |
126 | PROF(draw_piano_notes(), draw_piano_cycles); | ||
130 | PROF(draw_cursors(), draw_cursor_cycles); | 127 | PROF(draw_cursors(), draw_cursor_cycles); |
131 | } | 128 | } |
132 | 129 | ||
@@ -184,7 +181,6 @@ update(void) { | |||
184 | redraw_bank_buttons = true; | 181 | redraw_bank_buttons = true; |
185 | redraw_bpm = true; | 182 | redraw_bpm = true; |
186 | redraw_play_pause = true; | 183 | redraw_play_pause = true; |
187 | redraw_piano_note = true; | ||
188 | redraw_params = true; | 184 | redraw_params = true; |
189 | redraw_scale = true; | 185 | redraw_scale = true; |
190 | } | 186 | } |
diff --git a/src/scale.c b/src/scale.c index 7704815..197959e 100644 --- a/src/scale.c +++ b/src/scale.c | |||
@@ -88,7 +88,7 @@ scale_note(s32 current, s32 inc) { | |||
88 | s32 pos = current % 12; | 88 | s32 pos = current % 12; |
89 | s32 offset = 0; | 89 | s32 offset = 0; |
90 | for (int i = 1; i <= 12; i++) { | 90 | for (int i = 1; i <= 12; i++) { |
91 | s32 k = (current_scale_root + pos + i * inc) % 12; | 91 | s32 k = (pos - current_scale_root + i * inc) % 12; |
92 | if (k < 0) { | 92 | if (k < 0) { |
93 | k *= -1; | 93 | k *= -1; |
94 | k = 12 - k; | 94 | k = 12 - k; |
diff --git a/src/sequencer.c b/src/sequencer.c index 3635657..f3dff04 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -15,7 +15,6 @@ bool redraw_channels = true; | |||
15 | bool redraw_bank_buttons = true; | 15 | bool redraw_bank_buttons = true; |
16 | bool redraw_params = true; | 16 | bool redraw_params = true; |
17 | bool redraw_bpm = true; | 17 | bool redraw_bpm = true; |
18 | bool redraw_piano_note = true; | ||
19 | bool redraw_scale = true; | 18 | bool redraw_scale = true; |
20 | bool update_bpm = false; | 19 | bool update_bpm = false; |
21 | u8 bar_counter = 0; | 20 | u8 bar_counter = 0; |
@@ -352,7 +351,6 @@ play_step(void) { | |||
352 | bar_counter++; | 351 | bar_counter++; |
353 | } | 352 | } |
354 | step_counter = (step_counter + 1) % 16; | 353 | step_counter = (step_counter + 1) % 16; |
355 | redraw_piano_note = true; | ||
356 | } | 354 | } |
357 | 355 | ||
358 | void | 356 | void |
@@ -457,7 +455,6 @@ handle_channel_selection(void) { | |||
457 | trig_selection_loc = 0; | 455 | trig_selection_loc = 0; |
458 | param_selection_loc = 0; | 456 | param_selection_loc = 0; |
459 | input_handler = handle_trigger_selection; | 457 | input_handler = handle_trigger_selection; |
460 | redraw_piano_note = true; | ||
461 | redraw_params = true; | 458 | redraw_params = true; |
462 | } else if (key_tap(KEY_LEFT)) { | 459 | } else if (key_tap(KEY_LEFT)) { |
463 | input_handler = handle_pattern_selection; | 460 | input_handler = handle_pattern_selection; |
@@ -503,7 +500,6 @@ stop_sound(void) { | |||
503 | SOUND_NOISE_CTRL = 0; | 500 | SOUND_NOISE_CTRL = 0; |
504 | redraw_play_pause = true; | 501 | redraw_play_pause = true; |
505 | redraw_pattern_buttons = true; | 502 | redraw_pattern_buttons = true; |
506 | redraw_piano_note = true; | ||
507 | } | 503 | } |
508 | 504 | ||
509 | void | 505 | void |
@@ -544,7 +540,6 @@ toggle_playing(void) { | |||
544 | SOUND_NOISE_CTRL = 0; | 540 | SOUND_NOISE_CTRL = 0; |
545 | redraw_play_pause = true; | 541 | redraw_play_pause = true; |
546 | redraw_pattern_buttons = true; | 542 | redraw_pattern_buttons = true; |
547 | redraw_piano_note = true; | ||
548 | if (settings.sync == SYNC_IN_LINK) { | 543 | if (settings.sync == SYNC_IN_LINK) { |
549 | return; | 544 | return; |
550 | } | 545 | } |
@@ -685,12 +680,18 @@ handle_right_col_selection(void) { | |||
685 | } | 680 | } |
686 | } break; | 681 | } break; |
687 | case R_COL_SCALE: { | 682 | case R_COL_SCALE: { |
688 | current_scale--; | 683 | if (key_hold(KEY_SELECT)) { |
689 | if (current_scale < 0) { | 684 | current_scale_root--; |
690 | current_scale = SCALE_NUM - 1; | 685 | if (current_scale_root < 0) { |
686 | current_scale_root = 11; | ||
687 | } | ||
688 | } else { | ||
689 | current_scale--; | ||
690 | if (current_scale < 0) { | ||
691 | current_scale = SCALE_NUM - 1; | ||
692 | } | ||
693 | redraw_scale = true; | ||
691 | } | 694 | } |
692 | // TODO: add root note change & keyboard viz. | ||
693 | redraw_scale = true; | ||
694 | } break; | 695 | } break; |
695 | } | 696 | } |
696 | } else if (key_tap(KEY_R)) { | 697 | } else if (key_tap(KEY_R)) { |
@@ -714,11 +715,15 @@ handle_right_col_selection(void) { | |||
714 | } | 715 | } |
715 | } break; | 716 | } break; |
716 | case R_COL_SCALE: { | 717 | case R_COL_SCALE: { |
717 | current_scale++; | 718 | if (key_hold(KEY_SELECT)) { |
718 | if (current_scale >= SCALE_NUM) { | 719 | current_scale_root = (current_scale_root + 1) % 12; |
719 | current_scale = 0; | 720 | } else { |
721 | current_scale++; | ||
722 | if (current_scale >= SCALE_NUM) { | ||
723 | current_scale = 0; | ||
724 | } | ||
725 | redraw_scale = true; | ||
720 | } | 726 | } |
721 | redraw_scale = true; | ||
722 | } break; | 727 | } break; |
723 | } | 728 | } |
724 | } else if (key_tap(KEY_B)) { | 729 | } else if (key_tap(KEY_B)) { |
@@ -1293,7 +1298,6 @@ handle_trigger_selection(void) { | |||
1293 | } | 1298 | } |
1294 | trig->active ^= 1; | 1299 | trig->active ^= 1; |
1295 | redraw_trigs = true; | 1300 | redraw_trigs = true; |
1296 | redraw_piano_note = true; | ||
1297 | } | 1301 | } |
1298 | } else if (key_tap(KEY_L)) { | 1302 | } else if (key_tap(KEY_L)) { |
1299 | s32 inc = -1; | 1303 | s32 inc = -1; |
@@ -1305,7 +1309,6 @@ handle_trigger_selection(void) { | |||
1305 | trig->note = scale_note(trig->note, inc); | 1309 | trig->note = scale_note(trig->note, inc); |
1306 | } | 1310 | } |
1307 | redraw_trigs = true; | 1311 | redraw_trigs = true; |
1308 | redraw_piano_note = true; | ||
1309 | } else if (key_tap(KEY_R)) { | 1312 | } else if (key_tap(KEY_R)) { |
1310 | s32 inc = 1; | 1313 | s32 inc = 1; |
1311 | if (key_hold(KEY_SELECT)) { | 1314 | if (key_hold(KEY_SELECT)) { |
@@ -1316,7 +1319,6 @@ handle_trigger_selection(void) { | |||
1316 | trig->note = scale_note(trig->note, inc); | 1319 | trig->note = scale_note(trig->note, inc); |
1317 | } | 1320 | } |
1318 | redraw_trigs = true; | 1321 | redraw_trigs = true; |
1319 | redraw_piano_note = true; | ||
1320 | } | 1322 | } |
1321 | 1323 | ||
1322 | // Move trigger cursor. | 1324 | // Move trigger cursor. |
@@ -1328,7 +1330,6 @@ handle_trigger_selection(void) { | |||
1328 | trig_selection_loc = MAX(trig_selection_loc - 1, 0); | 1330 | trig_selection_loc = MAX(trig_selection_loc - 1, 0); |
1329 | } | 1331 | } |
1330 | redraw_params = true; | 1332 | redraw_params = true; |
1331 | redraw_piano_note = true; | ||
1332 | } else if (key_tap(KEY_RIGHT)) { | 1333 | } else if (key_tap(KEY_RIGHT)) { |
1333 | if (trig_selection_loc != 7 && trig_selection_loc != 15) { | 1334 | if (trig_selection_loc != 7 && trig_selection_loc != 15) { |
1334 | trig_selection_loc = MIN(trig_selection_loc + 1, 15); | 1335 | trig_selection_loc = MIN(trig_selection_loc + 1, 15); |
@@ -1340,11 +1341,9 @@ handle_trigger_selection(void) { | |||
1340 | input_handler = handle_right_col_selection; | 1341 | input_handler = handle_right_col_selection; |
1341 | } | 1342 | } |
1342 | redraw_params = true; | 1343 | redraw_params = true; |
1343 | redraw_piano_note = true; | ||
1344 | } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { | 1344 | } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { |
1345 | trig_selection_loc = (trig_selection_loc + 8) % 16; | 1345 | trig_selection_loc = (trig_selection_loc + 8) % 16; |
1346 | redraw_params = true; | 1346 | redraw_params = true; |
1347 | redraw_piano_note = true; | ||
1348 | } else if (key_tap(KEY_A)) { | 1347 | } else if (key_tap(KEY_A)) { |
1349 | if (key_hold(KEY_SELECT)) { | 1348 | if (key_hold(KEY_SELECT)) { |
1350 | if (patterns[pattern_selection_loc].empty) { | 1349 | if (patterns[pattern_selection_loc].empty) { |
@@ -1364,7 +1363,6 @@ handle_trigger_selection(void) { | |||
1364 | case 3: { input_handler = handle_param_selection_noise; } break; | 1363 | case 3: { input_handler = handle_param_selection_noise; } break; |
1365 | } | 1364 | } |
1366 | redraw_params = true; | 1365 | redraw_params = true; |
1367 | redraw_piano_note = true; | ||
1368 | } | 1366 | } |
1369 | } | 1367 | } |
1370 | } | 1368 | } |