Introduction To Juce DSP Module: Building An Oscillator
The next
step in our audio programming journey is learning about the Juce dsp module.
DSP stands for Digital Signal Processing and that is what we have been working
on with the programs in the previous blog posts. This module comes built with
some handy tools we can use to process our digital audio and make cool sounds
which is what we are here to do. This post will focus on the dsp module
Oscillator class which will give us a simple framework for building an
oscillator.
Before I
get to explaining what an oscillator is, I would like to post a quick answer to
a question from the white noise generator post. I was asked if I know how the
random value is generated by the Juce random class. I read the documentation,
and the truth is I am not entirely sure what classification their method for
getting a random fall into, but they said that their random values are
generated from system values, mostly the system time. Also, if the random is
called multiple times the previous random value factors into the calculation of
the new random value so that the values will be even more random as you go on,
they claim. I do not really understand this process but maybe you know more
than me and these clues can help you. If this gives you some insight into what
they are doing so you can figure it out, feel free to comment on it so I can
learn something myself. The
documentation did not give me any more detail unfortunately.
With
that quick detour out of the way, the rest of this post will focus on building
an oscillator with different wave shape equations and variable frequency with a
slider like we build before with the sine wave synthesizer. This time I do not
have a tutorial program to link for you, but I learned from "The Audio Programmer" on YouTube so definitely check his channel out. I will show you the important
pieces of this program and it is easy to build so you should be able to build it
too.
An
oscillator is basically an audio device/program that will output different kinds
of waves. In this tutorial I will share a few equations so that you can use the
dsp module to output sine waves, square waves, and sawtooth waves. These all
have a different sound and there are many others that you can look up and plug
into the oscillator to make different synth sounds. In case you don’t build
this program you can watch this video to listen to some examples of each of
these waves at one frequency: https://www.youtube.com/watch?v=VRD9Uj2YTBk&ab_channel=SynthSchool.
Firstly,
you need to start by creating a new application and choose the basic plugin
template. I went ahead and made a slider to select the frequency I want to
output just like the previous example program. For the range of values I chose
20 to 20,000 because this is the human hearing range. I also used the set skew
function of the slider and set 500 to the middle value of the slider as the ear
perceives the super low frequencies less so it is better to skew the frequency change
control to the higher end of the spectrum. I also set a global variable called
currentFreq and an override of the sliderValueChanged() method so that upon the
slider value changing the currentFreq value will be set to the slider value.
Those
are all the GUI building blocks we need to make the oscillator. From here we need
to make the Oscillator. In our plugin processor file we need to declare a juce::dsp::Oscillator
with a float type. We will also pass in a function that the oscillator will use
when creating waves. We can start with a simple sine wave, just using sin(x).
Includes sneak peak of other waveform functions |
The next
step is setting up our prepareToPlay() callback function which will be called
before the processBlock(). We first need to declare a juce::dsp::ProcessSpec. We
then set the ProcessSpec.maximumBlockSize, sampleRate, and numChannels by the values
automatically passed into the prepareToPlay() function and by used the getTotalNumOutputChannles()
method. We that call the prepare function on our oscillator and pass in our processSpec.
This is the way these values are communicated to any of our dsp objects. You
may also notice in the screenshots here that there is a dsp::Gain object and
this is simply used to control the volume. Go ahead and follow my example if
you would like to keep the volume ceiling low. After calling the prepare method
we call the setFrequency() method on our oscillator and pass in currentFreq.
This will simply determine what frequency our oscillator starts out at.
prepareToPlay() function |
Finally
we need to set up out processBlock() method. Here we need a juce::dsp::AudioBlock
object with our output buffer passed to it. We then go ahead and set the
frequency of our slider again using the same method from before according to
the currentFreq. Whenever this value changes between samples the new value will
be applied to any new samples which can result in some fun sounds when sliding
the volume slider quickly. Finally we just go ahead and call the process method
of our oscillator (and our gain object too right afterward to control the volume,
optionally) and pass in a new juce::dsp::ProcessContextReplacing of type float
which is itself passed the audio block we just made. This outputs our processed
signal (replacing its context, although there is no input signal in this
program) so we can actually hear the signal generated. Now we officially have a
working oscillator using the dsp module!
The last
step you can take passing in some other equations to the oscillator object when
you declare it. If you’re up for a challenge you can also create a GUI
component that will change the equation used, although I did not do this myself
this time. We started with sin(x) for a sine wave but to get a square wave you
can insert “x < 0.0f ? -1.0f : 1.0f;” and to get a saw wave you can insert “x
/juceMathConstants<float>::pi;”. Try these out and listen to the
difference.
That’s
all for this post. In the next I would like to use a dsp::Waveshaper to process
a guitar input signal and use some different functions to get some different gain
sounds. We will see how successful I am upon posting. In the meantime, let me
know if there are any questions about the material here.
Comments
Post a Comment