Different behavior between integer and ugen math?

I’m working on an additive synth, and one of it’s components is applying a kind of windowing function to an array of amplitude values. basically I define a parabola and that parabola defines which amps are 0 and which are 1 and everything in between.

you can get idea of what i’m trying to do by plotting this graph

(
{
	var center = 32;
	var height = 1;
	var width = 16;
	
	var harms = (1..32);
	var amps = (1..32);
	
	var notch = amps.collect({|a|
		height * (1-((a-center) / width).pow(2));
	}).clip(0,1);
	
	notch.plot(discrete: true);
	SinOsc.ar(440 * harms, mul: notch/32).sum;
}.play
)

play around with the center, height and width values to gain an intuition about how it should work. and hear the added sines. this is essentially a bandpass filter. center moves the center, width is like the bandwidth or resonance and height is basically the slope.

Now change center to a Ugen

(
{
	var center = MouseX.kr(0, 32);
	var height = 1;
	var width = 16;
	
	var harms = (1..32);
	var amps = (1..32);
	
	var notch = amps.collect({|a|
		height * (1-((a-center) / width).pow(2));
	}).clip(0,1);
	
        // plot doesn't work with a ugen in the graph
	// notch.plot(discrete: true);
	SinOsc.ar(440 * harms, mul: notch/32).sum;
}.play
)

as I move the mouse across the screen, you can definitely hear the ‘filter’ ‘opening up’ but this is no longer mimicking a band pass, but more like a lowpass.

anyone have any idea what’s happening here?

‘pow’ documentation notes that “NOTE: When used with UGens which produce a negative signal this function extends the usual definition of exponentiation and returns neg(neg(a) ** b) . This allows exponentiation of negative signal values by noninteger exponents.”

I.e., aUGen pow: something = (abs(a) pow: b) * sign(a).

For your case, you could replace .pow(2) with .squared.

a = { DC.kr(-1).squared.poll(0) }.play;
UGen(UnaryOpUGen): 1

a = { DC.kr(-1).pow(2).poll(0) }.play;
UGen(BinaryOpUGen): -1

hjh

beautiful! thank you!