Writing to buffer on trigger

I’d like to write from a oscillator Ugen, to a buffer, preferably with BufWr, but upon a trigger. Ive tried using Dbufwr, but i cant seem to get it working.

b = Buffer.alloc(s, 44100*1.01,bufnum:0);
(
{
	var trig = Impulse.kr(1);
	var freq = Demand.kr(trig,0,Dseq([100,200],inf));
	Demand.kr(trig, 0, Dbufwr(SinOsc.ar(freq)*Env.perc().kr,b,Line.kr(0,44100*1.01-1,1.01,doneAction:2),0));
}.play;
)

What i try to achieve here is filling a buffer with a sineperc every second, with alternating frequencies.
Another approach i can think of is just using BufWr, but then i need something that can trigger BufWr. Possibly i need something that evaluates a fuction upon trigger, but so far i havent found anything like that. Any suggestions?

You should break this down into smaller steps:

  1. Make a SynthDef for your “sineperc” audio so the Ugen graph is precompiled. This is important for when you’re writing into a buffer because you don’t want a Ugen graph function being compiled every time you run the function while also trying to write into a buffer. You can change the value to the out argument depending on your needs.
(
SynthDef(\sineperc, {
	|freq = 100, out|
	var sig = SinOsc.ar(freq)*Env.perc.ar(2);
	Out.ar(out, sig);
}).add;
)
  1. Generate the audio that you want to send to the buffer. I like routines, but you can do this with patterns or demand rate. Routines feel more direct and intuitive for me personally, but I think I’m not in the majority. Here’s my approach:
(
fork{
	loop{
		[100, 200].do{
			|f|
			Synth(\sineperc, [\freq, f]);
			1.wait;
		};
	}
}
)
  1. Record to a buffer. I did this by making a SynthDef that writes to a buffer. If you’re trying to control when this happens, you can change it in the routine or add a trigger argument to start BufWr. If you just want your sounds going to the buffer, this will work.
(
SynthDef(\bufWrite, {
	|in, bufNum|
	var input = In.ar(in, 1);
	BufWr.ar(input, bufNum, Phasor.ar(0, 1, 0, BufFrames.kr(bufNum)));
}).add;
)

So once I had all of this, I added it to my routine, along with a ~bus variable in case you want to change the bus that’s being used.

(
~bus = 0; //really whatever you want...
fork{
	Synth(\bufWrite, [\in, ~bus, \bufNum, ~foo]);
	loop{
		...
		};
	}
}
)

So the whole thing looks:

s.freeAllBuffers

~foo = Buffer.alloc(s, s.sampleRate*5, 1);

(
SynthDef(\sineperc, {
	|freq = 100, out|
	var sig = SinOsc.ar(freq)*Env.perc.ar(2);
	Out.ar(out, sig);
}).add;

SynthDef(\bufWrite, {
	|in, bufNum|
	var input = In.ar(in, 1);
	BufWr.ar(input, bufNum, Phasor.ar(0, 1, 0, BufFrames.kr(bufNum)));
}).add;
)

(
~bus = 0; //really whatever you want...
fork{
	Synth(\bufWrite, [\in, ~bus, \bufNum, ~foo]);
	loop{
		[100, 200].do{
			|f|
			Synth(\sineperc, [\freq, f, \out, ~bus]);
			1.wait;
		};
	}
}
)

~foo.plot //now has the audio in it

Hope this helps though I’m not sure I fully understood your intent. If you’re trying to write to the buffer once/second, you can just free the buffer writing synth (either in the routine or with Done in the Ugen graph) and have the routine make that synth instead.

EDIT: this may be more in the spirit of what you’re after. This records to the buffer once/second AND plays sineperc.

s.freeAllBuffers

~foo = Buffer.alloc(s, s.sampleRate*5, 1);

(
SynthDef(\sineperc, {
	|freq = 100, out|
	var sig = SinOsc.ar(freq)*Env.perc.ar(2);
	Out.ar(out, sig);
}).add;

SynthDef(\bufWrite, {
	|in, bufNum, dura=1|
	var input = In.ar(in, 1);
	var free = FreeSelfWhenDone.kr(Line.kr(0,0,1));
	BufWr.ar(input, bufNum, Phasor.ar(0, 1, 0, BufFrames.kr(bufNum)));
}).add;
)

(
~bus = 0; //really whatever you want...
fork{
	loop{
		Synth(\bufWrite, [\in, ~bus, \bufNum, ~foo]);
		[100, 200].do{
			|f|
			Synth(\sineperc, [\freq, f, \out, ~bus]);
			1.wait;
		};
	}
}
)

~foo.plot
1 Like

RecordBuf has run and trigger inputs; perhaps these would handle it.

hjh