Xfer Serum advanced algorithm tutorial

 KVRer
 Topic Starter
 14 posts since 19 Nov, 2014
feel free to post questions about this tutorial here in the thread. I will answer them. I have been independently developing new methods of waveform generation and processing techniques using the math based system of programming one line of code in serum. many of the special processing tools I needed to make perfect waveforms and wavetables are missing in serum. However, Steve left the door wide open for innovation by giving us the tools to make the tools to make the wavetables! there is a lot to discuss so I will post the information in parts. you should read the manual before reading this tutorial. I will not repeat what is already written in the manual. you should also have the manual open to check anything you don't understand or remember.
first lets discuss how you make basic waveforms from code. the classic waveforms used in subtractive synthesis are the most basic math functions possible to generate single cycle waveforms. there is often more than one way to program the same result. I will list all possible combinations here. why do we need alternates? when we get to the more advanced tutorials you will see that some versions of these alternates will be easier to simplify when combined with other augmentations. for example x*1 can be reduced to x which is a simple SAW 180 out of phase also called RAMP.
SAW phase 0
x
SAW phase 180
x
square alternates phase 180
rint(w)*21
(x>0)*21
(x<0)*2+1
abs(x)/x
x/abs(x)
square alternates phase 0
rint(w)*2+1
(x<0)*21
(x>0)*2+1
abs(x)/x
x/abs(x)
SIN
sin(x*pi)
SIN phase 180
sin(x*pi)
TRIANGLE phase 180
abs(x)*21
TRIANGLE phase 0
abs(x)*21
PULSE phase 0 (see notes)
(x<a)*21
"a" should be replaced with a constant 1 <= a <= 1 to generate a single cycle waveform.
you can generate the full set of PWM tables starting and ending with silence at PWM = 0% or PWM = %100 using the code
(x<y)*21
if you do not remember y please read the manual again. alternatively we could do
(w<z)*21
for the same result. it may be useful to use the w<z version when modulating PWM from an expression that contains no negative numbers.
first lets discuss how you make basic waveforms from code. the classic waveforms used in subtractive synthesis are the most basic math functions possible to generate single cycle waveforms. there is often more than one way to program the same result. I will list all possible combinations here. why do we need alternates? when we get to the more advanced tutorials you will see that some versions of these alternates will be easier to simplify when combined with other augmentations. for example x*1 can be reduced to x which is a simple SAW 180 out of phase also called RAMP.
SAW phase 0
x
SAW phase 180
x
square alternates phase 180
rint(w)*21
(x>0)*21
(x<0)*2+1
abs(x)/x
x/abs(x)
square alternates phase 0
rint(w)*2+1
(x<0)*21
(x>0)*2+1
abs(x)/x
x/abs(x)
SIN
sin(x*pi)
SIN phase 180
sin(x*pi)
TRIANGLE phase 180
abs(x)*21
TRIANGLE phase 0
abs(x)*21
PULSE phase 0 (see notes)
(x<a)*21
"a" should be replaced with a constant 1 <= a <= 1 to generate a single cycle waveform.
you can generate the full set of PWM tables starting and ending with silence at PWM = 0% or PWM = %100 using the code
(x<y)*21
if you do not remember y please read the manual again. alternatively we could do
(w<z)*21
for the same result. it may be useful to use the w<z version when modulating PWM from an expression that contains no negative numbers.

 KVRer
 Topic Starter
 14 posts since 19 Nov, 2014
