Pdef set , how exactly?

Excited to read in thor Magnusson guide that Pdefs can be set from outside just like Synthdefs
However , I don’t get the expected results
The sc manual is imho verry scarce when it comes to info about Pdef.set
I tried it with assigning the pdefs to variables and without , both set parameters do nothing
https://thormagnusson.gitbooks.io/scoring/content/PartIV/chapter16.html

(
SynthDef (\kick,
{
		arg pitch=50,patt=0.001,pdec=0.325,pcurve=(-50),pamt=100,att=0.001,dec=0.700,noisefreq=100,shamt=4,vol=0.3,out;
		var kick,penv,ampenv,noiseosc;
		penv=EnvGen.ar(Env([0,1,0],[patt,pdec],[0,pcurve]),doneAction:2);
		kick=SinOsc.ar(pitch+(penv*pamt))*0.9;
		noiseosc=LPF.ar(WhiteNoise.ar(0.1),noisefreq);
		kick=(noiseosc+kick)*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]))!2;
		kick=SineShaper.ar(kick*shamt)*vol;
		kick=(HPF.ar(kick,20));
		Out.ar(out,kick);
}).add
)
//
t=TempoClock(124/60).permanent_(true)


(~ward=(
	Pdef(\kik,
		Pbind(\instrument,\kick,
			\dur,1/2,
			\pitch,Pseq([50,75],inf),
			\pdec,0.8,
			\shamt,Pseq([2,8,2,2],inf),
			\vol,0.5,
			\out,0,
	))
)
)

~ward=Pdef(\kik).set(\dur,1/4);
~ward=Pdef(\kik).set(\dur,1/4,\pitch,Pseq([50,75,120,75]));

~ward=Pdef(\kik).play(t)
~ward.stop
~ward.pause

This is Thor magnusson’s example , I replaced the instrument with my kick instrument , the changes also don’t work , after the necessar changes freq to pitch etc

(
Pdef(\scale, Pbind(    \instrument,\kick,
                    \freq, Pseq([62, 64, 67, 69, 71, 74], inf).midicps,
                    \dur,  Pseq([0.25, 0.5, 0.25, 0.25, 0.5, 0.5], inf)
)); 
)

a = Pdef(\scale).play;
a.pause     // pause. the stream
a.resume     // resume it
a.stop     // stop it (resets it)
a.play     // start again


Pdef(\scale).set(\out, 20); // outbus 20 
Pdef(\scale).set(\out, 0); // outbus 0 

// here we set the duration of the envelope in our instrument
Pdef(\scale).set(\envdur, 0.2);


Pdef(\scale).set(\freq, Pseq([72,74,72,69,71,74], inf).midicps);

Another example .
If one could make the changes how to use Pdef.set I’d be delighted

(
SynthDef(\Sqwer,
	{| ampattack =0.001,ampdecay=1,filtattack=0.001,filtdecay=0.500,osc1amp=0.3,osc2amp=0.3,osc3amp=0.3,offset1=0,offset2=0.2,offset3=(-0.2),filterfreq=600,res=1,freq=30,
		filteramount=100,pan=0,vol=0.7,fsh=5,xfade=0,out|
		var sig,sig1,sig2,sig3,ampenvelope,filterenvelope;
		filterenvelope=EnvGen.ar(Env([0,1,0],[filtattack,filtdecay],[0,-5]),doneAction:0);
		ampenvelope=EnvGen.ar(Env([0,1,0],[ampattack,ampdecay],[0,-5]),doneAction:2);
		sig1=Pulse.ar((freq+offset1).midicps,mul:osc1amp);
		sig2=Pulse.ar((freq+offset2).midicps,mul:osc2amp);
		sig3=Pulse.ar((freq+offset3).midicps,mul:osc3amp);
		sig=sig1+sig2+sig3;
		sig=SVF.ar(sig,(filterfreq+(filterenvelope*filteramount)).clip(20,20000),res:res,lowpass:1);
		sig=sig*ampenvelope;
		sig=XFade2.ar(sig,FreqShift.ar(sig,fsh),pan:xfade);
		sig=sig*vol;
		sig=Pan2.ar(sig,pos:pan)!2;
		Out.ar(0,sig);
}).add
)

Synth(\Sqwer,[\freq,58,\offset1,-24,\offset2,-0.3,\offset3,0.1,\filterfreq,800,\filteramount,600,\xfade,0,\fsh,3]);


