aboutsummaryrefslogtreecommitdiffstats
path: root/src/scale.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-08-22 17:44:01 +0200
committerBad Diode <bd@badd10de.dev>2023-08-22 17:44:01 +0200
commit5d86238b8cc3c6dba95e90eed9fb444bb276f02e (patch)
treed3b1d4c4509631a3dace28486b6887445298af1f /src/scale.c
parent9c0c004b78a12861ed03ce851d0885d68a25cb02 (diff)
downloadstepper-5d86238b8cc3c6dba95e90eed9fb444bb276f02e.tar.gz
stepper-5d86238b8cc3c6dba95e90eed9fb444bb276f02e.zip
Added initial implementation of scale mode
Diffstat (limited to 'src/scale.c')
-rw-r--r--src/scale.c102
1 files changed, 102 insertions, 0 deletions
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 @@
1typedef 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
21char *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
40char *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
59typedef u8 Scale[12];
60Scale 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
80int current_scale = SCALE_CHRM;
81int current_scale_root = 0;
82
83s32
84scale_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}