Review: execution, resolution, environments, etc

My understanding of this problem was always sketchy. Here are three bits of code that illustrate my confusion and ignorance.

   Ndef(\tgrains, {  

	var rate, snd, trigRate, centerPos;

	// mouse movement X and Y:
	   trigRate =, 200, 1);
	   centerPos =,;

the well-known strategy. But,

   Ndef(\tgrains).addSpec(\trigRate, [2, 220,'exp']);
   Ndef(\tgrains).addSpec(\centerPos, [1, BufDur(b),'exp']);

   Ndef(\tgrains, {  |trigRate = 60, centerPos = 2|

	var rate, snd;


fails silently until NDef(\tgrains).gui; And also…

k.elAt(\sl, 1).action_({|el| Ndef(\tgrains).set(\centerPos, el.value.linexp(0.0,1.0, 1,BufDur(b)))});

using Modality to attempt a link to a nanoKontrol2 to control trigRate with a slider.

Can someone please give me a quick explanation and a suggestion about where to go to find a more or less compete and understandable explanation about why snippet 1 works while snippets 2 & 3 don’t?
It would also be great to see a solution or work around so I can get a dynamic value into my Specs.
Thanks for your help.

quick observation…
BufDur(b) will never work and you used it twice.
It’s either b.duration, or The latter if you plan on swapping buffers, the first if you’re not inside a SynthDef/Ndef.
hope that little typo was the issue.

Thanks for getting back. I find that niether the .kr nor the .ir version work in Ndef(\tgrains).gui or the Modality slider assignment.
However, b.duration seems to work in both situations even with a buffer swap.

I’m still no further ahead regarding the theory but this seems to solve my immediate issue.
Thanks again. …edN

I’m still no further ahead regarding the theory but this seems to solve my immediate issue.

Ok, here’s an attempt to clarify a bit more (hope it doesn’t do the opposite and blur)

BufDur(b) is the same as writing and this does not evaluate to a number - it gives you a new object. try it by running…
BufDur(b); //-> a BufDur

So in for example .linexp(0.0,1.0, 1,BufDur(b)) the linexp method can’t really know what the value for the fourth argument should be. It expects a number but we give it a new object.
In a parallel universe linexp might give you a warning or crash here, but our linexp doesn’t complain so it’s not easy to spot the error. It just swallows the new object and fail silently or you get some unexpected result.
That line must be written .linexp(0.0,1.0, 1, b.duration) for it to work. Then the linexp method will get the duration of b as a proper floating-point value for the fourth argument.

When to use b.duration over is a separate question. It has to do with language vs server code.

Because BufDur is a UGen it is only useful inside a synthesis graph i.e. within a SynthDef/Ndef or {}.play construction. Think of a BufDur as something that sends out a continuous signal.
Your Ndef(\tgrains).set and Ndef(\tgrains).addSpec are both language side code though so a signal there won’t work. You will want to use b.duration there as it returns a single value.


b = Buffer.alloc(s, 1000);  //one thousand samples, 1000/44100≈0.0227 (or whatever sr you use)

//sclang side...
//a single number

//as b.duration returns a number it also can be used inside a synth...
Ndef(\a, {b.duration.poll;}).play
//but then that particular duration value is hardcoded into the definition - no good for general purpose code

//it is better practice to use a BufDur ugen inside of a synth...
Ndef(\b, {;}).play
//even though in this example it make no difference. Just as bad we have now hardcoded the buffer number b into the definition.

//the whole reason to use BufDur though is that you can use an argument and query the duration of any buffer...
Ndef(\c, {|buf|;}).set(\buf, b).play
c = Buffer.alloc(s, 2000);
Ndef(\c).set(\buf, c);
//now your synth code is generic and you can use it with any buffer (also swap buffers while the synth is running)

and last here’s a common error that we all run into from time to time…

Ndef(\d, {BufDur(b).poll;}).play  //BAD
//this is how BufDur fail silently - BufDur(b) need a rate - either .ir or .kr



1 Like

As lucid as ever, Fredrik. Thank you very much. The example code helps to see the behaviour in other contexts.

Side note: Please see also Code markup: Correct style – not using code markup tags may corrupt the code displayed in the forum (* may become boldface; "straight quotes" become “curved typographic quotes” etc).