PolyBLEP oscillators

Tale
KVRist

478 posts since 12 Apr, 2010, from Lowlands of Holland
I mentioned polyBLEP oscillators in another thread, where I was aksed what they are. I must admit I only understand them up to a certain point, so I may not be able to fully explain how they work, but I can show you that they work.

Just like (min)BLEPs, the basic idea of polyBLEPs is that you calculate a naive (non-bandlimited) waveform, and you then correct it at the transients. However, unlike minBLEPs you don't need an extra large precomputed table for this, you just caclulate a trivial polynomial, and you only do this for two(!) samples per transient. Check this out:

Code: Select all
`double t = 0.; // 0 <= t < 1double dt = freq / sample_rate;...double poly_blep(double t, double dt){  // 0 <= t < 1  if (t < dt)  {    t /= dt;    // 2 * (t - t^2/2 - 0.5)    return t+t - t*t - 1.;  }  // -1 < t < 0  else if (t > 1. - dt)  {    t = (t - 1.) / dt;    // 2 * (t^2/2 + t + 0.5)    return t*t + t+t + 1.;  }  // 0 otherwise  else  {    return 0.;  }}double poly_saw(double t, double dt){  // Correct phase, so it would be in line with sin(2.*M_PI * t)  t += 0.5;  if (t >= 1.) t -= 1.;  double naive_saw = 2.*t - 1.;  return naive_saw - poly_blep(t, dt);}...for (int i = 0; i < nFrames; ++i){  output[i] = poly_saw(t, dt);  t += dt;}`

Code originally adapted from http://www.acoustics.hut.fi/publications/papers/smc2010-phaseshaping/

Using the code above you can also create other waveforms, either directly (square, pulse), or by integrating other waveforms (square/pulse for triangle, saw for full-wave rectified sine).

Because PolyBLEPs are quasi-bandlimited, there will be some audible aliasing, especially when the fundamental approaches the Nyquist frequency. This is because the polynomial doesn't produce a clean sine. At 44.1 or 48 kHz this may be a problem, but this could be fixed by crossfading to a actual sine wave or to a brute-force Fourier series waveform. At higher sample rates this problem should fix itself, because the fundamental frequency will be way out of audible range before it approaches Nyquist.

PolyBLEPs attenuate higher harmonics slightly too much, so they might sound slightly dull, but again, this will probably only be audible at lower sample rates. (That being said, I have rejected polyBLEPs for Combo Model V for this very reason. That, and because in my case it was only marginally faster than BLITs.)

For those running REAPER (or ReaJS): I have a demo synth in JS that uses polyBLEPs:

Lame audio demo:
http://www.taletn.com/reaper/mono_synth.mp3

Slighty less lame audio demo:
http://www.taletn.com/reaper/poly_blep.mp3
Last edited by Tale on Tue Mar 05, 2013 3:23 pm, edited 1 time in total.
Martinic Scanner Vibrato
Banned
Oh wow. I may already be doing something like this. (So it means poly[nomial]BandLimitedstEP?)

Though off the top of my head I think my implementation is 3 or 4 samples, not just 2. Maybe that's due to the shape of my function?

The only problem I'm having is what happens when they overlap in time, as happens at very high frequencies and/or short pulse widths. If I can get that fixed I'm done.
Tale
KVRist

478 posts since 12 Apr, 2010, from Lowlands of Holland
AdmiralQuality wrote:(So it means poly[nomial]BandLimitedstEP?)

Yes.

AdmiralQuality wrote:Though off the top of my head I think my implementation is 3 or 4 samples, not just 2. Maybe that's due to the shape of my function?

More samples will further reduce aliasing, but it will also sound slightly duller. Another way to supposedly improve quality would be to use other (higher-order?) polynomials (see here). However, I couldn't detect much improvement, so for me two samples using this polynomial would seem the sweet spot, but YMMV.

AdmiralQuality wrote:The only problem I'm having is what happens when they overlap in time, as happens at very high frequencies and/or short pulse widths. If I can get that fixed I'm done.

If you would use two samples this wouldn't be a problem, because your fundamental can't be higher than Nyquist (thus shorter than two samples) ayway.

