1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
typedef enum Scales {
SCALE_CHRM,
SCALE_MAJR,
SCALE_MINR,
SCALE_PMAJ,
SCALE_PMIN,
SCALE_BLUE,
SCALE_DORI,
SCALE_PHYR,
SCALE_LYDI,
SCALE_MIXO,
SCALE_LOCR,
SCALE_PERS,
SCALE_HMIN,
SCALE_IWAT,
SCALE_INSN,
SCALE_HIRA,
SCALE_NUM,
} Scales;
int current_scale = SCALE_CHRM;
int current_scale_root = 0;
char *scale_short[] = {
"CHRM",
"MAJR",
"MINR",
"PMAJ",
"PMIN",
"BLUE",
"DORI",
"PHYR",
"LYDI",
"MIXO",
"LOCR",
"PERS",
"HMIN",
"IWAT",
"INSN",
"HIRA",
};
char *scale_long[] = {
"CHROMATIC",
"MAJOR",
"MINOR",
"PENTATONIC MAJOR",
"PENTATONIC MINOR",
"BLUES",
"DORIAN",
"PHYRGIAN",
"LYDIAN",
"MIXOLYDIAN",
"LOCRIAN",
"PERSIAN",
"HUNGARIAN MINOR",
"IWATO",
"IN-SEN",
"HIRAJOSHI",
};
typedef u8 Scale[12];
Scale scales[] = {
// 1 b2 2 b3 3 4 b5 5 b6 6 b7 7 <- Major
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // CHRM
{1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1}, // MAJR
{1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0}, // MINR
{1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0}, // PMAJ
{1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0}, // PMIN
{1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0}, // BLUE
{1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0}, // DORI
{1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0}, // PHYR
{1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1}, // LYDI
{1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0}, // MIXO
{1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0}, // LOCR
{1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1}, // PERS
{1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1}, // HMIN
{1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0}, // IWAT
{1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0}, // INSN
{1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0}, // HIRA
};
s32
scale_note(s32 current, s32 inc) {
if (inc > 1 || inc < -1) {
return CLAMP(current + inc, (s32)NOTE_C_2, (s32)NOTE_C_8 - 1);
}
s32 pos = current % 12;
s32 offset = 0;
for (int i = 1; i <= 12; i++) {
s32 k = (pos - current_scale_root + i * inc) % 12;
if (k < 0) {
k *= -1;
k = 12 - k;
}
offset += inc;
if (scales[current_scale][k] == 1) {
break;
}
}
return CLAMP(current + offset, (s32)NOTE_C_2, (s32)NOTE_C_8 - 1);
}
|