Portamento up and down

Hi,

I have written some code for a portamento Pbind sequence, it is almost what I want but not quite.

I want a sequence that starts on a frequency, here it is 80hz, portamentos up to another, eg. 100Hz, then goes back to 80Hz and repeats on a loop, up and down.

So, 80Hz(slideup)100Hz(slidedown)80Hz(slideup)100Hz(slidedown)…

Here is my synth def,

(
	SynthDef(\portamentoSin, {
		arg out=0, pan=0, freq=440, endFreq=440, dur=1, amp=2.0, atk=0.0001, rel=0.1;
		var sus, sig, env;
		sus = dur - atk - rel;
		env = EnvGen.ar(Env.linen(atk, sus, rel), doneAction:2);
		sig = SinOsc.ar(XLine.kr(freq, endFreq, dur).poll);
		Out.ar(out, Pan2.ar(sig, pan, amp) * env);
	}).add;
)

and my Pbind

(
	Pbind(\instrument, \portamentoSin,
		\freq, 80,
		\endFreq, 100,
		\octave, 5, 
		\dur,  20,
		\atk, 0.01,
		\rel, 0.09
	).play;
)

How can i integrate the slide down into the code as well?

Thanks

you could use an EnvGen instead of Line to set the shape.

You should also look at wrapping the frequency in Lag.ar or its variants and using Pmono instead of Pbind for a traditional portamento synth.

I’ve had a look at the help file on Lag.ar, but can’t work out how to integrate that into a portamento function.

how about

(
SynthDef(\porto, { |freq 300 lagTime 1|
	var sig = Saw.ar( Lag.kr( freq, lagTime ), 0.1 );
	Out.ar(0, sig)
}).add
)
Pmono(*[
	\porto,
	freq: Pwhite(300, 900, inf),
	lagTime: Pwhite(0, 2.0, inf),
	dur:1
]).play

Ah okay,

But i’m still not sure how to get a oscillating pattern that repeats. I need something that goes linearly up from a value, eg 100Hz-200Hz, then back down, 200Hz-100Hz, and repeats.

I can’t work out how to integrate that into the freq: instruction.

Thanks

How about something like this

(
SynthDef(\porta, {
	var sig = LFSaw.ar(\freq.kr(440).lag(\lt.kr(0.3)));
	var env = Env.asr().kr(2, \gate.kr(1));
	Out.ar(0, sig * \amp.kr(0.3) * env)
}).add;
)

(
Pdef(\test, 
	Pmono(
		\porta,
		\freq, Pseq([80, 100], inf),
		\lt, 2,
		\legato, 1
)).play
)

Nah, I’m not quite sure what’s going on there but the frequency doesn’t go from 80 - 100. It just sort of fluctuates about in that region, doesn’t go linearly back and forth.

Maybe using Lag isn’t the right approach. The linear ramp I had initially is the closet I’ve been. But I just need to get it to ramp back down and repeat

I’m back to tweaking my initial code.

(
	SynthDef(\portamentoSin, {
		arg out=0, pan=0, freq=440, endFreq=440, dur=1, amp=0.001, atk=0.0001, rel=0.1, bus = 0;
		var sus, sig, env;
		sus = dur - atk - rel;
		env = EnvGen.ar(Env.linen(atk, sus, rel), doneAction:2);
	    sig = SinOsc.ar(XLine.kr(freq, endFreq, dur).poll, \phase.kr(0));
	    sig = sig * env * 0.01;
	Out.ar(bus, sig)
	}).add;
)

x = Synth(\portamentoSin, [freq: 80, endFreq: 100, dur: 20])

And i’m trying to just use a synth object to play the SynthDef. I need to integrate a downramp XLine.kr, into the sig variable but I can’t work out how

(
	SynthDef(\portamentoSin, {
		arg out=0, pan=0, freq=440, endFreq=440, dur=1, amp=0.001, atk=0.0001, rel=0.1, bus = 0;
		var sus, sig, env;
		sus = dur - atk - rel;
		env = EnvGen.ar(Env.linen(atk, sus, rel), doneAction:2);
	    sig = SinOsc.ar(EnvGen.ar(Env.triangle(dur).range(freq,endFreq)).poll, \phase.kr(0));
	    sig = sig * env * 0.01;
	Out.ar(bus, sig)
	}).add;
)

x = Synth(\portamentoSin, [freq: 80, endFreq: 100, dur: 20])
1 Like

Thanks! Triangle function, yep that did it.

Lag is tricky to synchronize because it operates by “move x% of the way toward the target” – multiplication rather than addition. When the input value changes, it moves quickly at first and then “brakes” as it approaches the target value:

{ Lag.ar(LFPulse.ar(400), (1/400) * 0.8) }.plot;

I think the example was trying to compensate for the initial quick movement by specifying a longer lag time – but this means not exactly reaching the target.

For a lag-style linear ramp at kr, there’s VarLag (OK for kr, not for ar though – this example is kr).

(
SynthDef(\porta, {
	// let's unpack some of those nested parens, for readability
	var freq = VarLag.kr(\freq.kr(440), \lt.kr(0.3),
		curvature: 0  // linear
	);
	var sig = Saw.ar(freq);
	var env = Env.asr().kr(2, \gate.kr(1));
	sig = LPF.ar(sig, 1500);
	Out.ar(0, (sig * \amp.kr(0.3) * env).dup)
}).add;
)

(
Pdef(\test, 
	Pmono(
		\porta,
		\freq, Pseq([80, 100], inf),
		// for linear, should match lagtime to duration
		\lt, Pkey(\dur) / Pfunc { thisThread.clock.tempo },
		\legato, 1
	)
).play
)

hjh

1 Like