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!

processBlock() method

               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

Popular posts from this blog

Detour: A Simple White Noise Generator

Conclusion