(
Pdef(\tyu,
	Pbind(\instrument,
		\Sqwer,
		\dur,Pseq([1/3,1/3,1/3],inf),
		\freq,Pseq([48,53,50,46],inf)-12,
		\offset1,0,
		\offset2,0.2,
		\offset3,0.1,
		\filterfreq,Prand([200,1000,400,1600,3000,500,120,2000],inf),
		\filteramount,1500,
		\filtdecay,Pwhite(0.01,0.2,inf),
		\ampdecay,Pwhite(0.1,0.3,inf),
		\vol,0.4,
		\res,0.5,
		\xfade,-0.3,
		\fsh,Pwhite(0,5,inf),
		\out,0,
	)
)
)
;
Pdef(\tyu).set(\vol,0.1,\res,0.5,\freq,Pseq([60,58,56,55]))
Pdef(\tyu).set(\vol,0.1,\res,0,\freq,Pseq([66,60,60,63]))




;
Pdef(\tyu).play(t)
Pdef(\tyu).stop
t=TempoClock(124/60).permanent_(true);

O.k , it works now
It seems that the parameter that you want to set from outside must not be available in the pdef

notice the absence of filteramount in the Pdef\Pbind
As always , I encounter another issue ,when there is pseq in inside the pdef.set it won’t work
Example , eliminating the \filterfreq,Pseq([500,400,1000,300,200],inf from the Pbind and putting it in the Pdef.set doesn’t work
Altough the Thor Magnusson example clearly has a Pseq inside the Pdef.set
For me this would be the most imporant thing , I know we can replace the data inside Pbind\Pseq with variables from outside but then we need to re-execute the pind
Would be great to have these inside a pdef.set

(
Pdef(\bebe,
	Pbind(\instrument,
		\Sqwer,
		\dur,Pseq([
			~piet,~miet],inf),
		\freq,Pseq([
			~pitch1,
			~pitch2
		],inf),
		\offset1,0,
		\offset2,12.2,
		\offset3,-0.1,
		\filterfreq,Pseq([500,400,1000,300,200],inf),
		\filtdecay,0.01,
		\filtattack,Pseq([0.001,0.001,0.02,0.001,0.05,0.05],inf),
		\ampdecay,Pwhite(0.1,0.3,inf),
		\vol,0.6,
		\res,0.6,
		\xfade,-0.5,
		\fsh,Pwhite(0,10,inf),
		\out,~verbus,
		

	)
)
)

Pdef(\bebe).set(\filteramount,5000);
~piet=Pseq([1/4,1/4,1/4],4)
~miet=Pseq([1/3,1/3,1/3],6)
~pitch1=Pseq([48,46,47],4)
~pitch2=Pseq([50,44,49,47],4)

Pdef(\bebe).set(\filteramount,50);


Pdef(\bebe).play(t)
Pdef(\bebe).stop(t)

t=TempoClock(124/60).permanent_(true);

This example shows the \filterfreq,Pseq removed from the Pbind and put inside the Pdef.set , but it won’t work

(
SynthDef(\Sqwer,
	{| ampattack =0.001,ampdecay=1,filtattack=0.001,filtdecay=0.500,osc1amp=0.3,osc2amp=0.3,osc3amp=0.3,offset1=0,offset2=0.2,offset3=(-0.2),filterfreq=600,res=1,freq=30,
		filteramount=100,pan=0,vol=0.7,fsh=5,xfade=0,out|
		var sig,sig1,sig2,sig3,ampenvelope,filterenvelope;
		filterenvelope=EnvGen.ar(Env([0,1,0],[filtattack,filtdecay],[0,-5]),doneAction:0);
		ampenvelope=EnvGen.ar(Env([0,1,0],[ampattack,ampdecay],[0,-5]),doneAction:2);
		sig1=Pulse.ar((freq+offset1).midicps,mul:osc1amp);
		sig2=Pulse.ar((freq+offset2).midicps,mul:osc2amp);
		sig3=Pulse.ar((freq+offset3).midicps,mul:osc3amp);
		sig=sig1+sig2+sig3;
		sig=SVF.ar(sig,(filterfreq+(filterenvelope*filteramount)).clip(20,20000),res:res,lowpass:1);
		sig=sig*ampenvelope;
		sig=XFade2.ar(sig,FreqShift.ar(sig,fsh),pan:xfade);
		sig=sig*vol;
		sig=Pan2.ar(sig,pos:pan)!2;
		Out.ar(out,sig);
}).add
)

Synth(\Sqwer,[\freq,58,\offset1,-24,\offset2,-0.3,\offset3,0.1,\filterfreq,800,\filteramount,600,\xfade,0,\fsh,3]);


(
Pdef(\bebe,
	Pbind(\instrument,
		\Sqwer,
		\dur,Pseq([
			~piet,~miet],inf),
		\freq,Pseq([
			~pitch1,
			~pitch2
		],inf),
		\offset1,0,
		\offset3,-0.1,
		\filtdecay,0.01,
		\filtattack,Pseq([0.001,0.001,0.02,0.001,0.05,0.05],inf),
		\ampdecay,Pwhite(0.1,0.3,inf),
		\vol,0.6,
		\res,0.6,
		\xfade,-0.5,
		\fsh,Pwhite(0,10,inf),
		\out,0,
		

	)
)
)

Pdef(\bebe).set(\filteramount,5000,\offset2,7.2,\filterfreq,Pseq([500,400,1000,300,200],inf),)
~piet=Pseq([1/4,1/4,1/4],4)
~miet=Pseq([1/3,1/3,1/3],6)
~pitch1=Pseq([48,46,47],4)
~pitch2=Pseq([50,44,49,47],4)

Pdef(\bebe).set(\filteramount,50);


Pdef(\bebe).play(t)
Pdef(\bebe).stop(t)

t=TempoClock(124/60).permanent_(true);

One possibe solution would be to keep the Pseqs without the data inside the Pbind , and the data in the Pdef.set but we can’t have the same \filterfreq name in both

how about this?:

Pdef(\foo,[dur:0.1].p).play
Pdef(\foo, Pdef(\foo).pattern.set(\dur,1))

Have you tried Pbindef? I didn’t have time to look at all your code, but I think this is what you want:

(
Pdef(\tyu,
	Pbind(\instrument,
		\Sqwer,
		\dur,Pseq([1/3,1/3,1/3],inf),
		\freq,Pseq([48,53,50,46],inf)-12,
		\offset1,0,
		\offset2,0.2,
		\offset3,0.1,
		\filterfreq,Prand([200,1000,400,1600,3000,500,120,2000],inf),
		\filteramount,1500,
		\filtdecay,Pwhite(0.01,0.2,inf),
		\ampdecay,Pwhite(0.1,0.3,inf),
		\vol,0.4,
		\res,0.5,
		\xfade,-0.3,
		\fsh,Pwhite(0,5,inf),
		\out,0,
	)
).play(t);
)

Pbindef(\tyu, \vol, 0.1, \res, 0, \freq, Pseq([66, 60, 60, 63], inf));

I don’t really get that
I wan’t the sequence data , even better the sequence inside the Pdef.set (if possible)
Like this
So I can atually change the whole sequence on the fly

Pdef(\foo).set(\pitch,Pseq([ 60,63,67],inf),\dur,Pseq([1/3,1/3,1/4],inf))
Pdef(\foo).set(\pitch,Pseq([Pseq([50,55],4),Pseq([55,57],3)],inf),\dur,Pseq([1/6,1/6,1/6],inf))

First, understand how event patterns process.

There is an “event in progress.” An empty event template is passed into next – this initializes the event in progress. Then the pattern-streams modify this event – Pbind loops through each name-value pair and puts the value into the event-in-progress under its name.

IIRC Pdef(\name).set puts values into the empty event template. Then, the later modifications may overwrite the template values.

What you’re talking about later is to modify the subsequent modifications to the event being built.

This indeed can be done with Pbindef.

I’m afraid here that p is not a standard library method. It’s from some extension, but I don’t know which one.

hjh

Altough I have not yet investigated the Pbinddef , but it seems this is not a.set , so doesn’t change the parameters on the fly .

It’s not a.set, but it does change parameters on the fly. Take a simple example:

Pdef(\aa, Pbind(\dur, 1)).play;
Pbindef(\aa, \dur, 1/4, \degree, 3);

You should hear the change there. Keep in mind that the quant value for your Pdef will determine when the change happens. If you are using a very large value for quant, then you won’t hear the change right away. The defaultQuant is 1, unless you changed that somewhere in your code, so you might want to check that.

Pdef.defaultQuant; // check it
Pdef.defaultQuant = 0.5; // change it

Awesome ,Pbindef is exactly what I wanted , thanks a lot

(
(

	Pbindef(\bb,
	\instrument,
		\Sqwer,
		\dur,Pseq([1/4,1/4,1/4],inf),
		\freq,Pseq([48,50,53,57],inf),
		\offset1,0,
		\offset2,0.2,
		\offset3,-0.1,
		\filterfreq,500,
		\filteramount,5000,
		\filtdecay,0.070,
		\ampdecay,Pwhite(0.1,0.3,inf),
		\vol,0.3,
		\res,0.5,
		\xfade,-0.3,
		\fsh,Pwhite(0,2,inf),

	)
)
)


Pbindef(\bb,\filterfreq,Pseq([500,1000,200,1500],inf))
Pbindef(\bb,\filtdecay,0.012,\filterfreq,Pseq([500,1000,200,1500],inf))
Pbindef(\bb,\freq,Pseq([60,57,55,53,50,48,47],inf))

Pbindef(\bb,\dur,Pseq([1/4,1/4,1/4,1/4],inf))
Pbindef(\bb,\dur,Pseq([1/8,1/4,1/8,1/4],inf))


Pbindef(\bb).play(t)
Pbindef(\bb).stop(t)

Anyone knows why the Pbinddef that houses the 4 PSeqs (chord for each ) gives an error ?
When I paste the code directly in the Master Pdef it works , the chord is also used in another instrument and there it plays flawlesly
The ] is so called nmatched , but it doesntt

