Anti-Aliasing For Wavetables

Mar
Mar Maryland, USAMember Posts: 21 Sine

I'm building an ultra-synth in Reaktor and I'm using the Sample Loop Module for different wavetables I've create. However, I'm experiencing a lot of aliasing from playback when using the WT's; even in Osc Loop Mode Excellent. Does any programmer of Reaktor know how to solve this issue? It would be most appreciated since this is an important factor in the synths creation.

Tagged:

Best Answers

  • colB
    colB Member Posts: 242 Saw
    Answer ✓

    There is no 'issue', Reaktor gives you the tools to build almost anything. If NI tried to second guess everything that anyone might want to make at some point in the future, that would be madness. Instead they created an amazing environment enabling us to make our own things, and use things made by others.


    Main thing to remember is that Primary level modules are very old - all the recent stuff is in Core. There hasn't been much new audio related stuff in Primary for ~16 years. Changes to primary since 2005 have mostly been bug fixes and updates to support new features added to core. Maybe the last major addition to Primary was the sine bank and modal bank in 2010?

    So don't expect too much from Primary level audio generation and processing components.

    Stick with it though - it's great. You'll probably find some wavetable based oscillators in the User Library that you can study for inspiration... iirc the monovox used this approach. not 100% sure though ;)

    https://www.native-instruments.com/en/reaktor-community/reaktor-user-library/entry/show/11763/

  • colB
    colB Member Posts: 242 Saw
    Answer ✓

    Why "shame on Reaktor"?

    You can build your own "clean wavetable playback" in Reaktor. That's the point. That's why core has taken over, because design and engineering of audio devices is about choices, not about being forced to use one design that by definition would have to incorporate massive compromises.

    With Reaktor using core, you get to choose the correct compromises for the specific project you are working on, based on your own specifications. That's awesome, and there is definitely no shame in it!

    I have made many things in Reaktor that would have been impossible in Kontakt, Serum, ANA 2, or most other plugins. Shame on them ;)

  • colB
    colB Member Posts: 242 Saw
    edited March 2 Answer ✓

    Not sure though - @NI Marcus did say they are making an ultra synth, so understanding is there that this is a development environment, and that it is capable of amazing things. It's just the expectations vs reality stage that everyone goes through when learning about this stuff.

    To me it's obvious that if all the components were high level, there would be too many limitiations, and all ultra synths would end up being so similar that they were pointless... which is kinda what Reaktor was like before core ;). But I've seen things... and all that old man jazz :-D


    Back on to wavetables though - not something I've spent a lot of time thinking about...

    If you have some wave table recorded at e.g. 44100Hz at MIDI note 60, then for notes lower than that, just a good interpolation is all that would be required to prevent aliasing, however, the lower you go, the more dull the sound will be because you start to miss those upper harmonics that are now tuned down a couple of octave...

    For notes higher, it's more problematic, because upper harmonics that were bandlimited at note60 could now be above nyquist and so cause aliasing.

    So various options might be (and this is why you cant have a general one size fits all wavetable module):

    • Just accept that there is aliasing and stick a high pass on it to kill aliases below the fundamental
    • create multiple samples at different frequencies, so you never have to tune up, and never down by more than some interval
    • process the table at initialisation by filtering so there are multiple copies each progressively filtered at a lower cutoff, so that it can be pitched up further using interpolation without causing aliasing
    • some fancy pants real time processing that does the same thing but without the pre-processing step (difficult with Reaktor methinks)
    • do a shit ton of oversampling, then filtering, then downsampling

    Each of those might be appropriate, or not, in some specific situation. It's completely unreasonable to expect NI to cover all the bases, and possible new techniques that haven't been invented yet, for not just wavetables, but all the different types of process that folk might want for some arbitrary project.

    What other options are there?

    What does Serum do?

    One thing that would be cool is the pre-procesing option, but one that uses fancy high tech analysis (fft and other even more esoteric stuff), so there are options to e.g. preserve frequency response envelope while changing pitch... but because it's preprocessed, it gets converted back to time domain during initialisation, so there's no problem with latency, or cpu load.

    Another issue is what different folks perceptions of what a 'wavetable' is. For old school me, it's a bank of multiple single cycle waves of some exact number of samples (usually a power of 2), so maybe 64 different cycles, each 1024 samples long. But having a look at some of the free 'wavetabes' I found last night, not all follow this format, some have transient attacks at the start that don't fit into the format. For that you would need a more intelligent player that finds the cycles itself using maybe self correlation and zero crossings, or something... to me that's not a proper wavetable, but some sort of mutant sample player :)

  • Laureano Lopez
    Laureano Lopez Cordoba, ArgentinaMember Posts: 55 Tri
    edited March 3 Answer ✓

    Hmm, so on importing a wavetable, you could do one pass, through a bunch of filters, each creating a new table half the size of the previous to go up in octaves... I suppose the filters would have to be designed, or analysed carefully - linear phase and all that - and have the output adjusted for the phase delay...

    Pretty much I think. The ens at the link doesn't do the downsampling, so all tables are the same size. In Carbon the tables are all saved in a single table module -you can see by inspecting that each shape is repeated in a progressively shorter version. This guy says the drop-sample approach makes playback more cpu intensive. If you downsample each copy you can use a single filter for all steps, with a fixed cutoff at sr/4. Then you can always transpose each table down, not up, and there's no aliasing at all -I think this is what Carbon 2 does. This makes top harmonics suddenly appear/disappear when the table is switched though, so you can get more fancy and crossfade between tables. That does sound like a cpu hog 😁

    Edit: when I say sr/4 I mean pi/2, like, sr/4 of the previous step's rate, not the actual SR.R. It means the filter is static, like, the coefficients don't need to change. If you don't downsample, you need a filter with a variable cutoff. You can see in the linked ens that the filter is very complicated, and the playback very simple.

  • colB
    colB Member Posts: 242 Saw
    Answer ✓

    Yes, the SR/4 filter thing working with the same coefficients as you step down the same rate is one of the few things that I 'got' a long time ago - just seems intuitive - unlike most of DSP!

    I wonder if the drop sample approach is actually easier on cpu because smaller tables take up less cache, particularly in the case where you cross fade, which is the only way to go IMO. I suppose there will be a crossover point in terms of table size and scaling jump size... probably different depending on the system cache size, cpu family etc. The only saving you really make by not doing it is that you only need to calculate the index once, then use the same index for both tables when crossfading, otherwise it's just an interpolation either way surely?

    For cool wavetable scanning FX, you might be cross fading between two sets of tables... one crossfade to mitigate the octave step, the other one to morph between two wave shapes. Definitely want to minimise table size in that case I would think?

