Re: Hardsynced squarewave and anti aliasing technics
[email protected] Sun, 30 May 2021 09:13:40 +0800
| Newsgroups | gmane.comp.audio.supercollider.user |
|---|---|
| Message-ID | <CAFniQ7X32SbNC0J6UAvRaM0DSf1OG2jMAji2J=qSp23UUAasXQ@mail.gmail.com> |
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/