(
   Pbindef(\bb,
   \instrument,
   	\Sqwer,
        \dur,1/4,
   	\freq,Pseq([48,60,53,57],inf),
   	\offset1,0,
   	\offset2,0.2,
   	\offset3,-0.1,
   	\filterfreq,500,
   	\filteramount,5000,
   	\filtdecay,0.070,
   	\ampdecay,Pwhite(0.1,0.3,inf),
   	\vol,0.3,
   	\res,0.5,
   	\xfade,-0.3,
   	\fsh,Pwhite(0,2,inf),

   )
)



Pbindef(\bb,\filterfreq,Pseq([500,1000,200,1500],inf))

Pbindef(\bb,\freq,Pseq([///doesn't work
   Pseq([[60,65,72]],4),
   Pseq([[63,65,67]],4)-3,
   Pseq([[60,69,65]],4)-7,
   Pseq([[53,60,67]],4)+2],inf))



Pbindef(\bb,\freq,Pseq([60,48,40],inf))

Pbindef(\bb,\filterfreq,Pseq([1500,500,1500,15000],inf))

Pbindef(\bb,\filtdecay,0.012,\filterfreq,Pseq([500,1000,200,1500],inf))

Pbindef(\bb,\freq,Pseq([60,57,55,53,50,48,47],inf))

