diff options
author | Bad Diode <bd@badd10de.dev> | 2023-08-22 17:44:01 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-08-22 17:44:01 +0200 |
commit | 5d86238b8cc3c6dba95e90eed9fb444bb276f02e (patch) | |
tree | d3b1d4c4509631a3dace28486b6887445298af1f | |
parent | 9c0c004b78a12861ed03ce851d0885d68a25cb02 (diff) | |
download | stepper-5d86238b8cc3c6dba95e90eed9fb444bb276f02e.tar.gz stepper-5d86238b8cc3c6dba95e90eed9fb444bb276f02e.zip |
Added initial implementation of scale mode
-rw-r--r-- | src/globals.c | 60 | ||||
-rw-r--r-- | src/main.c | 8 | ||||
-rw-r--r-- | src/scale.c | 102 | ||||
-rw-r--r-- | src/sequencer.c | 8 |
4 files changed, 111 insertions, 67 deletions
diff --git a/src/globals.c b/src/globals.c index a971120..23012c8 100644 --- a/src/globals.c +++ b/src/globals.c | |||
@@ -189,63 +189,3 @@ typedef enum Prob { | |||
189 | PROB_20, | 189 | PROB_20, |
190 | PROB_NUM, | 190 | PROB_NUM, |
191 | } Prob; | 191 | } Prob; |
192 | |||
193 | typedef enum Scales { | ||
194 | SCALE_CHRM, | ||
195 | SCALE_MAJR, | ||
196 | SCALE_MINR, | ||
197 | SCALE_PMAJ, | ||
198 | SCALE_PMIN, | ||
199 | SCALE_BLUE, | ||
200 | SCALE_DORI, | ||
201 | SCALE_PHYR, | ||
202 | SCALE_LYDI, | ||
203 | SCALE_MIXO, | ||
204 | SCALE_LOCR, | ||
205 | SCALE_PERS, | ||
206 | SCALE_HMIN, | ||
207 | SCALE_IWAT, | ||
208 | SCALE_INSN, | ||
209 | SCALE_HIRA, | ||
210 | SCALE_NUM, | ||
211 | } Scales; | ||
212 | |||
213 | char *scale_short[] = { | ||
214 | "CHRM", | ||
215 | "MAJR", | ||
216 | "MINR", | ||
217 | "PMAJ", | ||
218 | "PMIN", | ||
219 | "BLUE", | ||
220 | "DORI", | ||
221 | "PHYR", | ||
222 | "LYDI", | ||
223 | "MIXO", | ||
224 | "LOCR", | ||
225 | "PERS", | ||
226 | "HMIN", | ||
227 | "IWAT", | ||
228 | "INSN", | ||
229 | "HIRA", | ||
230 | }; | ||
231 | |||
232 | char *scale_long[] = { | ||
233 | "CHROMATIC", | ||
234 | "MAJOR", | ||
235 | "MINOR", | ||
236 | "PENTATONIC MAJOR", | ||
237 | "PENTATONIC MINOR", | ||
238 | "BLUES", | ||
239 | "DORIAN", | ||
240 | "PHYRGIAN", | ||
241 | "LYDIAN", | ||
242 | "MIXOLYDIAN", | ||
243 | "LOCRIAN", | ||
244 | "PERSIAN", | ||
245 | "HUNGARIAN MINOR", | ||
246 | "IWATO", | ||
247 | "IN-SEN", | ||
248 | "HIRAJOSHI", | ||
249 | }; | ||
250 | |||
251 | int current_scale = SCALE_CHRM; | ||
@@ -49,13 +49,14 @@ WITH REGARD TO THIS SOFTWARE. | |||
49 | // that it's clear it's affecting all triggers. | 49 | // that it's clear it's affecting all triggers. |
50 | // + Fix keyboard note drawing bugs. | 50 | // + Fix keyboard note drawing bugs. |
51 | // + Fix stop button behaviour. | 51 | // + Fix stop button behaviour. |
52 | // + Scale mode for entering notes. | ||
53 | // - Shortcut to quickly exit/enter chain mode. | ||
54 | // - Make sure bank switching is queued like patterns. | ||
55 | // | ||
52 | // - Improve SRAM saving to make room for longer patterns and/or more banks. | 56 | // - Improve SRAM saving to make room for longer patterns and/or more banks. |
53 | // - Scale mode for entering notes. | ||
54 | // - Higher resolution clock to allow for microtiming and more accurate tempo. | 57 | // - Higher resolution clock to allow for microtiming and more accurate tempo. |
55 | // - Multiple pattern chains per bank that we can toggle between, gotta study | 58 | // - Multiple pattern chains per bank that we can toggle between, gotta study |
56 | // if they fit in the SRAM. | 59 | // if they fit in the SRAM. |
57 | // - Shortcut to quickly exit/enter chain mode. | ||
58 | // - Make sure bank switching is queued like patterns. | ||
59 | // - Add settings for "performance mode" in which banks are not saved by | 60 | // - Add settings for "performance mode" in which banks are not saved by |
60 | // default while changing patterns. | 61 | // default while changing patterns. |
61 | // - Make sure sync works with the same cable for in/out. | 62 | // - Make sure sync works with the same cable for in/out. |
@@ -72,6 +73,7 @@ WITH REGARD TO THIS SOFTWARE. | |||
72 | #include "globals.c" | 73 | #include "globals.c" |
73 | #include "settings.c" | 74 | #include "settings.c" |
74 | #include "dsound.c" | 75 | #include "dsound.c" |
76 | #include "scale.c" | ||
75 | #include "sequencer.c" | 77 | #include "sequencer.c" |
76 | 78 | ||
77 | #define PROF_ENABLE 0 | 79 | #define PROF_ENABLE 0 |
diff --git a/src/scale.c b/src/scale.c new file mode 100644 index 0000000..51d46fe --- /dev/null +++ b/src/scale.c | |||
@@ -0,0 +1,102 @@ | |||
1 | typedef enum Scales { | ||
2 | SCALE_CHRM, | ||
3 | SCALE_MAJR, | ||
4 | SCALE_MINR, | ||
5 | SCALE_PMAJ, | ||
6 | SCALE_PMIN, | ||
7 | SCALE_BLUE, | ||
8 | SCALE_DORI, | ||
9 | SCALE_PHYR, | ||
10 | SCALE_LYDI, | ||
11 | SCALE_MIXO, | ||
12 | SCALE_LOCR, | ||
13 | SCALE_PERS, | ||
14 | SCALE_HMIN, | ||
15 | SCALE_IWAT, | ||
16 | SCALE_INSN, | ||
17 | SCALE_HIRA, | ||
18 | SCALE_NUM, | ||
19 | } Scales; | ||
20 | |||
21 | char *scale_short[] = { | ||
22 | "CHRM", | ||
23 | "MAJR", | ||
24 | "MINR", | ||
25 | "PMAJ", | ||
26 | "PMIN", | ||
27 | "BLUE", | ||
28 | "DORI", | ||
29 | "PHYR", | ||
30 | "LYDI", | ||
31 | "MIXO", | ||
32 | "LOCR", | ||
33 | "PERS", | ||
34 | "HMIN", | ||
35 | "IWAT", | ||
36 | "INSN", | ||
37 | "HIRA", | ||
38 | }; | ||
39 | |||
40 | char *scale_long[] = { | ||
41 | "CHROMATIC", | ||
42 | "MAJOR", | ||
43 | "MINOR", | ||
44 | "PENTATONIC MAJOR", | ||
45 | "PENTATONIC MINOR", | ||
46 | "BLUES", | ||
47 | "DORIAN", | ||
48 | "PHYRGIAN", | ||
49 | "LYDIAN", | ||
50 | "MIXOLYDIAN", | ||
51 | "LOCRIAN", | ||
52 | "PERSIAN", | ||
53 | "HUNGARIAN MINOR", | ||
54 | "IWATO", | ||
55 | "IN-SEN", | ||
56 | "HIRAJOSHI", | ||
57 | }; | ||
58 | |||
59 | typedef u8 Scale[12]; | ||
60 | Scale scales[] = { | ||
61 | // 1 b2 2 b3 3 4 b5 5 b6 6 b7 7 <- Major | ||
62 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // CHRM | ||
63 | {1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1}, // MAJR | ||
64 | {1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0}, // MINR | ||
65 | {1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0}, // PMAJ | ||
66 | {1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0}, // PMIN | ||
67 | {1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0}, // BLUE | ||
68 | {1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0}, // DORI | ||
69 | {1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0}, // PHYR | ||
70 | {1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1}, // LYDI | ||
71 | {1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0}, // MIXO | ||
72 | {1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0}, // LOCR | ||
73 | {1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1}, // PERS | ||
74 | {1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1}, // HMIN | ||
75 | {1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0}, // IWAT | ||
76 | {1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0}, // INSN | ||
77 | {1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0}, // HIRA | ||
78 | }; | ||
79 | |||
80 | int current_scale = SCALE_CHRM; | ||
81 | int current_scale_root = 0; | ||
82 | |||
83 | s32 | ||
84 | scale_note(s32 current, s32 inc) { | ||
85 | if (inc > 1 || inc < -1) { | ||
86 | return CLAMP(current + inc, (s32)NOTE_C_2, (s32)NOTE_C_8 - 1); | ||
87 | } | ||
88 | s32 pos = current % 12; | ||
89 | s32 offset = 0; | ||
90 | for (int i = 1; i <= 12; i++) { | ||
91 | s32 k = (current_scale_root + pos + i * inc) % 12; | ||
92 | if (k < 0) { | ||
93 | k *= -1; | ||
94 | k = 12 - k; | ||
95 | } | ||
96 | offset += inc; | ||
97 | if (scales[current_scale][k] == 1) { | ||
98 | break; | ||
99 | } | ||
100 | } | ||
101 | return CLAMP(current + offset, (s32)NOTE_C_2, (s32)NOTE_C_8 - 1); | ||
102 | } | ||
diff --git a/src/sequencer.c b/src/sequencer.c index ce09658..609ccee 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -406,7 +406,7 @@ handle_channel_selection(void) { | |||
406 | case 3: { trig = &pat->ch4.notes[i]; } break; | 406 | case 3: { trig = &pat->ch4.notes[i]; } break; |
407 | default: {trig = &pat->ch1.notes[i]; } break; | 407 | default: {trig = &pat->ch1.notes[i]; } break; |
408 | } | 408 | } |
409 | trig->note = MAX((s32)trig->note + inc, (s32)NOTE_C_2); | 409 | trig->note = scale_note(trig->note, inc); |
410 | } | 410 | } |
411 | redraw_trigs = true; | 411 | redraw_trigs = true; |
412 | } else if (key_tap(KEY_R)) { | 412 | } else if (key_tap(KEY_R)) { |
@@ -423,7 +423,7 @@ handle_channel_selection(void) { | |||
423 | case 3: { trig = &pat->ch4.notes[i]; } break; | 423 | case 3: { trig = &pat->ch4.notes[i]; } break; |
424 | default: {trig = &pat->ch1.notes[i]; } break; | 424 | default: {trig = &pat->ch1.notes[i]; } break; |
425 | } | 425 | } |
426 | trig->note = MIN((s32)trig->note + inc, (s32)NOTE_C_8 - 1); | 426 | trig->note = scale_note(trig->note, inc); |
427 | } | 427 | } |
428 | redraw_trigs = true; | 428 | redraw_trigs = true; |
429 | } | 429 | } |
@@ -1292,7 +1292,7 @@ handle_trigger_selection(void) { | |||
1292 | } | 1292 | } |
1293 | // Decrease note. | 1293 | // Decrease note. |
1294 | if (trig->active && !empty) { | 1294 | if (trig->active && !empty) { |
1295 | trig->note = MAX((s32)trig->note + inc, (s32)NOTE_C_2); | 1295 | trig->note = scale_note(trig->note, inc); |
1296 | } | 1296 | } |
1297 | redraw_trigs = true; | 1297 | redraw_trigs = true; |
1298 | redraw_piano_note = true; | 1298 | redraw_piano_note = true; |
@@ -1303,7 +1303,7 @@ handle_trigger_selection(void) { | |||
1303 | } | 1303 | } |
1304 | // Increase note. | 1304 | // Increase note. |
1305 | if (trig->active && !empty) { | 1305 | if (trig->active && !empty) { |
1306 | trig->note = MIN((s32)trig->note + inc, (s32)NOTE_C_8 - 1); | 1306 | trig->note = scale_note(trig->note, inc); |
1307 | } | 1307 | } |
1308 | redraw_trigs = true; | 1308 | redraw_trigs = true; |
1309 | redraw_piano_note = true; | 1309 | redraw_piano_note = true; |