serum vs earlevel wavetable question

DSP, Plug-in and Host development discussion.
RELATED
PRODUCTS
Derozer
KVRist
Topic Starter
106 posts since 18 Nov, 2017

Post Wed Aug 17, 2022 9:14 am

hi all,

i used to learn wavetable synthesis using the gold earlevel tutorial here (and following): https://www.earlevel.com/main/2012/05/0 ... roduction/

basically, for a single cycle, it creates lots of tables, bandlimited, get riding of aliasing at higher freq and such (minimaps, right?). thus the name "wavetable" (same cycle, reduced on harmonics each).

if instead i export a wavetable from serum, it just export (every 2048 samples) a single cycle for each waveform (no a version of each cycle to be played at different freq, basically).

so the question: is this a different wavetable approch? (i.e. cycle sequence instead of minimaps of a single cycle)? or serum wave are not bandlimited and play with aliasing without carry about removing harmonics due to input freq? or what am i missing here?

or simply it split the wav bank every 2048 samples, FFT and create dinamically n minimaps for each cycle?

it seems different approch on the same topic :P

thanks

User avatar
karrikuh
KVRist
346 posts since 6 Apr, 2008

Post Wed Aug 17, 2022 10:21 am

Derozer wrote: Wed Aug 17, 2022 9:14 am or simply it split the wav bank every 2048 samples, FFT and create dinamically n minimaps for each cycle?
I believe that's what WT synths are doing. Storing the complete mipmap in the file would be a waste of disk space, as it contains mostly redundant information. I suspect generating the mipmap on the fly in RAM could also be faster than reading from disk storage

User avatar
mystran
KVRAF
7199 posts since 12 Feb, 2006 from Helsinki, Finland

Post Wed Aug 17, 2022 2:56 pm

Usually you'd store just the base waveform and generates the mips as you load. It takes very little time to do a few FFTs and you avoid any possible issues with your single cycle waveform files not containing the correct mips. It also means you can take the same wavetables from one synth to another (or even different versions of the same plugin, in case you ever decide to change how the mips are done) even if their internal idea of mips (or maybe another anti-aliasing strategy) differs.
Preferred pronouns would be "it/it" because according to this country, I'm a piece of human trash.

Derozer
KVRist
Topic Starter
106 posts since 18 Nov, 2017

Post Wed Aug 17, 2022 10:00 pm

I see :) thanks

JustinJ
KVRist
77 posts since 31 Oct, 2017

Post Thu Aug 18, 2022 3:15 am

As others have said, there's no good reason these days to store the different mipmaps. Just generate them at load time.

More interesting questions are around how many mipmaps to have per octave etc. Many recommend a different mipmap every three semitones or so but if you oversample x2 then you can probably get away with one per octave.

An interesting point about Serum is that it seems to not bother with the mipmaps if you select any of the wave altering options (bend, asym, flip, mirror, sync, etc) which makes sense if you think about it. The downside is that it then aliases like hell.

Another option, and the one I've gone with, is to forget about pre-generated mipmaps and calculate the band-limited wavetable in realtime by using iFFT every 'n' samples (say, 256). There are more incremental ways of doing it but I've not had chance to look into them and the current scheme works really well.

Like everything in DSP it's all about the trade-offs and what you want to achieve.

Derozer
KVRist
Topic Starter
106 posts since 18 Nov, 2017

Post Thu Aug 18, 2022 7:23 am

JustinJ wrote: Thu Aug 18, 2022 3:15 am Another option, and the one I've gone with, is to forget about pre-generated mipmaps and calculate the band-limited wavetable in realtime by using iFFT every 'n' samples (say, 256). There are more incremental ways of doing it but I've not had chance to look into them and the current scheme works really well.
interesting...

any example of this "live calculation" approch? code? papers?

thanks

JustinJ
KVRist
77 posts since 31 Oct, 2017

Post Thu Aug 18, 2022 3:51 pm

Derozer wrote: Thu Aug 18, 2022 7:23 am interesting...

any example of this "live calculation" approch? code? papers?

thanks
I read Zebra2 works this way but I don't know of any open source or papers. There's a few synths out there that let you do things to the partials in realtime (VPS Avenger, Thorn, Europa) so I suspect they're doing something similar.