simple mixing of two waveforms
before you can understand how crossfading and mixing works, you must understand how volume is controlled or modulated. those familiar with analog subtractive synthesis concepts will understand this as VCA (voltage controlled amplifier). any waveform multiplied by 0 will be muted. any waveform multiplied by 1 will have output = input. any waveform multiplied by a number > 1 will increase in volume. any waveform multiplied by a number 0 <= number < 1 will be attenuated.
sin(x*pi)*0
sin(x*pi)*0.5
sin(x*pi)*1
sin(x*pi)*1.5
notice sin(x*pi)*1 looks exactly like sin(x*pi). this is because the *1 is redundant. if you ever see something that has *2/2 you can replace it with *1/1 or *1 or just delete it!
so now we have a voltage controlled amplifier but how do we modulate it from a control signal? lets look at some example control signals. type z and hit enter. there may be a bug that this will not work. you might need to work around the bug by typing z+x*0. I think serum ignores anything that does not contain at least one of the following "x, w, sel, in" if you just booted up serum but did not enter any expression yet. this control signal can be used to make a sound fade in. when used in conjunction with the complementary reverse control signal 1z, we can crossfade two signals
example
sin(x*pi)*(1z)+(x*z)
everything before the + is the starting waveform, everything after the + is the ending waveform. this example will crossfade from sin to saw.
before you can understand how crossfading and mixing works, you must understand how volume is controlled or modulated. those familiar with analog subtractive synthesis concepts will understand this as VCA (voltage controlled amplifier). any waveform multiplied by 0 will be muted. any waveform multiplied by 1 will have output = input. any waveform multiplied by a number > 1 will increase in volume. any waveform multiplied by a number 0 <= number < 1 will be attenuated.
sin(x*pi)*0
sin(x*pi)*0.5
sin(x*pi)*1
sin(x*pi)*1.5
notice sin(x*pi)*1 looks exactly like sin(x*pi). this is because the *1 is redundant. if you ever see something that has *2/2 you can replace it with *1/1 or *1 or just delete it!
so now we have a voltage controlled amplifier but how do we modulate it from a control signal? lets look at some example control signals. type z and hit enter. there may be a bug that this will not work. you might need to work around the bug by typing z+x*0. I think serum ignores anything that does not contain at least one of the following "x, w, sel, in" if you just booted up serum but did not enter any expression yet. this control signal can be used to make a sound fade in. when used in conjunction with the complementary reverse control signal 1z, we can crossfade two signals
example
sin(x*pi)*(1z)+(x*z)
everything before the + is the starting waveform, everything after the + is the ending waveform. this example will crossfade from sin to saw.

 KVRian
 1184 posts since 13 May, 2004 from SF Bay Area, California
 KVRist
 78 posts since 4 Jan, 2012 from USA
The Ternary Conditional Operator
There's an undocumented feature in the equation editor that's crucial for creating piecewise waveforms. Some of you who program should be familiar with the ternary conditional operator, which looks like this (a ? b : c). You can use it in Serum's equation editor exactly as you'd expect.
For those of you who aren't familiar, it's fairly easy to understand. Essentially, this lets you choose between two values (b and c) using a condition (a). The condition, a, has to be something that is true or false. If a is true, you get b, otherwise you get c. The most common way of using this is to make 'a' a comparison (x > y, x < y, x == y, etc). Here's a simple example to start out
In this case, your a is '2 > 1', your 'b' is 0, and your 'c' is 1. '2>1' is obviously true, so that entire block of code would simplify to b, which is 0. If 'a' were '2 < 1' instead, you'd end up with 'c', which is 1. You could even insert that entire block of code into a larger equation and it'd work exactly like any other mathematical function, like so
This would take the answer from the ternary conditional (which will always be 0 in this case) and multiply it by 2. The ternary conditional truly becomes useful when your comparison (a) uses a variable of some sort (e.g. x > 0), which lets you create functions that change dramatically under certain conditions, but that's enough for now. If there's enough interest I may type up a second part for this tutorial, showing some ways to use the ternary conditional in your own functions. If you want some examples to study for now, some of Steve Duda's default formulas use this feature.
There's an undocumented feature in the equation editor that's crucial for creating piecewise waveforms. Some of you who program should be familiar with the ternary conditional operator, which looks like this (a ? b : c). You can use it in Serum's equation editor exactly as you'd expect.
For those of you who aren't familiar, it's fairly easy to understand. Essentially, this lets you choose between two values (b and c) using a condition (a). The condition, a, has to be something that is true or false. If a is true, you get b, otherwise you get c. The most common way of using this is to make 'a' a comparison (x > y, x < y, x == y, etc). Here's a simple example to start out
Code: Select all
(2 > 1 ? 0 : 1)
Code: Select all
(2 > 1 ? 0 : 1) * 2
Facts are meaningless, you can use facts to prove anything that's even remotely true

 KVRer
 Topic Starter
 14 posts since 19 Nov, 2014