Pbindef(\bb,\dur,Pseq([1/8,1/4,1/8,1/4],inf))

Pbindef(\bb,\dur,Pseq([1/3,1/4,1/6,1/2],4))

Pbindef(\bb,\dur,Pseq([1/4,1/4,1/4,1/4],inf))

Pbindef(\bb,\dur,Pseq([1,1,1,1],inf))


Pbindef(\bb).play(t)

Pbindef(\bb).stop(t)

t=TempoClock(124/60).permanent_(true);

Hm weird I Had to put the blcok of code in between ()
Like this

(
Pbindef(\bb,\freq,Pseq([///doesn't work
	Pseq([[60,65,72]],4),
	Pseq([[63,65,67]],4)-3,
	Pseq([[60,69,65]],4)-7,
	Pseq([[53,60,67]],4)+2],inf))
)

While other Pbindefs just have enough with

Pbindef(\bb,\freq,Pseq([60,48,40],inf))

SuperCollider evaluates blocks of code, which unless specified as a block (by using parenthesis) is assumed to end at the line break.

It’s the same exact reason you had to wrap your first Pbindef in parentheses.

(
   Pbindef(\bb,
   \instrument,
   	\Sqwer,
        \dur,1/4,
   	\freq,Pseq([48,60,53,57],inf),
   	\offset1,0,
   	\offset2,0.2,
   	\offset3,-0.1,
   	\filterfreq,500,
   	\filteramount,5000,
   	\filtdecay,0.070,
   	\ampdecay,Pwhite(0.1,0.3,inf),
   	\vol,0.3,
   	\res,0.5,
   	\xfade,-0.3,
   	\fsh,Pwhite(0,2,inf),

   )
)

Or your multi-line SynthDefs.

1 Like

Pbindefs can also control Pdefs
What are the advantages of wrapping up a pbind in a Pdef

