@@ -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
0 commit comments