// title: midified arpeggiator/auto-accompaniment using patterns // author: 56228375 // description: // Proof of concept code for a midified arpeggiator/auto-accompaniment system, quickly reacting to chord changes // Midi is received as input, and supercollider's default instrument (I know, I know) is generating the output. // This code is accompaniment to a blog article at https://technogems.blogspot.com/2020/01/making-arpeggiator-in-supercollider.html // Let me know if you have ideas for improvement! (code-wise or feature-wise) // code: ( s.waitForBoot({ var right, left; var n0, n1, n2; var note_getter; MIDIdef.freeAll; if (~midi_initilized.isNil) { MIDIClient.init; MIDIIn.connectAll; ~midi_initialized = 1; }; ~note_table = 0!127; ~n = nil; MIDIdef.noteOn( \mynoteonhandler, // just a name for this handler { |val, num, chan, src| ~note_table[num] = 1; // update note table and update ~n ~n = ~note_table.selectIndices({|item, i| item != 0}); } ); MIDIdef.noteOff( \mynoteoffhandler, // just a name for this handler { |val, num, chan, src| ~note_table[num] = 0; // update note table and update ~n /* // only enable the following lines if you want the arpeggio to stop as soon as you release the keys ~n = ~note_table.selectIndices({|item, i| item != 0}); if (~n == []) { ~n = nil; }; */ } ); note_getter = { | index | Plazy { if (~n.isNil) { Pseq([Rest(1)]); } { ~n[index] ?? (~n[0] ?? Pseq([Rest(1)])); }; }; }; n0 = note_getter.(0); n1 = note_getter.(1); n2 = note_getter.(2); right = Pbind( \instrument, \default, \midinote, Pseq([ n0, n2, n1, n2] ++ (([ n0, n2, n1, n2] + 12)!2).flatten), \dur, Pseq([1, 1, 1, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ].normalizeSum*2) ); left = Pbind( \instrument, \default, \midinote, Pseq([ n0, n2, n0, n2, n0, n2, n0, n2] - 12), \dur, Pseq([1, 1, 1, 1, 1, 1, 1, 1].normalizeSum*2) ); if (~player.notNil) { ~player.stop; }; ~player = Pn(Ppar([right,left])).play; }); )