From aafbd7c5d620436eadb27eb236a59289a720b589 Mon Sep 17 00:00:00 2001 From: Leo Coogan Date: Wed, 4 Jun 2025 15:48:49 -0400 Subject: [PATCH] exponential wave oscillator --- exponential_waves.scd | 90 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 exponential_waves.scd diff --git a/exponential_waves.scd b/exponential_waves.scd new file mode 100644 index 0000000..db1a157 --- /dev/null +++ b/exponential_waves.scd @@ -0,0 +1,90 @@ +// 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); +) \ No newline at end of file