// expnw
(
{ |freq=220|
    var x, x1, sig;
    x = LFSaw.ar(freq).unipolar;
    x1 = Select.ar(x > 0.5, [x, 1-x]);
    sig = (8 * x1 * x - 1).bipolar;
    sig ! 2;
}.play
)

// expw
(
{ |freq=220|
    var x, sig;
    x = LFSaw.ar(freq).unipolar;
    x = Select.ar(x > 0.5, [x, 1-x]);
    sig = (8 * x * x - 1).bipolar;
    sig ! 2;
}.play
)

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


// The waveform is actually a negated welch window. You can create a skewable triangle out of a linear ramp signal and then just compute one half of the window, the triangle will mirror its shape. Additionally you can adjust the skew param to tilt the shape to the left and the right:

(
{
    var x, sig;
    x = LFSaw.ar(100).unipolar;
    x = Select.ar(x > 0.5, [x, 1-x]);
    (8 * x * x - 1).bipolar;
}.plot(0.02);
)

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

var unitWelch = { |phase|
    1 - squared(phase - 1);
};

var welchWindow = { |phase, skew|
    var warpedPhase = triangle.(phase, skew);
    unitWelch.(warpedPhase);
};

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


// Whats cool about that approach is that you can throw in different unit shapers instead of the unitWelch:

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

var unitTrapezoid = { |phase, width, duty = 1|
    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(BinaryOpUGen('==', width, 1), [trapezoid, pulse]);
};

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

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