I have a signal, $f(t)$. I know a function that can be used to generate this signal, such that I can determine its Fourier series. I want to express this Fourier series in simpler terms so that the waveform can be rendered by a GPU in parallel, with the added ability to change the lowpass cutoff frequency of the signal dynamically.

Take for example a saw wave with a fundamental frequency of 1 Hz, represented by the function:

$$f(t) = {-2\tan^{-1}(\cot(\pi t)) \over \pi}$$

I'm using this form of the saw wave because it's cyclic and easy for a GPU to calculate. Its Fourier series is rather difficult to solve, but I have the series on hand:

$$g(t, n) = {-2 \over \pi} \sum_{k=1}^n {\sin(k \pi t) \over k}$$

Now, I could technically use additive synthesis to generate the waveform using this series, but my project has real-time constraints and this simply won't do. A single saw wave might have hundreds of partials up to the Nyquist frequency. This takes a lot of time to compute, and on a GPU it's a branching nightmare. Since I'm rendering all of the samples in parallel, there is no history buffer for existing filtering algorithms to operate on, and I can't do that either.

What I'm trying to do is approximate this series as a function of $n \in Z$, without the summation. That way, it doesn't matter what cut-off I use, I get consistent performance across the board that's most likely a huge improvement over additive synthesis. Right now I'm trying to fit the curve manually, but this is a laborious process. Is there a way to find $h(t, n) \approx g(t, n)$, where $h(t, n)$ is the approximation of the series?

  • $\begingroup$ One thing you could do is pre-calculate and store the signal samples, basically trading memory for CPU. Is there a reason not to do this? $\endgroup$ – MBaz Jul 15 '15 at 1:39
  • $\begingroup$ @MBaz Wouldn't that involve some sort of resampling if the pitch is changed? On a GPU, that might be even slower. Even if that's an option, though, I'm trying to see if I can do things a different way out of pure interest. Call this personal research - I just want to know if it's a possible or effective method of synthesis. $\endgroup$ – NmdMystery Jul 15 '15 at 1:45
  • $\begingroup$ You should be able to avoid resampling by pre-calculating enough samples. Another idea: do you know the CORDIC algorithm? It can calculate trig functions by using additions and bit shifts only. You can have some control its precision by changing the number of iterations. en.wikipedia.org/wiki/CORDIC Maybe it is fast enough for your needs. $\endgroup$ – MBaz Jul 15 '15 at 2:05
  • $\begingroup$ @MBaz On GPU hardware, trig functions are already pretty cheap. It's the branching that does the damage - if each sample has a different number of partials, there's a lot of branching there. If this was a CPU, it wouldn't really matter (actually I probably wouldn't even be asking this question) but when you have other stuff happening on the GPU in addition to audio, adding the partials up just isn't going to work. That's also why I can't make it memory-intensive, either - I'll be using the GPU for graphics, too. $\endgroup$ – NmdMystery Jul 15 '15 at 2:28

Sounds like bandlimited synthesis.

with the added ability to change the lowpass cutoff frequency of the signal dynamically.

That makes it even more complicated.

  1. The simplest way to do this right is additive synthesis, as you know. That way you can adjust each harmonic's frequency and phase and amplitude on the fly. Yes, there are a lot of calculations if the fundamental frequency is low, but you can use approximations of sin() if that speeds things up. The 2-MAC resonant filter/oscillator (1, 2), for instance:

resonant oscillator waveform and spectrum

or various polynomial approximations with varying amounts of distortion:

enter image description here

  1. If the waveform is fixed and a submultiple of the sample rate, you could use IFFT synthesis, but for anything else I imagine this would be difficult because the harmonics cover multiple FFT bins. Maybe with overlapping and fading between chunks?

Otherwise the best solution depends on what exact waveform you're trying to synthesize.

  1. If you only need a "sawtooth-like" waveform, for instance, you can use the DSF directly, which produces waveforms with harmonics that fall off linearly:

sawtooth-like DSF

  1. but if you want an actual square wave you use the DSF to generate a "bipolar" band-limited impulse train (BLIT):

2 summed BLITs

and then leaky-integrate the sum. 2

These methods can't be used for arbitrary waveforms, however, and can't be used for swept-frequency chirps or swept-frequency LPFs (as you want?), since the harmonics suddenly disappearing from one sample to the next produces a pop or click which can't be filtered out after the fact.

You could probably use this method for the low harmonics and then combine with additive synthesis of the top harmonics and then fade those in and out to prevent the clicks. In other words, as a harmonic disappears from one sample, you seamlessly replace it with an additive-synthesis harmonic at the same frequency and phase, which you can then fade out more smoothly.

  1. Wavetable synthesis, fading between wavetables as harmonics disappear?

  2. Then there are other methods. :)


  • $\begingroup$ I just read a little bit of each of those links and at least one of them looks promising - I'm going to try to replicate this and I'll get back to you :) $\endgroup$ – NmdMystery Jul 15 '15 at 3:07
  • $\begingroup$ lotsa ways to do bandlimited synthesis of the classic analog waveforms. in addition to the BLIT or BLEP (or whatever is the going acronym), there is simple wavetable synthesis. $\endgroup$ – robert bristow-johnson Jul 15 '15 at 5:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.