Oversampling oscillators

Hi All,

I’ve been working on making some oversampling oscillators in c++. Beginnings of the project are here:

I have made a Saw and VarSaw just as proof of concept and to learn how to do it. These use Jatin Chowdhury’s VariableOversampling class from Mads’s ported plugins. Has anyone else made any oversampling oscillators? I would love to know if I am just repeating work that already exists.

Here is a video comparing FM with a VarSaw and the oversampled OVarSaw2, and despite YouTube’s best attempts to add their own aliasing, I hear a striking difference:

If these will be valuable to the community, I’ll move forward and make more of these. But I would have questions for those who are wiser than I. I had to switch my approach from an “SC Source” approach to a “Mads” approach (basically because I couldn’t get the SC approach to play with the Oversampling library). But I might need help when making wavetable oscillators.

Anyhow, I would love any feedback on these.

Sam

7 Likes

Inside the undocumented classes there are lots of UGens that seems to be oversampling ones, but I am not sure why they are all spread over there, maybe they did not work as expected… It seems that they are part of SCPlugins. I remember seeing even more of them, but I could not find right now…

Clipper4 
Clipper8 
Clipper32 
SoftClipper4 
SoftClipper8
SoftClipAmp4 
SoftClipAmp8 
OSWrap4 
OSWrap8 
OSFold4 
OSFold8 
OSTrunc4 
OSTrunc8

BTW, Jatin Chowdhury plugins are simply amazing. It is great that we can have some of them ported to SC! I hope one day we can have all of them!

This is really helpful. I can probably downsample using this code from the BerlachUGens library for wavetable-based synths, since it is written in the SC Plugins MACRO style. The problem I was having adapting to that style of code is that I don’t know how you store a Class, like VariableOversampling, in the classic UGen data structure. I was putting in the Unit struct, but it was getting corrupted somehow. If I make it a global variable, it works, but then there can only be one instance of the oscillator in SC. Not good. If anyone has an easy answer to that, I’m all ears. Or I could just turn the code into a macro, but that seems silly.

Sam

if one would like to do FM with high indices on a saw wave “without aliasing” my go to would be Squine. unfortunately you cant drive the phase of it.

As with Dre, I had forgotten about Squine. That’s a great oscillator. But these have very different sounds, mostly because the squine will always be a sine wave in the upper register while the oversampling oscillator doesn’t change shape. Since variety is the spice of life, I think it would be great to have more options.

What would be interesting is a Squine oversampling by 2x and then being downsampled. Might be the best of both worlds.

Sam

yes, you are absolutely right :slight_smile: it sounds more dull beause of that. i just wanted to mention it because its very stable for modulation.

oh, might be cool :slight_smile:

I’m curious here: what is the difference between a band limited oscillator and an oversampled one? I would understand if the FM was happening before the downsampling needed, but otherwise isn’t it the same thing, apart from the fact the OS one might not be as drastic in its antialiasing?

I’m hearing a difference indeed, but I wonder where it lies… is it in the spill of the DS filter? That would explain the dullness (aka there is more aliasing and we like it…)

I’m getting an error when trying to compile it:

CMake Error at CMakeLists.txt:17 (add_library):
  Cannot find source file:

    OSaw2.cpp

  Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm .h
  .hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90 .f95 .f03 .hip .ispc

Seems like the source code file names have been changed to OversamplingOscillators.cpp instead. Would this fix it? I’m not familiar with cmake… would changing line 17 and 18 in CMakeLists.txt fix it? If so I can submit a pull request.


edit -
I tried that, and it allowed me to successfully run cmake .. -DCMAKE_BUILD_TYPE=Release -DSC_PATH=patch/to/sc but then I got the following error during cmake --build . --config Release:

~/OversamplingOscillators/OversamplingOscillators.hpp:6:10: fatal error: 'VariableOversampling.hpp' file not found
#include "VariableOversampling.hpp"
         ^~~~~~~~~~~~~~~~~~~~~~~~~~

Hmm. How was that even building before? Very strange. I fixed it.

Boris, you need to have the source code for ported plugins. I just updated the project so that ported plugins source is in a folder you specify with cmake. So, now the following should work to compile (if you plug in the correct directories on your computer with SC source and ported plugins source):

mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DSC_PATH=<PATH TO SC SOURCE> -DPORTED_PATH=<PATH TO PORTED PLUGINS SOURCE>
cmake --build . --config Release

I am also not exactly a cmake veteran, so hopefully that fixes it.

