Blog 1 - JUCE FOR BEGINNERS
Have you tried and failed to do some Audio programming, only to be told to learn C++, then told to learn DSP, then C, then CSound, then read a 15 year old book and work it out yourself? ME TOO. This is for you, you poor poor soul.
After fighting my way through most of the Kontakt 6 manual, (and by most, I mean about 6 chapters, but hey, it’s rough going) I’ve decided to take the not so logical step of moving to JUCE. I thought i’d start this process by doing an exercise with the hive mind of the internet, and doing some of the tutorials i’ve found, as well as developing and explaining some basic principles of C++ and JUCE (an audio programming thingo). I’ve been fiddling with JUCE for a little while now, but haven’t managed to get very far. Most of the time, I’m doing a little in JUCE, lots in Tensorflow, lots of angry googling, and then reverting to Max/MSP.
After some time with MAX, and gen~ (which allows you to export max patches straight to JUCE ) ((not an easy task, but maybe I will get some time to help out, as it DOES work*) , I’ve decided to bite the bullet and really get into Audio Programming, the proper way. What I will be doing here is explaining my whole process. A process in which, I am by no means an expert, and will probably make horrible mistakes before I make correct decisions. In this way, it would be radical if people wanted to correct me.
What I seem to be finding online is a stream of “Well, this is how you do it basically, it’s not how we would do it, but it’s how you could, in this VERY PARTICULAR example. But you shouldn’t do it this way. Ever. MOVING ON!”. On top of this, it seems that Audio programming is reserved for the seasoned computer science professionals, and, while i’m well aware of the detriment to the field I will have, i’m going to give it a go anyway.
I’m not going to go through the Install process, as it’s all quite straightforward (you can install it here) and you’ve also got to install an IDE. For my purposes, I will be on OSX, so we’re using Xcode, which you can grab in the App store or here.
I’m going to build the noise gate from here. It’s the second one, after arpeggiator. I’m aware it gets mega complicated, but we’ll see how we go. I’m going to first try and write it without copping out and downloading the PIP package (a package that will give me the Projucer file, that will then build the plugin) and instead try and decipher the bullshit advice i’m given.
It’s quite exciting actually, because what i’d really like to do is reverse engineer this, and take out everything ABOVE a certain threshold, like the ducker plugin in Logic. I’ve used this to great effect to grab all the breaths and such BEFORE speaking, which I think sounds great. Inevitably, I will end up getting frustrated and giving up on this reverse engineering, so I guess a side-chained noise gate could be interesting as well. If you haven’t played with the Ducker in logic, load up an AUX track and hold option as you select the plugin slot.
So, once you’ve fiddled with that. Let’s move on.
NoiseGate class, we’re suppose to have defined several private member variables to implement our noise gate behaviour as shown below: (keep in mind, don’t worry about the “ at the start and end, as i’m just trying to be fancy with Squarespace.
We define these private member variables in our header file.
A New Project
Open the Projucer, click on Audio Plug in (because that’s what we’re making) and name it NoiseGate. The capitalisation is important, the naming is, it all is. If you want to name it something else, that’s cool too, you will just increase your chance of fucking up by about a billion, and you’ll have fun trying to copy code examples once the naming nomenclature gets creative. I am using a mac, so I will be going through Xcode hell, so if you’re lucky enough to not have to do that, yippee for you.
Once you’re done with that, Save and open in IDE (next to the exporter and the play button at the top of the window (still in Projucer). The rest of the projucer stuff we’ll get into, as it’s pretty great. It lets you add binary files (whatever they are), images, other JUCE libraries and even build bits of the UI. It’s pretty neat, even though it’s only cursory knowledge on my part so far.
We’ve got two sets of files in our Source Folder (which is the C++ source code). PluginProcessor and PluginEditor. The way audio programming works, as far as I understand so far, is that the audio processing and the graphics processing HAVE to be seperate. If they aren’t, there are all sorts of clicks and pops and terribleness that goes into the audio whenever you try and chance a graphics element while moving the knob or whatever. In our instance, I will try and break it down. PluginProcessor is how it works, PluginEditor is how it looks. We keep them seperate, so that there are no clicks and pops as we change graphics, and the whole thing stays optimized and effective without jamming or stopping up. This apparently gets harder and harder, but all the Timur Doumler tutorials on malloc means nothing to me at this stage.
There are tons of great audio links I will hopefully be sharing, and if you’ve got more, that’s swell.
So there are also two parts of these files in our source folder (source code : C++). There are .cpp and .h files. The .h (stands for header files) is where you tell the computer WHICH functions or classes you’d like to use. We’ll get into what the difference is. For now, just think. You want a slider? You tell the computer you want a slider in the .h file. The flip side is the .cpp file, where you tell the computer WHAT the slider does. Or whatever else you are programming. It’s explained EVEN BETTER HERE
Dive into the Source folder and find the PluginProcessor.h file. This is where we will declare some seperate elements to build into the functions. As you can see from the finished product;
It’s quite UI Lite. We can tell we’ll need the text “Threshold” and “Alpha”. We’ll need a number readout of the value, and a slider. I guess the slider will also need min/max values, and we can probably futz with the colour a bit, but that’s the gist of the whole thing.
So let’s start with the plugin functionality, because the JUCE tutorial told me to. Praise the Sun.
Crack open the PluginProcessor.h and scroll on downtown. The Projucer has written all of this for us (good little Projucer) so we’ve only got ourselves and it to blame in a moment. Writing out this at the bottom of our file sets it as a private variable.
C++ offers the possibility to control access to class members and functions by using access specifiers. Access specifiers are used to protecting data from misuse.
Public class members and functions can be used from outside of a class by any function or other classes. You can access public data members or function directly by using dot operator (.) or (arrow operator-> with pointers).
Private class members and functions can be used only inside of class and by friend functions and classes.
So we use public variables all over the place, and private ones in very small but well connected ways. Because we want our threshold, alpha and such to be used only in the processor, we declare them privately.
.CPP and .H
When you get bored of this tutorial, and you are absent mindedly flipping between the .cpp and the .h you’ll see a number of interesting things. For instance, when you look at the .h you’ll see
Then, when you look at the .cpp file you’ll see;
COINCEDENCE? I THINK NOT
This is what C++ is built for. We can see the declaration of the function in the .h file, and some of the implementation in the .cpp file. There’s a slight difference in how they are used. The reason we have to use NoiseGateAudioProcessor::producesMidi() and not just producesMidi() is because the producesMidi() has been declared thusly;
So in fact it’s part of the CLASS NoiseGateAudioProcessor, not just a floaty function. I think for me this was one of the hardest things moving from something like C# and visual programming languages to C++. Obviously it’s simple for a computer science major, but hey, that ain’t me, so hopefully i’m saving you a WORLD of hurt trying to work it out. Something that a lot of people will do (me included) when they first pick up JUCE is to crack open the documentation, and then go on a large foray of wasted time head-scratching not understanding WHERE all this code comes from. When you’re starting to build your own things in JUCE, this is where you’ll be living, although you really need to understand the Hierarchy of C++ in order to get the most out of it. So in this instance, the class AudioProcessor is at the top of the tree, the NoiseGateAudioProcessor is an abstracted subclass of that, and then we have derived our functions producesMidi(); below that. So now you’re probably wondering where producesMidi came from, and what else you can do with an audioprocessor. No? Well. Fine then..
Seen any good movies lately..?
OKAY GREAT LETS LOOK AT THE AUDIO PROCESSOR.
That be here;
If you flick through the documentation you’ll see all sorts of different ones, whereas we are looking for this one. You’ll see a HUGE number of different functions, and the really cool thing is that we can write ANY of these in our program. So this is what JUCE is ACTUALLY FOR. Someone else (thank you Jules and Co.) has actually written most of this stuff out so that we don’t have to, and we simply inherit from their hard work, write our own Abstract versions of their classes, and use those!
You’ll see in this instance it says “virtual bool” but don’t worry too much about that at this stage. It’s really exciting because we can add all this stuff! For instance, if we scroll a bit more we’ll find things like getBypassParameter() and getPlayHead for doing tempo/DAW synced stuff. How exciting! Now a few of these might need to be declared differently, so we’ll stick to this version so far, as this blog entry has turned quite long as it is.
Ensure that you have added those private variables and hit ⌘ + B to build it, hoping for no errors.
Now if you do get an error, that’s okay. It’s USUALLY a typo issue. Go back and ensure that you’ve dotted your t’s and crossed your i’s, and it’s usually a semicolon or a simple typo, particularly in the function part of the typing. For instance, you can call a slider whatever the hell you want, but you can’t declare a Slidler instead. If not, it could have been something you changed in the Projucer before you started the project. As we’ve started really clean, there really shouldn’t be any errors, but hey, this may be a totally defunct blog post in 2 years like the rest of the literature on Audio Programming, so if not, drop me a comment and I will pretend I can help you out. If you run this, you should just have an empty box with “Hello World!” written in it. We’ll focus on changing that soon, but for now don’t stress.
I may actually leave this at this point for now, as there’s quite a bit to look into so far. Have a read through some of the AudioProcessor Documentation and make sure to read up on PluginProcessor.h, .cpp and PluginEditor.h and .cpp. We’ll continue this plugin very shortly, so don’t get mad at me, just click on the next blog!
If you liked this blog, and you’d like to hear more, please hit the “Subscribe via-email” to be notified of new posts when I write them. I won’t be spamming you, but it would be brilliant to develop a resource that’s for those in Audio trying to get into programming, as many of the resources are more to do with programmers learning audio.