- Vst Plugins Deactivated In Waveform 88
- Vst Plugins Deactivated In Waveform 87
- Vst Plugins Deactivated In Waveform 80
- Vst Plugins Deactivated In Waveform 8 Tutorial
Each patch can have 4 layers of sound made from over 500 DSP waveforms, filtered by 34 types, modulated by 8 LFOs and 12 envelopes. You can import your own audio and then have it pulled apart into individual grains and modulated to within an inch of its life.
After all this GUI stuff it’s time for some audio programming. First we’ll generate the classic Sine, Saw, Square and Triangle waveforms.
Let’s begin by running the duplicate script:
Again, you’ll have to go to Product → Scheme → Edit Scheme… and change “Run” so that it starts REAPER64.app with your reaper-project.RPP (as described earlier). If Reaper complains about the AU not being found, change the names and IDs in resource.h, or remove the DigitalDistortion.component.
Creating the Oscillator Class
All of this will be about DSP, but we will not just write our code into the ProcessDoubleReplacing
function. Instead, we will create an Oscillator
class. Best drum vst plugins free 2017. It will be called from ProcessDoubleReplacing
and will fill buffers with double
values for the current waveform. To generate the waveforms, we’ll first take the most intuitive approach. We will then see the disadvantages and find a better-sounding way.
Create a new Class by going to File → New → File…:
Call it Oscillator.
Now make sure Oscillator.cpp gets compiled when we build. Go to your project settings, select a target (e.g. AU) and click Build Phases. Click the plus button below Compile Sources and add the .cpp file (you’ll have to do this for every target you need):
Let’s write the header first. Put this between the #define
and #endif
in Oscillator.h:
We are using an enum
to indicate which waveform the oscillator is generating. Here it defaults to a sine wave, but this can be changed using the setMode
member function. Calculating π this way is more portable than using the M_PI
constant.
The Oscillator stores the frequency, phase and sample rate. Just to be clear, the phase is the value that will change all the time to indicate where in the waveform cycle the oscillator currently is. The phase increment is the amount that’s added to the phase every sample.
Finally, there’s more setter functions (for frequency and sample rate) and, most importantly, generate
. This is the function that takes a buffer of doubles and fills it with sample values.
Let’s add the implementation of the setter functions (in Oscillator.cpp):
The mPhaseIncrement
depends on both mFrequency
and mSampleRate
, so it has to be updated everytime one of the two is changed. We could calculate it every sample, but of course it’s far more efficient to do it here.
Add the implementation for generate
:
This function will be called everytime ProcessDoubleReplacing
is called. We’re using a switch
to use the right code for whatever waveform is currently selected.
Generating Waveforms
Vst Plugins Deactivated In Waveform 88
The code for generating a sine wave is quite simple:
Note that we’re not working with mFrequency
and mSampleRate
here. We’re just incrementing mPhase
and make sure it stays between 0
and twoPI
. The only more complex operation is the call to the C sin()
function, which on many systems will be calculated on a hardware level.
Here’s the code for the saw wave:
The interesting part is — again — the line of code that’s writing into the buffer. When I see formulas like these, I like to decompose them:
mPhase
goes from0
upwards, and jumps back to0
when it reachestwoPI
.- So
(mPhase / twoPI)
goes from0
upwards and jumps back to0
when it reaches1
. - This means that
(2.0 * mPhase / twoPI)
goes from0
up and jumps back at2
. - When
mPhase
is0
, the expression1.0 - (2.0 * mPhase / twoPI)
is1
. WhilemPhase
goes upwards, the expression goes downwards and jumps back to1
when it reaches-1
.
So we have a downwards saw wave!
The lower part that’s dealing with mPhase
is duplication that could be avoided, but in that case we would have to take the switch
statement into the loop. This would also prevent duplicating the for
statement, but the code would switch
more often than neccessary.
In most programming scenarios, we would prefer brevity and readability over performance. DSP code that’s executed 44100 or 96000 times per second can be an exception to this rule. But be aware that the compiler will optimize a lot behind the scenes and what feels like “a lot of work” to you (the programmer), may be very trivial compared to other areas you’re not thinking about.
Next is the square wave:
You’re already familiar with the lower part. Every cycle is twoPI
long, so the if
statement causes the first half of every cycle to have values of 1
, and the second half to have values of -1
. So there’s a very sudden jump when mPhase
becomes greater than mPI
. That’s a square wave.
The triangle wave is just a little more complex:
If you decompose -1.0 + (2.0 * mPhase / twoPI)
like I did above, you’ll notice that it’s the inverse of the above saw wave: It’s an upwards saw wave.
Let’s go from here: Taking absolute values (fabs
) of the upwards saw wave means that all values below 0
will be inverted (flipped around the x axis). This means that the values will go up and down. Subtracting 0.5
centers the waveform around 0
. Multiplying by 2.0
makes the values go between -1
to +1
. We have a triangle wave.
Let’s use our oscillator! Include Oscillator.h and add an Oscillator
member to your Synthesis
class:
We also renamed mThreshold
to mFrequency
.
In Synthesis.cpp, rename all instances of Threshold
with Frequency
. Now change the parameter initialization inside the constructor:
We’re re-using the knob for testing our class. We’ll be able to change the oscillator’s frequency between 50 Hz and 20 kHz (the default will be 440 Hz).
Change the createPresets
member function:
Inside Reset
, we have to tell the oscillator what sample rate is being used:
If we didn’t do this and the oscillator had the wrong sample rate, it would still generate the same waveforms, but at the wrong frequencies. GetSampleRate
is a member function that’s inherited from the IPlugBase
class.
We have to edit OnParamChange
as well, so the oscillator’s frequency can be changed using the knob.
Finally, ProcessDoubleReplacing
has to use the oscillator:
Basically we’re letting mOscillator
fill the left channel buffer. Then we copy everything into the right channel buffer.
Let’s hear how it sounds! Run the VST2 or AU target. If you get linker errors, make sure you added Oscillator.cpp to the Compile Sources phase.
Once it’s running, you’ll hear a steady tone. Turn the knob and the frequency will change. Now change the initial value of mOscillatorMode
in Oscillator.h, by modifying the constructor’s initializer list:
Run again and you’ll hear a sharper tone. Try OSCILLATOR_MODE_SQUARE
and OSCILLATOR_MODE_TRIANGLE
, too. Note the different timbres and turn the frequency knob. For all waveforms except the sine, you’ll hear that once you get into high frequencies, strange noises appear. There are additional tones, even below the base frequency. They sound inharmonic and when you turn the knob up and down, they move in the opposite direction!
Aliasing
If you look at the code for the square wave, you’ll notice that every time mPhase
becomes greater than mPI
, the waveform will jump from the positive max to the negative max, all from one sample to the next. The opposite jump happens when twoPI
is subtracted from mPhase and it becomes less than mPI
again. Generally, sudden jumps in a waveform mean that there’s a lot of high frequency content. Imagine somebody told you to construct this jump using as many sine waves as you like, but only sine waves. Given the generally round shape of sine waves, you can imagine how you’d need a lot of sine waves with a very high frequency. You actually need an infinite number of sine waves with frequencies going towards infinity to create a perfect square, saw or triangle wave.
In computers, everything is finite. You have a limited amount of disk space and RAM, so when you record one second of audio, your computer can only use a finite number of values to save it. This number (called the Sample Rate) can be any value, but is often 44100, 48000 or 96000 samples per second. An audio signal stored using a finite number of samples per second is called discrete.
To describe a signal that’s oscillating between +1 and -1, you need at the very least two samples per cycle: one with the value +1 and one with the value -1. So if you have 44100 samples per second, the maximum frequency you can describe is 22050 Hz (see Nyquist frequency).
So, it’s not possible to describe a perfect square, saw or triangle wave in a discrete time signal. If we try to do it (by generating the sharp jumps in the waveform), we will get aliasing effects. For more information, click here.
How can we generate the best, alias-free wave for a given sample rate? “Best” meaning “closest to the shape we calculated above”.
The Nyquist frequency is a constraint that’s expressed in the frequency domain. It doesn’t say “Your waveform shouldn’t have spikes that are steeper than X”. It says “Your signal shouldn’t have frequencies above X Hz”. So we need to shift our work to the frequency domain. We will do that in a future post, but in the next post we’ll look at how we can receive incoming MIDI data.
You can download the code we’ve created so far here.
Stereo channel vst plugin. After all this GUI stuff it’s time for some audio programming. First we’ll generate the classic Sine, Saw, Square and Triangle waveforms.
Let’s begin by running the duplicate script:
Again, you’ll have to go to Product → Scheme → Edit Scheme… and change “Run” so that it starts REAPER64.app with your reaper-project.RPP (as described earlier). If Reaper complains about the AU not being found, change the names and IDs in resource.h, or remove the DigitalDistortion.component.
Creating the Oscillator Class
All of this will be about DSP, but we will not just write our code into the ProcessDoubleReplacing
function. Instead, we will create an Oscillator
class. It will be called from ProcessDoubleReplacing
and will fill buffers with double
values for the current waveform. To generate the waveforms, we’ll first take the most intuitive approach. We will then see the disadvantages and find a better-sounding way.
Create a new Class by going to File → New → File…:
Call it Oscillator.
Now make sure Oscillator.cpp gets compiled when we build. Go to your project settings, select a target (e.g. AU) and click Build Phases. Click the plus button below Compile Sources and add the .cpp file (you’ll have to do this for every target you need):
Let’s write the header first. Put this between the #define
and #endif
in Oscillator.h:
We are using an enum
to indicate which waveform the oscillator is generating. Here it defaults to a sine wave, but this can be changed using the setMode
member function. Calculating π this way is more portable than using the M_PI
constant.
The Oscillator stores the frequency, phase and sample rate. Just to be clear, the phase is the value that will change all the time to indicate where in the waveform cycle the oscillator currently is. The phase increment is the amount that’s added to the phase every sample.
Finally, there’s more setter functions (for frequency and sample rate) and, most importantly, generate
. This is the function that takes a buffer of doubles and fills it with sample values.
Let’s add the implementation of the setter functions (in Oscillator.cpp):
Vst Plugins Deactivated In Waveform 87
The mPhaseIncrement
depends on both mFrequency
and mSampleRate
, so it has to be updated everytime one of the two is changed. We could calculate it every sample, but of course it’s far more efficient to do it here.
Add the implementation for generate
:
This function will be called everytime ProcessDoubleReplacing
is called. We’re using a switch
to use the right code for whatever waveform is currently selected.
Vst Plugins Deactivated In Waveform 80
Generating Waveforms
The code for generating a sine wave is quite simple:
Note that we’re not working with mFrequency
and mSampleRate
here. We’re just incrementing mPhase
and make sure it stays between 0
and twoPI
. The only more complex operation is the call to the C sin()
function, which on many systems will be calculated on a hardware level.
Here’s the code for the saw wave:
The interesting part is — again — the line of code that’s writing into the buffer. When I see formulas like these, I like to decompose them:
mPhase
goes from0
upwards, and jumps back to0
when it reachestwoPI
.- So
(mPhase / twoPI)
goes from0
upwards and jumps back to0
when it reaches1
. - This means that
(2.0 * mPhase / twoPI)
goes from0
up and jumps back at2
. - When
mPhase
is0
, the expression1.0 - (2.0 * mPhase / twoPI)
is1
. WhilemPhase
goes upwards, the expression goes downwards and jumps back to1
when it reaches-1
.
So we have a downwards saw wave!
The lower part that’s dealing with mPhase
is duplication that could be avoided, but in that case we would have to take the switch
statement into the loop. This would also prevent duplicating the for
statement, but the code would switch
more often than neccessary.
In most programming scenarios, we would prefer brevity and readability over performance. DSP code that’s executed 44100 or 96000 times per second can be an exception to this rule. But be aware that the compiler will optimize a lot behind the scenes and what feels like “a lot of work” to you (the programmer), may be very trivial compared to other areas you’re not thinking about.
Next is the square wave:
You’re already familiar with the lower part. Every cycle is twoPI
long, so the if
statement causes the first half of every cycle to have values of 1
, and the second half to have values of -1
. So there’s a very sudden jump when mPhase
becomes greater than mPI
. That’s a square wave.
The triangle wave is just a little more complex:
If you decompose -1.0 + (2.0 * mPhase / twoPI)
like I did above, you’ll notice that it’s the inverse of the above saw wave: It’s an upwards saw wave.
Let’s go from here: Taking absolute values (fabs
) of the upwards saw wave means that all values below 0
will be inverted (flipped around the x axis). This means that the values will go up and down. Subtracting 0.5
centers the waveform around 0
. Multiplying by 2.0
makes the values go between -1
to +1
. We have a triangle wave.
Let’s use our oscillator! Include Oscillator.h and add an Oscillator
member to your Synthesis
class:
We also renamed mThreshold
to mFrequency
.
In Synthesis.cpp, rename all instances of Threshold
with Frequency
. Now change the parameter initialization inside the constructor:
We’re re-using the knob for testing our class. We’ll be able to change the oscillator’s frequency between 50 Hz and 20 kHz (the default will be 440 Hz).
Change the createPresets
member function:
Inside Reset
, we have to tell the oscillator what sample rate is being used:
If we didn’t do this and the oscillator had the wrong sample rate, it would still generate the same waveforms, but at the wrong frequencies. GetSampleRate
is a member function that’s inherited from the IPlugBase
class.
Vst Plugins Deactivated In Waveform 8 Tutorial
We have to edit OnParamChange
as well, so the oscillator’s frequency can be changed using the knob.
Finally, ProcessDoubleReplacing
has to use the oscillator:
Basically we’re letting mOscillator
fill the left channel buffer. Then we copy everything into the right channel buffer.
Let’s hear how it sounds! Run the VST2 or AU target. If you get linker errors, make sure you added Oscillator.cpp to the Compile Sources phase.
Once it’s running, you’ll hear a steady tone. Turn the knob and the frequency will change. Now change the initial value of mOscillatorMode
in Oscillator.h, by modifying the constructor’s initializer list:
Run again and you’ll hear a sharper tone. Try OSCILLATOR_MODE_SQUARE
and OSCILLATOR_MODE_TRIANGLE
, too. Note the different timbres and turn the frequency knob. For all waveforms except the sine, you’ll hear that once you get into high frequencies, strange noises appear. There are additional tones, even below the base frequency. They sound inharmonic and when you turn the knob up and down, they move in the opposite direction!
Aliasing
If you look at the code for the square wave, you’ll notice that every time mPhase
becomes greater than mPI
, the waveform will jump from the positive max to the negative max, all from one sample to the next. The opposite jump happens when twoPI
is subtracted from mPhase and it becomes less than mPI
again. Generally, sudden jumps in a waveform mean that there’s a lot of high frequency content. Imagine somebody told you to construct this jump using as many sine waves as you like, but only sine waves. Given the generally round shape of sine waves, you can imagine how you’d need a lot of sine waves with a very high frequency. You actually need an infinite number of sine waves with frequencies going towards infinity to create a perfect square, saw or triangle wave.
In computers, everything is finite. You have a limited amount of disk space and RAM, so when you record one second of audio, your computer can only use a finite number of values to save it. This number (called the Sample Rate) can be any value, but is often 44100, 48000 or 96000 samples per second. An audio signal stored using a finite number of samples per second is called discrete.
To describe a signal that’s oscillating between +1 and -1, you need at the very least two samples per cycle: one with the value +1 and one with the value -1. So if you have 44100 samples per second, the maximum frequency you can describe is 22050 Hz (see Nyquist frequency).
So, it’s not possible to describe a perfect square, saw or triangle wave in a discrete time signal. If we try to do it (by generating the sharp jumps in the waveform), we will get aliasing effects. For more information, click here.
The pop-up box reporting the missing plugins does NOT give the option to locate these ‘missing’ plugins. Although, again, they are on my laptop.I know that I could just re-load the plugins in question, but patch selections / presets are lost if I do this. Which leads me to my question — is there ANY way to relocated the plugins without losing my settings??? Vst plugin error reason. Further, on Serato Sample, I have to re-load the samples I had chosen (not to mention their key, the same slice settings, etc.) which is impossible.You would think that this would be a common issue and/or easily rectified, but I can’t seem to find any solutions.
How can we generate the best, alias-free wave for a given sample rate? “Best” meaning “closest to the shape we calculated above”.
The Nyquist frequency is a constraint that’s expressed in the frequency domain. It doesn’t say “Your waveform shouldn’t have spikes that are steeper than X”. It says “Your signal shouldn’t have frequencies above X Hz”. So we need to shift our work to the frequency domain. We will do that in a future post, but in the next post we’ll look at how we can receive incoming MIDI data.
You can download the code we’ve created so far here.