PolyBLEP oscillators
-
- KVRist
- 239 posts since 22 Jan, 2007 from Germany
Well, yep, box filtering isn't the best filter when it comes to transition width. The first examples I posted also had a 8.5kHz low-pass on them, the last two I posted are raw ... and contain a higher amount of high frequency content.2DaT wrote:All those box filtered waveforms are very dull at high frequencies.
But i am looking forward for sine sync spectrums
Here are another two samples, this time (slave) sweeping up to 14kHz.
Sawtooth, 96kHz, no filters, flac (2.6MB)
Sine, 96kHz, no filters, flac (1.7MB)
Master: 220Hz, slave: 55Hz to 14.08kHz.
... when time becomes a loop ...
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
-
- KVRian
- 563 posts since 23 Nov, 2010
It has very low aliasing even if it does rolloff the highs a fair bit.
How does the integral oscillator work? I mean I can see that you are generating an integral signal and differentiating that to get the actual output. And I can see that you are hard syncing the integral signal. I dont get how you are making the whole thing band limited.
I think I remember reading about differentiated wavetables that were then integrated on playback, and that reduced aliasing, but I don't remember ever reading anything about integral based waveforms.
Thanks,
How does the integral oscillator work? I mean I can see that you are generating an integral signal and differentiating that to get the actual output. And I can see that you are hard syncing the integral signal. I dont get how you are making the whole thing band limited.
I think I remember reading about differentiated wavetables that were then integrated on playback, and that reduced aliasing, but I don't remember ever reading anything about integral based waveforms.
Thanks,
Chris Jones
www.sonigen.com
www.sonigen.com
-
- KVRist
- 239 posts since 22 Jan, 2007 from Germany
It's direct quasi-bandlimited synthesis by basically just oversampling and averaging/box-filtering.sonigen wrote:I dont get how you are making the whole thing band limited.
It might get clearer with a simple example:
Consider a naive, digital oscillator with an 8 bits accumulator. We now have e.g. a step size (phase increment) of 4. To reduce aliasing we oversample by, well, let's say a factor of 8 using a simple averaging filter.
You would now sum 8 sub-samples for one output sample and just divide the result by 8.
Now, we do have a fixed step size, which is 4 in our case. I.e. we increment the accumulator by 4 for each sample. This can also be represented by 4 times incrementing by 1 and this means we just have a sum of natural numbers ... and there's a formula to calculate the sum for natural numbers.
Instead of adding 8 sub-sample outputs and dividing by 8, we now just calculate the sum over the step width and divide by the step width.
And to get the sum over our step width we just need to do a:
Code: Select all
sum(phase + step) - sum(phase)
You can compare this to the zero delay filters where you can e.g. solve the filter using an iterative approach (this is our loop case) or by solving for 'out' (this is the formula case).
Yeah, as I said, the box filter has a pretty bad transition width. My synths normally run internally at 96kHz and get resampled to the desired output rate, so in my case the attenuation in the highs can be neglected, as the strong attenuation then starts way beyond human hearing.sonigen wrote:It has very low aliasing even if it does rolloff the highs a fair bit.
Last edited by neotec on Tue Oct 29, 2013 8:43 am, edited 1 time in total.
... when time becomes a loop ...
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
-
- KVRian
- 563 posts since 23 Nov, 2010
-
- KVRist
- 239 posts since 22 Jan, 2007 from Germany
... my latest experiments also showed that you can expand this technique to give you PM without aliasing.
... when time becomes a loop ...
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
-
- KVRer
- 29 posts since 23 Nov, 2012
Anyone tried to port it to SE ?? Would be very interested in having such an OSC at my disposal
-
- KVRist
- 60 posts since 6 Dec, 2013 from The land of confusion
Nice work dude - I just tried this in reaper - sounds smoooooth!!
Love reaperJS for dsp R&D - awesome!
Love reaperJS for dsp R&D - awesome!
-
Richard_Synapse Richard_Synapse https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=245936
- KVRian
- 1136 posts since 20 Dec, 2010
This is the same as DPW right?neotec wrote:And to get the sum over our step width we just need to do a:
That's basically the whole trick about this ... it's just a pretty high oversampled, naive, digital oscillator decimated by an averaging/box filter, only that you're doing the oversampling by using formulas instead of loops.Code: Select all
sum(phase + step) - sum(phase)
Richard
Synapse Audio Software - www.synapse-audio.com
-
- KVRist
- 60 posts since 6 Dec, 2013 from The land of confusion
Isn't there a easy fix for the flaw in DPW to handle the sum crossing and changing
DT? something like this would maybe bring it up to the polyblep quality?
Edit - The only flaw was my misunderstanding the DPW algo
The correct integral of a naive saw is t*t-t
no need to handle sum's across the 0-1 wrap since the signed integral at 1 is 0!
it can be done slightly quicker tho with the proper integral (1 multiply less)
DT? something like this would maybe bring it up to the polyblep quality?
Code: Select all
float DPW(float t,float dt)
{
static float psum;
t=frac(t);
sum=(t*2.)-1.; // naive saw
sum=sum*sum;
float res=(sum-psum)/(dt*4.);
// Sum crossing fix: 1. Or whatever the integral
// for the entire naive waveform is
if ((t-dt)<0.) res+=1./(dt*4);
psum=sum;
return res;
}
Edit - The only flaw was my misunderstanding the DPW algo
The correct integral of a naive saw is t*t-t
no need to handle sum's across the 0-1 wrap since the signed integral at 1 is 0!
it can be done slightly quicker tho with the proper integral (1 multiply less)
Code: Select all
float DPW(float t,float dt) // assuming t is frac wrapped
{
static float psum;
sum=t*t-t; // Correct Signed naive integral
float res=(sum-psum)/dt;
psum=sum;
return res;
}
-
- KVRist
- 95 posts since 25 Jul, 2007 from Finland
And hard clipping. Here's 20Hz - 20kHz sine sweep clipped with hard clipper using this technique (trapezoidal integration for the non-clipped part), the bottom image is naive hard clipping for comparison.neotec wrote:... my latest experiments also showed that you can expand this technique to give you PM without aliasing.
- KVRian
- 1091 posts since 8 Feb, 2012 from South - Africa
Just for completeness - EPTR Saw (efficient polynomial transition region).
Haven't checked it against DPW but the CPU is in the same ballpark.
Andrew
Code: Select all
float SawOut;
phaseAccumulator = phaseAccumulator + 2.f * phaseIncrement;
if (phaseAccumulator > 1.f - phaseIncrement)
{
SawOut = phaseAccumulator - (phaseAccumulator/phaseIncrement) + (1.f / phaseIncrement) - 1.f;
phaseAccumulator = phaseAccumulator - 2.f;
}
else
{
SawOut = phaseAccumulator;
}
Andrew
- KVRian
- Topic Starter
- 519 posts since 12 Apr, 2010 from The Netherlands
Thanks for sharing.
I have just checked, and the frequency response is also virtually the same.Ichad.c wrote:Haven't checked it against DPW but the CPU is in the same ballpark.
- KVRian
- 1091 posts since 8 Feb, 2012 from South - Africa
Yeah, I though as much, thanks for testing! On my machine it has *slightly* better CPU, this is definetly a winner in the 'cheap & chearful class', since it behaves better when modulating.Tale wrote:Thanks for sharing.
I have just checked, and the frequency response is also virtually the same.Ichad.c wrote:Haven't checked it against DPW but the CPU is in the same ballpark.
Andrew
-
- KVRian
- 513 posts since 3 Sep, 2009 from Poland
Just tested the "box filter" oscillator, its really cheap. I just don't get this line / idea:
out = (integral(newPhase) - integral(phase) + lastIntegral) / (step + lastStep)
Neotec: could you explain?
out = (integral(newPhase) - integral(phase) + lastIntegral) / (step + lastStep)
Neotec: could you explain?
giq