Waveform tables

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

ctmg wrote:My spies tell me antti uses a blep table with 64 branches and no interpolation. My spies also tell me that aciddose uses 8 branches with spline interpolation.
By branches, do you mean phase shifted versions of the table?
Image
Don't do it my way.

Post

Borogove wrote:
ctmg wrote:My spies tell me antti uses a blep table with 64 branches and no interpolation. My spies also tell me that aciddose uses 8 branches with spline interpolation.
By branches, do you mean phase shifted versions of the table?
Yep. Although easiest is to just make one oversampled table and index into it ;)

Code: Select all

sample = blep_table[index*branches + branch];
(but I'm sure you knew that, your DSP fu is much greater than mine :shrug:)

Post

>> watch yer eardrums with this one..
>> it's a bit unpleasant

Cool.
Really switching?

>> But i have my doubts the audible click
>> is caused by the discontinuity rather than
>> just a bump in the signal power.

A bump in signal power is what a discontinuity is about.

I have a prototype of a BLIT in my source folder.
I don't attenuate the top harmonic in my BLIT the switches are in-your-face. But this is so easy to do since sin(n*x) is already generated for the algorithm.

I also have done a BLEP prototype (with both steps for saw and ramps for triangle) but I don't like the algo - keeping track of current offsets, slopes and when to blend in tables seems a complete mess to me. Especially the ramps cause headaches because the bandlimiting will cause a delay of a few samples in the ramp start, which will propagate through all of the rest of the signal. BLEP seems unelegant to me and also not very good for parallelization, since you must do logic-code on a per voice case that branches differently on each voice.

Post

I have nothing good to add at this time but I want this thread to send me emails. ;)

Post

Christian Schüler wrote:BLEP seems unelegant to me and also not very good for parallelization, since you must do logic-code on a per voice case that branches differently on each voice.
Yep. Even if BLEP might be faster in absolute terms, I'm thinking I'm going to go with differentiated parabolic and 2:1 oversampling and just accept a small amount of aliasing for my next project. Besides, I'm sharing cache with other processes, so it's nicer than a table-heavy solution...
Image
Don't do it my way.

Post

>>I'm thinking I'm going to go with differentiated parabolic and 2:1 oversampling

eh? What's that?

Post

mistertoast wrote:>>I'm thinking I'm going to go with differentiated parabolic and 2:1 oversampling

eh? What's that?
Antti just published a paper on it -- it's a cheaty way to make a sawtooth with less aliasing than usual.

The basic idea is that if you square a naive (aliasing) sawtooth, you get a series of parabolas, with harmonics dropping off twice as fast as usual for sawtooth -- including the aliased harmonics; you then differentiate it (take the sample-to-sample deltas rather that the raw value of the parabolic) to get back to a sawtooth shape -- but the aliased harmonics are quieter than a naive saw. It seems like cheating to me, but it seems to work. 96KHz sampling rate, 2KHz fundamental, the aliases below 32KHz (!!) are theoretically 60dB down. Unless I did the math wrong, which is entirely possible.
Image
Don't do it my way.

Post

Borogove wrote:
mistertoast wrote:>>I'm thinking I'm going to go with differentiated parabolic and 2:1 oversampling

eh? What's that?
Antti just published a paper on it -- it's a cheaty way to make a sawtooth with less aliasing than usual.

The basic idea is that if you square a naive (aliasing) sawtooth, you get a series of parabolas, with harmonics dropping off twice as fast as usual for sawtooth -- including the aliased harmonics; you then differentiate it (take the sample-to-sample deltas rather that the raw value of the parabolic) to get back to a sawtooth shape -- but the aliased harmonics are quieter than a naive saw. It seems like cheating to me, but it seems to work. 96KHz sampling rate, 2KHz fundamental, the aliases below 32KHz (!!) are theoretically 60dB down. Unless I did the math wrong, which is entirely possible.
Oooh I missed that!

Link me please? :D

Post

Differentiated parabolic is a strange name for sampling integral of the waveform, and then taking finite difference on the result. Name comes from doing this for saw wave synthesis (single period of saw is just a line, and it's integral is parabolic).

This can be done for any waveform though, as long as care is taken to generate the integrated version such that it's periodic as well (namely, that DC doesn't build up). I've tried it for variable ramp triangle among other things and it works fine for pretty much anything when you get the details of integral generation fine.

Idea is that integrated waveform has it's harmonics falling 6db/Oct faster than the original, which means the aliasing in low frequencies is much lower when sampled. Differentiation then fixes the original harmonics back to where they should be.

As for personal opinion, with around 4 times oversampling it sounds okayish, while not very clean.

