Roland Supersaw - any idea how the original was done?

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

antto wrote:
1.1077003479
1.0633006096
1.0204008818
1
0.9810999632
0.9382010102
0.8908000588

i was (and still am) curious to find out if the real detuning coefficients somehow turn out to be some simple whole numbers
it seems (iirc) that the detuning of the upper three saws vs the lower three saws is not symetrical in any way, i think i tried converting the frequencies into pitch (log scale) and it isn't symetrical there either
In summary, I think there will be no integer or even floating-point rhyme or reason behind these offsets. I am convinced they are hand-picked integers in a two-dimensional matrix. The integers you search for do exist, but you won't find any specific, pretty, mathematical rhyme or reason behind them.

This isn't a problem from the instrument designer's or musician's point of view, because if there is a simple mathematical relationship between the frequencies, the sound would be less interesting. For instance: if our center is 440Hz, and the sidebands were +- 2Hz, 438 and 442, then we'd hear both sidebands beat with the center frequency exactly twice a second and they'd beat against each other 4 times a second. Just not that interesting. If it were +2Hz, -2.5Hz, then we'd hear the beat rhythm repeat every 5 seconds, and so on. Much better to pick ratios where the numbers are irrational, or at least fractions so long that they'd take minutes to repeat, if not days or years.

--------------------------

So first let's review how a single sawtooth is probably generated.

The easiest way to make a (noisy, non-bandwidth-limited sawtooth)(which is what these apparently are) is to have a, say, 32-bit integer (sometimes called an "accumulator") that represents phase, and if you use that phase directly as your audio output, you get a sawtooth. From your frequency, you determine an "increment", an amount that you increment that phase by every cycle. (The accumulator accumulates these increments, hence the name.) When you go off one end (too high) the CPU automatically wraps it around to "low" which means the sawtooth output has a vertical jump once a cycle. This is just like a car odometer rolling over from 999,999.9 to 0. I'm POSITIVE this is how the supersaw sawtooths are generated. Nothing is simpler, and we see the exact kind of noise this generates.

Example: say the synth runs at 44.1kHz and we're playing A4 at 440Hz. The increment would be 2^32 * 440 / 44100 = 42,852,281. We just have a phase--it starts out at a random value--and we add 42,852,281 to the accumulator 44,100 times a second. Every 100 or 101 additions the accumulator wraps back from most-high value to most-low, at which point our phase--and the sawtooth we see if we use the raw phase as audio--go from gently climbing to taking a big plummet. (And the fact it's sometimes 100, sometimes 101, is why it is so noisy.)

(They can't, I think, pre-calculate 2^32/44100 and simply do one operation to take that *440, because in integer math the order of operations is critical because of rounding and overflow. I haven't checked but I think you'd have unacceptable pitch inaccuracy if you pre-calculated 2^32/44100=97391, and just calculated your increment as 97391 * freq. You get a more accurate answer if you FIRST do all your multiplies together, THEN do all your dividing. But even then you still have a worry: make sure you have big-enough integer variables that they don't overflow. To do 2^32*20,000/44,100, at the top of human hearing, after the multiply you need at least 47 bits...)

Now, pitch isn't steady. It changes smoothly, due to pitch envelope, portamento, and LFO. To get that smooth change, with every sample, the increment must change. And, pitch rising or falling is basically always on an exponential scale: falling by an octave a second means frequency changes by a factor of 2 a second, and our increment would also need to halve in a second. But, I don't think there's a way to do exponential calculations like this without floating point. What you can do fast in integers is add an increment to your increment. That gives a reciprocal curve, not an exponential curve. But if you recalculate that increment-of-the-increment every 64 samples or something, then you end up getting a super-close approximation of any curve you want with a bunch of short reciprocal curves. And the math per sample isn't just simple, but simplest-POSSIBLE. A single integer addition/subtraction to change the increment, then another single integer addition to change the accumulator:

increment = increment + incrementOfIncrement
accumulator = accumulator + increment

Do that 64 times, then finally one time calculate a new increment-to-the-increment. That calculation is simply:

