Skip to content

Commit 9966929

Browse files
committed
misc
1 parent 403c8fa commit 9966929

File tree

2 files changed

+108
-7
lines changed

2 files changed

+108
-7
lines changed

src/arpeggiator.c

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -307,14 +307,103 @@ int arpeggiator_generate_chord(const Arpeggiator *arp, int root_note, int *chord
307307

308308
// Apply voicing/inversion if specified
309309
if (arp->voicing > 0 && note_count > 1) {
310-
int inversion = arp->voicing % note_count;
311-
for (int i = 0; i < inversion; ++i) {
312-
int bass_note = chord_notes[0];
313-
// Move bass note up one octave
314-
for (int j = 0; j < note_count - 1; ++j) {
315-
chord_notes[j] = chord_notes[j + 1];
310+
int voicing_level = arp->voicing;
311+
312+
// Voicing levels 1-8: Basic inversions (rotate notes up by octaves)
313+
if (voicing_level <= 8) {
314+
int num_inversions = voicing_level % note_count;
315+
for (int i = 0; i < num_inversions; ++i) {
316+
int bass_note = chord_notes[0];
317+
// Move bass note up one octave
318+
for (int j = 0; j < note_count - 1; ++j) {
319+
chord_notes[j] = chord_notes[j + 1];
320+
}
321+
chord_notes[note_count - 1] = bass_note + 12;
322+
}
323+
}
324+
// Voicing levels 9-12: Drop voicings (drop 2, drop 3, etc.)
325+
else if (voicing_level <= 12 && note_count >= 3) {
326+
int drop_type = voicing_level - 8; // 1=drop2, 2=drop3, 3=drop2&4, 4=drop2&3
327+
int temp_notes[8];
328+
memcpy(temp_notes, chord_notes, sizeof(int) * note_count);
329+
330+
switch (drop_type) {
331+
case 1: // Drop 2
332+
if (note_count >= 2) {
333+
chord_notes[0] = temp_notes[0];
334+
chord_notes[1] = temp_notes[1] - 12; // Second down octave
335+
for (int i = 2; i < note_count; ++i) {
336+
chord_notes[i] = temp_notes[i];
337+
}
338+
}
339+
break;
340+
case 2: // Drop 3
341+
if (note_count >= 3) {
342+
chord_notes[0] = temp_notes[0];
343+
chord_notes[1] = temp_notes[1];
344+
chord_notes[2] = temp_notes[2] - 12; // Third down octave
345+
for (int i = 3; i < note_count; ++i) {
346+
chord_notes[i] = temp_notes[i];
347+
}
348+
}
349+
break;
350+
case 3: // Drop 2&4
351+
if (note_count >= 4) {
352+
chord_notes[0] = temp_notes[0];
353+
chord_notes[1] = temp_notes[1] - 12; // Second down octave
354+
chord_notes[2] = temp_notes[2];
355+
chord_notes[3] = temp_notes[3] - 12; // Fourth down octave
356+
for (int i = 4; i < note_count; ++i) {
357+
chord_notes[i] = temp_notes[i];
358+
}
359+
}
360+
break;
361+
case 4: // Drop 2&3
362+
if (note_count >= 3) {
363+
chord_notes[0] = temp_notes[0];
364+
chord_notes[1] = temp_notes[1] - 12; // Second down octave
365+
chord_notes[2] = temp_notes[2] - 12; // Third down octave
366+
for (int i = 3; i < note_count; ++i) {
367+
chord_notes[i] = temp_notes[i];
368+
}
369+
}
370+
break;
371+
}
372+
}
373+
// Voicing levels 13-16: Open/Spread voicings
374+
else {
375+
int spread_type = voicing_level - 12; // 1=open harmony, 2=wide spread, 3=clustered, 4=alternating octaves
376+
int temp_notes[8];
377+
memcpy(temp_notes, chord_notes, sizeof(int) * note_count);
378+
379+
switch (spread_type) {
380+
case 1: // Open harmony (spread notes across larger range)
381+
for (int i = 0; i < note_count; ++i) {
382+
chord_notes[i] = temp_notes[i] + (i * 5); // Spread by perfect 4ths
383+
}
384+
break;
385+
case 2: // Wide spread (alternating octaves)
386+
for (int i = 0; i < note_count; ++i) {
387+
chord_notes[i] = temp_notes[i] + ((i % 2) * 12); // Every other note up octave
388+
}
389+
break;
390+
case 3: // Clustered voicing (close harmony)
391+
// Keep notes close together in one octave range
392+
for (int i = 1; i < note_count; ++i) {
393+
while (chord_notes[i] - chord_notes[i-1] > 12) {
394+
chord_notes[i] -= 12;
395+
}
396+
while (chord_notes[i] - chord_notes[i-1] < 0) {
397+
chord_notes[i] += 12;
398+
}
399+
}
400+
break;
401+
case 4: // Alternating octaves (root position with octave displacement)
402+
for (int i = 0; i < note_count; ++i) {
403+
chord_notes[i] = temp_notes[i] + ((i / 2) * 12); // Groups of 2 in same octave
404+
}
405+
break;
316406
}
317-
chord_notes[note_count - 1] = bass_note + 12;
318407
}
319408
}
320409

src/gui.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,18 @@ void gui_draw(Synth *synth, SDL_Window *window, SDL_GLContext gl_context,
627627

628628
// Voicing
629629
ImGui::SliderInt("Voicing", &synth->arp.voicing, 0, 16, "%d");
630+
if (ImGui::IsItemHovered()) {
631+
const char* voicing_descriptions[] = {
632+
"Root Position",
633+
"1st Inversion", "2nd Inversion", "3rd Inversion", "4th Inversion",
634+
"5th Inversion", "6th Inversion", "7th Inversion", "8th Inversion",
635+
"Drop 2", "Drop 3", "Drop 2&4", "Drop 2&3",
636+
"Open Harmony", "Wide Spread", "Clustered", "Alternating Octaves"
637+
};
638+
if (synth->arp.voicing >= 0 && synth->arp.voicing <= 16) {
639+
ImGui::SetTooltip("%s", voicing_descriptions[synth->arp.voicing]);
640+
}
641+
}
630642

631643
ImGui::Separator();
632644
ImGui::Text("Presets:");

0 commit comments

Comments
 (0)