Call for help regarding anti-aliasing

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Hello everyone!

I am a programmer who knows practically nothing about DSP.
I tried to generate some digital sounds.
I thought how hard can it be?
Needless to say, the sounds did not sound right.
I found out that this is due to what you DSP folks call "aliasing".
Actually, I found out that there is a whole science and a whole world out there behind that stuff that I initially approached as "how hard can it be?"
So, now I am in this weird situation where I am trying to find a solution to make my stuff work without knowing enough about the subject.

So, I need the help of some people who are very knowledgeable about DSP in order to understand things. I need to have some long, involved discussions.

I came up with a solution by myself, which currently only works for square waves, and achieves results that are identical to polynomial anti-aliasing (PolyBLEP,) but even if I am to keep working on it and extend it to work for any waveform, I will still need help.

I have prepared a document which contains a few words about myself and what I am looking for. It also contains some audio files, waveforms, and frequency analysis to show how my "empirical" algorithm compares to PolyBLEP.

It can be found here:
https://docs.google.com/document/d/1SMF ... sp=sharing

If you would be interested in having some discussions with a programmer who is practically ignorant of DSP, to enlighten him about DSP, please respond here, or send me an e-mail. My e-mail address is michael at michael dot gr.

Cheers,
Michael.

Post

You said that polynomial anti-aliasing "requires a custom-made algorithm for each type of waveform".

Particular waveforms are often used as examples because they have a small number of features (e.g. a sawtooth contains a single jump, or a triangle wave contains two ramps). But if you have many such features, you just apply similar aliasing-reduction to each of them.

Here's a sketch (roughly) explaining how things like BLEP reduce aliasing - perhaps you can compare this to your scheme, and see if there's some common ground:
poly-bl-illustration-small.png
This illustration includes jumps and ramps, but you can extend this to any other features you want.
You do not have the required permissions to view the files attached to this post.
Last edited by signalsmith on Tue May 04, 2021 4:22 pm, edited 1 time in total.

Post

It is possible to write (quite efficient) BLEP-code (whether polynomial or otherwise) that takes an arbitrary array of piecewise polynomial segments up to some fixed order. You can do things like let the user edit cubic-splines in a graphical editor and then play them back as BLEP-waveforms just fine.

The basic idea is that your oscillator keeps track of the index of the current segment, then when incrementing the phase check whether you reached the end point of the current segment. If this is the case, then you solve all the non-zero derivatives for both the current segment and the next segment at the transition point, subtract the two to get the BLEP gains, insert the relevant BLEPs into the output buffer, then increment the segment index and repeat (in case the frequency is high enough that you skipped whole segments within a single sample) until the phase is within the current segment.

If you only have a small fixed set of waveforms, then hard-coding allows you to optimize stuff like only computing the discontinuities and derivatives that are known to be non-zero for this particular waveform, but other than that the performance hit of a well-designed fully general BLEP oscillator is a lot less than you'd think.

Post