figure out desired pitch "pitchThen" we'll want in 64 samples (could be LOTS of math)
incrementThen = 2^32 * pitchThen / 44100
incrementOfIncrement = (incrementThen - incrementNow+32)/64.

And the divide by 64 is actually just shifting right six bits, not even an integer divide (much slower than a shift).

-------------

So now let's look at the sidebands. I've looked at trying to use the center frequency's increment-of-increments for the sidebands too and while you can get close for a short segment, after the segment is over the sideband increments will need such a big adjustment I think it'd make too much noise. However, simply calculating the sidebands the same way the main signal is calculated should be fast enough.

Calculating an increment for say the top sideband, at maximum detune, naively, would be 2^32 * 440 / 44100 * 1.1077003479. The 1.1077003479 could be calculated on the fly with floating point math, but it'd be much faster to simply pre-calculate it for each detune amount for each sideband and put those pre-calculated values into a two-dimensional array.

But even if pre-calculated, we still have a floating point operation. Especially when supersaw started, I don't think there was any floating point math--too expensive! My guess is that instead of getting 1.1077003479 out of a table, they're further pre-calculating 44100/1.1077003479 and putting that into the table. So, calculation for the sideband increment, given a frequency of 440, is instead: 2^32 * 440 / 39812. The 39812 would again come from a two-dimensional array, indexed by sideband# and detune amount.

-----------------------------

OK, so that's the bad news for you. Those numbers 1.1077003479 and so on are probably in fact integers like 39812 in a table, and those integers are so high and have so many factors that you're not going to boil their relationship down into a simple "small" fraction like 18/17 or something. Furthermore, being in a table frees them from having to be calculated, which means they don't have to be an easy-to-calculate number. They could be (and for reasons I gave at the top, probably are) irrationals like 10th root of 2 or something, selected to be nearish but not exactly on -10%/6%/2%/+2%/6%/10%. And finally, these irrational numbers aren't even static; instead they're multipled by a detune amount then converted to integers.
For every detune, you'll get different rounding errors... which means even if you could do hyper-accurate pitch detection and calculate these integer values for one detune level, the integers for the next detune level would have to be found from scratch.

OTOH, if you could find the output frequency of the keyboard in question (may be 44.1kHz or 32kHz or something) and you got HYPER-accurate measurements of the detune amounts, I'm guessing that for each value of detune you WOULD ultimately find very specific integers.

In summary, the numbers you're curious about probably exist, but my guess is that they're both big integers, not small fun ratios, and that their ratios also vary somewhat with detune amount.

Post

The JP-8000 is still the best even compared to a mighty Moog One.

https://youtu.be/TFwFdGzHmG0?t=89
Orion Platinum, Muzys 2

Post

Hi v1o, How do you compare the JP-8000 to my soft synth Moselle's Swarm oscillator, that can do 100s of sawtooths (or more? watch the video!) https://www.youtube.com/watch?v=EbCqdmUbAo4

Post

Swiss Frank wrote: Sun Nov 01, 2020 6:05 am100s of sawtooths (or more? watch the video!)
How many voices do you need before any individual interference patterns are lost into a random mush, and you might as well be using PADSynth-style generated samples instead?

Post

> How many voices do you need

You mean, how many sawtooths/etc.?

> before any individual interference patterns are lost into a random mush

"Mush" is in the ear of the beholder. But it depends on the note you're playing, filtering detune amount, etc.

PADSynth doesn't let you vary detune with an envelope, or by Attack or ModWheel etc. My synth lets you modify it with anything. Conversely, my synth's Swarm oscillator only does saw, triangle and square, while PADSynth can do many. There's only a narrow range of sounds where you could use either approach, I think.

(In fact I have a PADSynth-based oscillator as well. I love it.)

Post

Swiss Frank wrote: Mon Nov 02, 2020 4:18 amYou mean, how many sawtooths/etc.?
Yeah - with two sawtooths, you get a clear comb-filter interference pattern. With three, the pattern is less simple but still distinguishable. But if you have 1000 or something then they blend together into a solid texture, and increasing to 10000 doesn't sound any different.
Swiss Frank wrote: Mon Nov 02, 2020 4:18 amPADSynth doesn't let you vary detune with an envelope, or by Attack or ModWheel etc.
Sure it can: https://soundcloud.com/signalsmith-audi ... BiWF3cVJnj https://soundcloud.com/signalsmith-audi ... a5vfv9uS49

