Band Limited Table Look Up Oscillator C++
Please note that you cannot implement a band-limited oscillator with a pure (stateless) function like:

Sample s = saw(x);


The reason is that the function must be aware of the rate at which x change to generate a signal with the correct bandwidth

For example, let us assume your sample rate is 48kHz. If you call your function in this order:

saw(0.00000000);
saw(0.00000001);
saw(0.00000002);


You can see that the argument is slowly changing to the point that aliasing is not an issue, so your function could return something like x / M_PI - 1 (assuming input is in [0, 2 pi[ ; and output in [-1, 1]) without any lookup table. But now, if you call it this way:

saw(0.0);
saw(3.0);
saw(6.0);


We are getting close to Nyquist frequency and the output must then be heavily band-limited - actually closer to sin.

So a band-limited sawtooth or square cannot be generated by mere waveshaping of the naive saw. You need your function to be aware of the target frequency so that it can make the right decision.

Another related misconception that can be found in your code is that you assume that you would need only one table. There is just not one single "band-limited sawtooth" waveform that would work for all frequencies. For low frequencies, there is very little different between the band-limited saw and the naive saw. For high frequencies, the band-limited saw is effectively a sine. So you have to define how much memory you want to dedicate to your task, and generate many band-limited tables corresponding to various frequencies. At run-time, you decide which one to use depending on the frequency of the signal. If this is for a musical application in which you don't want to hear the transition from one table to the next as notes rise in pitch, you'll need to add one further layer of interpolation on top of that to crossfade from one table to the next. A typical implementation would use one table by octave or per 8 semitones.