// osk -- offener schaltkreis // 2010 arnolfini bristol // christoph haag, martin rumori, franziska windisch, ludwig zeller // thanks to anselm bilbo bauer ( // globals q = q ? (); // print algorithmic status messages q.verbose = false; // global volume q.volume = -12.dbamp; // soundfile location q.sfpath = "/opt/osk/snd".standardizePath; q.files = [ [ q.sfpath +/+ "1.wav", -6.dbamp ], [ q.sfpath +/+ "2.wav", -6.dbamp ], [ q.sfpath +/+ "3n.wav", -6.dbamp ], [ q.sfpath +/+ "4n.wav", -6.dbamp ], [ q.sfpath +/+ "5n.wav", -6.dbamp ], [ q.sfpath +/+ "6.wav", -6.dbamp ], [ q.sfpath +/+ "7n.wav", -6.dbamp ], [ q.sfpath +/+ "8n.wav", -6.dbamp ] ]; ); ( // synthdefs // grain player SynthDef.new(\oskgrain, { arg out, gain, playgain, limitgain, bufnum, start, transp, attack = 0.1, sustain = 0.1, release = 0.1; var env, sig, envsig, outsig; env = EnvGen.ar(Env.linen(attack, sustain, release), doneAction: 2); sig = playgain * PlayBuf.ar(1, bufnum, transp * BufRateScale.kr(bufnum), 1.0, start, loop: 1, doneAction: 0); envsig = env * sig; outsig = gain * Limiter.ar(HPF.ar(envsig, 60), limitgain, 0.1); Out.ar(out, outsig); }).store; // loop player SynthDef.new(\oskloop, { arg out, gain = 0.5, bufnum; Out.ar(out, gain * PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum), loop: 1)); }).store; ); ( // startup s.waitForBoot({{ "osk startup sequence initiated...".postln; // load files "loading soundfiles...".postln; q.buffers = q.files.collect({ arg f; Buffer.read(s, f[0], action: { arg buf; "finished loading %\n".postf(buf.path); }); }); s.sync; "% soundfiles loaded.\n".postf(q.files.size); // algorithmic osk processes // global activity pattern q.act = Pbind.new(\act, Pbrown.new(0.0, 1.0, 0.05, inf)); // local pattern q.osks = q.files.collect({ arg f, i; Pbindf.new(q.act, \instrument, \oskgrain, \gain, Pfunc.new({ q.volume; }), \playgain, q.files[i][1], \limitgain, -12.dbamp, \finish, { ~start = rrand(0, q.buffers[i].numFrames); ~laststart = ~start; ~dur = ~act.linexp(0.0, 1.0, q.buffers[i].duration, 0.1) * rrand(0.5, 2.0); ~transp = 1.0.perform([ '*', '/' ].choose, rrand(1.0, ~act.linlin(0.0, 1.0, 1.0, 2.0))); ~attack = ~dur * 0.1; ~release = ~dur * 0.1; ~sustain = ~dur - ~release; ~bufnum = [ [ q.buffers[i] ], q.buffers ].wchoose([ 1 - ~act, ~act ]).choose; ~out = i; if (q.verbose, { "osk%: act % start at %s dur %s transp % from file %\n".postf(i, ~act.round(0.01), (~start / s.sampleRate).round(0.1), ~dur.round(0.1), ~transp.round(0.1), ~bufnum.path.basename); }); }); }); // osk players q.players = q.osks.collect({ arg p; p.play; }); // notify about volume "% algorithmic osk players started.\n".postf(q.players.size); "verbose is %.\n".postf(if (q.verbose, "ON", "OFF")); "global volume set to % dB.\n".postf(q.volume.ampdb); }.fork}); ); // stop players // q.players.do({ arg p; p.stop; }); // verbose // q.verbose = true; // q.verbose = false; // ( // simple loop players // q.synths = q.buffers.do({ arg buf, i; // Synth.new(\oskloop, [ \out, i, \bufnum, buf ]); }); // ) // stop simple loop players // q.synths.do({ arg syn; syn.free; }); // free buffers // q.buffers.do({ arg buf; buf.free; }); // EOF