(
SynthDef (\kick,
{
		arg pitch=50,patt=0.001,pdec=0.325,pcurve=(-50),pamt=100,att=0.001,dec=0.700,noisefreq=100,shamt=4,vol=0.3,out;
		var kick,penv,ampenv,noiseosc;
		penv=EnvGen.ar(Env([0,1,0],[patt,pdec],[0,pcurve]),doneAction:2);
		kick=SinOsc.ar(pitch+(penv*pamt))*0.9;
		noiseosc=LPF.ar(WhiteNoise.ar(0.1),noisefreq);
		kick=(noiseosc+kick)*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]))!2;
		kick=SineShaper.ar(kick*shamt)*vol;
		kick=(HPF.ar(kick,20));
		Out.ar(out,kick);
}).add
)


(
Pdef(\kik,
	Pbind(\instrument,\kick,
		\dur,1,
		\pitch,Pseq([50,50],inf),
		\pdec,0.8,
		\shamt,Pseq([2,2,2,2],inf),
		\vol,0.8,
))
)


Pbindef(\kik,\dur,Pseq([1/4,1/4,1/4,1/4],inf))
Pbindef(\kik,\dur,Pseq([1/4,1/2],inf))
Pbindef(\kik,\dur,Pseq([1,1/2],inf),\pitch,Pseq([150,250,300],inf),\vol,0.3)
Pbindef(\kik,\dur,Pseq([1,1/2,1/4,1/8],inf),\pitch,Pseq([50,100,150,250,350],inf))

Pdef(\kik).play(t);
Pdef(\kik).stop;

I have noticed when changing between different Pbindefs there is a time difference between pdefs
Example kick is playing at dur 1
A bass line with pbind 1/4 changing to 1/3 and then to 3 measures …
Here is sample example , there is a tempoclock
Play the kick at default 1 beat
Change the \crt fmbass \dur with the provided Pbindefs ,top bottom , let it play for a few beats.
Switching between \dur 1 and \dur 1/6 should be anough to bring out the sync issue
Here’s an audio example , the kick is dur ,1,
I switch the fm sound between \dur1 and \dur 1/6 back to dur \1 , it’s immediatly noticeable
I then stop the fm sound and set it to dur \1 , press play to have it n sync again

The only way to get the sync between pattens back is to stop and restart one
Is this becasue the default quant is expressed in seconds ?
Would be great to solve this issue , just execute code , from top to bottom

t=TempoClock(123/60).permanent_(true)

(
SynthDef (\kick,
{
		arg pitch=50,patt=0.001,pdec=0.325,pcurve=(-50),pamt=100,att=0.001,dec=0.700,noisefreq=100,shamt=4,vol=0.3,out;
		var kick,penv,ampenv,noiseosc;
		penv=EnvGen.ar(Env([0,1,0],[patt,pdec],[0,pcurve]),doneAction:2);
		kick=SinOsc.ar(pitch+(penv*pamt))*0.9;
		noiseosc=LPF.ar(WhiteNoise.ar(0.1),noisefreq);
		kick=(noiseosc+kick)*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]))!2;
		kick=SineShaper.ar(kick*shamt)*vol;
		kick=(HPF.ar(kick,20));
		Out.ar(out,kick);
}).add
)


(
Pdef(\kik,
	Pbind(\instrument,\kick,
		\dur,1,
		\pitch,Pseq([50,50],inf),
		\pdec,0.8,
		\shamt,Pseq([2,2,2,2],inf),
		\vol,0.5,
		\out,0,
))
)

///////
Pdef(\kik).play(t);
Pdef(\kik).stop;
// 

(
SynthDef(\twoop,
{
|fmamt=2,modoffset=24,moatt=0.001,modrel=0.500,ampatt=0.001,amprel=0.800,pitch=48,outt=0.3,pan=0.2,feed=0.2,out|
var mod,modenv,ampenv,carr;

		mod=SinOscFB.ar((pitch+modoffset).midicps,feedback:feed)*fmamt;
		modenv=EnvGen.ar(Env.perc(moatt,modrel),doneAction:0);
		ampenv=EnvGen.ar(Env.perc(ampatt,amprel),doneAction:2);
		carr=SinOsc.ar(pitch.midicps,(mod*modenv))*ampenv*outt;
		carr=Pan2.ar(carr,pos:pan);
		Out.ar(out,carr);
}).add
)
//  
(
Pdef(
	\crt,
	Pbind(
		\instrument,
		\twoop,
		\pitch,Pseq([60],inf),
		\dur,Pseq([1/4,1/4,1/2,1/4],inf),
		\fmamt,Prand([2,1,3,10,2,10,2,3,4,11],inf),
		\modrel,Prand([0.1,0.15],inf),
		\modoffset,Prand([12,12,12,12],inf),
		\feed,Pwhite(0.3,0.5,inf),
		\pan,Prand([-0.3,0,0.3],inf),
		\amprel,Pwhite (0.08,0.1,inf),
		\out,0,
		)
	)
);