Answers

  • colB
    colB Member Posts: 242 Saw

    Are you sure its aliasing, not some other issue?

    If it is definitely aliasing, are you sure it's not baked into the wavetables?

    If you are sure that the wavetables are completely bandlimited, and there is no other issue, then you just discovered where most of the work is to be found ;) welcome to the wonderful world of expectations vs reality in DIY DSP!

    First thing I would do is start trawling the net for academic papers on how to reduce or prevent aliasing in wavetable synthesis. Then I would trawl for information on how to understand the maths well enough to know which parts I can ignore... and so it goes

    A cubic or higher order interpolation is probably going to be a good start? Id guess that's what the Sample Loop module uses, although using Primary modules is problematic, because if they exhibit problems, you can't fix them. Core is better because you can scratch build, or modify when library things aren't quite providing what you need.

  • Mar
    Mar Maryland, USAMember Posts: 21 Sine

    Thanks for your reply. Sounds like a task to create a anti-alias module by DSP. Reaktor should have known about this issue. Especially since Kontakt 6 does wavetable synthesis importing without aliasing. Lol.

  • colB
    colB Member Posts: 242 Saw
    Answer ✓

    There is no 'issue', Reaktor gives you the tools to build almost anything. If NI tried to second guess everything that anyone might want to make at some point in the future, that would be madness. Instead they created an amazing environment enabling us to make our own things, and use things made by others.


    Main thing to remember is that Primary level modules are very old - all the recent stuff is in Core. There hasn't been much new audio related stuff in Primary for ~16 years. Changes to primary since 2005 have mostly been bug fixes and updates to support new features added to core. Maybe the last major addition to Primary was the sine bank and modal bank in 2010?

    So don't expect too much from Primary level audio generation and processing components.

    Stick with it though - it's great. You'll probably find some wavetable based oscillators in the User Library that you can study for inspiration... iirc the monovox used this approach. not 100% sure though ;)

    https://www.native-instruments.com/en/reaktor-community/reaktor-user-library/entry/show/11763/

  • Mar
    Mar Maryland, USAMember Posts: 21 Sine

    Then there is a issue...Shame on Reaktor it should give high clean wavetable playback in Osc Mode. Other programs like Kontakt, Serum, ANA 2 can do it why can't Reaktor.

  • colB
    colB Member Posts: 242 Saw
    Answer ✓

    Why "shame on Reaktor"?

    You can build your own "clean wavetable playback" in Reaktor. That's the point. That's why core has taken over, because design and engineering of audio devices is about choices, not about being forced to use one design that by definition would have to incorporate massive compromises.

    With Reaktor using core, you get to choose the correct compromises for the specific project you are working on, based on your own specifications. That's awesome, and there is definitely no shame in it!

    I have made many things in Reaktor that would have been impossible in Kontakt, Serum, ANA 2, or most other plugins. Shame on them ;)

  • colB
    colB Member Posts: 242 Saw
    edited March 2 Answer ✓

    Not sure though - @NI Marcus did say they are making an ultra synth, so understanding is there that this is a development environment, and that it is capable of amazing things. It's just the expectations vs reality stage that everyone goes through when learning about this stuff.

    To me it's obvious that if all the components were high level, there would be too many limitiations, and all ultra synths would end up being so similar that they were pointless... which is kinda what Reaktor was like before core ;). But I've seen things... and all that old man jazz :-D


    Back on to wavetables though - not something I've spent a lot of time thinking about...

    If you have some wave table recorded at e.g. 44100Hz at MIDI note 60, then for notes lower than that, just a good interpolation is all that would be required to prevent aliasing, however, the lower you go, the more dull the sound will be because you start to miss those upper harmonics that are now tuned down a couple of octave...

    For notes higher, it's more problematic, because upper harmonics that were bandlimited at note60 could now be above nyquist and so cause aliasing.

    So various options might be (and this is why you cant have a general one size fits all wavetable module):

    • Just accept that there is aliasing and stick a high pass on it to kill aliases below the fundamental
    • create multiple samples at different frequencies, so you never have to tune up, and never down by more than some interval
    • process the table at initialisation by filtering so there are multiple copies each progressively filtered at a lower cutoff, so that it can be pitched up further using interpolation without causing aliasing
    • some fancy pants real time processing that does the same thing but without the pre-processing step (difficult with Reaktor methinks)
    • do a ***** ton of oversampling, then filtering, then downsampling

    Each of those might be appropriate, or not, in some specific situation. It's completely unreasonable to expect NI to cover all the bases, and possible new techniques that haven't been invented yet, for not just wavetables, but all the different types of process that folk might want for some arbitrary project.

    What other options are there?

    What does Serum do?

    One thing that would be cool is the pre-procesing option, but one that uses fancy high tech analysis (fft and other even more esoteric stuff), so there are options to e.g. preserve frequency response envelope while changing pitch... but because it's preprocessed, it gets converted back to time domain during initialisation, so there's no problem with latency, or cpu load.

    Another issue is what different folks perceptions of what a 'wavetable' is. For old school me, it's a bank of multiple single cycle waves of some exact number of samples (usually a power of 2), so maybe 64 different cycles, each 1024 samples long. But having a look at some of the free 'wavetabes' I found last night, not all follow this format, some have transient attacks at the start that don't fit into the format. For that you would need a more intelligent player that finds the cycles itself using maybe self correlation and zero crossings, or something... to me that's not a proper wavetable, but some sort of mutant sample player :)

  • Laureano Lopez
    Laureano Lopez Cordoba, ArgentinaMember Posts: 55 Tri
    edited March 3

    - create multiple samples at different frequencies, so you never have to tune up, and never down by more than some interval

    - process the table at initialisation by filtering so there are multiple copies each progressively filtered at a lower cutoff, so that it can be pitched up further using interpolation without causing aliasing

    Here is an example of the second method (I haven't used it, but may serve as a guide). These two ideas can be used together if each copy is downsampled from the previous one. This approach is used in Carbon 2:

    understanding is there that this is a development environment

    Probably, but comparing with Kontakt or Serum points to the contrary. I'm only bashing NI though, and only their marketing approach, which has the side effect of relegating development on Reaktor itself.

  • colB
    colB Member Posts: 242 Saw
    edited March 3

    Hmm, so on importing a wavetable, you could do one pass, through a bunch of filters, each creating a new table half the size of the previous to go up in octaves... I suppose the filters would have to be designed, or analysed carefully - linear phase and all that - and have the output adjusted for the phase delay...

    ...up to a point where you just fade to a sine wave to annoy the 0.1% of folk with golden ears that can hear the difference at 14KHz :-)

    then on playback, you crossfade between them to prevent noticeable edges between the octaves...

    the devil will undoubtedly be in the detail as always

    EDIT: which seems to be exactly what the ens at the linky you posted is doing... :) nice

  • Laureano Lopez
    Laureano Lopez Cordoba, ArgentinaMember Posts: 55 Tri
    edited March 3 Answer ✓

    Hmm, so on importing a wavetable, you could do one pass, through a bunch of filters, each creating a new table half the size of the previous to go up in octaves... I suppose the filters would have to be designed, or analysed carefully - linear phase and all that - and have the output adjusted for the phase delay...

    Pretty much I think. The ens at the link doesn't do the downsampling, so all tables are the same size. In Carbon the tables are all saved in a single table module -you can see by inspecting that each shape is repeated in a progressively shorter version. This guy says the drop-sample approach makes playback more cpu intensive. If you downsample each copy you can use a single filter for all steps, with a fixed cutoff at sr/4. Then you can always transpose each table down, not up, and there's no aliasing at all -I think this is what Carbon 2 does. This makes top harmonics suddenly appear/disappear when the table is switched though, so you can get more fancy and crossfade between tables. That does sound like a cpu hog 😁

    Edit: when I say sr/4 I mean pi/2, like, sr/4 of the previous step's rate, not the actual SR.R. It means the filter is static, like, the coefficients don't need to change. If you don't downsample, you need a filter with a variable cutoff. You can see in the linked ens that the filter is very complicated, and the playback very simple.

  • colB
    colB Member Posts: 242 Saw
    Answer ✓

    Yes, the SR/4 filter thing working with the same coefficients as you step down the same rate is one of the few things that I 'got' a long time ago - just seems intuitive - unlike most of DSP!

    I wonder if the drop sample approach is actually easier on cpu because smaller tables take up less cache, particularly in the case where you cross fade, which is the only way to go IMO. I suppose there will be a crossover point in terms of table size and scaling jump size... probably different depending on the system cache size, cpu family etc. The only saving you really make by not doing it is that you only need to calculate the index once, then use the same index for both tables when crossfading, otherwise it's just an interpolation either way surely?

    For cool wavetable scanning FX, you might be cross fading between two sets of tables... one crossfade to mitigate the octave step, the other one to morph between two wave shapes. Definitely want to minimise table size in that case I would think?

  • Laureano Lopez
    Laureano Lopez Cordoba, ArgentinaMember Posts: 55 Tri
    edited March 8

    (Files removed from the next messages to reduce old version pollution.)

    Here is a mip-map generator with drop-sample. The source array size must be a power of two. The target table size is source size * 2 - 2. It takes source size * 3 - 4 + filter latency * 2 * (log2(source size) - 1) events to fill the target table. The filter is probably a bit excessive, a smaller one may be ok. It has 31 samples of latency. I preloaded a 1024-samples saw (naively computed so it's aliased by itself), so we need 1024 * 3 - 4 + 31 * 2 * (log2(1024) - 1) = 3626 events. Each step needs twice the filter latency to load the delay lines before starting to take their output, otherwise the past would be zeros. I'm clocking on SR.C, but it would work with an iteration too. Later I'll see how to solve the playback module with crossfade... This is not like exhaustively debugged so, let me know if you see something wrong.

    Edit: I made it multitable, preloaded it with a saw and a square. The event count was still wrong, but now I fixed my iterator and it's right. Hopefully 😒

  • Laureano Lopez
    Laureano Lopez Cordoba, ArgentinaMember Posts: 55 Tri
    edited March 8

    Well, here's a wavetable oscillator, full of all kinds of compromises 😁

    I revised a couple more things in the mip-map generator, it still makes the same tables. I heavily adapted the Carbon 2 oscillator for the rest. For some reason the Carbon phasor syncs table changes to its cycle -I can't see why and it doesn't seem good, as it causes clicks that otherwise don't happen. So I scrapped the phasor and adapted the core sine's one instead. In Carbon the tables are extended before and after to account for the three extra samples needed by the 4-point interpolator. That complicates things a lot for very little, so I make the readers wrap around. I convert the frequency to pitch in octaves, with zero at the base frequency of the table. This solves table selection, because table indexes are octaves too, so we don't need routing. It also solves the crossfade, which is the fractional part of the pitch.

    To avoid aliasing, we might set both tables above the osc frequency so that we only transpose down -this doesn't quite work, as the interpolator still aliases its stopband. We also lose too much top end, and we start to hear the lobes in the interpolator's response, which are not much nicer than aliasing. The lobes are worse in the low octaves, and aliasing is worse in the high octaves. To find a compromise, I "widen" the pitch used for octave selection, so that we switch tables a little before an octave. This way, low frequencies use the tables below and above, high frequencies use the next two tables, and the change is done progressively.

    I don't have anything at hand to make an apples-to-apples comparison, but this doesn't seem to take too much cpu, even modulating frequency at audio rate.

  • Studiowaves
    Studiowaves Member Posts: 197 Tri

    I had a similar issue with aliasing, I stopped the high frequency oscillators from modulating in an fm synth. Afterwards the aliasing stopped dead too because the fm was no longer producing sidebands above the nyquist. At least at a volume level I could hear.

  • Jonathan Tremblay
    Jonathan Tremblay Las Vegas, USAMember Posts: 5 Sine

    Mhmmm interesting.. 🧐

Back To Top