The idea is that you store the partials of your wavetable by calculating the FFT at load time.

When a 'note on' is detected, you make a copy of these partials and zero out the partials that would exceed Nyquist when played at your note frequency. Then, you perform an inverse FFT to get the waveform back and it's this waveform that you play. How to do this part is on the earlevel website.

In your wavetable process code you'll be interpolating between a source and target wavetable over, say, 256 samples. When you've counted 256 samples you'll swap the source and target pointers and copy to the target buffer a new band-limited wavetable using the same process as 'note on' above. The new target wavetable data can come from perhaps a sequence of wavetables that you're cycling through. Reset the sample counter and you're all good.

That's about it really. You have to do all this per voice and it's mostly housekeeping.

drofdissonance
KVRer
3 posts since 10 Mar, 2020

Post Mon Aug 22, 2022 6:14 am

The downside of these ifft methods is they have a low practical modulation bandwith limit. if the modulation bandwith is too high, you have to reperform the ifft too often to avoid aliasing. I believe thats why serum uses the more simplistic mipmap approach. you can push the modulation much faster that way. Could be super efficient if your staying away from audio rate modulation.

kerfuffle
KVRer
14 posts since 2 Jul, 2021

Post Mon Aug 22, 2022 7:50 am

Matt Tytel's ADC 2021 talk was about building wavetable oscillators. Worth watching: https://www.youtube.com/watch?v=qlinVx60778

Derozer
KVRist
Topic Starter
106 posts since 18 Nov, 2017

Post Sat Aug 27, 2022 9:27 am

kerfuffle wrote: Mon Aug 22, 2022 7:50 am Matt Tytel's ADC 2021 talk was about building wavetable oscillators. Worth watching: https://www.youtube.com/watch?v=qlinVx60778
very nice video, thanks for share it.

after watching it, at this point, i am not sure which kind of wavetable is the one illustrated by earlevel; it is not minblip of course...

is his way a common wavetable technique or just a Nigel custom implementation? seems pretty valid.

whats your opinion?

User avatar
Urs
u-he
26804 posts since 8 Aug, 2002 from Berlin

Post Sat Aug 27, 2022 11:33 am

JustinJ wrote: Thu Aug 18, 2022 3:51 pm
Derozer wrote: Thu Aug 18, 2022 7:23 am interesting...

any example of this "live calculation" approch? code? papers?

thanks
I read Zebra2 works this way but I don't know of any open source or papers. There's a few synths out there that let you do things to the partials in realtime (VPS Avenger, Thorn, Europa) so I suspect they're doing something similar.

The idea is that you store the partials of your wavetable by calculating the FFT at load time.

When a 'note on' is detected, you make a copy of these partials and zero out the partials that would exceed Nyquist when played at your note frequency. Then, you perform an inverse FFT to get the waveform back and it's this waveform that you play. How to do this part is on the earlevel website.

In your wavetable process code you'll be interpolating between a source and target wavetable over, say, 256 samples. When you've counted 256 samples you'll swap the source and target pointers and copy to the target buffer a new band-limited wavetable using the same process as 'note on' above. The new target wavetable data can come from perhaps a sequence of wavetables that you're cycling through. Reset the sample counter and you're all good.

That's about it really. You have to do all this per voice and it's mostly housekeeping.
In Zebra the rate of swapping (and crossfading) between two buffers depends on the "Resolution" parameter. Lower resolution equals less CPU, but somehow then adds a "time posterize" effect.

In Hive we made the computation so fast, the we simply keep calculating newly band limited wavetables every 16-64 or so samples. IIRC the modulation rate is about the same that one can get with other synths before they start getting artefacts. One point about Hive is that we store the wavetable as spectrum in memory, and we compute wavetables of variable length. I.e. "if aliasing permits", we'll use wavetables of 64 samples length, which particularly helps with high pitched notes that have only few harmonics left. The code to do all this with SIMD and stuff was tricky bugger, but it is exceptionally fast and smooth.

I think Vital uses a very similar technique as Hive/Zebra, and it's open source. I think it calculates a new wavetable for each buffer, which I think it also internally computes every 64 samples.

The main point for doing this on the fly is that one can also apply other processes on the spectrum or waveform on the fly, and band limit them. This is how Zebra's OscFX work and from what I gather, Vital's realtime oscillator effects as well.

