Pdef first, Ndef afterwards -> sound stops for a few seconds

Hi there

I am trying to control a few Ndefs and a Pdef via TouchOSC (https://www.dropbox.com/s/u081w9k7e519skr/instrument.touchosc?dl=0).

(

(
OSCdef.new(

		\bins_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\bins, msg[1].linexp(0,1,0.05,30));
	},
	'/inst_4/bins'
	);
);

(
OSCdef.new(

		\dur_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\dur, msg[1].linexp(0,1,0.01,2));
	},
	'/inst_4/dur'
	);
);

(
OSCdef.new(

		\factor_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\factor, msg[1].linlin(0,1,0,1));
	},
	'/inst_4/factor'
	);
);

(
OSCdef.new(

		\freq_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\freqhi, msg[1].linexp(0,1,10,17000));
	},
	'/inst_4/freq'
	);
);

(
OSCdef.new(

		\interp_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\interp, msg[1].linlin(0,1,0,1));
	},
	'/inst_4/interp'
	);
);

(
OSCdef.new(

		\level_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\level, msg[1].linlin(0,1,0,2));
	},
	'/inst_4/level'
	);
);

(
OSCdef.new(

		\pan_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\pan, msg[1].linlin(0,1,-1,1));
	},
	'/inst_4/pan'
	)
);


(
OSCdef.new(

		\shift_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\shift, msg[1].linlin(0,1,-15,15));
	},
	'/inst_4/shift'
	);
);

(
OSCdef.new(

		\wrap_4,
	{
		arg msg, time, addr, port;
		Pdef(\zingy).set(\wrap, msg[1].linexp(0,1,0.01,4));
	},
	'/inst_4/wrap'
	);
);

(
OSCdef.new(

	\on_4,
	{
		arg msg, time, addr, port;

if(msg[1]==1.0) {

(
(
SynthDef(\sinegrain, {
	arg pan,freq,stretch,shift,interp,bins,factor,mul,wrap,level;
	var grain, chain;

	grain = (LFPar.ar(freq, 0, mul)*(XLine.kr(1.001,0.001,0.1,doneAction:2)-0.001));
	chain = FFT({LocalBuf(1024)}!2,grain);
	chain = PV_BinShift(chain,stretch,shift,interp);
	chain = PV_MagSmear(chain,bins);
	chain = PV_MagSmooth(chain,factor);
	Out.ar(0,Pan2.ar(XFade2.ar(grain.wrap2(wrap),(IFFT(chain)),pan,level)))
	}).add;
);

(
	Pdef(\zingy).envir = (dur: 0.1, freqlo: 100, freqhi: 7000, pan: (-1), bins:1.0, factor:0.1,mul:0.1,
	shift:0.2, interp:0, level:0.1, wrap:0.2)
);

Spec.add(\freqlo, \freq); Spec.add(\freqhi, \freq);

Pdef(\zingy).source = Pbind(
	\instrument, \sinegrain,
	\freq, Pwhite(Pkey(\freqlo), Pkey(\freqhi)),
);
				

)


		} {
			Pdef(\zingy).clear
			};
		},
	'/inst_4/on'
)
);

(
OSCdef.new(

	\play_4,
	{
		arg msg, time, addr, port;

		if(msg[1]==1.0) {
			Pdef(\zingy).play
		} {
			Pdef(\zingy).stop(3)
		};
	},
	'/inst_4/play'
)
)

);

(

(
OSCdef.new(

		\freqa_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\freqa, msg[1].linexp(0,1,0.25,100));
	},
	'/inst_5/freqa'
	);
);

(
OSCdef.new(

		\freqb_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\freqb, msg[1].linexp(0,1,0.01,1.4));
	},
	'/inst_5/freqb'
	);
);

(
OSCdef.new(

		\mul_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\mul, msg[1].linexp(0,1,0.01,2.4));
	},
	'/inst_5/mul'
	);
);

(
OSCdef.new(

		\densc_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\densc, msg[1].linexp(0,1,0.03,10));
	},
	'/inst_5/densc'
	);
);

(
OSCdef.new(

		\repeat_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\repeat, msg[1].linexp(0,1,0.25,100));
	},
	'/inst_5/repeat'
	);
);

(
OSCdef.new(

		\mulsig_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\mulsig, msg[1].linexp(0,1,0.02,6));
	},
	'/inst_5/mulsig'
	);
);

(
OSCdef.new(

		\delay_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\delay, msg[1].linexp(0,1,0.01,1));
	},
	'/inst_5/delay'
	)
);