wow I did not know we could do that! they say necessity is the mother of invention. I needed this once so I found my own way to do it using other tools. I do use the < > symbols now but before that I was using ((a+offset)/abs(a+offset)+1)/2 this is a square wave with offsets to use it as a switch to mute signals when a>0. I could just put some extra minuses to get the complementary mute for the second side of the switch ((aoffset)/abs(aoffset)+1)/2 also reduce to ((a+offset)/abs(aoffset)+1)/2
then I read the manual I started doing (a>0)*expression1+(a<=0)*expression2. this is another switch that mutes expression1 when a<=0 but mutes expression2 when a>0.
so all three methods that give the same result are
((a+offset)/abs(a+offset)+1)/2*expression1+((a+offset)/abs(aoffset)+1)/2*expression2
(a>0)*expression1+(a<=0)*expression2
(a > 0 ? expression1 : expression2)
then I read the manual I started doing (a>0)*expression1+(a<=0)*expression2. this is another switch that mutes expression1 when a<=0 but mutes expression2 when a>0.
so all three methods that give the same result are
((a+offset)/abs(a+offset)+1)/2*expression1+((a+offset)/abs(aoffset)+1)/2*expression2
(a>0)*expression1+(a<=0)*expression2
(a > 0 ? expression1 : expression2)

 KVRer
 Topic Starter
 14 posts since 19 Nov, 2014
tone sweeps with zero crossing correction
maybe the best way is to show you. try this sine tone sweep in serum right now.
sin((x+1)*pi*(z+1))
notice the waveform does not end at the zero crossing. we could use the spectral edit tools of serum to zero all the phases automatically or tweak the bars with the mouse. thats not what I want to do all the time. I wanted to just type something that would fix it. I added a VCA to fade out the last %5 with some nonlinear curve that would mimic the falling edge of a sine wave returning to zero. I tested the VCA shape first like this
w^32+1
you need to wrap the expression containing the + in () to prevent unwanted order of operation errors before you can use it as a VCA.
(w^32+1)
then apply the VCA to the tone sweep
sin((x+1)*pi*(z+1))*(w^32+1)
fade out
(w^32+1)
(w^16+1)
fade in
((1w)^32+1)
((1w)^16+1)
maybe the best way is to show you. try this sine tone sweep in serum right now.
sin((x+1)*pi*(z+1))
notice the waveform does not end at the zero crossing. we could use the spectral edit tools of serum to zero all the phases automatically or tweak the bars with the mouse. thats not what I want to do all the time. I wanted to just type something that would fix it. I added a VCA to fade out the last %5 with some nonlinear curve that would mimic the falling edge of a sine wave returning to zero. I tested the VCA shape first like this
w^32+1
you need to wrap the expression containing the + in () to prevent unwanted order of operation errors before you can use it as a VCA.
(w^32+1)
then apply the VCA to the tone sweep
sin((x+1)*pi*(z+1))*(w^32+1)
fade out
(w^32+1)
(w^16+1)
fade in
((1w)^32+1)
((1w)^16+1)

 KVRer
 Topic Starter
 14 posts since 19 Nov, 2014
