Noise Gate Pt 3

How exciting! A third one! I’ve now blown out my word count by quite a bit, but I think it’s better to see the whole thing, don’t you? No? Well… I guess I’ll keep doing it anyway.
So we’ve had a bit of a play with the Constructor/Destructor, and we know what variables are. I’d say we are flying! But I guess that’s what motion sickness will do to you.

We are now at our third block of code from the tutorial, and I really do feel they had missed out a smidge, although the tutorial is for “intermediate”. It’s a bit like a beginner JUCE book that I read at one stage that was a HUNDRED AND EIGHTY FUCKING PAGES before they talked about Audio. We get it, you can make a calculator out of Juce, and make MsPAINT. Amazing. Not exactly what we want though is it? I’m going to try and keep this as Audio Centred, though we’ll undoubtably solve puzzles and make Zork at some point.

This next line of code is;

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

In programming minds, this is a pretty well thought out process. I’m told by JUCE that in the isBusesLayoutSupported() function, we ensure that the number of input channels is identical to the number of output channels and that the input buses are enabled.

So we have bool (can only be true or false, 0 or 1)


Let’s have a look at isBusesLayoutSupported in the documentation. If we move to AudioProcessor::Bus, we’ll see what we are looking for.

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

Look at all my purty highlights! We could use this command, or a few others to check what’s going on.
◆ isNumberOfChannelsSupported()
◆ supportedLayoutWithChannels()

Are some of the other functions that do SIMILAR but not THE SAME thing.

What we’re trying to do is assume that the entire Layout (stereo, with Channel 1 L and Channel 2 R) is supported, NOT that it has two channels, OR that is has a L and an R, but that it exists in this configuration.

The Code So Far…

Our current project that JUCE spat out looks lyk dis;

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

Which looks pretty convoluted, and you’re probably afraid to delete anything from this. Luckily, you have my ham-fisted approach behind you! And together we can break anything!

Now, we aren’t using a MIDI Effect, so we can go ahead and can a bit of this straight away. I suppose we could set it so that our NoiseGate is triggered by some MIDI, maybe that would be a fun expansion later on. For now, we’ll get rid of;

 #if JucePlugin_IsMidiEffect

ignoreUnused (layouts);

    return true;


When we fuck that off, we get a bright red line, which means

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

This is because we removed an #if at the start. Now, you’re probably wondering why there’s a big ol octothorpe in front of the if statement. This is because it’s all preprocessor code, IE, code that is written by the Projucer. Re-generating files can make this messy, because the code you’ve written between these will be erased by the Projucer occasionally. What we want to do is ensure that what WE want is there, because JUCE ain’t the boss of us. So let’s get rid of all the #endif in these points, taking special attention to eradicate the one outside the curly braces towards the end of the function. By removing these, we’ll probably get the “Control may reach end of non-void function”, which doesn’t sound great, but we’ll deal with that as we go, as we’ve not yet written the code so Xcode can calm the fuck down for now.

Now the sidechain we don’t care too much about, as that will proc the function we are looking for anyway, but it’s a good idea to ensure our input/output is the same, so we don’t pump sick beats off into the abyss (and crash our plugin/DAW). Now when we pop in their (JUCE) code, we get an error, and we get our first Build Failed (or maybe our tenth?)

Expected function body after function declarator

This fella has to do with how the function has been declared.

The override keyword serves two purposes:

It shows the reader of the code that “this is a virtual method, that is overriding a virtual method of the base class.”

The compiler also knows that it’s an override, so it can “check” that you are not altering/adding new methods that you think are overrides.

As you can see, there’s a great deal of inheritance and virtual methods and shit going on here. Really a Gregor Mendel pile of shit that I am not totally familiar with at this stage, but we’ll get to it. I’m fairly sure at this stage that it’s more to do with parent and child relationships (or the equivalent of) when it comes to constructing abstracted classes from inheriting from a base class.

Gosh I sound like a programmer already.

For now, we’ll just get rid of override. We could change the function declaration, but let’s keep moving, and see if it messes us up later on or not.

The Function’s Function…

Because our function is checking the compatibility of channels and the coherence between the input/output channel count, we’re looking to return the answer of layouts (from the Bus class). If you’re not sure how to get to the bus class, you can hold ⌘ + click on what you’re looking to find. For instance, hold ⌘ + click on BusesLayout (in the parenthesis after isBusesLayoutSupported (const BusesLayout& layouts)) and it’ll take you to the Bus class declaration, where the masters of JUCE have written some stuff that’s relevant to this usage of Bus. We can see that we’re using a pretty stock version of the function in our own code, as it pretty closely matches the declaration. It is, after all, pretty standard to check these sorts of things.

It gets a SMIDGE hairy where we look at the rest of the code of this line, with && and ! in it, meaning AND and NOT respectively. Boolean is, as i’ve said, all true and false, so we’re expecting it to read the code like a sentence, and answer YES or NO, essentially. When I have read programming books, one of the issues I have is that when they introduce types like int (integer, whole numbers), float (floating point, decimal place numbers) and the like, they hit you with a storm of information. Unsigned int and char and string and bool and float and this flurry of technical terminology. I get that it’s great to know, but instead of proceeding that way, I am going to explore the code through these tutorials, and make sure that we learn what we have to. Being on a “need to know” basis seems pretty intuitive to me, because otherwise there’s this veritable tome of information about C++ programming standards and books to read that are really dry and full of stuff we’re not interested in. We are into audio programming, so I want to try and just introduce concepts as they come. It might take a little longer to get to the finished product, but I think it’ll leave us with a much greater understanding of what’s occuring when we write the lines of code. Otherwise we’ll be stuck knowing what a float, and int and such are, but not where to use them or why. I’ll try my best to expound on these concepts as I find them out, and if it doesn’t work for you, drop me a line. I’ll consider it, as I know that there are plenty of industry downsides to only learning what you need.

Back to the tutorial.

return layouts.getMainInputChannelSet() == layouts.getMainOutputChannelSet()

&& ! layouts.getMainInputChannelSet().isDisabled();

So the line is actually saying

“Tell me that the Main Input’s Channel Set matches the Main Outputs Channel Set AND that it’s NOT Disabled.”
If this is false, we’ll close this shit down, as we don’t want crazy stuff happening with mismatching input/output numbers, or we’ll throw an error.

The Wrap Up

So we’ve had a look today at Boolean logic, and at all the different types of Input/Output mappings that JUCE is capable of. Having a look through the documentation showed us the multiple ways of declaring pieces of code, and their differing arguments, and we pretended to learn a bit about override. We’ll keep moving and, as we get to the scarier parts of the code (the actual audio processing) we’ll start making some serious headway. If you’re diggin’ it, let me know. If not, I guess don’t?