BUILDING A NOISE GATE PT. 2

We left off last time with just about NOTHING done in our noise gate. But that’s okay! Hopefully you’ve had a fifteen moments to get lost in that JUCE tutorial by Timur about thread safety, and hopefully your day had a few of these moments in it.

If you’re just joining the blog, welcome! Here’s a project with where we are currently up to (we’ve literally built a new project and added 4 lines, and joked about things all this time. Really, it’s lucky you’re here to keep us on track)

Now that we have completed our declaration of the private member variables (nod your head and pretend you understand, it will make you look real smrt) we can move to the .cpp file to add some functionality in.

Now the JUCE tutorial says;

In the class constructor, we initialise the plugin with three stereo buses for the input, output and sidechain respectively [1]. We also add two parameters namely threshold and alpha [2] as shown below.
Screen Shot 2019-05-05 at 6.00.06 pm.png

Let’s break down what that means.

Screen Shot 2019-05-05 at 6.03.59 pm.png

The Constructor

The class constructor does the initialisation that JUCE tuts are talking about. In our version, we’ll be adding this here.

A class constructor is a special member function of a class that is executed whenever we create new objects of that class.

A constructor will have exact same name as the class and it does not have any return type at all, not even void. Constructors can be very useful for setting initial values for certain member variables.

The return type they are talking about could be all sorts of things, but we’ll get to that. This line of code tells us what needs to be created when being constructed, and, the squiggle (tilde~) tells us what needs to be removed at the end, because it is the destructor.

destructor is a special member function of a class that is executed whenever an object of it's class goes out of scope or whenever the delete expression is applied to a pointer to the object of that class.

A destructor will have exact same name as the class prefixed with a tilde (~) and it can neither return a value nor can it take any parameters. Destructor can be very useful for releasing resources before coming out of the program like closing files, releasing memories etc.

We can tell that this is the Constructor and Destructor, because they have the same name with the exception of the ~. Now you might ask;

Why do we put these here and not in the header file?

What’s a Constructor?

Where did these come from?

Well, two of these are expected, but if you’re asking about the constructor…

So, I can only assume, as I am just developing these ideas as we go, and because JUCE does not help us with this AT ALL, but I assume that because if we look it up in the documentation, bus properties is a struct;

Screen Shot 2019-05-05 at 6.10.26 pm.png

It is for this reason we’ll add it to the constructor. I guess constructors make structures, easy way to remember. Knowing the logical nature of code development, this is probably the exact purpose. If we now go diggin’ into the Class documentation and click on the BusesProperties, we can find a few bits of the roadmap that might help us decipher this Kafka-esque nightmare. One thing I will say, it takes a long time to get to the point where you understand all the relevant components for an audio plugin. Even more so when you get into more algorithms. I am certainly excited to learn more, as I feel it happens more and more when you really dig in and try and find this stuff yourself. There are a lot of tutorials that just sort of tell you “Obviously we need an AudioProcessorValueTree state so let’s do one of those and then createAndAddParameter…” and they just trail off and make mouth noises until you stop watching the video.
ANYWAY
Let’s see how we go.

Buses Properties

Inside this window we can see some BusesProperties withInput and withOutput. These are addressed by the . after the BusesProperties(). So we are starting to understand how to get within these data hierarchies and get to the point where it makes sense!

Let’s focus on breaking down the entirety of the first assignment in our constructor.

So JUCE have this as our first channel, keeping in mind we’ll need an Audio Input, and Audio Output and IN THIS INSTANCE we have an additional Sidechain input. Unfortunately this time we won’t be using said sidechain to make SICK BEATZ but instead we’ll use it as the controller to cut low level noise.

In the documentation we have;

withInput (const String &name, const AudioChannelSet &defaultLayout, bool isActivatedByDefault=true) const

So we need a String (which is basically some words, characters, letters, WHATEVER, inside “ “)

Then we need a comma.

Then we need a const (unchangeable) AudioChannelSet &defaultLayout.

Clicking on this brings us to a whole new circle of hell;

https://docs.juce.com/master/classAudioChannelSet.html

Which shows us all of the channel configurations that JUCE is capable of. Which is actually really really exciting! It lets us use Ambisonics and 7.1 and all sorts of crazy things that I have never heard of (like octagonal, and 35th ambisonic channels and bottom left side) for whatever plugin we are generating. Maybe next time we can make a surround sound plugin! (we won’t!)

So we’re just looking for a plugin that can take in stereo. We could make it mono if we wanted to, but lets keep it stereo.

