Saturday 11 May 2013

Building Our Gain Plug-In

Building the plug-in is done in exactly the same way we built the JUCE demo plug-in.

Go to the 'Config' tab in The Introjucer. It should have been clever and created an exporter relevant to whatever OS you are using. If not, remember you can add a new project exporter by right clicking on the name of the project at the top of the list.

Also remember that we need to tell it where to find the VST SDK files.

Once you have done that, you can leave The Inrojucer and build the plug-in using whatever tools you have installed, as discussed earlier.

Hopefully you should end up with a new plug-in which you can test out in the host of your choice. Congratulations you have programmed your very own audio plug-in.

You should now have a good groundwork in order to start making your own, super funky, plug-ins. Maybe one day I will do a tutorial on making plug-in editors with JUCE.

Have a nice day now!
Sean

Plug-In Editors

A plug-in editor is the plug-in's custom GUI. It is the interface through which we edit the plug-ins parameters.

As mentioned previously we are not going to deal with doing a custom GUI just yet. This means we need to tell the host that it should make its own interface for our plug-in.  It does this using all the information about the plug-in's parameters we gave it earlier.

Look at the code in 'PluginProcessor.cpp' and find this bit:
bool GainPluginAudioProcessor::hasEditor() const
{
    return true; // (change this to false if you choose to not supply an editor)
}
There is even a comment here to tell us what we need to do. We will do what it says.

I'll just give a quick overview of the bits present in this function you may not have seen before.

The return type of the function is 'bool'. This is a Boolean value (either 'true' of 'false'). So the host can ask our plug-in if it has an editor, using the 'hasEditor' function. All the plug-in needs to do is return 'true' or 'false'. We will change it to 'false'. The code should now look like this:
bool GainPluginAudioProcessor::hasEditor() const
{
    return false; // (change this to false if you choose to not supply an editor)
}
That is all we need to change in our code. Save this change to your project. The next job is to build the plug-in.

Have a nice day now!
Sean

The Audio Processing

Now it is time for us to write the actual processing in our plug-in.

All we want to do is take the value stored in our 'gain' variable and multiply the incoming audio by it.

The is done in the 'processBlock' function, which should currently look something like this:
void GainPluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    // This is the place where you'd normally do the guts of your plugin's
    // audio processing...
    for (int channel = 0; channel < getNumInputChannels(); ++channel)
    {
        float* channelData = buffer.getSampleData (channel);

        // ..do something to the data...
    }

    // In case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
}
You may now be thinking "Gulp! There is a lot of code there." Don't worry, we don't need to pay attention to all of it for now.

Firstly, any line that starts with a '//' is a comment (if you are looking at the code in The Introjucer they will be written in green text). These are not part of the code, they are put in by programmers to explain the code. Read them, they are useful.

Let's look at the first line now. We have a function called 'processBlock' which has two input arguments and returns 'void'. Looking at the input arguments you might be thinking "Oh No! Arbitrary punctuation, what does this mean". I'm fairly certain most people have this reaction when they first start programming in C/C++ . As your knowledge of the language progresses you will become much more comfortable with these things. Rather than describe exactly what it means (there are plenty of books/websites which will tell you that) I will try and give a brief overview.

The plug-in host gives audio to our plug-in in blocks called 'buffers'. These buffers contain the audio samples to be processed. Now, the functions we have seen so far are given data from the input arguments and then give some other data back using the 'return' keyword. The 'processBlock' function does things a different way. In essence, rather than send the buffer of samples to the function and expect a processed buffer of samples in return, the host gives the function access to edit the samples directly. This means we can do processing on the input arguments as if they were the data itself. This is what those pesky looking ampersands are doing in our code.

Now we have discussed that, we can look at what the input arguments are. We have an 'AudioSampleBuffer' called 'buffer' and a 'MidiBuffer' called 'midiMessages'. We are not doing anything with midi so let's ignore this second argument.

The first argument is an 'AudioSampleBuffer', this is an object that exists within the JUCE API to make things easier for us. All we need to know for now, is that it contains all the samples that we need to process.

Next let's look at the last bit of the code:
// In case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
This has comments to describe what it does. We don't need to worry about changing it. Just leave it where it is.

