Conditionals in Pbind

Hello,

I am not able to solve this problem: \amp should be 0.04, when \freq is above 300. And it should be 0.02, when freq is over 600:

(6.collect{|i|

	Pbind(
		\amp, 0.1,
		\scale, ~erv,
		\instrument,\sawy,
		\freq, Pseq([200,350, 500, 700],1),
		\amp, Pfunc{|e| if (e[\freq] > 300, {0.04}, {0.1})}, Pfunc{|e| if (e[\freq] > 600, {0.02}, {0.1})},
		\atk, 1,
		\dcy, 1,
		\dur,Pswitch1([Rest(1),1, Pseq([0.5, 0.5],1)],Pseq(~vl[i],1)),

).play(c)})

Any help would be appreciated!

Reformatting your \amp expression for readability:

Pfunc { |e|
	if (e[\freq] > 300) {
		0.04
	} {
		0.1
	}
}, Pfunc{|e| if (e[\freq] > 600, {0.02}, {0.1})},

… so the > 600 branch is entirely outside of Pfunc, so it’s not part of the conditional at all.

If you want to use if-then-else syntax, then second condition needs to be inside one of the outer if {} functions.

Perhaps a matter of taste, but I prefer to perform the most restrictive test first. You’re asking > 300 first, which, if true, then requires a second test > 600. But you could do > 600 first:

if (e[\freq] > 600) {
	0.02
} {
	if(e[\freq] > 300) {
		0.04  // <= 600, but > 300
	} {
		0.1  // <= 300
	}
}

case may be neater-looking than nested ifs – this is equivalent to if-then-elseif-then-elseif... in other languages.

case
{ e[\freq] > 600 } { 0.02 }
{ e[\freq] > 300 } { 0.04 }
{ 0.1 }

hjh

1 Like

In case you hadn’t considered these, here are some alternatives that do something similar…

You could consider this a relationship, such that when the pitch is high, the amplitude is low. Done here with Pkey and linlin.

Pbind(
	\dur, 1,
	\freq, Pseq([200, 350, 500, 700], 1),
	\amp, Pkey(\freq).linlin(300, 600, 0.1, 0.02, \minmax), // note the clip mode
).trace.play

If you explicitly want to map to each frequency to some state, rather that write a Pfunc for each case you could do it once, assigning an index to each state.

Pbind(
	\dur, 1,
	\freq, Pseq([200, 350, 500, 700], 1),
	\index, Pfunc({|e| 
		case
		{ e[\freq] <= 300 } { 0 }
		{ e[\freq] <= 600 } { 1 }
		{ 2 } 
	}),
	\amp, Pindex([0.1, 0.02, 0.04], Pkey(\index))
).trace.play
1 Like

Thank you so much for your help. case may be the most elegant solution here, you are right, it is neater-looking and more quickly to understand than the nested ifs. Thank you!

Jordan, thank you for your help. You are perfectly right, I was trying to have this kind of relationship when the pitch is high, the amplitude is low. Great, thank you so much, there is (obviously) so much to learn.

Are you trying to do amplitude key tracking to make higher fundamentals less piercing? I prefer to do that in the SynthDef rather than the sequencer:

sig = sig * freq.explin(1000, 2000, 0, -10).dbamp;

This creates a nice gentle slope where the amplitude is unchanged up to 1kHz, and then gently drops by -10 dB from 1kHz to 2kHz.

2 Likes

Nathan, That’s a nice way to do this, thank you for your advice!