Sine hard sync

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

Post

It looks like i come up with a hard sync question all two years :)

I wonder what the best way is for a sine hard sync.

I had a look at the this paper by Vaidm:
https://www.native-instruments.com/file ... neSync.pdf

I managed to implement the scaled single ordinary BLEP step (same that i also use for a SAW) and antialiasing was already surprisingly good. But not good enough to use it without oversampling.

I'm struggling understanding the other ideas that have a better performance (n-order BLEP's and Ringmodulation solution). It would take me months to understand the paper, so i hope for some help.

Can someone explain the ideas behind these approaches?

Post

AFAICT the idea with the ringmod solution is that you can use a bandlimited envelope (generated the same way you generate a square BLEP) you can use this to "switch" (ie. switch out one side, switch in other side) a sine and the total bandwidth is just the sine frequency plus the envelope bandwidth. So if your sine is below some know frequency B and your envelope also has bandwidth B you only need a sampling rate of 2*B to say within limits (ie. basically you oversample by 2x).

The idea with the order-N BLEP approach is to simply compute a finite number of derivatives and then add a BLEP of the corresponding order for each. For an analytic sine, this will only give you approximate band-limiting, but every additional derivative adds another 6dB/octave decay to the aliasing. If you approximate a sine with a piecewise polynomial, then you can obviously get exact results (for the piecewise polynomial approximation), but in practice building high-order BLEPS is a bit tricky (though cubics are workable).

That said ... thanks to the nature of BLEPs (ie. it has to be "just right" or it will tend to make things worse) you really kinda need to understand the methods properly in order to actually get good results.

Post

Hi mystran. Thanks a lot for the answers. I'm having a hard, but also interesting, time with that one.
mystran wrote: Thu May 07, 2020 7:32 pm AFAICT the idea with the ringmod solution is that you can use a bandlimited envelope...
In this solution i do not add a BLEP i'm using it to blend the two sines. Is this an ordinary BLEP? The step is really steep, i'm wondering how this would work. I have to think about it a bit more. I'm not sure if i already understand how this can be done.
mystran wrote: Thu May 07, 2020 7:32 pm ...BLEP of the corresponding order for each...
Do i have to add different BLEP's and BLAMP's with different scalings for every discontinuity in the sync or how do i combine the different BLEP's and BLAMP's?

I have to think about it a bit more...

Post

I focus on the N-BLEP solution for now. I managed reduce aliasing a lot with working first and second order BLEP's (the one used for the triangle). Looks like the first order BLEP is scaled with x1 (the delta value) and the second order BLEP is scaled with x0.5 (the difference of the sample delta in the waveform, before and after the step).

Now i will try to generate an oversampled 3rd order BLEP table (the last one i want to add). I will try to integrate the second order BLEP and remove the ramp somehow like i did for the second order BLEP. After that i will try to mix it like the second order BLEP with a scaling of x0.25. I guess i can't take the delta in the waveform for this. I will try.

Hope this works. I'll let you know.

Any information about 3rd order BLEP's is welcome! :)

Post

xhy3 wrote: Sat May 09, 2020 8:58 am I focus on the N-BLEP solution for now. I managed reduce aliasing a lot with working first and second order BLEP's (the one used for the triangle). Looks like the first order BLEP is scaled with x1 (the delta value) and the second order BLEP is scaled with x0.5 (the difference of the sample delta in the waveform, before and after the step).
The absolute scaling depends on how you normalize your BLEPs. It's probably easiest to scale them such that you can simply take the difference between derivatives on each side of the discontinuity, so triangle basically gets twice it's slope, but the important part is just to be consistent.
Now i will try to generate an oversampled 3rd order BLEP table (the last one i want to add). I will try to integrate the second order BLEP and remove the ramp somehow like i did for the second order BLEP. After that i will try to mix it like the second order BLEP with a scaling of x0.25. I guess i can't take the delta in the waveform for this. I will try.
For higher order BLEPs numerical error accumulation becomes a problem REALLY fast, especially when it comes to the second half of the BLEP. So a better approach is to start with a unit step that goes from 0 to 1, then instead of integrating the whole thing and subtracting the trivial step, you can integrate only the first half (eg. use trapezoidal) and then take advantage of the known symmetry to mirror the samples for the second half. If you integrated an odd number of times then also invert the sign of the second half. No subtraction of any trivial waveforms is required this way and the error accumulation is reduced greatly. Even then, you want to compute these in double precision even if you end up converting the final results to singles (for actual processing) afterwards.

Also note that each additional round of integration places (significantly) greater demand for the quality of your original filter kernel, even if you could somehow integrate exactly using analytical integration. With the above use of symmetry, this actually tends to be the limiting factor in terms of the maximum order you can use. Basically if your kernel is not good enough, then the resulting BLEP will be complete(!) garbage and you will have to improve the original filter (eg. make it longer and/or use a better window, etc). For Lagrange-interpolators, one can show that the the maximum useful degree of BLEP is always the same as the degree of the interpolator (which is also the maximum degree of a polynomial the interpolator can reconstruct exactly; this is basically the condition we need), but for typical (eg. windowed) kernels the practical solution is to simply bump the quality until it works.