That leaves this bit:
// This is the place where you'd normally do the guts of your plugin's
    // audio processing...
    for (int channel = 0; channel < getNumInputChannels(); ++channel)
    {
        float* channelData = buffer.getSampleData (channel);

        // ..do something to the data...
    }
We don't need any of that bit, so let's get rid of it and replace it with:
buffer.applyGain (gain);
This is, again, new syntax for you. That JUCE object 'AudioSampleBuffer', I mentioned earlier, has a bunch of functions associated with it (called its methods). We are using the 'applyGain' method here. This takes a float as an input argument and multiplies all the samples in the 'AudioSampleBuffer' by it. We are taking the float stored in our 'gain' variable and applying it to the samples in the 'AudioSampleBuffer' called 'buffer' (the input argument).

Remember that because of those ampersands we saw earlier, processing this input argument processes the host's samples themselves. We do not need to return the processed samples back to the host.

That is our processing done! Your 'processBlock' should now look something like this:
void GainPluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    buffer.applyGain (gain);

    // In case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
}
Save these changes to your project and we can move to the last bit of code we need to edit.

Have a nice day now!
Sean

The setParameter Function

Look through 'PluginProcessor.ccp' until you find a bit that looks like this:
void GainPluginAudioProcessor::setParameter (int index, float newValue)
{
}
When the host calls this function is is asking to set a specific parameter to a specific value.

There are two things we need to note about this function. Firstly the return type 'void'. This means that the function won't actually return a value. The host is just telling the plug-in to change a parameter value, it does not require anything in return.

Next is that we have two input arguments, an integer called 'index' and a float called 'newValue'. The first argument is the index of the parameter being set (like the argument to getParameter). The second is the value to set the parameter to.

Once again we can ignore the 'index' argument as we only have one parameter. We need to pay attention to the 'newValue' argument though as we need to store it in our parameter variable.

We will change to code to this:
void GainPluginAudioProcessor::setParameter (int index, float newValue)
{
    gain = newValue;
}
All we are doing here is take the value given as an input argument, 'newValue', and storing it in our 'gain' variable. Save these changes to your project and we can move to the next step.

Now our host is able to:
  • Ask the plug-in how many parameters it has.
  • Get the names of those parameters.
  • Get the values of those parameters.
  • Set the value of those parameters.
There are only a couple more things we need to do before we have a working plug-in.

Have a nice day now!
Sean

Getting Parameter Values from the Plug-In

The host has two way in which it can ask for the value of a given parameter. The 'getParameter' and 'getParameterText' functions.

The getParameter Function:

If the host calls this function it is expecting a float value in the range of 0 to 1 to be returned.

Currently your code for this function should look like this:
float GainPluginAudioProcessor::getParameter (int index)
{
    return 0.0f;
}
As with the 'getParameterName' function we have an input argument so the host can select which parameter it wants information about. We only have one parameter so we can ignore this.

We need to change this so that it returns the value stored in our 'gain' variable. We do this like so:
float GainPluginAudioProcessor::getParameter (int index)
{
    return gain;
}
Hopefully this change should be fairly self explanatory.

The getParameterText Function:

If the host calls this function it is expecting a string containing the value of our parameter. It will display this string in the interface it will build for our plugin. If we are scaling the value outside the range of 0 to 1 (say it is the frequency of an EQ band) we can return a value here that will make more sense to the user (something in the range 20 - 20000 say). We can also add units onto the end of the string (such as Hz).

The code you currently have for this function should look something like this:
const String GainPluginAudioProcessor::getParameterText (int index)
{
    return String::empty;
}
We don't need to scale the parameter values in our plug-in. All we need to do for this function is convert the float stored in our 'gain' variable to a string.

To do that we can change the code to this:
const String GainPluginAudioProcessor::getParameterText (int index)
{
    return String (gain);
}
Without going into too much detail, 'String (gain)' takes the value stored in 'gain' and converts it into a string. Our function then returns this string to the host so it can use it in its display.

The host can now ask our plug-in for the current value of its parameters. Save these changes to your project and we will move on.

Next we will look at how to tell the plug-in what to do when the host tries to set its parameters.

Have a nice day now!
Sean

Parameter Values

The value of a parameter can be changed at any time by the host. Because of this we need to assign a place to store the current value. We can then refer to or update this stored information as and when we need. We can do this by declaring a variable in our code in which we will store the current value of our gain parameter.