It took a bit of figuring out, but in the end it's computationally cheap with no extra memory requirements.

Post

> It took a bit of figuring out, but in the end it's computationally cheap with no extra memory requirements.

How'd you do it? It's quite noticable in your 3-note demo, and agree that's the thing I thought wasn't possible. (I love the other example, as music, but my old ears actually can't hear the envelope in action.)

> But if you have 1000 or something then they blend together into a solid texture, and increasing to 10000 doesn't sound any different

I've found cases where 700 vs. 7,000 do sound a bit different. I'll agree they're similar though.

Post

Idk if anyone has mentioned this already, because I'm too lazy to scroll through all pages, but Adam Szabo, the developer of this synth: https://www.adamszabo.com/vstplugins/jp6k/

has once written a paper on the traditional supersaw: https://pdfs.semanticscholar.org/1852/2 ... 68a251.pdf

and it's a really good read!

Post

Eine Alte Oma wrote: Tue Nov 24, 2020 12:28 am Idk if anyone has mentioned this already, because I'm too lazy to scroll through all pages, but Adam Szabo, the developer of this synth: https://www.adamszabo.com/vstplugins/jp6k/

has once written a paper on the traditional supersaw: https://pdfs.semanticscholar.org/1852/2 ... 68a251.pdf

and it's a really good read!
That PDF paper was used as reference to model Corona Super 7 unison mode :)

Post

Yes, it's famous and I've read it several times before making my own oscillator with 7000 sawtooths.

Post

Swiss Frank wrote: Sat Feb 03, 2018 6:51 am
antto wrote:
1.1077003479
1.0633006096
1.0204008818
1
0.9810999632
0.9382010102
0.8908000588
i was (and still am) curious to find out if the real detuning coefficients somehow turn out to be some simple whole numbers
...
Note: the mean of the frequency factors is not 1 (the offsets do not sum to zero). But they have to. Otherwise, the sound will be detuned as a whole. Am I wrong?

I just finished a supersaw for Korg user oscillators. I adjusted each of the offset coefficients as follows:

offset_old(k) := factor(k)-1 (factor(k) defined as above)

for k not middle:
offset_new(k) := offset_old(k) - mean{offset_old vector without middle element}

offset_new(middle) := 0

Regarding the whole discussion:

Nothing is said if the amplitudes are exactly equal or made slightly unequal to better handle cancellation.

Is it for sure that all sawtooths in the original implemenation are equal in polarity? Would make sence. If not, you get more pronounced cancellation and this pulse width effect (ok, only for two, but can be generalized).

On the other hand, highpassing a sawtooth leads to bad exploitation of the dynamic range, because the signal shifts in one direction.

Post

synthpark wrote: Thu Apr 08, 2021 9:35 am Note: the mean of the frequency factors is not 1 (the offsets do not sum to zero). But they have to. Otherwise, the sound will be detuned as a whole. Am I wrong?
The mean frequency is 1.00021, which is only about +0.37 cents. The limit of human perception is possibly somewhere around 5 cents, so I think this might not be significant.

Post

signalsmith wrote: Thu Apr 08, 2021 10:07 am
The mean frequency is 1.00021, which is only about +0.37 cents. The limit of human perception is possibly somewhere around 5 cents, so I think this might not be significant.
EDIT: Sorry, you were actually right. I read 37 cents at first :lol: Yeah it doesn't really matter.
Case solved.
Last edited by synthpark on Thu Apr 08, 2021 11:52 am, edited 6 times in total.

Post

I think you want geometric mean.

Post

mystran wrote: Thu Apr 08, 2021 10:46 am I think you want geometric mean.
and the result is 0.997909655362177

If you were right, TZFM would go out of tune when modulating a sine with a square wave which shifts it x Hz up and down (I know this isn't exactly the same). I would rather say the mean must be 0.

Post Reply

Return to “DSP and Plugin Development”