PA, I’m not sure what you are asking. In the video, I was comparing VarSaw, which is not band-limited, to OVarSaw2, which is oversampled and downsampled. VarSaw has audible folder over. If you like it…well, I can’t really help you. OVarSaw2 computes a signal at N times oversampling, so in the video at 768000 (obviously overkill) and then filters it to downsample. I am using someone else’s library for this, so I have no idea if it is a good filter (and that is way beyond my knowledge), but the code comes from a trusted source. In comparison, Squine I think uses a polyblep approach to bandlimit, though I am not 100 sure.

Sam

I was just confused as I thought that VarSaw was like Saw (band limited) and years of Max usage where Tri and Saw both exist as bandlimited versions.

Now asking if I like aliasing oscillators… you hear my tunes, of course I love them :slight_smile:

Anyway, my question was about the sounding difference between a more additive approach vs a more subtractive approach to band-limiting… so I’ll go read back and I found this cool resource:

I might find what I’m looking for.

Congrats for the good work on these.

Did some digging and it appears that AAFilter.hpp in portedplugins uses an 8th-order Butterworth by default.

I’m mostly certain the polynomial approach found in the Husserl tutorials can be seen in the faust source:

It makes sense that those oscillators sound so good.

Sam

1 Like

Thanks Sam! I was able to compile them. Looking forward to playing with them.

Thanks for your work on this!

I’m not going to send a billion updates to this thread, but for fun I coded up JOS’s faust bandlimited sawtooth in C++ and added to the same repo.

It blends two different version of JOS’s oscillator, the second order polynomial for frequencies below 5000 and the 4th order for frequencies above 10000. This is a lovely oscillator that allows frequency modulation across the spectrum.

This reinforces my feeling that we need these oscillators. Aside from basic functionality that has become possible over the past 20 years, there are some questionable design issues in the source. For example: VarSaw doesn’t allow a-rate modulation of the width, which is silly for anyone who has used analog gear. I imagine the same can be said for LFPulse, though I haven’t looked yet. Another weird one: VOsc interpolates over buffers at k-rate, which causes audible glitching with large wavetable sets. I am sure there are more.

So I am going to go forward with making a set of oversampling and polynomial bandlimited. Hopefully it will be of use. I will either see if it can be added to source or perhaps added to the ported plugins if Mads feels it fits there.

Sam

10 Likes

Hi All,

I have been working for a bit on these Oversampling and Bandlimited Oscillators. The repo is here:

Oversampling Oscillators use the VariableOversampling class from Jatin Chowdhury’s ChowDSP library to get 2,4,8, and 16x oversampling. That source is included with the download. Bandlimited oscillators are based on THE Julius Smith’s SawN, etc from “Alias-Suppressed Oscillators based on Differentiated Polynomial Waveforms”, Vesa Valimaki, Juhan Nam, Julius Smith, and Jonathan Abel in the faust source.

These are far from efficient, but I think they sound great. For instance, the SawBL, the bandlimited saw expands on Julius Smith’s faust algorithm by applying a 4th order polynomial transition to higher frequencies, a 2nd order polynomial to the lower frequencies, and uses a non-bandlimited sawtooth below 1hz. This adds a lot of compute, but also makes an oscillator that works across the entire frequency range, which isn’t possible with faust directly.

The main goal of this project was to make extreme modulation possible without too much aliasing. The “crown jewel” of the set is an oversampled version of the FM7 called PM7OS and an alternative FM7OS that has the same crazy 6x6 modulation matrix of the FM7, but uses FM instead of PM. I will say that PM7OS has something funky about it that I can’t figure out. It doesn’t quite sound the same as FM7 in the DX7 algorithms. I’m putting this out there in case someone is able to figure it out.

Anyhow, I would love any feedback, and hopefully I didn’t introduce any bugs right before release like I always seem to do, haha. Also, you have to build them yourself. I tried to make a GitHub action to do this, but I failed to do that so far.

Sam

8 Likes

Huh. I have no idea. Are you building the library with my instructions in the README or another way? I have no idea why it would need the IDE or QT to build a plugin. Doesn’t make sense. It also doesn’t make sense that it would need the CMakeLists.txt file from the IDE folder. Are you sure you are in the right directory in the terminal?

Sam

1 Like

yep user error! looking forward to trying…

Thanks for sharing. Just tested them, and think they sound very cool. Need more time to say something more about it, but first impression was great

Sometimes a buggy code can sound equally interesting too ))

Well, I did just fix a bug this morning, which is that I forgot to implement the “mul” argument in the ctl matrix of PM7OS and FM7OS. Fixed and updated. Shouldn’t change much as one barely uses those arguments.

But my goal is definitely not to make something that sounds like a DX7 (thought that would be a nice byproduct). It is to make an complex matrix that is beyond my understanding. Kind of taking Frederik’s f-ed up FM7 concepts, being more deliberate about it, and getting rid of all the aliasing.

Sam

3 Likes