TRand not working

Hi!

I am trying to create a live granular synth. For each grain to be created with GrainBuf, triggered with Dust i want to have random values within given ranges to be generated for different parameters. Right now I can’t really get it to work.

I have 2 problems:

1:
TRand poll output shows always 0.

SynthDef.new(\gran, {
	arg dens=20, grainSize=0.1, rate=1,
	buf=~granBuf, startTime=0, endTime=44100*5,
	ptrBus=~recPtrBus, amp=0.5, out=0;

	var sig=0, recPtr=0, playPos, safeLag=0, //safeLag is safe distance of granPtr behind recPtr
	bufSizeSamples, bufSampleRate,
	trig;

	bufSizeSamples = BufFrames.kr(~granBuf);
	bufSampleRate = BufSampleRate.kr(~granBuf);
	
	
	trig = Dust.ar(dens);

	safeLag = (grainSize*bufSampleRate*rate);
	
	playPos = TRand.kr(startTime, endTime, trig).poll(10);
	
	recPtr = In.ar(~recPtrBus);
	
	sig = GrainBuf.ar(
		numChannels: 1,
		trigger: trig,
		dur: grainSize,
		sndbuf: ~granBuf,
		rate:  1,
		pos: playPos / bufSizeSamples, //between 0 and 1
		interp: 2,
		envbufnum: -1,
		maxGrains: 512
	);


	sig = sig * amp;
	Out.ar(out, sig);
}).add;

2:
Ideally I would like the random generating parts enclosed in separate code blocks, for making it easier to do more processing, like here. I have tried to do

(
~generatePlayPos = {
	arg startTime, endTime, recPtr, safeLag;
	var playPos;

	playPos = rrand(startTime, endTime);
	if( ((recPtr-safeLag) < playPos).and(playPos < recPtr) ) {playPos = (recPtr-safeLag)};//if too close to record pointer, nudge to safeLag

	playPos;
}
)

but don’t know how to call it with each trigger from the Gran synthdef. Also upon evaluation from the SynthDef it gives the error: ERROR: Message ‘and’ not understood.

Any help appreciated!

Re part 2.

You can’t use if*, nor and with ugens, you have to do this numerically — I’d think about this as an interpolation.

var case1 = (recPtr-safeLag) < playPos ; // [0-1]
var case2 = playPos < recPtr; // [0-1]
var caseCombined = case1 * case2;
playPos.blend(recPtr-safeLag, caseCombined)

There are probably shorter way to write this, but I find this to be clear.


Technically you can also do

if(caseCombined, recPtr-safeLag,  playPos)

You could also use Select which can also be clear when you have ‘if else’ statements.

Select.kr(caseCombined, [playPos, recPtr-safeLag])
1 Like

Thanks! That is much clearer.

Do you perhaps know how to call the function on a trigger like Dust?

You can’t ‘call’ a function on a trigger. What I’d do is process the function all the time, then use sample-and-hold (Latch) to update the signal on a trigger.

Something like this.

var trig = ...;
var f = { ... };
var result = Latch.ar(f.(...), trig);
1 Like

Now unfortunately

var case1 = (recPtr-safeLag) < playPos ; // [0-1]
var case2 = playPos < recPtr; // [0-1]
var caseCombined = case1 * case2;

doesn’t work with numbers, as case 1 and 2 are boolean when variables are numbers. Is there a way for it to work both with UGens and numbers?

One issue here is the way you’ve written the upper bound:

startTime=0, endTime=44100*5

In a SynthDef, argument defaults must be literal values, not expressions. This is explained somewhere, but I forget where.

One solution is to delete it from the argument list and write:

var endTime = \endTime.kr(44100*5);

hjh

1 Like

Is there a way for it to work both with UGens and numbers?

Assuming you always want to evaluate this on the server, not in the language…

So there are many ways to think about this… Personally I wouldn’t even try, I’d instead just always write the arguments as DC.kr(n). This isn’t as efficient in some cases, but it really doesn’t matter.

1 Like