«Re: midified arpeggiator/auto-accompaniment using patterns» by elgiano
on 11 Jan'20 18:03 inRe: Let me know if you have ideas for improvement! (code-wise or feature-wise) -> I used an object prototype to streamline the process of registering notes and getting sequences of them. Code looks simpler to me and easier to further develop :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
( s.waitForBoot({ var right, left; MIDIdef.freeAll; if (~midi_initilized.isNil) { MIDIClient.init; MIDIIn.connectAll; ~midi_initialized = 1; }; ~n = ( table: Order(), noteOn: {|n,note| n.table[note] = 1}, noteOff: {|n,note| n.table.removeAt(note)}, get: {|n,i| n.table.indices[i] ?? n.table.indices.first ?? Rest(1) }, seq: {|n,notes| notes.asArray.collect{|i| Plazy{n.get(i)}} } ); MIDIdef.noteOn( \mynoteonhandler, // just a name for this handler { |val, num, chan, src| ~n.noteOn(num) } ); MIDIdef.noteOff( \mynoteoffhandler, // just a name for this handler { |val, num, chan, src| ~n.noteOff(num) // 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.table.clear */ } ); right = Pbind( \instrument, \default, \midinote, Pseq(~n.seq( [ 0, 2, 1, 2] ++ (([ 0, 2, 1, 2] + 12)!2).flatten )), \dur, 2*Pseq([1, 1, 1, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ].normalizeSum) ); left = Pbind( \instrument, \default, \midinote, Pseq(~n.seq([ 0, 2, 0, 2, 0, 2, 0, 2] - 12)), \dur, 2*Pseq([1, 1, 1, 1, 1, 1, 1, 1].normalizeSum) ); if (~player.notNil) { ~player.stop; }; ~player = Pn(Ppar([right,left])).play; }); )
reception
It looks much cleaner indeed. Great work! Thanks!!
hmm, on second thought your code produces a very different musical result from mine even though you didn't edit the pattern; it also stops the arpeggio when the notes are released. I'll need to examine in more detail why it's so different.
I see... you remove the notes from the table on noteOff. In my approach, I had an ~n which more or less corresponded to the "last active chord" and which remained intact even after the note off had come (this is more how autoaccompaniment works, and less how arpeggiators work). Anyway, it's a detail that should be fairly easy to adjust. I'm still a bit confused why your approach results in other notes being used than in my approach.
Ah I understand why your approach gives different notes now. In my approach I can do calculations on the "degrees" (e.g. I have a [ 0, 2, 1, 2] + 12 term in the "right" pattern). Since you rely on the indices in the Order object, it will return nil for a calculated degree. I guess the solution here would be not to use Order. (I had never heard about that class before your input :) )
(to clarify: the "nil" for a calculated degree eventually results in the first note of the chord being used instead of the expected degrees with transposition)
(How I wish I could edit my comments...) I used [ n0, n2, n1, n2 ] + 12, with n0-n2 functions, which allows for applying intuitive, arbitrarily complex transformations on the chord degrees. In your approach I'm not sure how that would best be done.