But seriously (and assuming standard waveforms): I haven't tried, but wouldn't my suggestion to crossfade to brute-force Fourier series fix this? You would only have to do this when the fundamental frequency is very high, so the Fourier series should be very short.
Martinic Scanner Vibrato
Banned
Tale wrote:
AdmiralQuality wrote:(So it means poly[nomial]BandLimitedstEP?)

Yes.

AdmiralQuality wrote:Though off the top of my head I think my implementation is 3 or 4 samples, not just 2. Maybe that's due to the shape of my function?

More samples will further reduce aliasing, but it will also sound slightly duller. Another way to supposedly improve quality would be to use other (higher-order?) polynomials (see here). However, I couldn't detect much improvement, so for me two samples using this polynomial would seem the sweet spot, but YMMV.

Interesting. In my tests the aliases just drop to nothing on the spectroscope as soon as I activate it. It does "round off" the top end some, but if I run it also in the oversampled domain, then it becomes WONDERFUL!

AdmiralQuality wrote:The only problem I'm having is what happens when they overlap in time, as happens at very high frequencies and/or short pulse widths. If I can get that fixed I'm done.

If you would use two samples this wouldn't be a problem, because your fundamental can't be higher than Nyquist (thus shorter than two samples) ayway.

Right. However a pulse width can conceptually be shorter than 2 samples.

But seriously (and assuming standard waveforms): I haven't tried, but wouldn't my suggestion to crossfade to brute-force Fourier series fix this? You would only have to do this when the fundamental frequency is very high, so the Fourier series should be very short.

That's an interesting angle I hadn't thought of. I was hoping to keep it "graceful". I'm pretty sure there's some way to apply one on top of the other (I think this happens in minBLEP too), I'm just not quite grokking it yet.
Tale
KVRist

478 posts since 12 Apr, 2010, from Lowlands of Holland
AdmiralQuality wrote:Interesting. In my tests the aliases just drop to nothing on the spectroscope as soon as I activate it. It does "round off" the top end some, but if I run it also in the oversampled domain, then it becomes WONDERFUL!

I haven't tried oversampling a polyBLEP yet, but it sounds promising. Thanks for the hint.
Martinic Scanner Vibrato
Banned
Tale wrote:
AdmiralQuality wrote:Interesting. In my tests the aliases just drop to nothing on the spectroscope as soon as I activate it. It does "round off" the top end some, but if I run it also in the oversampled domain, then it becomes WONDERFUL!

I haven't tried oversampling a polyBLEP yet, but it sounds promising. Thanks for the hint.

No problem! (I guess I can come out and say this, that I'm working on it for Poly-Ana. And it'll be an either/or/both approach, so you'll be able to use the existing oversampling capability PLUS this "polyBLEP" technique together, if you want. It's also incredibly CPU efficient, even at oversampled rates.)

I love your electronic organ clones, by the way. Didn't realize that was you. They're on my list of plug-ins to buy next time I'm liquid.
Tale
KVRist

478 posts since 12 Apr, 2010, from Lowlands of Holland
AdmiralQuality wrote:I love your electronic organ clones, by the way. Didn't realize that was you. They're on my list of plug-ins to buy next time I'm liquid.

No need to go all liquid on me; both Comb Model V and F are freeware (although donations are appreciated, of course).
Martinic Scanner Vibrato
Banned
Tale wrote:
AdmiralQuality wrote:I love your electronic organ clones, by the way. Didn't realize that was you. They're on my list of plug-ins to buy next time I'm liquid.

No need to go all liquid on me; both Comb Model V and F are freeware (although donations are appreciated, of course).

They ARE!?! Why did I think they were for pay? That's great news. (And I can't donate \$\$\$, but I can set you up with a Poly-Ana license. Contact me at aq AT admiralquality.com )
LemonLime
KVRist

231 posts since 15 Apr, 2012, from Toronto, ON
Thanks for the info on polyBLEP. That's great!
KVRian

1033 posts since 8 Feb, 2012, from South - Africa
Thanks Tale - that looks interisting! Has anybody tried this against DPW?
Urs
u-he

22231 posts since 7 Aug, 2002, from Berlin
It's basically a polynominal that follows the curve of a windowed sinc. Saves ram and divisions...

