In the code below I record sound input triggered by keyDownAction
until a keyUpAction
. I store the number of frames recorded by launching a Phasor
object simultaneously which is freed on keyUpAction
(this all works fine). I would like to be able to play back the exact number of frames I recorded once with BufRd
but am struggling with how to do so. If I use Phasor
to play from beginning of the buffer to the frame I stopped recording I can play exactly what I recorded, ending where the Phasor
stopped, but it loops that segment forever. If I switch to Line
(or use an Env
) I appear to have to somehow specify duration in seconds. I am unsure how to convert frames to seconds without potentially risking the accuracy of the playback that I am trying to preserve. Is there a way to play back my recording from the beginning of the buffer to the frame at which I stopped recording exactly and only once?
Below please find the Phasor
version that loops forever but otherwise does what I want. Any suggestions would be greatly appreciated.
s.boot;
~buf = Buffer.alloc(s, s.sampleRate * 60, 1);
~dur = Bus.control(s, 1);
(
SynthDef(\record, {|amp = 0.9, buf, in = 0, off = 0, rate = 1, recManualBus, start = 0, trig = 0|
var env, sig, phase;
sig = SoundIn.ar(in, amp);
phase = Phasor.ar(trig, BufRateScale.kr(buf) * rate, start, BufFrames.kr(buf));
BufWr.ar(sig, buf, phase);
Out.kr(recManualBus, phase);
FreeSelf.kr(off);
}).add;
SynthDef(\bufRd, {|amp = 0.9, buf, end, loop, out, rate = 1, start = 0, trig = 0|
var phase, play, sig;
phase = Phasor.ar(trig, BufRateScale.kr(buf) * rate, start, end);
sig = BufRd.ar(1, buf, phase, loop);
play = sig * amp;
Out.ar(out, Pan2.ar(play));
}).add;
)
(
var keyDown = False;
w = Window.new("keyTrigRec", Rect(50, 50, 275, 275));
w.background_(Color.white);
w.view.keyDownAction = { arg view, char, modifiers, unicode, keycode;
if(keycode == 49, {
if( keyDown == False, {
"start recording".postln;
w.background_(Color.red);
// start the record synth
x = Synth(\record, [\trig, 1, \buf, ~buf, \recManualBus, ~dur.index ]);
// block repeated triggers from space bar
keyDown = True;
});
});
};
w.view.keyUpAction = { arg view, char, modifiers, unicode, keycode;
if(keycode == 49, {
"stop recording".postln;
w.background_(Color.green);
fork {
x.set(\off, 1); // stop recording
// check position of phasor
~dur.get({ |recDur|
~numFrames = recDur;
("numFrames recorded:" + ~numFrames).postln;
});
s.sync;
~dur.set(0.0); // reset bus for next recording
};
keyDown = False;
});
};
w.front;
)
// play recording
y = Synth(\bufRd, [\buf, ~buf, \end, ~numFrames, \loop, 0, \trig, 1 ]);