Pdef.defaultQuant; // check it
Pdef.defaultQuant = 1; // change it



Pdef(\crt).stop;///////////FM
Pdef(\crt).play(t);

Pbindef(\crt,\dur,1,\fmamt,2)//alternate 
Pbindef(\crt,\dur,1/3,\fmamt,2)
Pbindef(\crt,\dur,1/6,\fmamt,2)
Pbindef(\crt,\dur,1/4,\fmamt,2)
Pbindef(\crt,\dur,3,\fmamt,2)
Pbindef(\crt,\dur,5,\fmamt,2)

You are indirectly referring to the fact that Pbindef(\aa) and Pdef(\aa) are referring to the same object (Pbindef(\aa) === Pdef(\aa); returns true). I did not realize this at first, so I think it is worth pointing out.

It may then seem like Pbindef(\aa, ...) is just a shortcut for Pdef(\aa, Pbind(...)), but there is one key difference that makes Pdef very useful in certain situations: Pbindef only replaces certain keys in the pattern (or adds them if they weren’t there before) while leaving the preexisting keys intact, but Pdef replaces the entire pattern. In essence, this means it not only replaces the keys that you tell it to replace, but it also removes the keys that you do not include in the new pattern.

This is very useful if you have built up a pattern that contains a lot of keys, and suddenly you want to remove a bunch of these keys and revert to the default values.

Pdef(\aa, Pbind()).play;
Pbindef(\aa, \degree, Pwhite(0, 7)); // add a key
Pbindef(\aa, \dur, 1/2); // add another key. Keeps the 'degree' key
// alternatively...
Pdef(\aa, Pbind(\dur, 1/2)); // "removes" all keys except the one given

If I change the dur in a Pdef from dur\1 to dur\1.02 (to get someting that will gradually fall out of sync with a dur\1 kick a reference ) , and then back to \1 , reanalyzing the Pdef always remains on beatsync.and the fm synth and kick will perfectly allign
Doing this from pbindefs not so .
But there is more ,when the Pdef is NOT inside Pbinddef , just a Pbindef and doing the same thing the it also loses sync just switching dur 1/6 back to dur\1
(second bit of code)
So this brings up back to square one , since pbindefs are needed to change parameters on the fly but they lose sync :frowning:

t=TempoClock(123/60).permanent_(true)

(
SynthDef (\kick,
{
		arg pitch=50,patt=0.001,pdec=0.325,pcurve=(-50),pamt=100,att=0.001,dec=0.700,noisefreq=100,shamt=4,vol=0.3,out;
		var kick,penv,ampenv,noiseosc;
		penv=EnvGen.ar(Env([0,1,0],[patt,pdec],[0,pcurve]),doneAction:2);
		kick=SinOsc.ar(pitch+(penv*pamt))*0.9;
		noiseosc=LPF.ar(WhiteNoise.ar(0.1),noisefreq);
		kick=(noiseosc+kick)*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]))!2;
		kick=SineShaper.ar(kick*shamt)*vol;
		kick=(HPF.ar(kick,20));
		Out.ar(out,kick);
}).add
)


(
Pdef(\kik,
	Pbind(\instrument,\kick,
		\dur,1,
		\pitch,Pseq([50,50],inf),
		\pdec,0.8,
		\shamt,Pseq([2,2,2,2],inf),
		\vol,0.5,
		\out,0,
))
)

///////
Pdef(\kik).play(t);
Pdef(\kik).stop;
// 

(
SynthDef(\twoop,
{
|fmamt=2,modoffset=24,moatt=0.001,modrel=0.500,ampatt=0.001,amprel=0.800,pitch=48,outt=0.3,pan=0.2,feed=0.2,out|
var mod,modenv,ampenv,carr;

		mod=SinOscFB.ar((pitch+modoffset).midicps,feedback:feed)*fmamt;
		modenv=EnvGen.ar(Env.perc(moatt,modrel),doneAction:0);
		ampenv=EnvGen.ar(Env.perc(ampatt,amprel),doneAction:2);
		carr=SinOsc.ar(pitch.midicps,(mod*modenv))*ampenv*outt;
		carr=Pan2.ar(carr,pos:pan);
		Out.ar(out,carr);
}).add
)
//  
(
Pdef(
	\crt,
	Pbind(
		\instrument,
		\twoop,
		\pitch,50,
		\dur,1,///change to 1.02 and then back to 1 and reanalyze result , perfect sync remains with kick 
		\fmamt,2,
		\modrel,Prand([0.1,0.15],inf),
		\modoffset,Prand([12,12,12,12],inf),
		\feed,Pwhite(0.3,0.5,inf),
		\pan,Prand([-0.3,0,0.3],inf),
		\amprel,Pwhite (0.08,0.1,inf),
		\out,0,
		)
	)
);

