// title: more fun with patternproxies, feat. a hack to access internals of the EventStreamPlayer // author: alln4tural // description: // possibly too-detailed demo of using functions to generate patterns, and then a function to modify the internals of the resulting EventStreamPlayers while they are running. // // * This latter function uses a sort of hack (thanks to [Jonatan](http://sccode.org/kymatica), see discussion on sc-users [here](http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/getting-at-an-EventStreamPlayer-s-Pbind-tp7586138p7586148.html)) to get at the arrays inside the patternpairs of the patternproxy inside the 'receiver' inside the stream of the player. // `z = i.stream.slotAt('receiver');` // // * The point here is that using this technique, one need not maintain administrative data about the patterns themselves -- one only has to remember the players as they are being created. // // ` // ` // and the meta-point here, beyond me having fun figuring out markdown, is that i would like to make an argument for a less hacky way of legally getting at an EventStreamPlayer's progenitor Pattern. // // // // * [http://soundcloud.com/all-n4tural/constant-blues-acapella-rmx](http://soundcloud.com/all-n4tural/constant-blues-acapella-rmx) // * [http://soundcloud.com/all-n4tural/worldwide-razzledazzle](http://soundcloud.com/all-n4tural/worldwide-razzledazzle) // code: // switching to mono cz SinedPink.aiff is boring // two BufRd-based synths, one percussive, one smoother: ( SynthDef(\bufRdperc1, {| out = 0, bufnum = 0, rate=1, inter=2, posfrac = 0.5, dur = 1, amp = 0.9| var widthfrac = (dur/BufDur.ir(bufnum)) * rate; var sig = Splay.ar([ BufRd.ar(1, bufnum, Phasor.ar( 0, (BufRateScale.kr(bufnum) * rate), (posfrac * BufSamples.kr(bufnum)), (posfrac * BufSamples.kr(bufnum)) + (widthfrac * BufSamples.kr(bufnum))), 1, inter) ]); Out.ar(out, sig * EnvGen.kr(Env.perc,1,1,0,dur,2) * amp ) }).add; SynthDef(\bufRdsmooth1, {| out = 0, bufnum = 0, rate=1, inter=2, posfrac = 0.5, dur = 1, amp = 1| var widthfrac = ((dur/2)/BufDur.ir(bufnum)) * rate; var forward = BufRd.ar(1, bufnum, Phasor.ar( 0, (BufRateScale.kr(bufnum) * rate.abs), (posfrac * BufSamples.kr(bufnum)) - (widthfrac * BufSamples.kr(bufnum)), (posfrac * BufSamples.kr(bufnum)) + (widthfrac * BufSamples.kr(bufnum))), 1, inter); var backward = BufRd.ar(1, bufnum, Phasor.ar( 0, (BufRateScale.kr(bufnum) * rate.abs * (-1)), (posfrac * BufSamples.kr(bufnum)) + (widthfrac * BufSamples.kr(bufnum)), (posfrac * BufSamples.kr(bufnum)) - (widthfrac * BufSamples.kr(bufnum))), 1, inter); var sound = BiPanB2.ar(forward,backward,FSinOsc.kr(dur)); sound = sound * EnvGen.kr(Env.sine,1,1,0,dur,2); sound = sound * amp; Out.ar(out, sound); }).add; ) // // two functions that generate Pbinds ( ~make1perc = { |durs, lib| var n = durs.size; Pbind( \bufnum, PatternProxy(Pseq({lib.choose}!n,inf)), \rate, PatternProxy(Pseq([1],inf)), \posfrac, PatternProxy(Pseq({512.rand/512}!n,inf)), \dur, PatternProxy(Pseq(durs,inf)), \amp, PatternProxy(Pseq({(1..3).choose}!n,inf)), \instrument,PatternProxy(Pfunc({ |ev| ("bufRdperc" ++ ev[\bufnum].numChannels) })) ); }; ~make1smooth = { |durs, lib| var n = durs.size; Pbind( \bufnum, PatternProxy(Pseq({lib.choose}!n,inf)), \rate, PatternProxy(Pseq([1],inf)), \posfrac, PatternProxy(Pseq({512.rand/512}!n,inf)), \dur, PatternProxy(Pseq(durs,inf)), \amp, PatternProxy(Pseq({(1..3).choose}!n,inf)), \instrument,PatternProxy(Pfunc({ |ev| ("bufRdsmooth" ++ ev[\bufnum].numChannels) })) ); }; // // // the function with the hack to get at, and modify while running, the internals of the patterns ~frac = { |n = 1| ~players.do{ |i| var z = i.stream.slotAt('receiver'); // the hack. it wd be nice to have legal method for this z.patternpairs.at(z.patternpairs.indexOf('posfrac') + 1).source = Pseq({512.rand/512}!n,inf) } }; ) // // // // fun things to execute at runtime // /* ~buffers is an array of mono Buffers. if you don't have any, you can do ~buffers = [Buffer.read(s, Platform.resourceDir ++ "/sounds/a11wlk01.wav")]; */ [1/8, 1/4, 1/2].do{|i| ~players = ~players.add((~make1perc.([i], [~buffers.choose])).play)} 1.do{~players = ~players.add((~make1smooth.([1], [~buffers.choose])).play)} ~frac.(); ~frac.(x = 1); ~frac.(x = x*2); ~frac.(x = x+2); ~frac.(x.postln); ~players.pop.stop;