Forum Rule: Always post complete source code & details to reproduce any issue!

New audio class for generating waveforms from sines
Hi,
I have created an audio class that allows to create waveforms (square, triangle, sawtooth) by addition from sine waves. I want to use the class for a synth that should not get aliasing problems in the higher frequency range. The basic idea is the FM synthesis of the Yamaha DX7, from which you can also extract "analog" waveforms by means of appropriately tuned operators.
The whole thing is based on the findings from https://lpsa.swarthmore.edu/Fourier/Series/ExFS.html. The class is designed so that you can determine which number of operators (or partials) you want to use. I did some benchmark tests with a Teensy3.5 and a Teensy3.6.
All this (with some collected info) can be found at https://codeberg.org/dcoredump/Synth_FM_Partial.
Maybe someone of you finds this useful or has hints for the use, optimization or what I did wrong
Have fun!
Holger
[EDIT] Forgot to say: The code is using floats, so you need a Teensy >= 3.5!
Last edited by C0d3man; 03282023 at 01:27 PM.

After thinking a bit about the name of the class, I think that yes, it is not FM. So the class and the project should rather be called Synth_Sine_Partial... hm. I'll leave it like that for now, but will rename it when I get the chance.

Originally Posted by
C0d3man
After thinking a bit about the name of the class, I think that yes, it is not FM. So the class and the project should rather be called Synth_Sine_Partial... hm. I'll leave it like that for now, but will rename it when I get the chance.
Renaming done: https://codeberg.org/dcoredump/Synth_Sine_Partial

I would suggest using complex arithmetic to sum a Fourier series, then only one sin() and one cos() call are needed per sample (or perhaps less often). Rotation is simply multiplication in the complex domain.
The arm_sin_f32 and arm_cos_f32 library routines are only tablebased approximations, I would worry are probably not spectrally pure enough to avoid audible artifacts.

Many thanks for your hints!
Originally Posted by
MarkT
I would suggest using complex arithmetic to sum a Fourier series, then only one sin() and one cos() call are needed per sample (or perhaps less often). Rotation is simply multiplication in the complex domain.
I had to search deep in my brain again to recapitulate the complex math and made some changes that now make the base class much more independent of the function that is to be emulated. I still have to test the whole thing to see if I didn't make any mistakes somewhere.
Originally Posted by
MarkT
The arm_sin_f32 and arm_cos_f32 library routines are only tablebased approximations, I would worry are probably not spectrally pure enough to avoid audible artifacts.
Yes, I had read and hoped that the speed increase is higher than the error that can occur. I have to check it again. Now I have first again the "normal" functions used and try then with it first.

I have now rebuilt the classes based on your hints. The whole thing seems to work quite well now. However, the CPU usage is now twice as high as before, but the advantage is that you can create any waveform, as long as you can describe it in a function.

Senior Member
I see your files have GPLv3 license. That's fine, but they can never be merged with the original library which uses MIT license.
Any chance you might consider using the same MIT license as the rest of the library? Then this could be included in a future version.

Hi Paul,
Originally Posted by
PaulStoffregen
I see your files have GPLv3 license. That's fine, but they can never be merged with the original library which uses MIT license.
Any chance you might consider using the same MIT license as the rest of the library? Then this could be included in a future version.
No problem. I have adjusted the license accordingly.

I have created a simple demo video (with audio) for all the waveforms: 20% square, 50% square, triangle, sawtooth  every waveform from 1 (only a sine wave) to 20 partials.
Be careful with the audio level!!!


Holger, thanks for putting this together. Good thinking material. But, I don't see why you can't just generate, for instance, a triangular waveform and then run this through a linearphase LP FIR filter. All components below the cutoff would align properly since the delay in the FIR is constant with frequencies. Those above the cutoff could be reduced arbitrarily low. The end result would seem to be the same, but less compute. I bet I am missing something?? Bob

Hi Bob,
thanks for your post!
Originally Posted by
Bob Larkin
Holger, thanks for putting this together. Good thinking material. But, I don't see why you can't just generate, for instance, a triangular waveform and then run this through a linearphase LP FIR filter.
I can explain it quite simply: Because I do not know better. :)
Originally Posted by
Bob Larkin
All components below the cutoff would align properly since the delay in the FIR is constant with frequencies. Those above the cutoff could be reduced arbitrarily low. The end result would seem to be the same, but less compute. I bet I am missing something?? Bob
I come from the FM synthesis (I love my DX7 ). The whole thing is more an attempt to generate analog waveforms differently and experiment with it. I still have a few ideas in mind, such as converting wavetables into corresponding coefficients and morphing between "waveforms" (coefficients). I don't know if this will be effective and what exactly will come out of it, but I am curious if there will be interesting results. Also the modulation of certain coefficients (e.g. by velocity or by LFOs) might be interesting.
Regards, Holger
Last edited by C0d3man; 05152023 at 10:25 AM.
Posting Permissions
 You may not post new threads
 You may not post replies
 You may not post attachments
 You may not edit your posts

Forum Rules