{"id":11638,"date":"2020-04-13T14:28:05","date_gmt":"2020-04-13T14:28:05","guid":{"rendered":"https:\/\/audioordeal.co.uk\/?p=11638"},"modified":"2020-04-19T10:55:08","modified_gmt":"2020-04-19T10:55:08","slug":"how-to-build-a-vst-compressor","status":"publish","type":"post","link":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/","title":{"rendered":"How to Build a VST: Compressor"},"content":{"rendered":"\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Compressors are one of the key plugins used in mixing and mastering. In this tutorial I’ll show you how to make one from scratch. At the end of this tutorial you’ll have built a working compressor with attack\/release controls and a soft\/hard knee selector.\u00a0<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

Project Setup<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Add\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Create a new audio plugin called Compressor with Projucer. Copy and paste the CircularBuffer<\/strong> files from the last tutorial into the source folder. Then add exisiting files in Projucer, select CircularBuffer.cpp<\/strong> and CircularBuffer.h<\/strong>.\u00a0<\/p>

You can download the files here.<\/p>

https:\/\/github.com\/aRycroft\/JuceTutorial5<\/span><\/a><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Add\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now select Add New CPP & Header File…<\/em> and create two files called Compressor.cpp<\/strong> and Compressor.h.<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

Compressor Class<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Open the project in your ide and head to Compressor.h.<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Add the following base code to Compressor.h<\/strong>.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t

\n\t\t\t\t
\n\t\t\t\t\t\t\t
#include \"CircularBuffer.h\"
#pragma once

class Compressor {
public:
private:
};<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Add these variables in the private section of the class.\u00a0tav\u00a0<\/em>is the averaging time used when calculating rms.<\/em><\/p>

CircularBuffer buffer;
float tav, rms, gain;\n<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

For now the compressor class will have one public function and a constructor that takes no arguments.<\/p>

Compressor();
float compressSample(float data, float thresh, float ratio, float attack, float release, float knee);<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Compressor.h\u00a0<\/strong>should look like this,<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Create definitions for the two functions in\u00a0Compressor.cpp.<\/strong><\/p>

In the Compressor()<\/b> constructor class initialise the CircularBuffer and set tav<\/em>, rms<\/em> and gain<\/em> to default values.<\/p>

buffer = CircularBuffer(150, 20);
tav = 0.01;
rms = 0;
gain = 1;<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

How Compressors Work<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

There are 3 main operations we need for a compressor.
1. Calculate how loud the incoming signal is.
2. Calculate how much to reduce the gain by.
3. Smooth the gain transition to avoid artefacts.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

1. Gain Detector<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

In the Limiter tutorial we used a peak detector to determine when to activate the limiter. This time we’re going to find the RMS\u00a0<\/strong>value of the waveform.\u00a0RMS\u00a0<\/strong>is the continous power of a waveform over time.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
rms = (1 - tav) * rms + tav * std::pow(data, 2.0f); \/\/1<\/span>
float dbRMS = 10 * std::log10(rms); \/\/2<\/span><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

\/\/1<\/span> Adjusts the rms value depending on the incoming signal.
\/\/2<\/span> Converts this value to the decibel scale.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

2. Gain reduction<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Users of this compressor will be able to decide the compression<\/a> ratio<\/strong>. This is how much the signal is compressed by once it passes a certain threshold<\/strong>.<\/p>

We convert the\u00a0ratio\u00a0<\/strong>to a slope<\/strong>, which is a decimal value.<\/p>

(Ratio) 1:4 -><\/strong> (Slope) 0.7<\/strong>
(Ratio) 1:2 -><\/strong> (Slope) 0.5<\/strong><\/p>

Next we multiply (threshold – dbRMS)<\/strong> by this slope<\/strong> factor. Then check that it is below 0 to make sure the signal is never boosted if the rms<\/strong> value is above the threshold<\/strong>.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Add\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
float slope = 1 - (1 \/ ratio); \/\/1<\/span>
float dbGain = std::min(0.0f, (slope * (thresh - dbRMS))); \/\/2<\/span>
float newGain = std::pow(10, dbGain \/ 20); \/\/3<\/span><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

\/\/1\u00a0Calculate slope from ratio<\/span>
\/\/2\u00a0Find the gain to be applied in db, and make sure it’s less than 0.0f<\/span>
\/\/3\u00a0Calculate the newGain in linear scale<\/span>
<\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

3. Smooth transition<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now we know what gain to apply to the current signal we need to smooth the transition to this new value. We do this using attack<\/strong> and release<\/strong> times.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
float coeff;
if (newGain < gain) coeff = attack; \/\/1<\/span>
else coeff = release; \/\/2<\/span>
gain = (1 - coeff) * gain + coeff * newGain; \/\/3<\/span><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

\/\/1\u00a0Declare coeff<\/strong> variable, if newGain<\/strong> is less than current gain set to attack<\/strong> variable<\/span>
\/\/2\u00a0Else set to\u00a0release<\/strong><\/span>
\/\/3 <\/span>Adjust\u00a0gain<\/strong> based on new gain and coeff<\/span>
<\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Finally we need to set and get values from our CircularBuffer<\/strong>.\u00a0<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
float compressedSample = gain * buffer.getData();\nbuffer.setData(data);\nbuffer.nextSample();\nreturn compressedSample;<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

Coding PluginProcessor<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

We now have a working Compressor class! But we aren’t doing anything with it yet.<\/p>

Head to\u00a0PluginProcessor.h<\/strong>.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
#include \"Compressor.h\" \/\/1<\/span>

Array allCompressors; \/\/2<\/span><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Include the new Compressor<\/strong> class at the top of the file, and declare a new array of Compressors<\/strong>.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now in PluginProcessor.cpp<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
\/\/Prepare To Play<\/span>\nfor (int channel = 0; channel < getNumOutputChannels(); channel++) {\n   allCompressors.add(Compressor());\n}\n\/\/Process Block\n<\/span>for (int i = 0; i < buffer.getNumSamples(); i++) {\n   for (int channel = 0; channel < getTotalNumOutputChannels(); channel++) {
auto* data = buffer.getWritePointer(channel);\n Compressor* comp = &allCompressors.getReference(channel); \/\/1<\/span>\n data[i] = comp->compressSample(data[i], -30.0f, 20.0f, 0.01f, 0.4f, 0.0f); \/\/2<\/span>
}\n}<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

In\u00a0PrepareToPlay<\/strong> create an array of Compressors.<\/p>

In\u00a0ProcessBlock <\/strong>loop through samples and channels.
\/\/ 1 <\/span>Get reference Compressor<\/strong> for the current channel.
\/\/ 2 <\/span>Calculate the compressed samples with some initial values passed into the compressSample<\/em> function.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Build your plugin now and you should hear the incoming audio being compressed. Try changing the values passed to the compressor class, then rebuilding to hear the difference.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

GUI<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

For this plugin we’re going to make a GUI\u00a0using ValueStateTree. <\/strong>As of April 2020 I believe this is the best way to make a pluginGUI in Juce.<\/p>

We’ll create a ValueStateTree<\/strong> in our plugin and let the Editor access and edit the tree. The PluginProcessor will only be able to read values from the tree. Using a ValueStateTree <\/strong>means we can easily save and recall the state of the plugin, as well as add parameter automation in a DAW.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Creating\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
\/\/PluginProcessor.h<\/span>\nAudioProcessorValueTreeState state;\n\/\/PluginProcessor.cpp\n<\/span>,
state(*this, nullptr, Identifier(\"params\"), {

}
)<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Declare an\u00a0AudioProcessorValueTreeState <\/strong>called state in PluginProcessor.h\u00a0<\/strong>then add a constructor in the AudioProcessor Constructor list.<\/p>

We’ll add the parameters to the StateTree in this constructor.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Add\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
std::make_unique<AudioParameterFloat>(
\"thresh\",
\"Threshold\",
NormalisableRange<float>(-60.0f, 20.0f, 0.01f),
10.0f),<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

This creates a unique pointer to an\u00a0AudioParameterFloat\u00a0<\/strong>with
identifier “thresh”,
name “Threshold”,
numberRange betwwen -60.0f -> 20.0f with spacing 0.01f,
default value of 10.0f<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Add the following AudioParameterFloat\u00a0<\/strong>parameters using the same method.<\/p>

“ratio” 1.0f -> 20.0f
“knee” 0.0f -> 24.0f
“attack” 0.01f -> 500.0f
“release” 0.01f -> 2000.0f<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
\u00a0std::make_unique(
\"thresh\",
\"Threshold\",
NormalisableRange(-60.0f, 20.0f, 0.01f),
10.0f),
std::make_unique(
\"ratio\",
\"Ratio\",
NormalisableRange(1.0f, 20.0f, 0.01f),
2.0f),
std::make_unique(
\"knee\",
\"KneeWidth\",
NormalisableRange(0.0f, 24.0f, 0.01f),
0.0f),
std::make_unique(
\"attack\",
\"Attack\",
NormalisableRange(0.01f, 500.0, 0.01f),
100.0f),
std::make_unique(
\"release\",
\"Release\",
NormalisableRange(0.01f, 2000.0f, 0.01f),
500.0f)<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now our statetree is setup in PluginProcessor\u00a0<\/strong>we need to pass it into\u00a0PluginEditor.<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Head to\u00a0PluginEditor.h<\/strong> and declare a pointer to an\u00a0AudioProcessorValueTreeState<\/strong> called params.<\/p>

Also change the constructor to receive an AudioProcessorValueTreeState\u00a0<\/strong>object.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now in\u00a0PluginEditor.cpp<\/strong> edit the constructor to receive the state and point params<\/strong> to the state object.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Back in\u00a0PluginProcessor.cpp\u00a0<\/strong>change the editor constructor to include passing the statetree.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now we’ve passed the stateTree to the editor we need to create some sliders to control the values in the tree.<\/p>

In\u00a0PluginEditor.h<\/strong>\u00a0create this typedef at the top of the file.<\/p>

typedef AudioProcessorValueTreeState::SliderAttachment SliderAttachment;<\/em><\/p>

This saves writing AudioProcessorValueTreeState::SliderAttachment everytime we want to use it.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Declare these sliders, labels and sliderattachments in PluginEditor.h<\/strong>. A slider attachment will allow values in the stateTree to be changed by a slider.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t

\n\t\t\t\t
\n\t\t\t\t\t\t\t
Slider threshSlider, slopeSlider, kneeSlider, attackSlider, releaseSlider;
Label threshLabel, slopeLabel, kneeLabel, attackLabel, releaseLabel;
std::unique_ptr<SliderAttachment> threshAttachment, slopeAttachment, kneeAttachment, attackAttachment, releaseAttachment;<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Add the following function to your\u00a0PluginEditor,\u00a0<\/strong>you can declare it as private in the header file as it won’t be called anywhere else.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
void CompressorAudioProcessorEditor::addSlider(String name, String labelText, Slider& slider, Label& label, std::unique_ptr& attachment) {
addAndMakeVisible(slider);
attachment.reset(new SliderAttachment(params, name, slider));
label.setText(labelText, dontSendNotification);
label.attachToComponent(&slider, true);
addAndMakeVisible(label);
}<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

We’ll use this to quickly add sliders, labels and attachments to the GUI.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now we can write this code in the Editor constructor to add all the sliders we want to the GUI and attach them to the stateTree.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t

\n\t\t\t\t
\n\t\t\t\t\t\t\t
addSlider(\"thresh\", \"Threshold\", threshSlider, threshLabel, threshAttachment);
addSlider(\"ratio\", \"Ratio\", slopeSlider, slopeLabel, slopeAttachment);
addSlider(\"knee\", \"Knee\", kneeSlider, kneeLabel, kneeAttachment);
addSlider(\"attack\", \"Attack\", attackSlider, attackLabel, attackAttachment);
addSlider(\"release\", \"Release\", releaseSlider, releaseLabel, releaseAttachment);<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Finally set the bounds of the slider components in the\u00a0resized()\u00a0<\/strong>function.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
threshSlider.setBounds(100, 0, 200, 50);
slopeSlider.setBounds(100, 50, 200, 50);
kneeSlider.setBounds(100, 100, 200, 50);
attackSlider.setBounds(100, 150, 200, 50);
releaseSlider.setBounds(100, 200, 200, 50);<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now we’re finished coding the PluginEditor<\/strong> but we’re not using the values in\u00a0PluginProcessor.<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
\/\/PluginProcessor.h
float* threshParam, *slopeParam, *kneeParam, *attackParam, *releaseParam;<\/span>
\/\/PluginProcessor.cpp -> PrepareToPlay
<\/span>threshParam = state.getRawParameterValue(\"thresh\");
scopeParam = state.getRawParameterValue(\"ratio\");
kneeParam = state.getRawParameterValue(\"knee\");
attackParam = state.getRawParameterValue(\"attack\");
releaseParam = state.getRawParameterValue(\"release\");<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Declare these pointers in the header file and set them to values in the stateTree in prepareToPlay.<\/p>

These pointers don’t directly store the float value. They point to the memory address where the value is stored.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Now we can pass these values into our CompressSample function. We can do some maths on the attack and release times to convert from seconds to milliseconds and from a linear to time scale.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
float at = 1 - std::pow(MathConstants::euler, ((1 \/ getSampleRate()) * -2.2f) \/ (*attackParam \/ 1000.0f));
float rt = 1 - std::pow(MathConstants::euler, ((1 \/ getSampleRate()) * -2.2f) \/ (*releaseParam \/ 1000.0f));

for (int i = 0; i < buffer.getNumSamples(); i++) {
for (int channel = 0; channel < getTotalNumOutputChannels(); channel++) {
auto* data = buffer.getWritePointer(channel);
Compressor* comp = &allCompressors.getReference(channel);
data[i] = comp->compressSample(data[i], *threshParam, *slopeParam, at, rt, *kneeParam);
}
}<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

The last thing we’re going to with the gui is add code to save and recall the StateTree we just created. We can do this by changing two functions in\u00a0PluginProcessor.cpp.<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
void CompressorAudioProcessor::getStateInformation(MemoryBlock& destData)
{
auto stateTree = state.copyState();
std::unique_ptr<XmlElement> xml(stateTree.createXml());
copyXmlToBinary(*xml, destData);
}

void CompressorAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
{
std::unique_ptr<XmlElement> xmlState(getXmlFromBinary(data, sizeInBytes));
if (xmlState.get() != nullptr && xmlState->hasTagName(state.state.getType())) {
state.replaceState(ValueTree::fromXml(*xmlState));
}
}<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

At this point we’ve got a fully working Compressor, with parameters that are saved when you stop using the plugin and recalled when you come back.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t

Adding a Soft Knee (OPTIONAL)<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

The compressor we built so far had a hard knee. That means when an RMS is detected above the threshold, the ratio is set instantaneously to the new ratio. By introducing an area where if an RMS is detected inside it the slope is changed along a curve, we can create a soft knee. This is regarded as giving a compressor a more natural sound, it has a subtle effect on the sound.<\/p>

There are many ways to interpolate between two points but we’re going to use lagrange interpolation.<\/p>

First off we’re going to write a function to do this in\u00a0Compressor.cpp.<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
float Compressor::interpolatePoints(float* xPoints, float* yPoints, float detectedValue) {
float result = 0.0f;
int n = 2;

\u00a0for (int i = 0; i < n; i++){
float term = 1.0f;
for (int j = 0; j < n; j++{
if (j != i) {
term *= (detectedValue - xPoints[j]) \/ (xPoints[i] - xPoints[j]);
}
}
result += term * yPoints[i];
}
return result;
}<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Don’t worry about understanding how this function works too much, all you need to know is that it takes an array of two xpoints, two y points and approximates a value between them.\u00a0<\/p>

This value will replace our slope<\/strong> value.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t
if (knee > 0 && dbRMS > (thresh - knee \/ 2.0) && dbRMS < (thresh + knee \/ 2.0)) {
\u00a0 \u00a0float kneeBottom = thresh - knee \/\u00a0 \u00a0 2.0, kneeTop = thresh + knee \/ 2.0;
float xPoints[2], yPoints[2];
xPoints[0] = kneeBottom;
xPoints[1] = kneeTop;
xPoints[1] = std::fmin(0.0f, kneeTop);
yPoints[0] = 0.0f;
yPoints[1] = slope;
slope = interpolatePoints(&xPoints[0], &yPoints[0], thresh);
thresh = kneeBottom;
}<\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

This block of code sets up some variables for the interpolation function we just wrote.<\/p>

First it checks the current\u00a0rms\u00a0<\/strong>value is in the knee zone, between thresh – knee \/ 2.0<\/em> and thresh + knee \/ 2.0.<\/em><\/p>

Then we make two arrays of points,\u00a0
xPoints holds the db values of the bottom and top of the knee region.
yPoints hold the slope values.<\/p>

Once these arrays are set up we interpolate a new slope value and set the threshold of the compressor to the lower knee value.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Rebuild the plugin and you should see\/hear a difference when you change the knee slider. Don’t worry if it doesn’t sound drastically different:)<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

That’s the end of this compressor tutorial, code can be found at the following link.<\/p>

https:\/\/github.com\/aRycroft\/JuceTutorial6<\/span><\/a><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"

Compressors are one of the key plugins used in mixing and mastering. In this tutorial…<\/p>\n","protected":false},"author":5,"featured_media":11696,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[5],"tags":[1399,2126],"jetpack_publicize_connections":[],"yoast_head":"\nHow to Build a VST: Compressor<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Build a VST: Compressor\" \/>\n<meta property=\"og:description\" content=\"Compressors are one of the key plugins used in mixing and mastering. In this tutorial...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/\" \/>\n<meta property=\"og:site_name\" content=\"Audio Ordeal\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/audioordeal\/\" \/>\n<meta property=\"article:published_time\" content=\"2020-04-13T14:28:05+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-04-19T10:55:08+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1366\" \/>\n\t<meta property=\"og:image:height\" content=\"768\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Alex Rycroft\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@audioordeal\" \/>\n<meta name=\"twitter:site\" content=\"@audioordeal\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alex Rycroft\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/\"},\"author\":{\"name\":\"Alex Rycroft\",\"@id\":\"https:\/\/audioordeal.co.uk\/#\/schema\/person\/65b8c997e71b94e5b808a95c59b915dd\"},\"headline\":\"How to Build a VST: Compressor\",\"datePublished\":\"2020-04-13T14:28:05+00:00\",\"dateModified\":\"2020-04-19T10:55:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/\"},\"wordCount\":1165,\"commentCount\":6,\"publisher\":{\"@id\":\"https:\/\/audioordeal.co.uk\/#organization\"},\"image\":{\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1\",\"keywords\":[\"compressor\",\"JUCE\"],\"articleSection\":[\"Production\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/\",\"url\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/\",\"name\":\"How to Build a VST: Compressor\",\"isPartOf\":{\"@id\":\"https:\/\/audioordeal.co.uk\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1\",\"datePublished\":\"2020-04-13T14:28:05+00:00\",\"dateModified\":\"2020-04-19T10:55:08+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#primaryimage\",\"url\":\"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1\",\"width\":1366,\"height\":768},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/audioordeal.co.uk\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Build a VST: Compressor\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/audioordeal.co.uk\/#website\",\"url\":\"https:\/\/audioordeal.co.uk\/\",\"name\":\"Audio Ordeal\",\"description\":\"Music Production, Podcast, and DJ Tutorials\",\"publisher\":{\"@id\":\"https:\/\/audioordeal.co.uk\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/audioordeal.co.uk\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/audioordeal.co.uk\/#organization\",\"name\":\"Audio Ordeal\",\"url\":\"https:\/\/audioordeal.co.uk\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/audioordeal.co.uk\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2018\/12\/20264578_449563855429575_294261634867900376_n.png?fit=960%2C960&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2018\/12\/20264578_449563855429575_294261634867900376_n.png?fit=960%2C960&ssl=1\",\"width\":960,\"height\":960,\"caption\":\"Audio Ordeal\"},\"image\":{\"@id\":\"https:\/\/audioordeal.co.uk\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/audioordeal\/\",\"https:\/\/x.com\/audioordeal\",\"https:\/\/www.instagram.com\/audioordeal\/\",\"https:\/\/www.youtube.com\/channel\/UCgF1D5SH0zrnq30JX4QU0dg?view_as=subscriber\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/audioordeal.co.uk\/#\/schema\/person\/65b8c997e71b94e5b808a95c59b915dd\",\"name\":\"Alex Rycroft\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/audioordeal.co.uk\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/dcf4b4c69b617f9e1e8349e83eb0bf33?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/dcf4b4c69b617f9e1e8349e83eb0bf33?s=96&d=identicon&r=g\",\"caption\":\"Alex Rycroft\"},\"description\":\"Producer, DJ, Musician and Audio Programmer. Writing tutorials for Audio Ordeal about using JUCE and Max for Live.\",\"url\":\"https:\/\/audioordeal.co.uk\/author\/alexrycroft\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Build a VST: Compressor","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/","og_locale":"en_US","og_type":"article","og_title":"How to Build a VST: Compressor","og_description":"Compressors are one of the key plugins used in mixing and mastering. In this tutorial...","og_url":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/","og_site_name":"Audio Ordeal","article_publisher":"https:\/\/www.facebook.com\/audioordeal\/","article_published_time":"2020-04-13T14:28:05+00:00","article_modified_time":"2020-04-19T10:55:08+00:00","og_image":[{"width":1366,"height":768,"url":"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1","type":"image\/jpeg"}],"author":"Alex Rycroft","twitter_card":"summary_large_image","twitter_creator":"@audioordeal","twitter_site":"@audioordeal","twitter_misc":{"Written by":"Alex Rycroft","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#article","isPartOf":{"@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/"},"author":{"name":"Alex Rycroft","@id":"https:\/\/audioordeal.co.uk\/#\/schema\/person\/65b8c997e71b94e5b808a95c59b915dd"},"headline":"How to Build a VST: Compressor","datePublished":"2020-04-13T14:28:05+00:00","dateModified":"2020-04-19T10:55:08+00:00","mainEntityOfPage":{"@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/"},"wordCount":1165,"commentCount":6,"publisher":{"@id":"https:\/\/audioordeal.co.uk\/#organization"},"image":{"@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1","keywords":["compressor","JUCE"],"articleSection":["Production"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/","url":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/","name":"How to Build a VST: Compressor","isPartOf":{"@id":"https:\/\/audioordeal.co.uk\/#website"},"primaryImageOfPage":{"@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#primaryimage"},"image":{"@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1","datePublished":"2020-04-13T14:28:05+00:00","dateModified":"2020-04-19T10:55:08+00:00","breadcrumb":{"@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#primaryimage","url":"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1","contentUrl":"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1","width":1366,"height":768},{"@type":"BreadcrumbList","@id":"https:\/\/audioordeal.co.uk\/how-to-build-a-vst-compressor\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/audioordeal.co.uk\/"},{"@type":"ListItem","position":2,"name":"How to Build a VST: Compressor"}]},{"@type":"WebSite","@id":"https:\/\/audioordeal.co.uk\/#website","url":"https:\/\/audioordeal.co.uk\/","name":"Audio Ordeal","description":"Music Production, Podcast, and DJ Tutorials","publisher":{"@id":"https:\/\/audioordeal.co.uk\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/audioordeal.co.uk\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/audioordeal.co.uk\/#organization","name":"Audio Ordeal","url":"https:\/\/audioordeal.co.uk\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/audioordeal.co.uk\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2018\/12\/20264578_449563855429575_294261634867900376_n.png?fit=960%2C960&ssl=1","contentUrl":"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2018\/12\/20264578_449563855429575_294261634867900376_n.png?fit=960%2C960&ssl=1","width":960,"height":960,"caption":"Audio Ordeal"},"image":{"@id":"https:\/\/audioordeal.co.uk\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/audioordeal\/","https:\/\/x.com\/audioordeal","https:\/\/www.instagram.com\/audioordeal\/","https:\/\/www.youtube.com\/channel\/UCgF1D5SH0zrnq30JX4QU0dg?view_as=subscriber"]},{"@type":"Person","@id":"https:\/\/audioordeal.co.uk\/#\/schema\/person\/65b8c997e71b94e5b808a95c59b915dd","name":"Alex Rycroft","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/audioordeal.co.uk\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/dcf4b4c69b617f9e1e8349e83eb0bf33?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dcf4b4c69b617f9e1e8349e83eb0bf33?s=96&d=identicon&r=g","caption":"Alex Rycroft"},"description":"Producer, DJ, Musician and Audio Programmer. Writing tutorials for Audio Ordeal about using JUCE and Max for Live.","url":"https:\/\/audioordeal.co.uk\/author\/alexrycroft\/"}]}},"featured_image_urls":{"full":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1",1366,768,false],"thumbnail":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?resize=150%2C150&ssl=1",150,150,true],"medium":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=300%2C169&ssl=1",300,169,true],"medium_large":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=640%2C360&ssl=1",640,360,true],"large":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=640%2C360&ssl=1",640,360,true],"1536x1536":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1",1366,768,true],"2048x2048":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1",1366,768,true],"newsphere-slider-full":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?resize=1280%2C720&ssl=1",1280,720,true],"newsphere-featured":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1024%2C576&ssl=1",1024,576,true],"newsphere-medium":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?resize=720%2C380&ssl=1",720,380,true],"woocommerce_thumbnail":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?resize=300%2C300&ssl=1",300,300,true],"woocommerce_single":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=600%2C337&ssl=1",600,337,true],"woocommerce_gallery_thumbnail":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?resize=100%2C100&ssl=1",100,100,true],"ppec_logo_image_size":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=107%2C60&ssl=1",107,60,true],"ppec_header_image_size":["https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=160%2C90&ssl=1",160,90,true]},"author_info":{"info":["Alex Rycroft"]},"category_info":"<a href=\"https:\/\/audioordeal.co.uk\/category\/production\/\" rel=\"category tag\">Production<\/a>","tag_info":"Production","comment_count":"6","jetpack_featured_media_url":"https:\/\/i0.wp.com\/audioordeal.co.uk\/wp-content\/uploads\/2020\/04\/compressor-juce.jpg?fit=1366%2C768&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pawm8q-31I","jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/posts\/11638"}],"collection":[{"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/comments?post=11638"}],"version-history":[{"count":14,"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/posts\/11638\/revisions"}],"predecessor-version":[{"id":11704,"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/posts\/11638\/revisions\/11704"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/media\/11696"}],"wp:attachment":[{"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/media?parent=11638"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/categories?post=11638"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/audioordeal.co.uk\/wp-json\/wp\/v2\/tags?post=11638"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}