To do this we will edit the 'PluginProcessor.h' file, so select that from the menu on the left. We only need to add one line of code here. Scroll down to the bottom of the file. Just above the line which says 'private:' add the following line of code:
float gain;
This declares a variable in which we can store the value for our gain parameter. The first part, 'float', says what data type is stored in the variable (a float in this case). The second part, 'gain', defines the identifier for the variable. Whenever we want to access the value stored in the variable we can use this identifier.

Save these changes to 'PluginProcessor.h' and return to 'PluginProcessor.cpp'.

At the moment we have only told the computer that we want to store a float and refer to it as 'gain'. We haven't actually stored anything in the variable yet. Before we store anything in it we need to know how the host thinks about parameter values.

The host assumes that any parameters our plug-in has take a value between 0 and 1. It will give the plug-in values in the range when it wants to set a parameter and will expect a value in this range when it asks for the value of a parameter. If we require values outside of this range it is our job to scale the values given by the host within out plug-in code. To keep things simple we will not bother with scaling the values. Our gain will have a range from 1 (unity gain) to 0 (muted).

The first thing we need to do in our code, is to set a default value for the gain parameter. If we did not do this and the host asked for the value of a parameter it will just get given some random value (or even worse crash). We can set this default value in the part of our code that looks like this:
GainPluginAudioProcessor::GainPluginAudioProcessor()
{
}
This is our plug-in's constructor function. Essentially this function is called when the plug-in is first loaded. We can use it to do any set up we need before the plugin is used. (Remember that yours might not be the same as this depending on the name of your Introjucer project).

We want to add some code inside the curly brackets, like so:
GainPluginAudioProcessor::GainPluginAudioProcessor()
{
    gain = 1.0f;
}
This will set the value store in the variable 'gain' to 1. Writing it as '1.0f' makes it so the value is already a float and wont need to be converted in order to be stored (if we wrote '1.0' it would be interpreted as a double), it is not entirely necessary. Now when our plug-in loads up the gain will automatically be set to 1.

Save these changes to your project and you are ready to move on.

Have a nice day now!
Sean

The getParameterName Function

Look a bit further down the code now until you find a bit like this:
const String GainPluginAudioProcessor::getParameterName (int index)
{
    return String::empty;
}
This function returns the name of a parameter to the host.

There are a couple of extra bits to the syntax of this function which we haven't seen yet. Firstly is the 'const' part at the beginning. The meaning of this is, again, beyond the scope of this discussion. Read some C/C++ literature and all will become apparent.

The more important part in what is inside the round brackets after the function name. In here we will find the arguments to the function. Arguments allow a function to have an input as well as an output.

The host can call this 'getParameterName' function in order to get the name of a specific parameter. To do this the host must specify which parameter it wants the name of. This is done by using an input argument.

Inside the round brackets in the first line of code we see (int index). This means that our function has one input argument. It will be an integer value (indicated by the 'int' part) and we will refer to it as 'index'. Remember the 'getNumParameters' function had an empty set of round brackets. That is how we show that a function has no input arguments.

If our plug-in had multiple parameters the host could get the name of a specific one by calling the 'getParameterName' function with that parameter's index number as an argument. Say we had three parameters, we could get the name of the first one by asking for the name of the parameter with index 0 (getParameterName (0)). For the second parameter we use index 1 and for the third parameter, index 2. Note that the indexing starts to 0 rather than 1, this is again a fundamental part of C/C++ programming.

We also need to note that this function returns a 'String', this is a data type which holds some text.

So this first line of code is telling us that our plug-in has a function called 'getParameterName' which takes one argument (an integer called index) and then returns a string of text.

As our gain plug-in only has one parameter we don't need to worry about the input argument to the function. The host knows we only have one parameter so will only call the 'getParameterName' function with the input argument 0. Because of this our code inside the curly brackets can be one line that returns the name of our parameter.

Currently, the code above returns an empty string (String::empty). The syntax of that may seem weird at the moment but as you become more familiar with C++ and JUCE it will make sense.

