Skip to content

Commit 2bd52b6

Browse files
committed
Update Scale and Arpeggiator
1 parent 402495c commit 2bd52b6

2 files changed

Lines changed: 102 additions & 17 deletions

File tree

Arpeggiator.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,6 @@ class Arpeggiator
8888
*/
8989
juce::MidiBuffer processBlock(int numSamples)
9090
{
91-
// std::cout << "In Arpeggiator::processBlock()" << std::endl;
92-
// std::cout << "samplesPerNote = " << samplesPerNote << std::endl;
93-
// std::cout << "samplesUntilNextNote = " << samplesUntilNextNote << std::endl;
94-
95-
// std::cout << "numSamples = " << numSamples << std::endl;
96-
// std::cout << "pattern = " << pattern << std::endl;
97-
// std::cout << "sampleRate = " << sampleRate << std::endl;
98-
9991
juce::MidiBuffer generatedMidi;
10092
if (sampleRate <= 0.0 || samplesPerNote <= 0.0 || pattern.isEmpty())
10193
return generatedMidi;
@@ -161,16 +153,20 @@ class Arpeggiator
161153
char octaveCommand = pattern[pos];
162154
pos = (pos + 1) % pattern.length(); // Consume octave command
163155

164-
// Start with the current global octave to calculate the new value.
165-
int targetOctave = octave;
156+
// Determine the starting point for this calculation.
157+
// If a local octave is already set for this step, use it. Otherwise, use the global octave.
158+
int currentStepOctave = (localOctave != -1) ? localOctave : octave;
159+
int targetOctave = currentStepOctave;
166160

167161
if (octaveCommand == '+')
168-
targetOctave = juce::jmin(7, octave + 1);
162+
targetOctave = juce::jmin(7, currentStepOctave + 1);
169163
else if (octaveCommand == '-')
170-
targetOctave = juce::jmax(0, octave - 1);
164+
targetOctave = juce::jmax(0, currentStepOctave - 1);
171165
else if (juce::CharacterFunctions::isDigit(octaveCommand))
172166
targetOctave = octaveCommand - '0'; // Correctly convert char '0'-'7' to int 0-7
173167

168+
// For both 'o' and 'O', we first set the localOctave for the current step's parsing.
169+
// If it's 'O', we'll also promote it to the global octave later.
174170
if (command == 'o')
175171
localOctave = targetOctave;
176172
else // 'O'
@@ -584,6 +580,8 @@ class Arpeggiator
584580
case 5: return 6.0; // 1/16T
585581
case 6: return 8.0; // 1/32
586582
case 7: return 12.0; // 1/32T
583+
case 8: return 16.0; // 1/64
584+
case 9: return 24.0; // 1/64T
587585
default: return 4.0;
588586
}
589587
}

MidiTools.h

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,36 @@ namespace MidiTools
4848
/** The available scale types. */
4949
enum class Type
5050
{
51+
// Major Scale Modes
5152
Major,
53+
Dorian,
54+
Phrygian,
55+
Lydian,
56+
Mixolydian,
57+
Aeolian,
58+
Locrian,
59+
// Melodic Minor Modes
5260
MelodicMinor,
61+
Dorianb9,
62+
LydianSharp5,
63+
Lydianb7, // Previously Bartok
64+
Mixolydianb13,
65+
LocrianNatural9,
66+
Altered,
67+
// Harmonic Minor Modes
5368
HarmonicMinor,
54-
Bartok
69+
LocrianNatural6,
70+
IonianSharp5,
71+
DorianSharp4,
72+
PhrygianDominant,
73+
LydianSharp2,
74+
Altered_bb7,
75+
// Other 7-note scales
76+
HarmonicMajor,
77+
DoubleHarmonicMajor,
78+
HungarianMinor,
79+
NeapolitanMajor,
80+
NeapolitanMinor
5581
};
5682

