Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
preset_scales.h
1#pragma once
2
3#include "model/scale/note_set.h"
4
5#include <array>
6#include <bitset>
7#include <cstdint>
8
9/* This "defines" all preset scales in one place, so the various tables they inhabit
10 * automatically stay in sync.
11 *
12 * NOTE: songs currently store scales as modeNotes, making them reasonably robust to
13 * redefinitions, but the default scale is stored in the flash storage as an index.
14 * See OFFSET_6|5_NOTE_SCALE for how to deal with that.
15 *
16 * The actual definitions expand this macro, picking the thing they need:
17 * - enum Scale
18 * - scalelikeNames
19 * - presetScaleNotes
20 *
21 * Use by defining DEF(id, name, notes) before invoking DEF_SCALES() and undefining it
22 * after.
23 *
24 * DEF_NOTES keeps the notes array intact on the trip through the preprocessor, since
25 * cpp doesn't understand arrays, seeing { and } as a normal tokens.
26 */
27#define DEF_NOTES(...) NoteSet({__VA_ARGS__})
28
29// Note: Value of note intervals taken from here: https://www.apassion4jazz.net/scales2.html
30#define DEF_SCALES() \
31 /* ============================== 7-note scales ============================== */ \
32 /* ------------- ORIGINAL DELUGE SCALES: modes of the major scale ------------ */ \
33 /* MAJO Major (Ionian) */ \
34 DEF(MAJOR_SCALE, "MAJOR", DEF_NOTES(0, 2, 4, 5, 7, 9, 11)) \
35 /* MINO Natural Minor (Aeolian) */ \
36 DEF(MINOR_SCALE, "MINOR", DEF_NOTES(0, 2, 3, 5, 7, 8, 10)) \
37 /* DORI Dorian (minor with raised 6th) */ \
38 DEF(DORIAN_SCALE, "DORIAN", DEF_NOTES(0, 2, 3, 5, 7, 9, 10)) \
39 /* PHRY Phrygian (minor with flattened 2nd) */ \
40 DEF(PHRYGIAN_SCALE, "PHRYGIAN", DEF_NOTES(0, 1, 3, 5, 7, 8, 10)) \
41 /* LYDI Lydian (major with raised 4th) */ \
42 DEF(LYDIAN_SCALE, "LYDIAN", DEF_NOTES(0, 2, 4, 6, 7, 9, 11)) \
43 /* MIXO Mixolydian (major with flattened 7th) */ \
44 DEF(MIXOLYDIAN_SCALE, "MIXOLYDIAN", DEF_NOTES(0, 2, 4, 5, 7, 9, 10)) \
45 /* LOCR Locrian (minor with flattened 2nd and 5th) */ \
46 DEF(LOCRIAN_SCALE, "LOCRIAN", DEF_NOTES(0, 1, 3, 5, 6, 8, 10)) \
47 /* ------------- NEW SCALES START HERE --------------------------------------- */ \
48 /* MELO Melodic Minor (Ascending) (matches Launchpad scale) */ \
49 DEF(MELODIC_MINOR_SCALE, "MELODIC MINOR", DEF_NOTES(0, 2, 3, 5, 7, 9, 11)) \
50 /* HARM Harmonic Minor (matches Launchpad and Lumi scale) */ \
51 DEF(HARMONIC_MINOR_SCALE, "HARMONIC MINOR", DEF_NOTES(0, 2, 3, 5, 7, 8, 11)) \
52 /* Exotic scales */ \
53 /* HUNG Hungarian Minor (matches Launchpad scale) */ \
54 DEF(HUNGARIAN_MINOR_SCALE, "HUNGARIAN MINOR", DEF_NOTES(0, 2, 3, 6, 7, 8, 11)) \
55 /* MARV Marva (matches Launchpad scale) */ \
56 DEF(MARVA_SCALE, "MARVA", DEF_NOTES(0, 1, 4, 6, 7, 9, 11)) \
57 /* ARAB Arabian (matches Lumi's ARABIC_B scale) */ \
58 DEF(ARABIAN_SCALE, "ARABIAN", DEF_NOTES(0, 2, 4, 5, 6, 8, 10)) \
59 /* ============================== 6-note scales ============================== */ \
60 /* WHOL Whole Tone (matches Launchpad and Lumi scale) */ \
61 DEF(WHOLE_TONE_SCALE, "WHOLE TONE", DEF_NOTES(0, 2, 4, 6, 8, 10, 0)) \
62 /* BLUE Blues Minor (matches Launchpad and Lumi BLUES scale) */ \
63 DEF(BLUES_SCALE, "BLUES", DEF_NOTES(0, 3, 5, 6, 7, 10, 0)) \
64 /* ============================== 5-note scales ============================== */ \
65 /* PENT Pentatonic Minor (matches Launchpad and Lumi scale) */ \
66 DEF(PENTATONIC_MINOR_SCALE, "PENTATONIC MINOR", DEF_NOTES(0, 3, 5, 7, 10)) \
67 /* HIRA Hirajoshi (matches Launchpad scale) */ \
68 DEF(HIRAJOSHI_SCALE, "HIRAJOSHI", DEF_NOTES(0, 2, 3, 7, 8))
69
73enum Scale : uint8_t {
74#define DEF(id, name, notes) id,
75 DEF_SCALES()
76#undef DEF
77 // clang-format off
78 LAST_PRESET_SCALE = HIRAJOSHI_SCALE,
79 NUM_PRESET_SCALES,
80 USER_SCALE = NUM_PRESET_SCALES,
81 NUM_ALL_SCALES,
82 RANDOM_SCALE = NUM_ALL_SCALES,
83 NO_SCALE,
84 NUM_SCALELIKE
85 // clang-format on
86};
87
88#define FIRST_6_NOTE_SCALE_INDEX WHOLE_TONE_SCALE
89#define FIRST_5_NOTE_SCALE_INDEX PENTATONIC_MINOR_SCALE
90
91// These are scale ids / indexes as stored in flash memory, by the official
92// firmware.
93#define OFFICIAL_FIRMWARE_RANDOM_SCALE_INDEX 7
94#define OFFICIAL_FIRMWARE_NONE_SCALE_INDEX 8
95
96extern const NoteSet presetScaleNotes[NUM_PRESET_SCALES];
97extern std::array<char const*, NUM_SCALELIKE> scalelikeNames;
98
99const char* getScaleName(Scale scale);
100
101Scale getScale(NoteSet notes);
102
103bool isUserScale(NoteSet notes);
104
105void ensureNotAllPresetScalesDisabled(std::bitset<NUM_PRESET_SCALES>& disabled);
106
107// When storing scale ids in the flash storage we have eg. RANDOM_SCALE and
108// NO_SCALE at 254 and 255 respectively, to leave rest of the range for future
109// scales, but at runtime it is nicer to have them contiguous.
110//
111// Similarly, there are gaps in the range for future 6-note and 5-note scales.
112//
113// So these two functions handle conversion from flash storage domain to
114// runtime domain.
115Scale flashStorageCodeToScale(uint8_t code);
116uint8_t scaleToFlashStorageCode(Scale scale);
Definition note_set.h:20