JustinJ
KVRist
77 posts since 31 Oct, 2017

Post Sun Aug 28, 2022 6:15 pm

Urs wrote: Sat Aug 27, 2022 11:33 am In Zebra the rate of swapping (and crossfading) between two buffers depends on the "Resolution" parameter. Lower resolution equals less CPU, but somehow then adds a "time posterize" effect.

In Hive we made the computation so fast, the we simply keep calculating newly band limited wavetables every 16-64 or so samples. IIRC the modulation rate is about the same that one can get with other synths before they start getting artefacts. One point about Hive is that we store the wavetable as spectrum in memory, and we compute wavetables of variable length. I.e. "if aliasing permits", we'll use wavetables of 64 samples length, which particularly helps with high pitched notes that have only few harmonics left. The code to do all this with SIMD and stuff was tricky bugger, but it is exceptionally fast and smooth.

I think Vital uses a very similar technique as Hive/Zebra, and it's open source. I think it calculates a new wavetable for each buffer, which I think it also internally computes every 64 samples.

The main point for doing this on the fly is that one can also apply other processes on the spectrum or waveform on the fly, and band limit them. This is how Zebra's OscFX work and from what I gather, Vital's realtime oscillator effects as well.
Thanks for confirming Urs - I'm pretty sure I read about Zebra doing this in a post from a year or two ago.
As I mentioned to the other poster, it's pretty much what I'm already doing. I'm performing on the fly 'morphing' effects on both the waveform and the spectrum. Wavetables are the usual 2048 floats but because I could be 'morphing' the original waveform, I'm not mip mapping. Interpolating using Hermite so it sounds good - I just wonder about the memory cache performance.

Thinking aloud, I could morph the 2k waveform, scale down according to note, FFT, band-limit, morph spectrum and then iFFT. Performing the scale down/mip would potentially mean less work for the FFT to do.

Speaking of which...did you ever run into performance issues with available FFT libs or feel the need to create an optimised proprietary version?

matt42
KVRian
1256 posts since 9 Jan, 2006

Post Sun Aug 28, 2022 6:43 pm

Writing a fully optimized FFT for all possible use cases is a major undertaking.

I’d recommend researching the available high performance libraries, checking their licensing requirements, benchmark their relative performance etc and make a selection based on your criteria

User avatar
mystran
KVRAF
7199 posts since 12 Feb, 2006 from Helsinki, Finland

Post Sun Aug 28, 2022 10:05 pm

JustinJ wrote: Sun Aug 28, 2022 6:15 pm Speaking of which...did you ever run into performance issues with available FFT libs or feel the need to create an optimised proprietary version?
Having written an FFT that isn't really the fastest out there, but it's still somewhat reasonable in terms of performance... I would like to warn you that going from a "basic textbook FFT" to something with reasonable performance is quite an ordeal.

You'll probably want to special case all small transforms (eg. up to 32-64, something like that) probably with split radix, then you need one strategy for medium sized transforms that fit L1 (where it's a good idea to stride many transforms so you save twiddle recomputation) and then another for larger transforms where you want to do text-book divide&conquer in order to keep the subtransforms in cache. There's a number of other things you can do, but point is you'll probably want a code-generator to manage all the variants.
Preferred pronouns would be "it/it" because according to this country, I'm a piece of human trash.

User avatar
Urs
u-he
26804 posts since 8 Aug, 2002 from Berlin

Post Mon Aug 29, 2022 1:04 am

@JustinJ is the software that uses this technique available somewhere? I'd love to check it out!

I found that linear interpolation suits me well, and I empirically developed a formula that gives me an optimal ratio between number of "quiet enough" bins on the top before interpolation noise becomes audible. I can try to dig this up.

The advantage of linear interpolation is that one can read four pairs of samples as double, then use SIMD to splice, deinterleave and weigh. For hermite one needs to do an unaligned load per sample (if using SIMD), which I found expensive compared to gain of sound quality. In the end no-one was able to spot the difference.

Re. FFT we currently use Apple's Accelerate framework on Mac and I believe KISS on Win/Linux. We've had trouble with thread safety and KISS, so we're probably going to switch to something else, and probably something that's in that Eigen thing that our mathematician keeps talking about.

Return to “DSP and Plug-in Development”