We need to change it to look like this:
const String GainPluginAudioProcessor::getParameterName (int index)
{
    return "Gain";
}
Double quotes are used to enclose strings in C/C++. So our function will now return a string which says 'Gain'. When the host asks for the parameter name it will get 'Gain' in return. We are a step closer to having our plug-in. Save these changes to your project and we can move on.

Have a nice day now!
Sean

The getNumParameters Function

So, we have now decided what our plug-in needs to tell the host and have made a new project in The Introjucer. Let's edit some code shall we? It would be very helpful at this point if you did a little background reading on C++. I will try to give you a basic understanding of what the bits of code we edit mean. If you want to understand the structure of the plug-in properly however, you will need to learn quite a bit about C++.

If you have come here straight after the previous post you should still have your project open in The Introjucer. You should also still have the 'Files' tab selected. Open up 'PluginProcessor.cpp' by clicking on it in list on the left. You should now have a text editor on the right with the source code in it (you should be able to see that The Introjucer has already generated a lot of code for us).

Scroll down until you see a bit of code that looks like this (it's at line 30 currently but this may change as the JUCE library is constantly updated):
int GainPluginAudioProcessor::getNumParameters()
{
    return 0;
}
Your code may not be the same as this depending on what you called your Introjucer project. The name of your project will be prefixed to the 'AudioProcessor::' part. Hency why mine is 'GainPluginAudioProcessor::'.

What we have here is a function. This is a bit of code that an application can run to do a certain job. The syntax may be a little baffling at first but once you get used to C++ it won't phase you.

The function we see above is called 'getNumParameters'. As you may be able to guess, when this function is run it will tell the host how many parameters our plug-in has.

The 'GainPluginAudioProcessor::' part before this name tells us that this function belongs to 'GainPluginAudioProcessor'. In a manner of speaking this is our plug-in, so we have a function called 'getNumParameters' which belongs to our plug-in.

The 'int' part before that tells us that the function will output an integer number. Declaring what type of data a function returns is a fundamental part of C/C++ programming and something you will have to get used to.

So that first line tells the host that it can ask our Plug-In ('GainPluginAudioProcessor') to run its 'getNumParameters' function and it should expect an integer value in return.

After that line we have a block of code enclosed in curly brackets. This is the code that will be executed when we run (call) the function. For this function all we need to do is return the number of parameters for our plug-in. For this we only need one line of code. We use the 'return' keyword to define the output of our function. The code above has 'return 0;', we need to change this to 'return 1;'.  The whole bit of code should look like this:
int GainPluginAudioProcessor::getNumParameters()
{
    return 1;
}
The semicolon marks the end of the statement. Essentially semicolons break the code up into separate steps. Again this is something which is fundamental to C/C++ programming and you will need to get used to.

Now when the host asks our plug-in to call its 'getNumParameters' function, it will get the answer 1 in return. That's exactly what we wanted. Save these changes to your project and then we can move on.

Next we will look at how to tell the host the name of that parameter.

Have a nice day now!
Sean


A Simple Gain Plug-In

For purposes of demonstration let's make a simple gain plug-in. Before we write any code let's lay out the information that the host will need to know about the plug-in:

Parameter Information:

How many parameters does the plug-in have?

One (the gain).

What are the parameters called?

Let's call it 'Gain'.

What are the parameter's values?

We need to tell the host the current gain setting of the plug-in.

Actions To Complete:

We also need to plan what our plug-in will do when the host asks it to do things:
Set this parameter to this value.
We will take the new value and store it somewhere for use in our processing.

Process this audio.

We will take the audio and apply the gain defined by our gain parameter.

What does the plug-in look like?

Tell the host it will need to construct its own interface for our plug-in.

Making a Project in The Introjucer:

The Introjucer is very handy when it come to getting started with a new plug-in. When we create a new Audio Plug-In project we will be given some template code to work from. This has default answers for everything a host might ask of our plug-in. This then leaves us to change the ones we want to use in our plug-in. 

Open The Introjucer and create a new project (File - New Project). Call it what ever you wish, I'm going to call mine 'GainPlugin'. Then, in the project type menu, select 'Audio Plug-In'. Save this project where you want and you are ready to start looking at some source code.

When you have created your project you will be given the Project Settings editor screen. This is a series of setting to do with our plug-in which we can edit using The Introjucer's GUI. If you mouse over them you should get a description of what they do at the bottom of the window. If you were making a plug-in for release you would need to edit some of these fields, they give information about the plug-in company and the unique id of the plug-in. For now we wont worry about any of this.

Click on the 'Files' tab on the top left. You should now see four source code files. 'PluginProcessor.cpp', 'PluginProcessor.h', 'PluginEditor.cpp' and 'PluginEditor.h'. These contain the source code for our plug-in. The first two describe the operation of the plug-in, what the parameters are and the audio processing. The second two describe a custom GUI. As we are not bothering with a custom GUI for now we will ignore this second pair of files.

A discussion of why there are two files for each job is beyond the scope of this blog. The '.h' file is a header file while the '.cpp' file is the main C++ source code. If you want to know more you will have to read some C++ programming literature.

In the next post we will open up one of these files and start to edit it.

Have a nice day now!
Sean

What is a Plug-In?

In order to be able to program audio plug-ins we need to know what one is. What information is a host expecting from our plug-in? What information is our plug-in expecting from a host?

A plug-in is a dynamically loaded object. This means it can be loaded into a host application when it is needed. The plug-in will add some new features to the operation of the host application. In the audio plug-in world we add some new audio processing algorithms to a DAW (or some other piece of audio software). In order for these new features to be accessible the host needs to know how to speak to the plug-in. The plug-in also needs to know how to respond when the host asks it for something.

This is achieved through the use of an Application Programming Interface (API). In essence the API defines what our plug-in needs to tell the host in order for everything to work. Every different plug-in format (VST/AU etc.) has a different API. If we were to work with each plug-in format individually we would need to rewrite our code using each of these different APIs. When we use JUCE we can write a plug-in using JUCE's API. There are then a series of "wrappers" which take this code and make it look like it was written with one of the other APIs. As mentioned previously this allows us to write one piece of code and compile it as any plug-in format that JUCE supports.

There are several different things that our plug-in can tell the host about itself. This tutorial will not cover all of them. There are two main areas we will deal with.
  1. Information about parameters.
  2. The audio processing.

Parameters:

A parameter is any feature of our plug-in that is changeable by the user. Say we had an EQ plugin, our parameters might be frequency, Q and gain for each channel. The plug-in needs to be able to tell the host.
  • How many parameters it has.
  • What each parameter is called.
  • The current value of each parameter.
The host can also ask to set the value of a parameter. Our plug-in needs to know what to do when the host does this.

Audio Processing:

Obviously our plug-in needs to know what to do with any audio given to it by the host.

What does the plug-in look like?

One other thing we will need to consider is the plug-ins appearance. I'm sure in your experience using audio plug-ins you have come across some pretty swizzy GUIs. For now we will not deal with how to make our own custom interfaces. From the information our plug-in gives the host about its parameters the host can build its own simple interface for us. It isn't going to look pretty but it will make the programming a lot simpler for us.

Now we know what information we need to put into our plug-in code we can start planning a simple plug-in.

Have a nice day now!
Sean

Let's Build the JUCE Demo Plug-In

Before we actually make our own plug-in it might be wise to make sure we can build a plug-in successfully. To do this we can build the JUCE demo plug-in.

Take a look in 'JUCE/extras/audio plugin demo'. In there you should find a file called 'JuceDemoPlugin.jucer'. This is an Introjucer project file so open it up in The Introjucer. On the left you should see two tabs; 'Files' and 'Config'. Click on the 'Config' tab and you should see something like this.



This is where we tell The Introjucer what tools we want to use to build our project. If you want to add a new project (say you are using Visual Studio 2012), you can right click on the bit at the top where it says "Juce Demo Plugin". From there you can create projects for any of the IDEs JUCE currently supports.

Once you have a project exporter for the build tool you are using there is one thing you may need to change. Select whatever project you are going to be using on the left (I am going to select Visual Studio 2008). On the right you should now see something like this.


We need to tell our compiler where to look for the VST SDK files. We can do this by editing the VST Folder and VST3 Folder options. For bot put in the location of the 'VST3 SDK' folder you downloaded earlier. For We can then save the Introjucer project and it will update whichever project file we altered.

Now all you need to do is build the plug-in. This is done in the same way we built The Introjucer earlier.

Just a quick word of warning about the "Save Project and Open In ..." button in The Introjucer. If you have several project exports which use the same platform, such as the multiple Visual Studio Exporters shown above. This button will open the one highest up on the list. You may wish to delete the project exporters you don't need, or just drag the one you want to the top of the list.

You should now have a built plug-in hiding away somewhere. They will be in the same directories, relative to the project file, as the Introjucer executables were when we built them.

On Linux you should find a VST plug-in called 'JuceDemoPlugin.so'.

On Windows you should find a VST plug-in called 'JuceDemoPlugin.dll'.

I believe on Mac that the XCode project is set up to take the built plug-in files and install them to the system so they should appear in whatever plugin host you are using. It should have also built VST and AU versions of the plug-in.

Take this plug-in and load it up in whatever host you desire. If it works, Huzzah! You have just built a working audio plug-in from source. This means you are ready to delve into some source code and start making your own.

Have a nice day now!
Sean

P.S. There is actually a JUCE demo plugin host which is fairly nifty. You can find it in the extras folder of the JUCE download. I'm sure you can work out how to build it yourself. Have Fun!

The Introjucer


The Introjucer is a little baby IDE which allows you to easily make JUCE projects. Rather than bother with having to make separate projects for the various platforms we wish to use, we can let it do all the hard work. All we need to do is create an Audio Plug-In project in The Introjucer. This will allow us to edit all the code we need to, then export it to a project for the specific platform we wish to use.

Before we can actually start using The Introjucer we need to build it from the source. This might sound scary if you have never compiled any code before but the JUCE library is all set up to make it super easy.

Remember the folder we downloaded which contained the JUCE library. Let's look in there now. If you navigate into 'JUCE/extras/Introjucer/Builds' you should find a set of folders containing projects for several different platforms and IDEs.

Windows:

On Windows all you will need to do is open the Visual Studio Project file for the version of Visual Studio you have. Then just hit F7 and let it chug away for a bit. If F7 doesn't work use the 'Build Solution' option in the Build menu. Again this should hopefully build with no errors. When it is done there should be a new folder, called 'Debug', in the same folder as the Visual Studio project. In there will be 'Introjucer.exe'.

Mac:

I am probably not the best equipped to instruct people in programming using XCode. But I can open a project file and build it (no applause necessary). All you need to do to build The Introjucer is open the XCode project file and hit ⌘ B. Again, hopefully everything should build with no errors. When it is done you should have a folder called 'build' in the same folder as the project file. In here you can navigate to 'build/Debug', in which you should find an executable called 'Introjucer'.

Linux:

You will notice if you look in the Linux folder all there is is a text file called "Makefile". This may seem fairly unassuming little file but if you open it in a text editor you might wee yourself a little. Going into what this file actually does would take a long time and is far beyond the scope of this blog. Suffice to say it allows us to use the Make utility to build The Introjucer application.

To do this we need to open a terminal and change directory to the directory that the Makefile is in. Assuming you put the JUCE folder in '/home/JUCE' you can do this by typing the following in the terminal prompt and hitting return.
cd /home/JUCE/extras/Introjucer/Builds/Linux
We can then run Make by typing the following in the terminal prompt and hitting return.
make
Let it do its stuff and hopefully it should finish building without any errors. When it is all done there should be another folder in the same folder as the Makefile called 'build'. In there you should find an executable file called 'Introjucer'.

Congratulations You Have Just Build The Introjucer!

If everything went well you should now have an executable for The Introjucer. If you ran into problems you may well need to consult Google / the JUCE forums. 

When you first launch The Introjucer you will be asked where you want to store the JUCE modules. Just point it at wherever you saved the JUCE library.

Now we are ready to actually do some stuff with audio plug-ins!

Have a nice day now!
Sean

P.S. Some of you may be wondering why I have got you to make the debug build of The Introjucer, or maybe you won't. I'd be interested to know if any Introjucer users out the actually bother with the release build. In my humble opinion, there is very little point. All that extra effort to select the release target in whatever IDE or, even worse, having to type an extra 14 characters when using make. That's bit too much!

What You Will Need


Before we start there are several bit and bobs you will need to download and install on your machines. These are, in no particular order:


The JUCE Library: 

This is a load of code which will help a lot in your adventures in building plug-ins. Details of how to get this can be found here. For reasons of keeping up to date I would recommend you download the latest bleeding-edge version of the library. Once you have downloaded it you should have a folder called 'JUCE' which you can save where you please. I like to put it in '/home/JUCE' on my Linux machines and' C:\JUCE' on Windows (In my Mac naivety I have just left it on the Desktop, I'm sure any Mac users reading this will find a much tidier home for it).


The VST SDK:

 This is necessary in order to build VST plug-ins. It is available from the Steinberg website here. When you have downloaded this you should have a folder called 'VST3 SDK' which again you can save wherever you please.


All the Necessary Build Tools:

This will be different for each platform.

Windows:

On Windows the easiest thing to do is install Visual Studio Express. This should give you everything you need to get going. As will become apparent later, we can easily make Visual Studio projects, which use JUCE, for versions of Visual Studio from 2005 to 2012. I use the 2008 version because I am a bit stuck in my ways, if you have no such convictions just get the 2012 version. Depending on the version of Visual Studio you have and the version of Windows you have you may need to install the Windows SDK as well. 

If you are a bit of an open source warrior, you can build JUCE projects on Windows using Code::Blocks and MinGW. It's a bit more fiddly and sometimes just fails to work completely. I would also question why, if you are that dedicated to open source stuff, you are using Windows in the first place.

Mac:

For you Mac users out there you will need to install XCode. As I mentioned previously I have 
very little experience in developing on a Mac but from what I have read Apple keep deciding to 
change where things live and messing things up a bit. The last time I installed XCode I also 
had to install the Command Line Tools and the Core Audio SDK. Some good instructions on getting XCode set up properly can be found here.

Linux:

Depending on which distribution of Linux you are using you may or may not have all the necessary things installed. Here you can find a list of all the packages you will need to install if you are using Ubuntu. The one amendment I would make to that list would be to install the build-essential package rather than the g++ package. The g++ package will only install the GNU C++ compiler, whereas build-essential will install some other useful tools (such as Make, which we will need). 

For other distros (Fedora perhaps) I'm sure you can Google around to find the equivalents of these packages. If you are using some really obscure Linux distro I will assume that you are already a programming whiz and should be able to sort this out by yourself.

Some Kind of Plug-In Host:

Obviously you will need to be able to test you plug-in once you have built it. I'm sure if you are interested in building audio plug-ins you will already have a preferred plug-in host. One thing I will mention is VST Plugin Analyser, which is a very good application for Windows which allows you to test your plug-ins properly. Word has it, as well, that there may be a Mac version some time in the future.


Once you have all this you should be ready to continue.

Have a nice day now!
Sean


What is this JUCE you speak of, and why should I be excited by it?


In short, JUCE is some kind of beautiful witchcraft which will better you life in ways you never imagined.

If you would like a more serious answer, here goes. JUCE is a library which contains lots of code to help in writing applications. The reason it is so exciting for audio plug-in development, is that it allows you to take the same piece of code and compile it as any of the main plug-in formats (VST/AU/RTAS/AAX). The code should also work across platforms, so with very little effort you should be able to build a VST on Linux, Windows and Mac from the same bit of code.

This means we can spend lots of time on making sure our plug-in does what we want. JUCE then does the tedious job of making it work in a variety of formats on a variety of platforms.

If you want to read more about JUCE you can go to the website.

Have a nice day now!
Sean

Introduction


Hello,

This blog hopes to provide a simple tutorial to help people get started with building audio plug-ins using the JUCE library. Perhaps strangely, I am aiming this blog at those who may have experience with audio signal processing (say through using Max/MSP or Pure Data) but have little to no experience with C++.

In no way is this going to be a tutorial on C++ programming, plenty of those already exist. If you are looking for a good introduction to C/C++ for audio applications I thoroughly recommend The Audio Programming Book. Rather, it will attempt to explain the structure of a JUCE audio plug-in and how you can edit the basic template to make a simple plug-in.

I will, for the most part, try to keep things as cross platform as I can. I am mostly Linux/Windows based myself but I make the occasional foray into the world of Mac (mostly on poorly conceived Hackintoshes which fail to work correctly). Thankfully JUCE is masterfully written and transferring code onto other platforms is a mostly painless procedure.

Anyhow, hopefully this blog will be of use to some people out there.

Have a nice day now!
Sean