signalsmith wrote: Tue May 04, 2021 12:23 pm...
Thank you for your response.
And that infographic looks really good!
Unfortunately, there is some distance between what you are describing and what I understand PolyBLEP is; also, what you are describing does not agree with the PolyBLEP implementation that I have in my hands, either in terms of how the waveform looks, or in terms of what the code does. So, I do not know what to do with it.
(I have this: https://github.com/martinfinke/PolyBLEP discussed here: http://www.martin-finke.de/blog/article ... scillator/ and it simply smoothens the edges using some math which to me is voodoo magic.)

Post

mystran wrote: Tue May 04, 2021 12:54 pm It is possible to write (quite efficient) BLEP-code (whether polynomial or otherwise) that takes an arbitrary array of piecewise polynomial segments up to some fixed order. You can do things like let the user edit cubic-splines in a graphical editor and then play them back as BLEP-waveforms just fine.
Yes, my algorithm currently only works with straight line segments, but I was just reading up on cubic interpolation, so that's probably going to be the next step after I have solved the aliasing problem.
mystran wrote: Tue May 04, 2021 12:54 pm solve all the non-zero derivatives for both the current segment and the next segment at the transition point, subtract the two to get the BLEP gains, insert the relevant BLEPs into the output buffer
Well, you are speaking an unknown language to me right there. Even if we assume that I understand what derivatives are, that I can find the non-zero ones, and that I can somehow do that "solve" thing to them, still, I have no idea what you mean by "subtract the two to get the BLEP gains, and insert the relevant BLEPs."
What two?
What are BLEP gains?
Exactly what is the nature of the entities that you are referring to as "the BLEPs"?
How can I tell which ones of them are the "relevant" ones?
Also, I see no mention of BLAMP, but that's also lurking there and needs to be dealt with, no?
mystran wrote: Tue May 04, 2021 12:54 pm If you only have a small fixed set of waveforms, then hard-coding allows you to optimize stuff like only computing the discontinuities and derivatives that are known to be non-zero for this particular waveform
That's a very interesting insight, thank you!
I did not think of that.
So, is there some sample code somewhere which computes all the "discontinuities and derivatives" indiscriminately, so that it might work with any waveform instead of a limited set of predefined waveforms?

Post

MikeNakis wrote: Tue May 04, 2021 7:48 pm Well, you are speaking an unknown language to me right there. Even if we assume that I understand what derivatives are, that I can find the non-zero ones, and that I can somehow do that "solve" thing to them, still, I have no idea what you mean by "subtract the two to get the BLEP gains, and insert the relevant BLEPs."
Some amount of math is sort of unavoidable when it comes to DSP: derivatives come from calculus.

A "BLEP" is a band-limited step. If we subtract the naive step, we get just the "BLEP residue". The integral (or "anti-derivative") is sometimes called "BLAMP" and is the difference between a naive and a band-limited unit-change in the first derivative (rate of change). We can also similarly compute BLEPs for higher order derivatives (in theory; numerically it gets more challenging for higher orders, but the first few can be done just fine).

Now, one of the useful properties of a polynomial is that it only has a finite number of non-zero derivatives. For example a constant-function has none, a linear function has one (it's first derivative is a constant function), a quadratic has two (the first derivative is a linear function, which then has a constant derivative), a cubic has three (the first derivative is a quadratic) and so on.

When you jump from one polynomial segment to another, you can solve (using calculus) all the non-zero derivatives (in addition to any actual step) for both segments at the transition point (after solving for the exact transition point) and then compute the difference. This is basically something like a power-series representation of the discontinuity. We can then use these differences (=BLEP gains) to scale the "BLEP residues" that need to be subtracted in order to remove just the aliasing part of the signal.

Post

MikeNakis wrote: Tue May 04, 2021 7:23 pm
signalsmith wrote: Tue May 04, 2021 12:23 pm...
Unfortunately, there is some distance between what you are describing and what I understand PolyBLEP is; also, what you are describing does not agree with the PolyBLEP implementation that I have in my hands, either in terms of how the waveform looks, or in terms of what the code does. So, I do not know what to do with it.
PolyBLEP typically does it's smoothing only within the two samples before and after the jump (discontinuity). May be thats whats confusing you when you compare it to the graphics above which may appear to do it in more than 2 samples, which indeed is in general what other more heavy BLEP methods work like (say MinBLEP).
www.solostuff.net
Advice is heavy. So don’t send it like a mountain.

Post

It has been a year, and I still haven't found the help I was seeking.
So, I would like to bump this thread in case someone would care to help me out.

(It is almost as if people don't particularly like the idea of having video calls with complete strangers from faraway places; who would guess?)

Post

I don't want to sound rough, but this is a well solved problem and there are lots of open source implementations and public papers, so probably after giving you the hints/directions/drawings of what you need to do you shouldn't be surprised of strangers not giving you their time for free to train you in basic math.

It is the equivalent of a non programmer asking you about C++ expression templates. Understanding that concept has a series of prerequisites.

Understanding blep bandlimiting requires basic calculus and a bit of signal theory.

I will try to give a plain low-math explanation of what you are trying to do: look at a very low frequency bandlimited square wave from a high quality oscillator of a soft synths of yours. Probably Charlatan could be using bleps. You will see that the square wave has ripples before and after the step (if it uses plain bleps).

What you are trying to calculate are those ripples alone, so you can superimpose them to a naive square wave. This is basically what signalsmith explained very graphically.

The same set of superimposed ripples also works for the saw wave, as it also contains a step. It also does for oscillator hard sync. Each of these steps is a discontinuity on the signal: the signal has a sudden value jump "in one sample" (theoretically the module is infinity at that single point).

Then there are signals without those jumps like e.g. the triangle wave (composed of linear segments). But those still have discontinuities on the first derivative, e.g. the derivative of a triangle wave is a square wave, so you have to correct those.

https://media.cheggcdn.com/media/b82/b8 ... 2IebTB.png

Then the same for each added order e.g. waves with quadratic, cubic, etc segments until you reach sin signals whose derivative is a cosine, so they have no steps on any derivative.

This is leaving out practical/numerical aspects.

For calculating the magnitude, width and point at where you have to insert that some math is going to be required. It is not a programming problem, but signal theory.
Last edited by rafa1981 on Thu Mar 03, 2022 11:58 am, edited 1 time in total.

Post

@rafa1981 not harsh at all, thanks for the reply. The C++ templates analogy was a good one, and I feel a bit embarrassed because I often answer questions on stackoverflow and I quite often see people there who are basically starting from zero and trying to learn programming one stackoverflow question at a time. So, I understand what you are talking about.

Here is the thing: I do not want to learn DSP, I just want to generate aliased waveforms. And I appreciate your (and other people's above) attempts to explain things to me, by means of long, well-written posts, but when you try to do that, you necessarily use your own terms, and your own assumptions as to what my knowledge gaps may be. Unfortunately, my terms may be different than yours, and my knowledge gaps may also be different than what you might guess. That's why I am specifically seeking interactive discussion. I do not know how successful I was at conveying this in the opening post of this thread, but I believe that in order for my questions to be answered I need to have actual discussions over video.

Post

MikeNakis wrote: Wed Mar 02, 2022 11:04 pm Here is the thing: I do not want to learn DSP
You have to.

How can you write oscillator without aliasing if you don't really understand what aliasing is?

Bare minimum you would need to know: shannon-nyquist, bandlimiting, aliasing, sinc, convolution, sampling, oversampling, windowing. Basically a beginning of a DSP textbook. I bet you can google articles or videos of these themes too.

You don't need very deep understanding of all the intricacies involved, but surface level understanding is absolutely necessary.

Also, for many cases PolyBLEP is not adequate. Actually it is rather poor and is only okay with additional 2x oversampling. You can certainly hear a massive difference between PolyBLEP and proper 16 sample BLEP. The only selling point of PolyBLEP is it's computational efficiency.

Post

MikeNakis wrote: Wed Mar 02, 2022 11:04 pm Here is the thing: I do not want to learn DSP, I just want to generate aliased waveforms.
It's a DSP problem. Do you want existing code that works, or do you want to write it yourself?

For the former, there are some band-limited oscillators in the DaisySP library (ported from elsewhere).

Post

@2DaT and @imrae thanks for your responses.

I do believe I have a fairly good understanding of what aliasing is. My definition might differ from a DSP textbook definition, because my understanding of it is intuitive, and therefore free from theoretical baggage, but I believe it is just fine; not just fine "for all practical purposes", but actually fine precisely because it is free from theoretical baggage.

Here, this is an excerpt from a text I am writing these days:
The Wikipedia article about aliasing (https://en.wikipedia.org/wiki/Aliasing) has a lot to say, but in my own words, aliasing is a phenomenon that occurs when we try to digitally approximate an analog (or purely mathematical) signal by naively generating samples that try to match as closely as possible the approximated signal. It occurs with graphics, when we try to approximate an ideal line using pixels of a certain discrete size, and it also occurs with sound, when we try to approximate an ideal waveform using samples at certain discrete intervals. Aliasing essentially means that our digital approximation will not only deviate from the ideal signal, but it will actually deviate by varying degrees along the signal, and these varying degrees of deviation will exhibit cycles of repetition. These repetitive variations in the deviation are, more often than not, perceptible by our senses, and rather unpleasant.
Please feel free to point out mistakes in my understanding of aliasing, you would be doing me a favor; but please make sure that the mistake you are pointing out is a factual mistake, not a mistake just because what I am saying is not exactly what the DSP textbook says with all its jargon and lofty theory, which is often hopelessly inapplicable to real-world solutions that must work real-time.

The bottom line is that if I was prepared to learn DSP then I would not be asking for help; I would just learn DSP and do it by myself. I am asking for help because I believe that it is precisely the synergy between a DSP engineer, and me, a programmer with 30+ years of experience, that might be the shortest path to coming up with results.

I looked at the DaisySP library and it has more or less the same C++ code which I have already ported to Java. I repeat, the problem with it is that it only works with a specific set of predefined waveforms, whereas what I want is a general purpose solution that will work with any waveform.

I am not decided yet on whether I want existing code that works, or to write it myself. Either possibility is open. If you look at the google document that I linked to in the initial post of this thread, I have done significant progress in the direction of writing it myself; but it is not quite there yet, and I am afraid that it is only with the help of someone knowledgeable about DSP that it will get there.

Post

MikeNakis wrote: Thu Mar 03, 2022 10:26 am The Wikipedia article about aliasing (https://en.wikipedia.org/wiki/Aliasing) has a lot to say, but in my own words, aliasing is a phenomenon that occurs when we try to digitally approximate an analog (or purely mathematical) signal by naively generating samples that try to match as closely as possible the approximated signal. It occurs with graphics, when we try to approximate an ideal line using pixels of a certain discrete size, and it also occurs with sound, when we try to approximate an ideal waveform using samples at certain discrete intervals. Aliasing essentially means that our digital approximation will not only deviate from the ideal signal, but it will actually deviate by varying degrees along the signal, and these varying degrees of deviation will exhibit cycles of repetition. These repetitive variations in the deviation are, more often than not, perceptible by our senses, and rather unpleasant.
Just think of those two things:

1. Imagine that we can do near infinite sampling rate. We will not have aliasing at all !! Why do you think is that ?

2. If the naive waveform generates any frequencies above half of the sampling rate, we will have aliasing. Why do think is that?

If you can answer those two questions your self. You probably won't need the textbook DSP math to understand it. (Edit: I'm not implying that it's easy to answer them).
www.solostuff.net
Advice is heavy. So don’t send it like a mountain.

Post

This description of aliasing misses any useful sense of what causes it, when it will be severe, and when it is avoided. It implies that aliasing is inevitable, which is not true.

It is possible for a digitally-generated signal to contain no aliasing. It is expected that, competently implemented, a digitally sampled signal will contain negligible aliasing.

Post Reply

Return to “DSP and Plugin Development”