Screen Shot 2019-05-05 at 6.36.10 pm.png

Now all we’ve got to do is work out how to use this information in JUCE. Again, we’re already inside the channel using .withInput, so we just add AudioChannelSet::stereo()

So, let’s open up PluginProcessor.cpp

Typing it all out

Screen Shot 2019-05-05 at 6.45.37 pm.png

Woohoo! How exciting!
So type it all in, and then we hit ⌘ + B,

Screen Shot 2019-05-05 at 7.18.00 pm.png

….

And WE DID IT.

If we made a mistake, let’s not lose heart. Sometimes errors look incredibly spooky, sometimes not so much. For instance, we might just be missing a curly brace (computer speak for { and } ) or a semicolon ( ; ) so we can fix that up!

Screen Shot 2019-05-05 at 7.19.25 pm.png

Now it’s all getting exciting, (after all, we’ve completed ONE task!) but now we have to refocus. It’s the extra bit, using addParameter to add those threshold and alpha so that we can use it. If we go back to the documentation for AudioProcessor and search for addParameter, we’ll find this;

Screen Shot 2019-05-05 at 7.22.17 pm.png

So this then tells us that all we need to do to add a parameter to the audio procesor (that being one that is managed by the Audio Processor, being deleted automatically when it is removed and such, is call void AudioProcessor::addParameter ( taking in an AudioProcessorParameter*). However, we are loooking for something with the ability to have decimal places, so we will be looking for AudioProcessorParameterFloat OR AudioParameterFloat as in the tutorial.
Searching this in the documentation gives us this page.

Searching through that and moving to the correct documentation of the function gives us;

Screen Shot 2019-05-06 at 2.28.16 pm.png


You may also find a different definition with a little 1/2 next to it. Right now we’ll use 2/2, as that format fits the tutorial one, but don’t freak out, we’ll get to the other entry (far inferior) ((but not really)) a bit later.

So we’ll need;

  • a parameterID (usually just a name to call on, somehow different to the parameter name, not entirely sure why, someone tell me..)

  • The parameter name to use (that definitely won’t be the same as the parameter ID…

  • The range from min->max

  • the default value to begin with

  • aaaaand a bunch of optionals that we’ll probably skip most of the time (sorry Jules..)

Completing the Code

addParameter (threshold = new AudioParameterFloat ("threshold", "Threshold", 0.0f, 1.0f, 0.5f)); // [2]
So in our example we call addParameter, set the threshold variable we used earlier, (the value declared in the header file (.h) to;

ParameterID = “threshold”

Name = “Threshold”

Min value = 0.0f (the f is there to tell us it’s of type float, meaning it can have decimal places, so it’s 0.0f not 0)

Max value = 1.0f

and

Default range of 0.5f

Pretty standard for a lot of controls to move between 0.0 and 1.0 instead of 0-255 or something insane like SOME people. By the way, the reason we’re using AudioParameterFloat and NOT just an AudioParameter of another type is for the Normalizable Range aspect. The big benefit here is that when using a Normalizable Range, it converts the entire mapping of the parameters to a 0.0->1.0. This range does not have to be linear either, as we have the opportunity to set the skew factor (that is, a point which changes the slide between values.

For instance;

The documentation of AudioParameterFloat gives us two entries. (You’ll see AudioParameterFloat 1/2 and AudioParameterFloat 2/2. This means we can either initialise it with the arguments inside 1/2 or 2/2, depending on what we’re looking for. The implementation we used above used 2/2. If we wanted to do the same-ish thing with 1/2 (a different implementation), we’d use THIS version.

Screen Shot 2019-05-05 at 10.53.22 pm.png

However this version means we need to write;

addParameter (threshold = new AudioParameterFloat ("threshold", "Threshold", 1.0, 0.5f));

This would ALSO allow us to change the category of the parameter (in case we wanted to build something that had a big chain perhaps) and it also allows us to Skew the range as I said earlier, by looking into the NormalisableRange documentation, so we can change the linearity of the parameter.

Anyway, let’s go back to our version from above;

addParameter (threshold = new AudioParameterFloat ("threshold", "Threshold", 0.0f, 1.0f, 0.5f)); //

Hitting build and we should see…


Hooray! We did it!

Hopefully that explained what exactly is going on when we’re looking at typing these things out. Instead of a tutorial that just tells you to do something, without explaining what in the fuck.

Anyway, hopefully you learnt something in this, I know I did. See you next time! If you’re diggin’ this, let me know! Drop a comment or jump onto the mailing list.

2 Comments