(
OSCdef.new(

		\freqd_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\freqd, msg[1].linexp(0,1,0.05,20));
	},
	'/inst_5/freqd'
	);
);

(
OSCdef.new(

		\damp_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\damp, msg[1].linexp(0,1,0.01,2));
	},
	'/inst_5/damp'
	);
);

(
OSCdef.new(

		\feedb_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\feedb, msg[1].linexp(0,1,0.01,4));
	},
	'/inst_5/feedb'
	);
);

(
OSCdef.new(

		\modd_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\modd, msg[1].linexp(0,1,0.01,3));
	},
	'/inst_5/modd'
	);
);

(
OSCdef.new(

		\modf_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\modf, msg[1].linexp(0,1,0.1,50));
	},
	'/inst_5/modf'
	);
);

(
OSCdef.new(

		\size_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\size, msg[1].linexp(0,1,0.05,20));
	},
	'/inst_5/size'
	);
);

(
OSCdef.new(

		\pan_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\pan, msg[1].linlin(0,1,-1,1));
	},
	'/inst_5/pan'
	);
);

(
OSCdef.new(

		\amp_5,
	{
		arg msg, time, addr, port;
		Ndef(\greyhole).set(\amp, msg[1].linlin(0,1,0,1));
	},
	'/inst_5/amp'
	);
);

(
OSCdef.new(

	\on_5,
	{
		arg msg, time, addr, port;

if(msg[1]==1.0) {

(
Ndef(\greyhole,
	{  |freqa=5,
		freqb=0.07, mul=0.12,
		densc=0.5, repeat=5,mulsig=0.3,
		delay=2,freqd=1,damp=0.1,
		feedb=0.2,modd=0.1,modf=2,size=1,pan=(-1),amp=0.7|
		{
	// LFTri resposible for low frequencies / rhythms
	var inSig = LFTri.ar(LFDNoise0.ar(freqa).exprange(0.1, 1000));
	var lfo = { LFDNoise3.ar(freqb).linexp(-1, 1, 1, 10) } ! 2;
	var i = Demand.kr(Dust.kr(densc), 0, Dxrand((0..10), repeat));
	var sig = Fb1.ar({ |in, out|
		// in[0][0] is the current (stereo) sample inSig
		// in[0][1] is the current (stereo) sample lfo
		(
			in[0][1] * (
				in[0][0] * mul + (
					// changes between out[in-23], out[n-41] and
					// out[n-60] cause high frequency changes,
					// Select depends on a signal from outside,
					// not previous samples as in example (2i)
					(in[1][0].squared - Select.kr(i, out).squared).sqrt
				)
			)
		).tanh
		}, [inSig, lfo], 2, [2, 1], [[23, 81, 60]],
		blockSize: s.options.blockSize,
		blockFactor: 64 / s.options.blockSize
	) * mulsig;
	var delaysig = DelayC.ar(Gendy3.ar(sig, delay, LFDNoise3.ar(freqd!2).range(0.01, 0.1)).lag(0.0006));
	// add frequency modulation by delay modulation
	// lopass filtering with lag
	XFade2.ar(DelayC.ar(sig, delay, LFDNoise3.ar(freqd!2).range(0.01, 0.1)).lag(0.0006),
				GreyholeRaw.ar(sig*0.9,delaysig*0.1,damp, delay, LFDNoise3.ar(freqd!2).range(0.01, 0.1),feedb,modd,modf,size).lag(0.0006),pan,amp)
		}
})
)
		} {
			Ndef(\greyhole).clear(5)
			};
		},
	'/inst_5/on'
)
);

(
OSCdef.new(

	\play_5,
	{
		arg msg, time, addr, port;

		if(msg[1]==1.0) {
			Ndef(\greyhole).play(0,2).fadeTime(2)
		} {
			Ndef(\greyhole).stop(3)
		};
	},
	'/inst_5/play'
)
)

)

If I start \zingy first and \greyhole afterwards with TouchOSC the sound stops for a few seconds. The other way round this problem doesn’t occur.
What can I do about this?

Thanks!

Hi aksu! Here is what’s going on:

  1. You play a Pdef: sclang starts scheduling successive events on your clock in real time,
  2. You run your Ndef: sclang has to first create a SynthDef from it. In your case, this operation takes a while, and during that time sclang is busy and can’t continue scheduling your events, so you get some silence.

Your Ndef probably takes a while to build because of Fb1… I haven’t played much with it, so I can’t help you finding optimal settings for it. It is mentioned in Fb1’s helpfile that different options could reduce compile time.

