aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-08-24 18:38:46 +0200
committerBad Diode <bd@badd10de.dev>2023-08-24 18:38:46 +0200
commitcf9912cd61c9499fc60a839042fcae1ac556e044 (patch)
tree47d396da1f5515038080adcd8c947e593a205b21
parent84f7dd59c87506a29f534a2f6a558799db38d256 (diff)
downloadstepper-cf9912cd61c9499fc60a839042fcae1ac556e044.tar.gz
stepper-cf9912cd61c9499fc60a839042fcae1ac556e044.zip
Add visual feedback and control for scale roots
-rw-r--r--src/drawing.c60
-rw-r--r--src/main.c20
-rw-r--r--src/scale.c2
-rw-r--r--src/sequencer.c40
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);
diff --git a/src/main.c b/src/main.c
index e3c60f8..c424d9c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
15bool redraw_bank_buttons = true; 15bool redraw_bank_buttons = true;
16bool redraw_params = true; 16bool redraw_params = true;
17bool redraw_bpm = true; 17bool redraw_bpm = true;
18bool redraw_piano_note = true;
19bool redraw_scale = true; 18bool redraw_scale = true;
20bool update_bpm = false; 19bool update_bpm = false;
21u8 bar_counter = 0; 20u8 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
358void 356void
@@ -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
509void 505void
@@ -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}