Pdef.defaultQuant; // check it
Pdef.defaultQuant = 1; // change it



Pdef(\crt).stop;///////////FM
Pdef(\crt).play(t);

Pbindef(\crt,\dur,1,\fmamt,2)// 
Pbindef(\crt,\dur,1.01,\fmamt,2)// 


t=TempoClock(123/60).permanent_(true)

(
SynthDef (\kick,
{
		arg pitch=50,patt=0.001,pdec=0.325,pcurve=(-50),pamt=100,att=0.001,dec=0.700,noisefreq=100,shamt=4,vol=0.3,out;
		var kick,penv,ampenv,noiseosc;
		penv=EnvGen.ar(Env([0,1,0],[patt,pdec],[0,pcurve]),doneAction:2);
		kick=SinOsc.ar(pitch+(penv*pamt))*0.9;
		noiseosc=LPF.ar(WhiteNoise.ar(0.1),noisefreq);
		kick=(noiseosc+kick)*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]))!2;
		kick=SineShaper.ar(kick*shamt)*vol;
		kick=(HPF.ar(kick,20));
		Out.ar(out,kick);
}).add
)


(
Pdef(\kik,
	Pbind(\instrument,\kick,
		\dur,1,
		\pitch,Pseq([50,50],inf),
		\pdec,0.8,
		\shamt,Pseq([2,2,2,2],inf),
		\vol,0.5,
		\out,0,
))
)

///////
Pdef(\kik).play(t);
Pdef(\kik).stop;
// 

(
SynthDef(\twoop,
{
|fmamt=2,modoffset=24,moatt=0.001,modrel=0.500,ampatt=0.001,amprel=0.800,pitch=48,outt=0.3,pan=0.2,feed=0.2,out|
var mod,modenv,ampenv,carr;

		mod=SinOscFB.ar((pitch+modoffset).midicps,feedback:feed)*fmamt;
		modenv=EnvGen.ar(Env.perc(moatt,modrel),doneAction:0);
		ampenv=EnvGen.ar(Env.perc(ampatt,amprel),doneAction:2);
		carr=SinOsc.ar(pitch.midicps,(mod*modenv))*ampenv*outt;
		carr=Pan2.ar(carr,pos:pan);
		Out.ar(out,carr);
}).add
)
//  
(///no more pdef , just pbindef
Pbindef(
	\crt,

		\instrument,
		\twoop,
		\pitch,50,
		\dur,1,///change to 1.02 and then back to 1 and reanalyze result ,no more sync
		\fmamt,2,
		\modrel,Prand([0.1,0.15],inf),
		\modoffset,Prand([12,12,12,12],inf),
		\feed,Pwhite(0.3,0.5,inf),
		\pan,Prand([-0.3,0,0.3],inf),
		\amprel,Pwhite (0.08,0.1,inf),
		\out,0,
		)
	)
);

Pdef.defaultQuant; // check it
Pdef.defaultQuant = 1; // change it



Pdef(\crt).stop;///////////FM
Pdef(\crt).play(t);

Pbindef(\crt,\dur,1,\fmamt,2)// 
Pbindef(\crt,\dur,1.02,\fmamt,2)// 


Not square one.

There is a hierarchy of behaviors here.

  • Pattern defines the general relationship between patterns and streams. Of particular relevance to this topic are asStream and asEventStreamPlayer. However, here, the link between the Pattern object and its contents is fixed: to change the contents, you pretty much need to throw away the old pattern object and make a new one.
  • Pattern’s subclass PatternProxy allows you to keep a constant reference to one proxy object, while replacing the contents freely.
  • PatternProxy’s subclass TaskProxy applies this “replace-contents” concept to an activity scheduled, and running, on a clock.
  • TaskProxy’s subclass EventPatternProxy extends this idea to event patterns / EventStreamPlayer – you can replace the entire pattern while playing.
  • EventPatternProxy’s subclass Pdef adds built-in named storage under a symbolic key.
  • Pdef’s subclass Pbindef uses the same storage repository as Pdef, but uses PbindProxy for the source pattern.