interpolating 3 waveforms
this is like a crossfade a to b followed by another crossfade b to c. it is necessary to have 3 control signals that always add up to 1 like 1 = VCAa+VCAb+VCAc. this is because the result is x = x*1 = x*(VCAa+VCAb+VCAc). we also know that x*VCAa+x*VCAb+x*VCAc = x*(VCAa+VCAb+VCAc). the first control signal is a half wave rectified saw
x*(x<0)
the second control signal is a triangle with no negative numbers.
abs(x)+1
the last control signal is the bottom half wave rectified saw with 1* or abs() to flip the sign on the negative numbers.
1*x*(x>=0)
reduced to
x*(x>=0)
notice that
abs(x*(x>=0))
reduces to
x*(x>=0)
canceling abs() only works if there are no positive numbers to the input of the function. this is rare that you will reduce things with abs(). it is just an oddball hack that works by luck.
but we can not make 256 waveforms without using z or y or in somewhere in the control signal. we must replace the x with a y to crossfade 3 sources. here is the answer.
a*(y*(y<0))+b*(abs(y)+1)+c*(y*(y>=0))
to prove it works lets fade a sine to saw to square.
sin((x+1)*pi)*(y*(y<0))+(x)*(abs(y)+1)+x/abs(x)*(y*(y>=0))
this is like a crossfade a to b followed by another crossfade b to c. it is necessary to have 3 control signals that always add up to 1 like 1 = VCAa+VCAb+VCAc. this is because the result is x = x*1 = x*(VCAa+VCAb+VCAc). we also know that x*VCAa+x*VCAb+x*VCAc = x*(VCAa+VCAb+VCAc). the first control signal is a half wave rectified saw
x*(x<0)
the second control signal is a triangle with no negative numbers.
abs(x)+1
the last control signal is the bottom half wave rectified saw with 1* or abs() to flip the sign on the negative numbers.
1*x*(x>=0)
reduced to
x*(x>=0)
notice that
abs(x*(x>=0))
reduces to
x*(x>=0)
canceling abs() only works if there are no positive numbers to the input of the function. this is rare that you will reduce things with abs(). it is just an oddball hack that works by luck.
but we can not make 256 waveforms without using z or y or in somewhere in the control signal. we must replace the x with a y to crossfade 3 sources. here is the answer.
a*(y*(y<0))+b*(abs(y)+1)+c*(y*(y>=0))
to prove it works lets fade a sine to saw to square.
sin((x+1)*pi)*(y*(y<0))+(x)*(abs(y)+1)+x/abs(x)*(y*(y>=0))

 KVRer
 Topic Starter
 14 posts since 19 Nov, 2014