As for BLEP and ramp nastiness, if you use linear-phase BLEPs with delay to get essentially zero-phase BLEP algo, you can easily generate ramp BLEP by taking advantage of the fact that a BLEP is essentially bandlimited heaviside step function, and what is being done is two non-periodic waves being crossfaded.

So a step for a saw is really..

(1+kx)*(1-BLEP(x)) + (kx-1)*BLEP(x)
= 1+kx + (kx-1-1-kx)*BLEP(x)
= 1+kx - 2*BLEP(x)

Now, one can do this when the ramps are going into different directions:

1+kx * (1-BLEP(x)) + 1-kx * BLEP(x)
= 1+kx + (1-kx-1-kx)*BLEP(x)
= 1+kx - 2*kx*BLEP(x)

There you go. Try it, it works. Why it works is left to be proven by somebody who feels like it's fun to write papers but the basic idea is that it's not the oneshot waves (up and down going ramps) that cause aliasing but only the periodic stepping/crossfading/whatever, and as long as the steps are properly aligned in periods in time, there'll be no aliasing in the result.

Now, as long as the patched waves are essentially just (possibly multiple times) integrated DC the approximation gives band-limited results, so you can use arbitary polynomials, at least in theory. And since polynomials can be approximate any curve, you could cheat a bit and use it on anything :D

Now, I haven't tried to above for hardsyncing sines, but I guess it should give decent results as long as the frequency of the sines isn't too high. Triangles sound (and look in an analyzer) fine all the way up until the BLEPs start cancelling each other and the thing fades.

As for the number of braches, I guess (can't be bothered to think right now) doubling the number of braches gives you same results as doubling the oversampling ratio, since what's being done really is sampling on higher sampling rate, and filtering down by cheating and only filtering stuff that actually causes ripples -> discontinuities. I remember seeing on the forum that antti was gonna publish a paper about something that's probably related so in case it is, I'll not spoil his fun even if the stuff seems kinda obvious. :roll:

PS. Been reading the forum for a long time, never posting anything, so I guessed it's my turn to try to contribute something.

Post

Borogove wrote:
mistertoast wrote:>>I'm thinking I'm going to go with differentiated parabolic and 2:1 oversampling

eh? What's that?
Antti just published a paper on it -- it's a cheaty way to make a sawtooth with less aliasing than usual.

The basic idea is that if you square a naive (aliasing) sawtooth, you get a series of parabolas, with harmonics dropping off twice as fast as usual for sawtooth -- including the aliased harmonics; you then differentiate it (take the sample-to-sample deltas rather that the raw value of the parabolic) to get back to a sawtooth shape -- but the aliased harmonics are quieter than a naive saw. It seems like cheating to me, but it seems to work. 96KHz sampling rate, 2KHz fundamental, the aliases below 32KHz (!!) are theoretically 60dB down. Unless I did the math wrong, which is entirely possible.
Links!! Links for the lazy people :D

Interesting first post there mystran :)

Post

Borogove wrote:Besides, I'm sharing cache with other processes, so it's nicer than a table-heavy solution...
This from the gentleman who told me I should just bite the bullet and stop worrying about using memory. :x :lol:

Post

mystran,

You need to talk more. No more lurking for you.

Post

mystran wrote:...

So a step for a saw is really..

(1+kx)*(1-BLEP(x)) + (kx-1)*BLEP(x)
= 1+kx + (kx-1-1-kx)*BLEP(x)
= 1+kx - 2*BLEP(x)

Now, one can do this when the ramps are going into different directions:

1+kx * (1-BLEP(x)) + 1-kx * BLEP(x)
= 1+kx + (1-kx-1-kx)*BLEP(x)
= 1+kx - 2*kx*BLEP(x)
Did you lose some parentheses in the first line of the second snip there?

If the saw and the ramp are offset, you can do a variable-duty width pulse, right? Is that what you're saying?

You need to go more slowly for the slow thinkers amongst us.

Post

So far, I've noticed these reasons to avoid the straightforward representation of the waves.

1) Speed/memory.
2) Non-aliasing sync function.

Am I missing anything?

Assuming I stick with straightforward wave representation (which I surely will for my current synth), are there any interesting ways to eliminate aliasing in osc sync?

I'm currently using the Casio filter trick to eliminate osc sync aliasing. The side effect is that the result ends up low-pass filtered. I wonder, does the minBlep osc sync solution also end up low-passing the signal?

Post

mistertoast wrote: Did you lose some parentheses in the first line of the second snip there?
Ah yeah. It should ofcourse read:

(1+kx) * (1-BLEP(x)) + (1-kx) * BLEP(x)

Post Reply

Return to “DSP and Plugin Development”