Post

Thanks for the answer. Such a great idea to use the symmetry while generating the BLEP's. I will try and report back!

Post

mystran wrote: Sat May 09, 2020 2:53 pm For higher order BLEPs numerical error accumulation becomes a problem REALLY fast, especially when it comes to the second half of the BLEP.
It's harder than i thought already for 3rd order. Still working on it. It does not work at the moment and makes things worse.

I was able to mirror the second order BLEP and it fits perfectly now :)

Can i scale the third order BLEP the same way i scale the second order BLEP with the same delta sample values?

Post

What convention you pick for scaling is up to you, but you need to know what the actual derivative of the final BLEP (in the per-branch sense) is in order to then scale this to match your waveform derivative (or rather the discontinuity magnitude in the derivative) when you mix the BLEP.

Post

mystran wrote: Mon May 11, 2020 4:33 pm What convention you pick for scaling is up to you, but you need to know what the actual derivative of the final BLEP (in the per-branch sense) is in order to then scale this to match your waveform derivative (or rather the discontinuity magnitude in the derivative) when you mix the BLEP.
Thanks for the information. I have done some more tests with my second order BLEP and scaled it manually. I was able to improve the aliasing a lot more in some situations. But it seems that there is no simple constant (constant * (newDelta - oldDelta)) that can be used to scale the BLEP. At least it does not lead to the best result.

Can it be that there is also some empirical tuning required to get the best result without using to much N-th order BLEP's?

Post

xhy3 wrote: Tue May 12, 2020 7:19 am But it seems that there is no simple constant (constant * (newDelta - oldDelta)) that can be used to scale the BLEP. At least it does not lead to the best result.
I'm not sure what "delta" is supposed to mean here. You almost certainly want to use analytic derivatives, not some finite difference scheme.

Post

Hi Mystran. Thanks for your time and thanks for being so patient.
mystran wrote: Tue May 12, 2020 8:36 am I'm not sure what "delta" is supposed to mean here. You almost certainly want to use analytic derivatives, not some finite difference scheme.
Thanks for pointing at this. I tried to get some values in the discrete world while it is much easier and accurate to just take the sin derivate.

I also forgot to take care about the phase increment (the frequency) to make the BLEP fit. This was the cause for the rising aliasing when i changed the frequencies.
I endet up with this code and i get the maximal anti aliasing on all frequencies with the second order BLEP now:

Code: Select all

float changeInDelta = cos(xTarget) - cos(xSource); // derivate of sin(x)
mixInBlep2(syncOffset, M_PI * phaseIncrement * changeInDelta);
Thanks!

And now i take another try on the 3rd order BLEP :)

Post

bleps.png
Just because they look so awesome :)
You do not have the required permissions to view the files attached to this post.

Post

BLEP3 now also reduced the aliasing around 6dB. Here is the code for completeness. I'm not sure why i have such a special scaling... maybe someone has an idea how to do it right, but it works:

Code: Select all

        // get waveform at that phase
        float xSource = 2.0f * M_PI * syncPhase;
        float valueOld = sin(xSource);
        float xTarget = 2.0f * M_PI * targetPhase;
        float valueNew = sin(xTarget);
        
        mixInBlep(syncOffset, valueNew - valueOld);
        
         // derivate of sin x -> cos x
        float changeInDelta = cos(xTarget) - cos(xSource);
        mixInBlep2(syncOffset, M_PI * phaseIncrement * changeInDelta); 
        
        // second derivate of sin x = -sin x
        changeInDelta = (-valueNew) - (-valueOld);
        mixInBlep3(syncOffset, 0.191563032 * phaseIncrement * phaseIncrement * changeInDelta); // scaling?

Post

Right, so every additional BLEP should give you an extra 6dB/octave slope in the aliasing harmonics.

Now, dsin(x)/dx = cos(x), but we also need to apply the rule for the "inner function" derivative so we get dsin(pi*f*x)/dx = pi*f*cos(pi*f*x). This is why the scaling depends on the frequency.

To get get the second derivative, we get take the derivative of pi*f*cos(pi*f*x) and get (pi*f)^2*-sin(pi*f*x) and the third derivative comes out as (pi*f)^3*-cos(pi*f*x) and so on. You can probably see a pattern here.

Post

mystran wrote: Tue May 12, 2020 6:44 pm Right, so every additional BLEP should give you an extra 6dB/octave slope in the aliasing harmonics.

Now, dsin(x)/dx = cos(x), but we also need to apply the rule for the "inner function" derivative so we get dsin(pi*f*x)/dx = pi*f*cos(pi*f*x). This is why the scaling depends on the frequency.

To get get the second derivative, we get take the derivative of pi*f*cos(pi*f*x) and get (pi*f)^2*-sin(pi*f*x) and the third derivative comes out as (pi*f)^3*-cos(pi*f*x) and so on. You can probably see a pattern here.
Thanks for the information. This was the last puzzle part. Things make sense now :)

Post Reply

Return to “DSP and Plugin Development”