Triangle wave from scratch

Hello community,

sorry for the noob question.
I’d like to generate a triangle wave from a phasor.
I have the feeling to be on the wrong way.
How would you do for the triangle waveform ?

(
{
	var trig = Impulse.kr(0);
	var freq = 60;

	var phasor = Phasor.ar(
		trig,
		(freq * SampleDur.ir),
		0,
		1
	);

	var saw = phasor * 2 - 1;
	var sinus = sin(phasor * (2 * pi));
	var par = abs(sin(phasor * (2 * pi))) * 2 - 1;
	var pulse = (phasor > 0.5) * 2 - 1;
	var tri = Select.kr(Duty.kr(freq.reciprocal, trig, Dseq([0, 1], inf)), [phasor, (1 - phasor)]) * 2 - 1; // this doesn't look good
	[saw, sinus, par, pulse, tri];
}.plot(60.reciprocal * 4);
)

with variable skew:

(
var triangle = { |phase, skew|
	Select.ar(phase > skew, [
		phase / skew,
		1 - ((phase - skew) / (1 - skew))
	]);
};

{
	var phase = Phasor.ar(DC.ar(0), \rate.kr(100) * SampleDur.ir);
	triangle.(phase, \skew.kr(0.5)) * 2 - 1;
}.plot(0.02);
)

or (these are identical):

(
var triangle = { |phase, skew|
	phase = phase.linlin(0, 1, skew.neg, 1 - skew);
	phase.bilin(0, skew.neg, 1 - skew, 1, 0, 0);
};

{
	var phase = Phasor.ar(DC.ar(0), \rate.kr(100) * SampleDur.ir);
	triangle.(phase, \skew.kr(0.5)) * 2 - 1;
}.plot(0.02);
)

here are some shapes combined:

(
var triangle = { |phase, skew|
	Select.ar(phase > skew, [
		phase / skew,
		1 - ((phase - skew) / (1 - skew))
	]);
};

var unitHanning = { |phase|
	1 - cos(phase * pi) * 0.5;
};

var unitTrapezoid = { |phase, width, duty|
	var steepness = 1 / (1 - width);
	var offset = phase - (1 - duty);
	var trapezoid = (offset * steepness + (1 - duty)).clip(0, 1);
	var pulse = offset > 0;
	Select.ar(width |==| 1, [trapezoid, pulse]);
};

var trapezoidalWindow = { |phase, skew, width, duty|
	var warpedPhase = triangle.(phase, skew);
	unitTrapezoid.(warpedPhase, width, duty);
};

var getMultiLFO = { |phase, skew, width, duty, mix|
	var trapezoid = trapezoidalWindow.(phase, skew, width, duty);
	var sine = unitHanning.(trapezoid);
	trapezoid * (1 - mix) + (sine * mix);
};

{
	var phase = Phasor.ar(DC.ar(0), \rate.kr(100) * SampleDur.ir);
	getMultiLFO.(phase, \skew.kr(0.95), \width.kr(0.65), \duty.kr(0.85), \mix.kr(0.5));
}.plot(0.021);
)

Thank you very much.@dietcv

Let me reformulate my question:
How to generate a triangle waveform form a phasor in the most crude way ?
Like I did for the saw, sinus, pulse etc.

(
{
	var phase = Phasor.ar(DC.ar(0), 100 * SampleDur.ir);
	((phase + 0.5).wrap(0, 1) * 2 - 1).abs * 2 - 1;
}.plot(0.02);
)

Another way using fold2:

(
{
	var trig = Impulse.kr(0);
	var freq = 60;

	var phasor = Phasor.ar(
		trig,
		(freq * SampleDur.ir),
		0,
		1
	);

	var saw = phasor * 2 - 1;
	var sinus = sin(phasor * (2 * pi));
	var par = abs(sin(phasor * (2 * pi))) * 2 - 1;
	var pulse = (phasor > 0.5) * 2 - 1;
	var tri = (phasor * 4).fold2(1);
	[saw, sinus, par, pulse, tri];
}.plot(60.reciprocal * 4);
)
1 Like

Thank you very much @dietcv & @TXMod