5783
/**
@@ -88,14 +114,75 @@ namespace MidiTools
88114
return notes;
89115
}
90116

117+
/** Returns an ordered list of names for all available scale types. */
118+
static const juce::StringArray& getScaleTypeNames()
119+
{
120+
static const juce::StringArray names = {
121+
// Major Scale Modes
122+
"Major (Ionian)",
123+
"Dorian",
124+
"Phrygian",
125+
"Lydian",
126+
"Mixolydian",
127+
"Aeolian",
128+
"Locrian",
129+
// Melodic Minor Modes
130+
"Melodic Minor",
131+
"Dorian b9",
132+
"Lydian #5",
133+
"Lydian b7 (Bartok)",
134+
"Mixolydian b13",
135+
"Locrian Natural 9",
136+
"Altered",
137+
// Harmonic Minor Modes
138+
"Harmonic Minor",
139+
"Locrian Natural 6",
140+
"Ionian #5",
141+
"Dorian #4",
142+
"Phrygian Dominant",
143+
"Lydian #2",
144+
"Altered bb7 (Ultralocrian)",
145+
// Other 7-note scales
146+
"Harmonic Major",
147+
"Double Harmonic Major",
148+
"Hungarian Minor",
149+
"Neapolitan Major",
150+
"Neapolitan Minor"
151+
};
152+
return names;
153+
}
154+
91155
private:
92156
void buildScale(int rootSemitone, Type scaleType)
93157
{
94158
static const std::map<Type, juce::Array<int>> scaleIntervals = {
95-
{Type::Major, {0, 2, 4, 5, 7, 9, 11}},
96-
{Type::MelodicMinor, {0, 2, 3, 5, 7, 9, 11}},
97-
{Type::HarmonicMinor, {0, 2, 3, 5, 7, 8, 11}},
98-
{Type::Bartok, {0, 2, 4, 6, 7, 9, 10}} // Lydian Dominant
159+
{Type::Major, {0, 2, 4, 5, 7, 9, 11}}, // Ionian
160+
{Type::Dorian, {0, 2, 3, 5, 7, 9, 10}},
161+
{Type::Phrygian, {0, 1, 3, 5, 7, 8, 10}},
162+
{Type::Lydian, {0, 2, 4, 6, 7, 9, 11}},
163+
{Type::Mixolydian, {0, 2, 4, 5, 7, 9, 10}},
164+
{Type::Aeolian, {0, 2, 3, 5, 7, 8, 10}},
165+
{Type::Locrian, {0, 1, 3, 5, 6, 8, 10}},
166+
{Type::MelodicMinor, {0, 2, 3, 5, 7, 9, 11}},
167+
{Type::Dorianb9, {0, 1, 3, 5, 7, 9, 10}},
168+
{Type::LydianSharp5, {0, 2, 4, 6, 8, 9, 11}},
169+
{Type::Lydianb7, {0, 2, 4, 6, 7, 9, 10}}, // Bartok / Lydian Dominant
170+
{Type::Mixolydianb13, {0, 2, 4, 5, 7, 8, 10}},
171+
{Type::LocrianNatural9, {0, 2, 3, 5, 6, 8, 10}},
172+
{Type::Altered, {0, 1, 3, 4, 6, 8, 10}},
173+
{Type::HarmonicMinor, {0, 2, 3, 5, 7, 8, 11}},
174+
{Type::LocrianNatural6, {0, 1, 3, 5, 6, 9, 10}},
175+
{Type::IonianSharp5, {0, 2, 4, 5, 8, 9, 11}},
176+
{Type::DorianSharp4, {0, 2, 3, 6, 7, 9, 10}},
177+
{Type::PhrygianDominant,{0, 1, 4, 5, 7, 8, 10}},
178+
{Type::LydianSharp2, {0, 3, 4, 6, 7, 9, 11}},
179+
{Type::Altered_bb7, {0, 1, 3, 4, 6, 8, 9}},
180+
// Other 7-note scales
181+
{Type::HarmonicMajor, {0, 2, 4, 5, 7, 8, 11}},
182+
{Type::DoubleHarmonicMajor, {0, 1, 4, 5, 7, 8, 11}},
183+
{Type::HungarianMinor, {0, 2, 3, 6, 7, 8, 11}},
184+
{Type::NeapolitanMajor, {0, 1, 4, 5, 7, 9, 11}},
185+
{Type::NeapolitanMinor, {0, 1, 3, 5, 7, 8, 11}}
99186
};
100187

101188
const auto& intervals = scaleIntervals.at(scaleType);

0 commit comments

Comments
 (0)