compressors and waveshapers
if you divide the frequency of a sine wave in half at the right phase, you can do a very crude maybe too perfect tube compression. the function looks like this
cos((x1)*pi/2)
the way it works is you put something in where the x is. what you see on your screen right now is the saw x running through a compressor. if we take the sin saw square crossfade from the last example, we can wrap it up inside the compressor like so.
cos(((sin((x+1)*pi)*(y*(y<0))+(x)*(abs(y)+1)+x/abs(x)*(y*(y>=0)))1)*pi/2)
that is confusing! try breaking it down before and after the x
cos((
x
1)*pi/2)
cos((
(sin((x+1)*pi)*(y*(y<0))+(x)*(abs(y)+1)+x/abs(x)*(y*(y>=0)))
1)*pi/2)
you can do foldover distortion with a VCA before the waveshaper function cos((x1)*pi/2). the vca must have gain > 1 to achieve folding. the VCA must be applied to x inside the function. I will use a VCA of 5*
cos((5*(sin((x+1)*pi)*(y*(y<0))+(x)*(abs(y)+1)+x/abs(x)*(y*(y>=0)))1)*pi/2)
there is a small problem with the phases moving around. if you want to fix it you can use Morph  Spectral (zero all phases). now would be a good time to exit the waveform edit screen and save the wavetable in your user folder by clicking the wavetable save icon.
if you would like to compress a signal or process it in any way after you do spectral edits, you will need to use the "in" variable. refer to the user manual if you are not familiar with "in". it takes the input from your screen. there is no need to use y or z but you can combine them if you have a good reason to do so.
I can run whats on screen through the compressor with
cos((in1)*pi/2)
there is a bug in serum if you hit enter twice, it will only compress once. you can work around the bug by changing the function in some insignificant way
cos((in1)*pi/2)+0*1
cos((in1)*pi/2)+0*11
cos((in1)*pi/2)+0*111
cos((in1)*pi/2)+0*1111
cos((in1)*pi/2)+0*11111
tap dancing
cos((in1)*pi/2)
cos((in1)*pi/2)+0
cos((in1)*pi/2)
cos((in1)*pi/2)+0
cos((in1)*pi/2)
you can do an infinite number of repetitions folding and spectral edits. you can also filter a fold. I am experiencing a bug that requires me to add +z*0 to everything to make the "in" variable call correctly. aparently "in" sometimes will not call without z or y present.
cos((5*in1)*pi/2)
zero phase
filter
cos((in1)*pi/2)
cos((in1)*pi/2)+0*1
cos((in1)*pi/2)+0*11
in*1.3
filter
if you divide the frequency of a sine wave in half at the right phase, you can do a very crude maybe too perfect tube compression. the function looks like this
cos((x1)*pi/2)
the way it works is you put something in where the x is. what you see on your screen right now is the saw x running through a compressor. if we take the sin saw square crossfade from the last example, we can wrap it up inside the compressor like so.
cos(((sin((x+1)*pi)*(y*(y<0))+(x)*(abs(y)+1)+x/abs(x)*(y*(y>=0)))1)*pi/2)
that is confusing! try breaking it down before and after the x
cos((
x
1)*pi/2)
cos((
(sin((x+1)*pi)*(y*(y<0))+(x)*(abs(y)+1)+x/abs(x)*(y*(y>=0)))
1)*pi/2)
you can do foldover distortion with a VCA before the waveshaper function cos((x1)*pi/2). the vca must have gain > 1 to achieve folding. the VCA must be applied to x inside the function. I will use a VCA of 5*
cos((5*(sin((x+1)*pi)*(y*(y<0))+(x)*(abs(y)+1)+x/abs(x)*(y*(y>=0)))1)*pi/2)
there is a small problem with the phases moving around. if you want to fix it you can use Morph  Spectral (zero all phases). now would be a good time to exit the waveform edit screen and save the wavetable in your user folder by clicking the wavetable save icon.
if you would like to compress a signal or process it in any way after you do spectral edits, you will need to use the "in" variable. refer to the user manual if you are not familiar with "in". it takes the input from your screen. there is no need to use y or z but you can combine them if you have a good reason to do so.
I can run whats on screen through the compressor with
cos((in1)*pi/2)
there is a bug in serum if you hit enter twice, it will only compress once. you can work around the bug by changing the function in some insignificant way
cos((in1)*pi/2)+0*1
cos((in1)*pi/2)+0*11
cos((in1)*pi/2)+0*111
cos((in1)*pi/2)+0*1111
cos((in1)*pi/2)+0*11111
tap dancing
cos((in1)*pi/2)
cos((in1)*pi/2)+0
cos((in1)*pi/2)
cos((in1)*pi/2)+0
cos((in1)*pi/2)
you can do an infinite number of repetitions folding and spectral edits. you can also filter a fold. I am experiencing a bug that requires me to add +z*0 to everything to make the "in" variable call correctly. aparently "in" sometimes will not call without z or y present.
cos((5*in1)*pi/2)
zero phase
filter
cos((in1)*pi/2)
cos((in1)*pi/2)+0*1
cos((in1)*pi/2)+0*11
in*1.3
filter
 KVRAF
 12522 posts since 21 Mar, 2008 from Hannover, Germany