Tip: Check out bitmap resize algorithms such as Catmull and Mitchell... they've been doing this forever
Banned
Urs wrote:Tip: Check out bitmap resize algorithms such as Catmull and Mitchell... they've been doing this forever

My first job was programming binary load-lifters, very similar to your vaporators in most respects!
Tale
KVRist

478 posts since 12 Apr, 2010, from Lowlands of Holland
Ichad.c wrote:Thanks Tale - that looks interisting! Has anybody tried this against DPW?

I have read an article that compared different oscillator algorithms, and it concluded that DPW gives good sound quality and very low computational complexity, while DPW2X and polyBLEP both give very good quality and low CPU computational complexity. But I haven't tried DPW or DPW2X myself (perhaps I should).
Martinic Scanner Vibrato
Z1202
KVRian

946 posts since 11 Apr, 2002
Urs wrote:It's basically a polynominal that follows the curve of a windowed sinc. Saves ram and divisions...

Tip: Check out bitmap resize algorithms such as Catmull and Mitchell... they've been doing this forever
More precisely, the curve of Si(x) (integral sine) (with some windowing of the difference against a non-bandlimited step). In this regard I've been always wondering, isn't it more efficient to have a piecewise polynomial approximation of such "windowed" Si(x) (or si(x), for that matter, if we use the residual approach), where the pieces would have a one-sample length. Because then you can use polynomials of much lower orders.
Tale
KVRist

478 posts since 12 Apr, 2010, from Lowlands of Holland
Tale wrote:But I haven't tried DPW or DPW2X myself (perhaps I should).

Alright... I have now compared polyBLEP and DPW myself, and here are the results (of a 220 Hz saw, graphs from REAPER's JS: Analysis/gfxanalyzer):

Naive

DPW (order 2)

DPW2X (order 2, 2x oversampled)

DPW (order 5?, from this old thread)

PolyBLEP from Tutorial: BLEPs (using PolyBLEPs but extensible)

PolyBLEP (Välimäki & Huovilainen, source code in OP)

PolyBLEP (Välimäki & Huovilainen), 2x oversampled

Higher order polyBLEP (Pekonen, as found here)

Alternate higher order polyBLEP (Pekonen #2, as also found here)

7th order 4 point PolyBLEP from Better polybleps polynomials

Fourier series

And here is the DPW source code (as adapted from FAUST's oscillator.lib):

Code: Select all
`// DPW (order 2)double x1 = 0.;double dpw(double t, double dt){  // Correct phase, so it would be in line with sin(2.*M_PI * t)  t += 0.5 + 0.5*dt;  if (t >= 1.) t -= 1.;  // Naive saw  double x = 2.*t - 1.;  double x0 = x*x;  double y = (x0 - x1) / (4.*dt);  x1 = x0;  return y;}// DPW (order 3)double x1 = 0., x2 = 0.;double dpw3(double t, double dt){  t += 0.5 + dt;  if (t >= 1.) t -= 1.;  double x = 2.*t - 1.;  double x0 = x*x*x - x;  double y = ((x0 - x1) - (x1 - x2)) / (24.*dt*dt);  x2 = x1;  x1 = x0;  return y;}`

Note that there is no graph for the 3rd order DPW, because its spectrum is exactly the same as for polyBLEP (i.e. it nulls). However, DPW seems a bit whobbly when you quickly change its frequency, a side-effect of differentiating I guess, so I would certainly prefer polyBLEP over 3rd order DPW.

2nd order DPW 2x oversampled, using a 6th order FIR filter (from "Antialiasing Oscillators in Subtractive Synthesis" by Välimäki & Huovilainen), seems to give slightly better quality than the non-oversampled polyBLEP, but of course at higher CPU usage.

EDIT: Added graphs for higher order DPW, Fourier series, higher order polyBLEPs, polyBLEP from Tutorial: BLEPs (using PolyBLEPs but extensible), and 7th order 4 point polyBLEP from Better polybleps polynomials, and updated all other graphs with lower floor.
Last edited by Tale on Sun Nov 02, 2014 2:20 pm, edited 6 times in total.
Martinic Scanner Vibrato
Next

Moderator: Moderators (Main)