Antialiased sawtooth generation

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

I have investigated numerous sawtooth generation methods (BLIT + integration, wavetables), which all work more or less well.

But I wonder if it would not be possible to generate a perfectly antialiased sawtooth by generating a naive non-aliased sawtooth and then inserting "something" only at the point of discontinuity (in a buffer, obviously) without any integrator or whatever - just reading out that "something" from a table, scaling it (scaling needed?), and adding it up to the point of discontinuity in the buffer.

I've tried adding up a (scaled) BLIT at the fractional position of discontinuity, but that didn't work (maybe my scaling wasn't correct).

Does anybody know what to insert at the point of discontinuity and what does it need to be?

Post

This is the so called "residual BLEP approach". You insert a (windowed) difference between a bandlimited step and non-bandlimited step.

The first introduction of the BLEP method was done AFAIK by Eli Brandt (just search for his page). However he is using the minimum-phase version, which I believe is a questionable addition. Linear-phase BLEP should be perfectly fine, even though the introduced latency is higher.

Obviously, instead of inserting the BLEPs directly, it is more convenient to insert the correction residuals (differences between BLEPS and non-bandlmited steps).

The BLEPs or BLEP residuals can be stored in a table or their polynomial approximations can be used (look for the PolyBLEP method).

Also take a look at my article
http://www.native-instruments.com/filea ... neSync.pdf
for a more generalized description of BLEP-based techinques.

Recently I also started a thread on music-dsp list with some in-depth theoretical questions regarding the BLEP method:
http://music.columbia.edu/pipermail/mus ... 72679.html

Post

I'm sure I tried that too and I still had (some) aliasing. Will give it another try.

Post

Depends on how long your BLEP is. I think 32 samples is fine, while I couldn't hear any aliaisng with 64 samples (IIRC, it was 2008 when I last worked on this)

Another method is very simple an surprisingly low in aliasing (long time since I tried, not sure if I'm explaining it correctly):

Have a naive sawtooth:

phase = phase + phaseInc; if( phase >= 1.f ) phase -= 1.f;

Square it:

phaseSqr = phase * phase;

Add 2 samples delay:

phaseDelayed = phaseSqr + phaseSqrz2;
phaseSqrz2 = phaseSqrz1;
phaseSqrz1 = phaseSqr;

Differentiate:

sawtooth = phaseDelayed - sawtooth; // sawtooth is your output

(someone please correct me if I got this wrong… my memory...)

Post

What means "I couldn't hear" any aliasing? How much is that? I'm looking to have at least -90bB signal-to-noise ratio, ... I was using 32 samples for the BLEP btw. No offense but your last posted code is really a poor man's oscillator ;) I'm looking for the highest possible quality.

Post

zamrate wrote:What means "I couldn't hear" any aliasing? How much is that? I'm looking to have at least -90bB signal-to-noise ratio, ... I was using 32 samples for the BLEP btw.
I don't know about the exact SNR, but I believe 32 samples should really get you at least a comparable one. I hope you're not using a rectangular window for your residual? A Kaiser window with the parameter in the range 4-8 should give you decent results.

Post

zamrate wrote:No offense but your last posted code is really a poor man's oscillator ;) I'm looking for the highest possible quality.
Lol, yes, indeed. Just pointing out that there are other methods than the ones you mentioned, and sometimes combining those methods yields better results.

Post

Had a really stupid bug in my code, it all works now. Yes the SNR is really good now.

Post

Z1202 wrote:
zamrate wrote:What means "I couldn't hear" any aliasing? How much is that? I'm looking to have at least -90bB signal-to-noise ratio, ... I was using 32 samples for the BLEP btw.
I don't know about the exact SNR, but I believe 32 samples should really get you at least a comparable one. I hope you're not using a rectangular window for your residual? A Kaiser window with the parameter in the range 4-8 should give you decent results.
Okay, actually, here is the point. I was somewhat wrong about the SNR, as the Si function decays rather slowly. However, you can get most of the aliasing centered around Nyquist. This is even easier at 88kHz or higher sampling rate, because you have a larger inaudible range there. Since you're aiming for the "highest quality", my guess is that you would need to use 88kHz or higher to reduce the aliasing from the nonlinearities, FM etc and to get more decent frequency responses from the filters (which is the case even with BLT/TPT/ZDF filters).

Post

It's not enough to have a great FIR, you need to have the interpolation to match it. There's no point in using a 32 sample BLEP from an FIR with a 110db stopband if you then have 16 branches and drop sample interpolation.

You'll get whichever is worse, the stopband of the source FIR, or the SnR of the interpolation scheme for interpolating the BLEP table. (Roughly speaking).
Chris Jones
www.sonigen.com

Post

sonigen wrote: You'll get whichever is worse, the stopband of the source FIR, or the SnR of the interpolation scheme for interpolating the BLEP table. (Roughly speaking).
Even with drop-sample though, you can push the interpolation noise down simply by using more branches and at some point (typically a couple of thousand branches .. but memory is cheap) the FIR becomes the bottleneck.

Post

I tend to think of "number of branches" being part of the interpolation scheme. Maybe it's not interpolation in itself, but it's part of the scheme IMO.
Chris Jones
www.sonigen.com

Post

ok

Post

A long time ago, i played with DPW up to the 5th order, it was quite efficient.. low CPU, low aliasing... but like other tricky methods (polybleps et al.) they have their flaws (problems with fast modulation).

If you want to generate lots of sawteeth, you can go the raw force way.

As today's memory is almost free, I think that the highest quality would be achieved by using a set of bandlimited tables (MIP MAPing).
You can synthesise your tables by simple additive synthesis.
(here is an old example in JS http://forum.cockos.com/archive/index.php/t-16771.html )

I think that BLEPs are useful if you want hardsync.
See you here and there... Youtube, Google Play, SoundCloud...

Post Reply

Return to “DSP and Plugin Development”