// title: loopr // author: LFSaw // description: // variable length looping engine // code: q = (); q.maxRecLength = 10; //in seconds q.numChans = 2; q.maxRecLengthSamples = q.maxRecLength * s.sampleRate; q.recLengthSamples = 0; q.recBuf = Buffer.alloc(s, q.maxRecLengthSamples, 2); q.playbackBuf = nil!10; q.player = nil!10; /* q.recBuf.updateInfo; // */ ( SynthDef(\looprRecorder, {|inBus = 0, recBuf = 0, gate = 1| var inSignal; var trigGate = 1-gate; // TODO: make automatic stop (when maxRecLength is reached) trigger as well // the signal to be recorded inSignal = In.ar(inBus, q.numChans); // send time used for recording back to language SendTrig.kr( trigGate, 0, Line.kr(0, q.maxRecLengthSamples, q.maxRecLengthSamples) ); // release synth when recGate closes FreeSelf.kr(trigGate); RecordBuf.ar(inSignal, recBuf, 0, recLevel: 1, preLevel: 0, doneAction: 2); }).add; SynthDef(\looprPlayer, {|buf = 0, loop = 1, out = 0| Out.ar(out, PlayBuf.ar(q.numChans, buf, loop:loop)); }).add; ) ( q.startRec = {|q, idx = 0, from| q.recTo = idx; q.recorder = Synth(\recorder, [\inBus, Ndef(\sound).bus.index, \recBuf, q.recBuf], 0, \addToTail); OSCFunc({ arg msg, time; q.recLength = msg[3]; q.recLengthSamples = (q.recLength * s.sampleRate).trunc; q.playbackBuf[q.recTo] = Buffer.alloc(s, q.recLengthSamples, q.numChans, {|buf| q.recBuf.copyMsg(buf, 0, 0, q.recLengthSamples); }) },'/tr', s.addr, nil, [q.recorder.nodeID, 0]).oneShot; }; q.stopRec = {|q, idx| idx.notNil.if{ q.recTo = idx; }; q.recorder.set(\gate, 0); }; q.playBack = {|q, idx = 0| q.player[idx] = Synth(\playback, [\buf, q.playbackBuf[idx]]) }; q.stopBack = {|q, idx = 0| q.player[idx].free; }; ) q.startRec(1) q.stopRec(1) q.playBack(1) q.stopBack(1) q.playBack(0) q.stopBack(0)