I have done my own waveforms since around 2 years using mostly the formula/equation editor in the discontinued DNR Wave Designer plugin. Some of the weaveforms were also used for the waveform content included with Tone2 Rayblaster (with the factory content and with one of the soundsets).
I had also used them for my patches in e.g. Tone2 RAblaster and also Tone2 Nemesis.
A bigger collection is included in a big wavetable for PPG Wavemapper 2 (see the link in the second post):
http://www.kvraudio.com/forum/viewtopic ... 1&t=424070
Not all of the waveforms in that wavetable are from Wave Designer, some were created using Cameleon 5000 (additive synth) and NI FM8.
https://dl.dropboxusercontent.com/u/532 ... e%2001.png
https://dl.dropboxusercontent.com/u/532 ... e%2002.png
It's also possible to do something like this which AFAIK is called "Wavelet" (there seem to be different options to create such waveforms in the formula editor):
https://dl.dropboxusercontent.com/u/532 ... et%201.png
I admit that i am more interested in creating new and/or more complex waveforms than in recreating known simple ones like e.g. Saw, Triangle, Pulse, Square etc.
Over the last 2 years i have collected a text file with a big amount of formulas that seem to look interesting to me.
Ingo
I had also used them for my patches in e.g. Tone2 RAblaster and also Tone2 Nemesis.
A bigger collection is included in a big wavetable for PPG Wavemapper 2 (see the link in the second post):
http://www.kvraudio.com/forum/viewtopic ... 1&t=424070
Not all of the waveforms in that wavetable are from Wave Designer, some were created using Cameleon 5000 (additive synth) and NI FM8.
Many thanks for this formula. This one also seems to work in Wave Designer. Here are two screenshots for a = 0.1 and a = 0.5 (= Square):eatyourguitar wrote: PULSE phase 0 (see notes)
(x<a)*21
"a" should be replaced with a constant 1 <= a <= 1 to generate a single cycle waveform.
you can generate the full set of PWM tables starting and ending with silence at PWM = 0% or PWM = %100 using the code
https://dl.dropboxusercontent.com/u/532 ... e%2001.png
https://dl.dropboxusercontent.com/u/532 ... e%2002.png
It's also possible to do something like this which AFAIK is called "Wavelet" (there seem to be different options to create such waveforms in the formula editor):
https://dl.dropboxusercontent.com/u/532 ... et%201.png
I admit that i am more interested in creating new and/or more complex waveforms than in recreating known simple ones like e.g. Saw, Triangle, Pulse, Square etc.
Over the last 2 years i have collected a text file with a big amount of formulas that seem to look interesting to me.
Ingo
Ingo Weidner
Win 10 Home 64bit / mobile i77700HQ 2.8 GHz / 16GB RAM //
Live 10 Suite / Cubase Pro 9.5 / Pro Tools Ultimate 2021 // NI Komplete Kontrol S61 Mk1
Win 10 Home 64bit / mobile i77700HQ 2.8 GHz / 16GB RAM //
Live 10 Suite / Cubase Pro 9.5 / Pro Tools Ultimate 2021 // NI Komplete Kontrol S61 Mk1

 KVRer
 Topic Starter
 14 posts since 19 Nov, 2014
ingonator thankyou for sharing. it will take me some time to play with all the stuff you posted. I also have a text file with many various codes in it. this is the only way to try new stuff without losing the stuff you have already done. I realized the presentation of my text file was lacking so I started writing this tutorial. I wanted to break it down for people with no programming or music theory or dsp experience. I see your wavelet example with mixing sin waves and a sin hump vca. this is what I was planning for the next tutorial. I have some insane complicated codes up my sleeve but people need to crawl before they can walk.
 KVRian
 551 posts since 28 Jul, 2011 from USA
Good stuff. Just commenting so I can add Serum as a related product to the thread.
 KVRian
 551 posts since 28 Jul, 2011 from USA
The fade out works for me every time, but the fade in formula you gave only does sometimes.eatyourguitar wrote: fade out
(w^32+1)
(w^16+1)
fade in
((1w)^32+1)
((1w)^16+1)
 KVRian
 551 posts since 28 Jul, 2011 from USA

 KVRian
 976 posts since 27 Jun, 2011
Has anybody tried some of these?
http://countercomplex.blogspot.ch/2011/ ... f.html?m=1
Or does that concept translate at all? It would be pretty awesome if it did.
http://countercomplex.blogspot.ch/2011/ ... f.html?m=1
Or does that concept translate at all? It would be pretty awesome if it did.
 KVRian
 551 posts since 28 Jul, 2011 from USA
Doesn't translate, but fun.wasi wrote:Has anybody tried some of these?
http://countercomplex.blogspot.ch/2011/ ... f.html?m=1
Or does that concept translate at all? It would be pretty awesome if it did.