However, here are two things you could try:

  • instead of creating and destroying the Ndef live, you could create it before you start playing and then just use .play/.stop while you play. The Ndef is compiled before you start, so you won’t get silences while you play

  • using a SynthDef instead of an Ndef, which you also can compile before starting, and then create/destroy/modulate Synth objects (you’ll miss fadeTime() though)

Hi elgiano

Ok, I see.

The reason I wanted to create and destroy the Ndef live was because I did not want to have all the synths running at the same time and overloading the server.

I tried some settings in Fb1’s helpfile. So far I don’t think it makes a big difference.

What seemed promising to me was to use SynthDef instead of Ndef.
For another Synth (not \greyhole) this worked really well.
But for \greyhole I don’t seem to be able to produce any sound:

(
SynthDef.new(\greyhole,
	
{  |freqa=5,
		freqb=0.07, mul=0.12,
		densc=0.5, repeat=5,mulsig=0.3,
		delay=2,freqd=1,damp=0.1,
		feedb=0.2,modd=0.1,modf=2,size=1,pan=(-1),amp=0.7|
		{
	// LFTri resposible for low frequencies / rhythms
	var inSig = LFTri.ar(LFDNoise0.ar(freqa).exprange(0.1, 1000));
	var lfo = { LFDNoise3.ar(freqb).linexp(-1, 1, 1, 10) } ! 2;
	var i = Demand.kr(Dust.kr(densc), 0, Dxrand((0..10), repeat));
	var sig = Fb1.ar({ |in, out|
		// in[0][0] is the current (stereo) sample inSig
		// in[0][1] is the current (stereo) sample lfo
		(
			in[0][1] * (
				in[0][0] * mul + (
					// changes between out[in-23], out[n-41] and
					// out[n-60] cause high frequency changes,
					// Select depends on a signal from outside,
					// not previous samples as in example (2i)
					(in[1][0].squared - Select.kr(i, out).squared).sqrt
				)
			)
		).tanh
		}, [inSig, lfo], 2, [2, 1], [[23, 81, 60]],
		blockSize: s.options.blockSize,
		blockFactor: 64 / s.options.blockSize
	) * mulsig;
	var delaysig = DelayC.ar(Gendy3.ar(sig, delay, LFDNoise3.ar(freqd!2).range(0.01, 0.1)).lag(0.0006));
	// add frequency modulation by delay modulation
	// lopass filtering with lag
	Out.ar(0,XFade2.ar(DelayC.ar(sig, delay, LFDNoise3.ar(freqd!2).range(0.01, 0.1)).lag(0.0006),
				GreyholeRaw.ar(sig*0.9,delaysig*0.1,damp, delay, LFDNoise3.ar(freqd!2).range(0.01, 0.1),feedb,modd,modf,size).lag(0.0006),pan,amp));
		}
}).play
)

Or am I doing something wrong here?

Am I understanding you correctly that I can’t fade out the SynthDefs?
At least using “.release(number)” is not haying the effect - to be exact none at all - I would hope for.

1 Like

Output: You don’t hear anything because you have an extra set of curly brackets, the one that opens after your argument list and closes after your Out UGen.

Release: In order to use .release, your synthdef needs to implement a sustained envelope. Furthermore, that envelope should be read by an EnvGen, whose gate has to be controlled by an argument called ‘gate’. See Node.release HelpFile
Something like sig = sig * EnvGen.kr( Env.asr(), \gate.kr(1), doneAction: 2 ) , where sig is the signal you are writing to your output.

Other: A few other considerations:

  1. SynthDef.play : maybe it was just for simplicity, to share on this forum, but I just want to make sure you know that in your code you shouldn’t do this, but rather first create the SynthDef, add it to server, and finally create/stop Synths when you want to hear them.
  2. ‘out’ argument: it’s a useful practice (and established convention) not to hardcode your output bus, but rather have an out argument that defaults to 0
// define out arg among your other args
SynthDef.new(\greyhole, {  | out=0, ...
// finally, use it
Out.ar(out, ...
  1. Watch out for how many channels you are outputting: currently you output four channels, as an array that looks like: [ [ a XFade2, a XFade2 ], [ a XFade2, a XFade2 ] ]. Maybe you just want to mix this into a stereo output, or to flatten it into a quadrophonic output.
  2. I suggest you write your final signal to a variable, so that you split that complex XFade2 operation from the output bus writing. Just for clarity, but also to make it easier to add an envelope, in case you want to implement the .release suggestion above. It would also make it easier to check how many channels you are actually outputting.

Output: ahh, stupid.

Release: Cool, that’s what I was looking for.

Other: Yes, that was a bit quick and dirty.

Cool, thanks a lot! Now everything works.

1 Like