// title: CloudGenMiniBuf streamlined // author: LFSaw // description: // CloudGenMini for use with samples. // Replaced all global variables to be members of the Tdef(\cloud0)-own environment. // This should help to create several instances of CloudGenMiniBuf // code: //CmdPeriod at end of code is to be used to prevent filling all buffers //use shift-drag to change fadeTime by seconds //obviously replace ur own file pathNames into the variable y and re-execute code s.boot; ( q = Tdef(\cloud0).set.envir; // use Tdef's own envir for everything Routine.run{ q.soundPath = (Platform.resourceDir +/+ "sounds/a11wlk01.wav"); s.sync; q.buffer = Buffer.readChannel(s, q.soundPath, channels: [0]); s.sync; q.bufFrames = q.buffer.numFrames; s.sync; ( SynthDef(\bufGab, { |out, amp=0.1, rate=1.0, bend=1.0, pos=1, sustain=0.01, pan| var snd = HPF.ar((LPF.ar((PlayBuf.ar(1, q.buffer, Line.ar((rate*BufRateScale.kr(q.buffer)), (rate*BufRateScale.kr(q.buffer)*bend), sustain), 1, pos, 0, 2)), 20000)),20); var env = EnvGen.ar(Env.sine(sustain, amp * 0.5), doneAction: 2); OffsetOut.ar(out, Pan2.ar(snd * env, pan)); }, \ir ! 5).add; SynthDef(\bufWide, { |out, amp=0.1, rate=1.0, bend=1.0, pos=1, sustain=0.01, pan, width=0.5| var holdT = sustain * width; var fadeT = 1 - width * sustain * 0.5; var snd = HPF.ar((LPF.ar((PlayBuf.ar(1, q.buffer, Line.ar((rate*BufRateScale.kr(q.buffer)), (rate*BufRateScale.kr(q.buffer)*bend), (fadeT*2+holdT)), 1, pos, 0, 2)), 20000)),20); var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeT, holdT, fadeT], \sin), levelScale: amp * 0.5, doneAction: 2); OffsetOut.ar(out, Pan2.ar(snd * env, pan)); }, \ir ! 5).add; SynthDef(\bufPerc, { |out, amp=0.1, rate=1.0, bend=1.0, pos=1, sustain=0.01, pan| var snd = HPF.ar((LPF.ar((PlayBuf.ar(1, q.buffer, Line.ar((rate*BufRateScale.kr(q.buffer)), (rate*BufRateScale.kr(q.buffer)*bend), sustain), 1, pos, 0, 2)), 20000)),20); var env = EnvGen.ar( Env.perc(0.1, 0.9, amp * 0.5), timeScale: sustain, doneAction: 2 ); OffsetOut.ar(out, Pan2.ar(snd * env, pan)); }, \ir ! 5).add; SynthDef(\bufPercRev, { |out, amp=0.1, rate=1.0, bend=1.0, pos=1, sustain=0.01, pan| var snd = HPF.ar((LPF.ar((PlayBuf.ar(1, q.buffer, Line.ar((rate*BufRateScale.kr(q.buffer)), (rate*BufRateScale.kr(q.buffer)*bend), sustain), 1, pos, 0, 2)), 20000)),20); var env = EnvGen.ar( Env.perc(0.9, 0.1, amp * 0.5, 4), timeScale: sustain, doneAction: 2 ); OffsetOut.ar(out, Pan2.ar(snd * env, pan)); }, \ir ! 5).add; ); s.sync; ( ( q.paramRNames = [\posRange, \rateRange, \bendRange, \durRange, \densRange, \ampRange, \panRange]; q.paramNames = [\pos, \rate, \bend, \grDur, \dens, \amp, \pan]; q.syndefNames = [\bufGab, \bufWide, \bufPerc, \bufPercRev]; Spec.add(\xfadeTime, [0.001, 1000, \exp]); Spec.add(\ring, [0.03, 30, \exp]); Spec.add(\grDur, [0.0001, (q.bufFrames/s.sampleRate), \exp]); Spec.add(\dens, [1, 1000, \exp]); Spec.add(\rate, [0.125, 8, \exp]); Spec.add(\bend, [0.5, 2, \exp]); Spec.add(\pos, [0, q.bufFrames-1, \lin]); Tdef(\cloud0) .set( \synName, \bufGab, \vol, 0.7, \current, ( rateRange: [0.5, 2.0], bendRange: [1.0, 1.0], posRange: [0, 4000], ampRange: [0.5, 1], durRange: [0.001, 0.01], densRange: [10, 1000], panRange: [-1.0, 1.0] ) ); Tdef(\cloud0, { |e| loop { s.sendBundle(s.latency, [ "/s_new", e.synName ? \bufGab, -1, 0, 0, \rate, q.dirSwitch*(exprand(e.current.rateRange[0], e.current.rateRange[1])), \bend, exprand(e.current.bendRange[0], e.current.bendRange[1]), \pos, rrand(e.current.posRange[0], e.current.posRange[1]), \amp, exprand(e.current.ampRange[0], e.current.ampRange[1]) * e.vol, \sustain, exprand(e.current.durRange[0], e.current.durRange[1]), \pan, rrand(e.current.panRange[0], e.current.panRange[1]) ]); exprand(e.current.densRange[0].reciprocal, e.current.densRange[1].reciprocal).wait; } }).quant_(0); ); ( q.randSet = { var randSet = (); q.paramRNames.do { |pName, i| randSet.put(pName, q.paramNames[i].asSpec.map([1.0.rand, 1.0.rand].sort) ); }; randSet; }; q.setNames = (1..8).collect { |i| ("set" ++ i).asSymbol }; q.setNames.do { |key| q[key] = q.randSet; } ) ); s.sync; ( q.stopAfterFade = false; q.xfadeTime = 3; q.morphtask = TaskProxy({ var startSet = q[\current], endSet = q[\target]; var stepsPerSec = 20; var numSteps = q.xfadeTime * stepsPerSec; var blendVal, morphSettings; if (q.target.notNil) { (numSteps).do { |i| // ["numSteps", i].postln; blendVal = (i + 1) / numSteps; morphSettings = endSet.collect({ |val, key| (startSet[key] ? val).blend(val, blendVal) }); q.current_(morphSettings); (1/stepsPerSec).wait; }; q.current_(q.target.copy); "morph done.".postln; if (q.stopAfterFade) { Tdef(\cloud0).stop; }; }; }).quant_(0); q.fadeTo = { |q, start, end, time, autoStop| q.current = q[start] ? q.current; q.target = q[end]; q.xfadeTime = time ? q.xfadeTime; if (autoStop.notNil) { q.stopAfterFade = autoStop }; q.morphtask.stop.play; }; ); defer{ q.makeCloudGui = { |q, tdef, posPoint| var win, ezRangers, fdBox; var setMinis, skipjack; posPoint = posPoint ? 400@400; // where to put the gui window win = Window.new("CloudGenMiniBuf", Rect.fromPoints(posPoint, (posPoint + (400@410)))).front; win.view.decorator_(FlowLayout(win.bounds.copy.moveTo(0, 0))); win.view.decorator.nextLine; // a just in time - gui for the Tdef z = TdefGui(tdef, parent: win); fdBox = EZNumber.new(win, 78@18, \Fade, ControlSpec(0.01, 100.0, \exp, 0.01, 3, nil), { |nbx| q.xfadeTime = nbx.value }, q.xfadeTime, false, 35); q.recordButton = Button(win, 51@19); q.recordButton.states_([["rec", Color.black, Color.white],["rec", Color.white, Color.red]]); q.recordButton.action = {|view| if (view.value==1) {s.record} {s.stopRecording}}; q.recordButton.value=0; win.view.decorator.nextLine; q.textView = StaticText(win, 125@45); q.textView.string = "myGrains"; q.textView.align = \center; q.textView.font = Font("Abadi MT Condensed Extra Bold", 22); q.textView.stringColor = Color.white; q.soundFileView = SoundFileView.new(win, Rect(0,0,202,45)).gridOn_(false); q.soundFile = SoundFile.new; q.soundFile.openRead(q.soundPath); q.soundFileView.soundfile = q.soundFile; q.soundFileView.read(0, q.soundFile.numFrames); q.soundFileView.backColor = Color.new255(190, 190, 190); q.soundFileView.refresh; q.dirCtlButton = Button(win, 52@45); q.dirCtlButton.states_([[">"],["<"]]) .action_( {q.dirSwitch = q.directions.at(q.dirCtlButton.value)} ); q.dirCtlButton.value = 0; q.directions = [1, -1]; q.dirSwitch = q.directions.at(q.dirCtlButton.value); win.view.decorator.nextLine; ezRangers = (); q.paramRNames.do { |name, i| ezRangers.put(name, EZRanger(win, 400@20, name, q.paramNames[i], { |sl| q.current[name] = sl.value; }, q.current[name], labelWidth: 70, numberWidth: 50, unitWidth: 10) .round_([1, 0.001, 0.001, 0.00001, 0.0001, 0.0001, 0.01][i]) ); }; Button.new(win, 126@20).states_([[\randomize]]) .action_({ q.target_(d.randSet); q.morphtask.stop.play; }); Button.new(win, 126@20).states_([[\continuous], [\fadeStops]]) .value_(q.stopAfterFade.binaryValue) .action_({ |btn| tdef.set(\stopAfterFade, btn.value == 1) }); Button.new(win, 126@20).states_([[\skipWatching], [\skipWaiting]]) .action_({ |btn| [ { skipjack.play }, { skipjack.stop }][btn.value].value }); win.view.decorator.nextLine; skipjack = SkipJack({ q.paramRNames.do { |name| ezRangers[name].value_(q.current[name]) }; fdBox.value_(q.xfadeTime); }, 0.5, { win.isClosed }, name: tdef.key); win.view.decorator.nextLine; q.setNames.do { |setname, i| var minisliders, setMinis; var zone = CompositeView.new(win, Rect(0,0,45, 96)); zone.decorator = FlowLayout(zone.bounds, 0@0, 5@0); zone.background_(Color.white); Button.new(zone, Rect(0,0,45,20)).states_([[setname]]) .action_({ q.target = q[setname]; q.morphtask.stop.play; }); Button.new(zone, Rect(0,0,45,20)) .states_([["save" ++ (i + 1)]]) .action_({ q[setname] = q.current.copy; setMinis.value; }); minisliders = q.paramRNames.collect { |paramRname| RangeSlider.new(zone, 45@8).enabled_(false); }; setMinis = { q.paramRNames.do { |paramRname, i| var paramName = q.paramNames[i]; var myrange = q[setname][paramRname]; var unmapped = paramName.asSpec.unmap(myrange); minisliders[i].lo_(unmapped[0]).hi_(unmapped[1]); } }; setMinis.value; }; EZSlider(win, 225@20, "vol", \amp, { |sl|tdef.set(\vol, sl.value) }, 0.7, false, 20, 36); StaticText.new(win, 60@20).string_("synthdef:").align_(\right); PopUpMenu.new(win, Rect(0,0,95,20)) .items_([\bufGab, \bufWide, \bufPerc, \bufPercRev]) .action_({ |pop| q.synName = pop.items[pop.value] }); }; q.makeCloudGui(Tdef(\cloud0)) }; // remove buffer when pressing Cmd-. CmdPeriod.doOnce({q.buffer.free;}); } )