Re: Hardsynced squarewave and anti aliasing technics

[email protected] Sun, 30 May 2021 00:50:07 -0400
Newsgroups gmane.comp.audio.supercollider.user
Message-ID <CAPjq8bT7VxcUx23CfqzhZ0MLJbbTPZNCrqEqGmr_4Rm3QS_Xrg@mail.gmail.com>
For a couple years I've been using this approximation of a square wave that
I found in some paper somewhere, can't find the paper right now, but it is
basically just multiplying a sine wave by some large value, calculated to
avoid extreme aliasing, and putting it through tanh distortion. Not perfect
but you can go a lot higher without noticeable aliasing than with a naive
approach and as a benefit supports hard sync using a phasor like James said:

var phase = Phasor.ar(syncSig, freq / SampleRate.ir, 0, 1) * 2pi;
var k = 12000 * (SampleRate.ir/44100) / (freq * log10(freq));
var sinSig = SinOsc.ar(0, phase);
var sqSig = tanh(sinSig * k);

a little more complicated to implement variable pulse width but I can share
my solution to that too if anyone's interested..

On Sat, May 29, 2021 at 9:14 PM <[email protected]> wrote:

> On Sun, May 30, 2021 at 7:14 AM <[email protected]> wrote:
> > Hi there,
> > May ask to you how to archive an hardsynced sware wave and the best
> practice to antialiasing,
>
> First, the bad news -- anti-aliasing is not well supported in
> SuperCollider. AFAIK would have to write it in C++ (or FAUST) as a
> binary UGen. (The most common way to handle antialiasing is
> oversampling -- compute the geometric waveform, with aliasing, but at
> 4x or 8x the sampling rate, and then use a filter to band-limit the
> signal *before* downsampling to the final rate. SC server doesn't have
> oversampling between UGens. A single UGen can oversample internally,
> but that needs C++ or FAUST. The other way might be related to BLEP
> but we don't have a way to apply that to an arbitrary signal.)
>
> But, a hard-synced pulse wave is not too difficult, if you take it apart.
>
> Many types of oscillators can be viewed in terms of the relationship
> between an increasing phase and the final output, e.g. a sinewave:
>
> ```
> p = {
>     var phase = Phasor.ar(0, 220 * SampleDur.ir, 0, 1);
>     [phase, (phase * 2pi).sin]
> }.plot;
>
> p.superpose_(true).refresh;
> p.plotColor_([Color.red, Color.green]).refresh;
> ```
>
> (It will look the same if you use `SinOsc.ar(220)` instead of the
> `sin` operator.)
>
> OK, now a square wave.
>
> ```
> p = {
>     var phase = Phasor.ar(0, 220 * SampleDur.ir, 0, 1);
>     [phase, LFPulse.ar(220, 0.5)]
> }.plot;
>
> p.superpose_(true).refresh;
> p.plotColor_([Color.red, Color.green]).refresh;
> ```
>
> In the relationship that emerges is: When the phasor is above a
> threshold, push it to +1; when below, -1. The threshold determines the
> pulse width.
>
> ```
> (
> a = {
>     var freq = MouseY.kr(200, 600, 1);
>     var width = MouseX.kr(0.01, 0.99, 0);
>     var ph = Phasor.ar(0, freq * SampleDur.ir, 0, 1);
>
>     // (ph > width) is 0 to 1
>     // we need -1 to 1
>     var pulse = (ph > width) * 2 - 1;
>
>     // width != 0.5 will have some DC offset
>     pulse = LeakDC.ar(pulse);
>
>     (pulse * 0.1).dup
> }.play;
> )
>
> a.release;  // when done
> ```
>
> You can't hard sync Pulse or LFPulse, but... you can do it to Phasor.
> And we know how to turn a Phasor into a (non-bandlimited ;'-/ ) pulse
> wave.
>
> ```
> (
> a = {
>     var freq = MouseX.kr(200, 1200, 1);
>     var width = LFDNoise3.kr(0.2).range(0.15, 0.5);
>     var syncfreq = MouseY.kr(50, 200, 1);
>     var syncOsc = SinOsc.ar(syncfreq);
>
>     // 'trigger' when syncOsc has an upward zero crossing
>     var ph = Phasor.ar(syncOsc, freq * SampleDur.ir, 0, 1, 0);
>
>     var pulse = (ph > width) * 2 - 1;
>
>     pulse = LeakDC.ar(pulse);
>     (pulse * 0.1).dup
> }.play;
> )
>
> a.release;  // when done
> ```
>
> (Move the mouse left/right for the classic sync sweep effect. At
> moderate frequencies it's not too bad.)
>
> hjh
>
> _______________________________________________
> sc-users mailing list
>
> info (subscription, etc.):
> http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
> search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
>