@@ -9,6 +9,7 @@ void arpeggiator_init(Arpeggiator *arp) {
99 memset (arp -> pattern , 0 , sizeof (arp -> pattern )); // Initialize pattern to all zeros
1010 arp -> step = 0 ;
1111 arp -> tempo = 120.0f ;
12+ arp -> rate = RATE_EIGHTH ;
1213 arp -> step_phase = 0.0f ;
1314 arp -> held_count = 0 ;
1415 memset (arp -> held_notes , 0 , sizeof (arp -> held_notes ));
@@ -17,6 +18,15 @@ void arpeggiator_init(Arpeggiator *arp) {
1718 arp -> hold = 1 ;
1819 arp -> octave = 0 ;
1920 arp -> octaves = 3 ;
21+
22+ // Initialize chord generation parameters
23+ arp -> chord_type = CHORD_MAJOR ;
24+ arp -> add_6 = 0 ;
25+ arp -> add_m7 = 0 ;
26+ arp -> add_M7 = 0 ;
27+ arp -> add_9 = 0 ;
28+ arp -> voicing = 0 ;
29+
2030 for (int i = 0 ; i < 16 ; ++ i ) {
2131 arp -> active_arpeggiated_notes [i ].active = 0 ;
2232 }
@@ -35,6 +45,8 @@ void arpeggiator_set_param(Arpeggiator *arp, const char *param, float value, str
3545 arp -> mode = (ArpMode )((int )value );
3646 else if (!strcmp (param , "tempo" ))
3747 arp -> tempo = value ;
48+ else if (!strcmp (param , "rate" ))
49+ arp -> rate = (ArpRate )((int )value );
3850 else if (!strcmp (param , "polyphonic" ))
3951 arp -> polyphonic = (int )value ;
4052 else if (!strcmp (param , "hold" )) {
@@ -49,6 +61,18 @@ void arpeggiator_set_param(Arpeggiator *arp, const char *param, float value, str
4961 arp -> octave = (int )value ;
5062 else if (!strcmp (param , "octaves" ))
5163 arp -> octaves = (int )value ;
64+ else if (!strcmp (param , "chord_type" ))
65+ arp -> chord_type = (ChordType )((int )value );
66+ else if (!strcmp (param , "add_6" ))
67+ arp -> add_6 = (int )value ;
68+ else if (!strcmp (param , "add_m7" ))
69+ arp -> add_m7 = (int )value ;
70+ else if (!strcmp (param , "add_M7" ))
71+ arp -> add_M7 = (int )value ;
72+ else if (!strcmp (param , "add_9" ))
73+ arp -> add_9 = (int )value ;
74+ else if (!strcmp (param , "voicing" ))
75+ arp -> voicing = (int )value ;
5276}
5377
5478void arpeggiator_note_on (Arpeggiator * arp , int note ) {
@@ -159,6 +183,41 @@ int arpeggiator_step(Arpeggiator *arp, float samplerate, struct Synth *synth) {
159183 } else {
160184 // Monophonic behavior (existing logic)
161185 switch (arp -> mode ) {
186+ case ARP_CHORD : {
187+ // Generate chord from the first held note (root)
188+ if (arp -> held_count > 0 ) {
189+ int chord_notes [8 ];
190+ int note_count = arpeggiator_generate_chord (arp , notes [0 ], chord_notes , 8 );
191+
192+ // Apply octave spread if requested
193+ int notes_to_play [8 ];
194+ int actual_count = 0 ;
195+ for (int i = 0 ; i < note_count && actual_count < 8 ; ++ i ) {
196+ int base_note = chord_notes [i ];
197+ for (int oct = 0 ; oct < arp -> octaves && actual_count < 8 ; ++ oct ) {
198+ notes_to_play [actual_count ++ ] = base_note + (arp -> octave * 12 ) + (oct * 12 );
199+ }
200+ }
201+
202+ // Play all chord notes simultaneously
203+ for (int i = 0 ; i < actual_count ; ++ i ) {
204+ int free_slot = -1 ;
205+ for (int j = 0 ; j < 16 ; ++ j ) {
206+ if (!arp -> active_arpeggiated_notes [j ].active ) {
207+ free_slot = j ;
208+ break ;
209+ }
210+ }
211+ if (free_slot != -1 ) {
212+ arp -> active_arpeggiated_notes [free_slot ].note = notes_to_play [i ];
213+ arp -> active_arpeggiated_notes [free_slot ].remaining_duration = step_time ;
214+ arp -> active_arpeggiated_notes [free_slot ].active = 1 ;
215+ synth_note_on (synth , notes_to_play [i ], 0.8f );
216+ }
217+ }
218+ }
219+ break ;
220+ }
162221 case ARP_UP :
163222 qsort (notes , arp -> held_count , sizeof (int ), order_compare );
164223 idx = arp -> step % arp -> held_count ;
@@ -176,38 +235,160 @@ int arpeggiator_step(Arpeggiator *arp, float samplerate, struct Synth *synth) {
176235 default :
177236 idx = 0 ;
178237 }
179- int note_to_play = notes [idx ];
180238
181- // Find a free slot for the new note
182- int free_slot = -1 ;
183- for (int j = 0 ; j < 16 ; ++ j ) {
184- if (!arp -> active_arpeggiated_notes [j ].active ) {
185- free_slot = j ;
186- break ;
239+ if (arp -> mode != ARP_CHORD ) {
240+ int note_to_play = notes [idx ];
241+
242+ // Find a free slot for the new note
243+ int free_slot = -1 ;
244+ for (int j = 0 ; j < 16 ; ++ j ) {
245+ if (!arp -> active_arpeggiated_notes [j ].active ) {
246+ free_slot = j ;
247+ break ;
248+ }
249+ }
250+ if (free_slot != -1 ) {
251+ arp -> active_arpeggiated_notes [free_slot ].note = note_to_play ;
252+ arp -> active_arpeggiated_notes [free_slot ].remaining_duration = step_time ; // Note duration is one step
253+ arp -> active_arpeggiated_notes [free_slot ].active = 1 ;
254+ synth_note_on (synth , note_to_play , 0.8f );
187255 }
188- }
189- if (free_slot != -1 ) {
190- arp -> active_arpeggiated_notes [free_slot ].note = note_to_play ;
191- arp -> active_arpeggiated_notes [free_slot ].remaining_duration = step_time ; // Note duration is one step
192- arp -> active_arpeggiated_notes [free_slot ].active = 1 ;
193- synth_note_on (synth , note_to_play , 0.8f );
194256 }
195257 }
196258
197259 arp -> step ++ ;
198260 return 0 ; // Return 0 to indicate success
199261}
200262
263+ int arpeggiator_generate_chord (const Arpeggiator * arp , int root_note , int * chord_notes , int max_notes ) {
264+ if (!chord_notes || max_notes < 8 ) return 0 ;
265+
266+ int note_count = 0 ;
267+ int root_in_octave = root_note % 12 ;
268+ int octave = root_note / 12 ;
269+
270+ // Basic chord tones based on chord type
271+ switch (arp -> chord_type ) {
272+ case CHORD_MAJOR :
273+ chord_notes [note_count ++ ] = root_note ;
274+ chord_notes [note_count ++ ] = root_note + 4 ; // Major third
275+ chord_notes [note_count ++ ] = root_note + 7 ; // Perfect fifth
276+ break ;
277+ case CHORD_MINOR :
278+ chord_notes [note_count ++ ] = root_note ;
279+ chord_notes [note_count ++ ] = root_note + 3 ; // Minor third
280+ chord_notes [note_count ++ ] = root_note + 7 ; // Perfect fifth
281+ break ;
282+ case CHORD_SUS :
283+ chord_notes [note_count ++ ] = root_note ;
284+ chord_notes [note_count ++ ] = root_note + 5 ; // Perfect fourth
285+ chord_notes [note_count ++ ] = root_note + 7 ; // Perfect fifth
286+ break ;
287+ case CHORD_DIM :
288+ chord_notes [note_count ++ ] = root_note ;
289+ chord_notes [note_count ++ ] = root_note + 3 ; // Minor third
290+ chord_notes [note_count ++ ] = root_note + 6 ; // Diminished fifth
291+ break ;
292+ }
293+
294+ // Add extensions if enabled
295+ if (arp -> add_6 && note_count < max_notes ) {
296+ chord_notes [note_count ++ ] = root_note + 9 ; // Sixth
297+ }
298+ if (arp -> add_m7 && note_count < max_notes ) {
299+ chord_notes [note_count ++ ] = root_note + 10 ; // Minor seventh
300+ }
301+ if (arp -> add_M7 && note_count < max_notes ) {
302+ chord_notes [note_count ++ ] = root_note + 11 ; // Major seventh
303+ }
304+ if (arp -> add_9 && note_count < max_notes ) {
305+ chord_notes [note_count ++ ] = root_note + 14 ; // Ninth (one octave above second)
306+ }
307+
308+ // Apply voicing/inversion if specified
309+ 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 ];
316+ }
317+ chord_notes [note_count - 1 ] = bass_note + 12 ;
318+ }
319+ }
320+
321+ return note_count ;
322+ }
323+
324+ const char * arpeggiator_rate_str (const Arpeggiator * arp ) {
325+ switch (arp -> rate ) {
326+ case RATE_QUARTER :
327+ return "1/4" ;
328+ case RATE_EIGHTH :
329+ return "1/8" ;
330+ case RATE_SIXTEENTH :
331+ return "1/16" ;
332+ case RATE_THIRTYSECOND :
333+ return "1/32" ;
334+ default :
335+ return "-" ;
336+ }
337+ }
338+
339+ const char * arpeggiator_chord_str (const Arpeggiator * arp ) {
340+ switch (arp -> chord_type ) {
341+ case CHORD_MAJOR :
342+ return "MAJ" ;
343+ case CHORD_MINOR :
344+ return "MIN" ;
345+ case CHORD_SUS :
346+ return "SUS" ;
347+ case CHORD_DIM :
348+ return "DIM" ;
349+ default :
350+ return "-" ;
351+ }
352+ }
353+
201354const char * arpeggiator_mode_str (const Arpeggiator * arp ) {
202355 switch (arp -> mode ) {
356+ case ARP_OFF :
357+ return "OFF" ;
358+ case ARP_CHORD :
359+ return "CHORD" ;
203360 case ARP_UP :
204361 return "UP" ;
205362 case ARP_DOWN :
206363 return "DOWN" ;
207- case ARP_ORDER :
208- return "ORDER" ;
364+ case ARP_UP_DOWN :
365+ return "UP_DOWN" ;
366+ case ARP_PENDULUM :
367+ return "PENDULUM" ;
368+ case ARP_CONVERGE :
369+ return "CONVERGE" ;
370+ case ARP_DIVERGE :
371+ return "DIVERGE" ;
372+ case ARP_LEAPFROG :
373+ return "LEAPFROG" ;
374+ case ARP_THUMB_UP :
375+ return "THUMB_UP" ;
376+ case ARP_THUMB_DOWN :
377+ return "THUMB_DOWN" ;
378+ case ARP_PINKY_UP :
379+ return "PINKY_UP" ;
380+ case ARP_PINKY_DOWN :
381+ return "PINKY_DOWN" ;
382+ case ARP_REPEAT :
383+ return "REPEAT" ;
209384 case ARP_RANDOM :
210385 return "RANDOM" ;
386+ case ARP_RANDOM_WALK :
387+ return "RANDOM_WALK" ;
388+ case ARP_SHUFFLE :
389+ return "SHUFFLE" ;
390+ case ARP_ORDER :
391+ return "ORDER" ;
211392 default :
212393 return "-" ;
213394 }
0 commit comments