So the requirement that I’m reading from you now is that you want quantized play/stop control (TaskProxy layer), independent control over data streams (Pbindef or PbindProxy), with barline sync (we’ll get to that).

BTW one thing with the SynthDef:

(
SynthDef(\kick, {
	arg pitch = 50, patt = 0.001, pdec = 0.325, pcurve = (-50), pamt = 100, att = 0.001, dec = 0.700, noisefreq = 100, shamt = 4, vol = 0.3, out;
	var kick, penv, ampenv, noiseosc;
	
	// uhm... don't put doneAction: 2 here.
	// why? because the synth is getting cut off
	// before the volume envelope has gone to silence.
	// so there's a loud click at the end.
	// 99.9999% of the time, doneAction:2 belongs in the volume envelope
	penv = EnvGen.ar(Env([0, 1, 0], [patt, pdec], [0, pcurve])/*, doneAction:2*/);
	
	kick = SinOsc.ar(pitch + (penv * pamt)) * 0.9;
	noiseosc = LPF.ar(WhiteNoise.ar(0.1), noisefreq);
	
	// doneAction HERE
	kick = (noiseosc + kick) * EnvGen.ar(Env([0, 1, 0], [att, dec], [0, -5]), doneAction: 2) ! 2;
	kick = SineShaper.ar(kick * shamt) * vol;
	kick = (HPF.ar(kick, 20));
	Out.ar(out, kick);
}).add;
)

Because Pbindef timing and barline sync are separate, I would suggest separating them into two objects.

// changeable pattern
(
Pbindef(\kik).quant = -1;
Pbindef(\kik,
	\instrument, \kick,
	\dur, 1,
	\pitch, Pseq([50, 50], inf),
	\pdec, 0.8,
	\shamt, Pseq([2, 2, 2, 2], inf),
	\vol, 0.5,
	\out, 0,
);
)

TempoClock.tempo = 132/60;

// wrapper for bar sync
(
Pdef(\k).quant = -1;  // whole-bar
Pdef(\k, Pbindef(\kik).asStream);

Pdef(\k).play;
)

(asStream isn’t strictly needed at this stage, but it will be important later.)

Then…

Pbindef(\kik, \dur, 0.75);
Pdef(\k, Pbindef(\kik).asStream);  // reset 'k' on its barline

Pbindef(\kik, \dur, 1);
Pdef(\k, Pbindef(\kik).asStream);  // reset 'k' on its barline

It’s boring to have to do the two statements every time – for this, you can write a helper function.

(
f = { |pbkey, playerKey ... pairs|
	// *pairs: see
	// http://doc.sccode.org/Overviews/SymbolicNotations.html#Where%20f%20is%20a%20function
	Pbindef(pbkey, *pairs);
	// try to reset on the next quant division
	Pdef(playerKey, Pdef(pbkey).asStream);  // rebuild this reference
};
)

f.(\kik, \k, \dur, 0.75);

f.(\kik, \k, \dur, 1);

Then, if you want for instance \dur to be barline-synced but other pairs to be free running… it’s a little ugly but this seems to do it.

(
var dataStream;

Pbindef(\meldur, \dur, 1).quant_(-1);

Pbindef(\meldata,
	\degree, Pn(Pseries(0, Pwhite(1, 2, inf), { rrand(4, 9) }), inf),
	\legato, Pwrand([0.8, 1.01], [0.15, 0.85], inf)
).quant_(-1);

// without a consistent stream, the melody resets on the barline too
dataStream = Pbindef(\meldata).asStream;

Pdef(\mel, Pchain(
	dataStream,
	Pbindef(\meldur)
)).quant_(-1);

~setMel = { |... pairs|
	var hitDur = false;
	pairs.pairsDo { |key, value|
		if(key == \dur) {
			hitDur = true;
			Pbindef(\meldur, \dur, value)
		} {
			Pbindef(\meldata, key, value)
		}
	};
	// refresh timing only if changing dur
	if(hitDur) {
		Pdef(\mel, Pchain(
			dataStream,
			Pbindef(\meldur)
		).asStream)
	};
};
)

Pdef(\mel).play;

~setMel.(\dur, 0.75);

~setMel.(\dur, 1);

Pdef(\mel).stop;

hjh

BTW what is this notation? :wink:

hjh