annotate effects/compressor/Source/PluginProcessor.cpp @ 1:04e171d2a747 tip

JUCE 4 compatible. Standardised paths on Mac: modules '../../juce/modules'; VST folder '~/SDKs/vstsdk2.4' (JUCE default). Replaced deprecated 'getSampleData(channel)'; getToggleState(...); setToggleState(...); setSelectedId(...). Removed unused variables. Ignore JUCE code and build files.
author Brecht De Man <b.deman@qmul.ac.uk>
date Sun, 22 Nov 2015 15:23:40 +0000
parents e32fe563e124
children
rev   line source
andrewm@0 1 /*
andrewm@0 2 This code accompanies the textbook:
andrewm@0 3
andrewm@0 4 Digital Audio Effects: Theory, Implementation and Application
andrewm@0 5 Joshua D. Reiss and Andrew P. McPherson
andrewm@0 6
andrewm@0 7 ---
andrewm@0 8
andrewm@0 9 Compressor: dynamic range compression effect
andrewm@0 10 See textbook Chapter 6: Dynamics Processing
andrewm@0 11
andrewm@0 12 Code by Joshua Reiss, Brecht de Man and Andrew McPherson
andrewm@0 13
andrewm@0 14 ---
andrewm@0 15
andrewm@0 16 This program is free software: you can redistribute it and/or modify
andrewm@0 17 it under the terms of the GNU General Public License as published by
andrewm@0 18 the Free Software Foundation, either version 3 of the License, or
andrewm@0 19 (at your option) any later version.
andrewm@0 20
andrewm@0 21 This program is distributed in the hope that it will be useful,
andrewm@0 22 but WITHOUT ANY WARRANTY; without even the implied warranty of
andrewm@0 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
andrewm@0 24 GNU General Public License for more details.
andrewm@0 25
andrewm@0 26 You should have received a copy of the GNU General Public License
andrewm@0 27 along with this program. If not, see <http://www.gnu.org/licenses/>.
andrewm@0 28 */
andrewm@0 29
andrewm@0 30 #include "PluginProcessor.h"
andrewm@0 31 #include "PluginEditor.h"
andrewm@0 32 CompressorAudioProcessor::CompressorAudioProcessor()
andrewm@0 33 // Initializer List
andrewm@0 34 :
andrewm@0 35 inputBuffer(1,1),
andrewm@0 36 nhost(0)
andrewm@0 37 {
andrewm@0 38 lastUIWidth = 850;
andrewm@0 39 lastUIHeight = 650;
andrewm@0 40 lastPosInfo.resetToDefault();
andrewm@0 41 }
andrewm@0 42 CompressorAudioProcessor::~CompressorAudioProcessor()
andrewm@0 43 {
andrewm@0 44 }
andrewm@0 45 //==============================================================================
andrewm@0 46 void CompressorAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
andrewm@0 47 {
andrewm@0 48 // Use this method as the place to do any pre-playback initialisation that you need.
andrewm@0 49 M = round(getNumInputChannels()/2);
andrewm@0 50 samplerate = (float)getSampleRate();
andrewm@0 51 bufferSize = getBlockSize();
andrewm@0 52 // Allocate a lot of dynamic memory here
andrewm@0 53 x_g .allocate(bufferSize, true);
andrewm@0 54 x_l .allocate(bufferSize, true);
andrewm@0 55 y_g .allocate(bufferSize, true);
andrewm@0 56 y_l .allocate(bufferSize, true);
andrewm@0 57 c .allocate(bufferSize, true);
andrewm@0 58 yL_prev=0;
andrewm@0 59 autoTime = false;
andrewm@0 60 compressorONOFF = false;
andrewm@0 61 resetAll();
andrewm@0 62 }
andrewm@0 63 void CompressorAudioProcessor::releaseResources()
andrewm@0 64 {
andrewm@0 65 // When playback stops, you can use this to free up any spare memory, etc.
andrewm@0 66 }
andrewm@0 67 void CompressorAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
andrewm@0 68 {
andrewm@0 69 if (compressorONOFF)
andrewm@0 70 {
andrewm@0 71 inputBuffer.setSize(M,bufferSize);
andrewm@0 72 inputBuffer.clear();
andrewm@0 73 for (int m = 0 ; m < M ; ++m)
andrewm@0 74 {
andrewm@0 75 if ( (threshold< 0) )
andrewm@0 76 {
andrewm@0 77 inputBuffer.clear(m,0,bufferSize);
andrewm@0 78 // Mix down left-right to analyse the input
andrewm@0 79 inputBuffer.addFrom(m,0,buffer,m*2,0,bufferSize,0.5);
andrewm@0 80 inputBuffer.addFrom(m,0,buffer,m*2+1,0,bufferSize,0.5);
andrewm@0 81 // compression : calculates the control voltage
andrewm@0 82 compressor(inputBuffer,m);
andrewm@0 83 // apply control voltage to the audio signal
andrewm@0 84 for (int i = 0 ; i < bufferSize ; ++i)
andrewm@0 85 {
b@1 86 buffer.getWritePointer(2*m+0)[i] *= c[i];
b@1 87 buffer.getWritePointer(2*m+1)[i] *= c[i];
andrewm@0 88 }
andrewm@0 89 inputBuffer.clear(m,0,bufferSize);
andrewm@0 90 // Mix down left-right to analyse the output
andrewm@0 91 inputBuffer.addFrom(m,0,buffer,m*2,0,bufferSize,0.5);
andrewm@0 92 inputBuffer.addFrom(m,0,buffer,m*2+1,0,bufferSize,0.5);
andrewm@0 93 }
andrewm@0 94 }
andrewm@0 95 }
andrewm@0 96 }
andrewm@0 97 // compressor functions
andrewm@0 98 void CompressorAudioProcessor::compressor(AudioSampleBuffer &buffer, int m)
andrewm@0 99 {
andrewm@0 100 alphaAttack = exp(-1/(0.001 * samplerate * tauAttack));
andrewm@0 101 alphaRelease= exp(-1/(0.001 * samplerate * tauRelease));
andrewm@0 102 for (int i = 0 ; i < bufferSize ; ++i)
andrewm@0 103 {
andrewm@0 104 //Level detection- estimate level using peak detector
b@1 105 if (fabs(buffer.getWritePointer(m)[i]) < 0.000001) x_g[i] =-120;
b@1 106 else x_g[i] =20*log10(fabs(buffer.getWritePointer(m)[i]));
andrewm@0 107 //Gain computer- static apply input/output curve
andrewm@0 108 if (x_g[i] >= threshold) y_g[i] = threshold+ (x_g[i] - threshold) / ratio;
andrewm@0 109 else y_g[i] = x_g[i];
andrewm@0 110 x_l[i] = x_g[i] - y_g[i];
andrewm@0 111 //Ballistics- smoothing of the gain
andrewm@0 112 if (x_l[0]>yL_prev) y_l[i]=alphaAttack * yL_prev+(1 - alphaAttack ) * x_l[i] ;
andrewm@0 113 else y_l[i]=alphaRelease* yL_prev+(1 - alphaRelease) * x_l[i] ;
andrewm@0 114 //find control
andrewm@0 115 c[i] = pow(10,(makeUpGain - y_l[i])/20);
andrewm@0 116 yL_prev=y_l[i];
andrewm@0 117 }
andrewm@0 118 }
andrewm@0 119 template <class T> const T& CompressorAudioProcessor::max( const T& a, const T& b )
andrewm@0 120 {
andrewm@0 121 return (a < b) ? b : a;
andrewm@0 122 }
andrewm@0 123 void CompressorAudioProcessor::resetAll()
andrewm@0 124 {
andrewm@0 125 tauAttack=0;tauRelease = 0;
andrewm@0 126 alphaAttack=0;alphaRelease = 0;
andrewm@0 127 threshold = 0;
andrewm@0 128 ratio= 1;
andrewm@0 129 makeUpGain= 0;
andrewm@0 130 yL_prev=0;
andrewm@0 131 for (int i = 0 ; i < bufferSize ; ++i)
andrewm@0 132 {
andrewm@0 133 x_g[i] = 0; y_g[i] = 0;
andrewm@0 134 x_l[i] = 0; y_l[i] = 0;
andrewm@0 135 c[i] = 0;
andrewm@0 136 }
andrewm@0 137 }
andrewm@0 138 //////////////////////////////////////////////
andrewm@0 139 float CompressorAudioProcessor::getThreshold()
andrewm@0 140 {
andrewm@0 141 return threshold;
andrewm@0 142 }
andrewm@0 143 float CompressorAudioProcessor::getRatio()
andrewm@0 144 {
andrewm@0 145 return ratio;
andrewm@0 146 }
andrewm@0 147 float CompressorAudioProcessor::getGain()
andrewm@0 148 {
andrewm@0 149 return makeUpGain;//problem?
andrewm@0 150 }
andrewm@0 151 float CompressorAudioProcessor::getAttackTime()
andrewm@0 152 {
andrewm@0 153 return tauAttack;
andrewm@0 154 }
andrewm@0 155 float CompressorAudioProcessor::getReleaseTime()
andrewm@0 156 {
andrewm@0 157 return tauRelease;
andrewm@0 158 }
andrewm@0 159 ////////////////////////////////////////////////////////
andrewm@0 160 void CompressorAudioProcessor::setThreshold(float T)
andrewm@0 161 {
andrewm@0 162 threshold= T;
andrewm@0 163 }
andrewm@0 164 void CompressorAudioProcessor::setGain(float G)
andrewm@0 165 {
andrewm@0 166 makeUpGain= G;
andrewm@0 167 }
andrewm@0 168 void CompressorAudioProcessor::setRatio(float R)
andrewm@0 169 {
andrewm@0 170 ratio= R;
andrewm@0 171 }
andrewm@0 172 void CompressorAudioProcessor::setAttackTime(float A)
andrewm@0 173 {
andrewm@0 174 tauAttack = A;
andrewm@0 175 }
andrewm@0 176 void CompressorAudioProcessor::setReleaseTime(float R)
andrewm@0 177 {
andrewm@0 178 tauRelease = R;
andrewm@0 179 }
andrewm@0 180 bool CompressorAudioProcessor::hasEditor() const
andrewm@0 181 {
andrewm@0 182 return true; // (change this to false if you choose to not supply an editor)
andrewm@0 183 }
andrewm@0 184 AudioProcessorEditor* CompressorAudioProcessor::createEditor()
andrewm@0 185 {
andrewm@0 186 return new CompressorAudioProcessorEditor (this);
andrewm@0 187 }
andrewm@0 188 //==============================================================================
andrewm@0 189 void CompressorAudioProcessor::getStateInformation (MemoryBlock& destData)
andrewm@0 190 {
andrewm@0 191 //Use this to store your parameters in memory block, either as raw data, or use XML or ValueTree classes as intermediaries to make it easy to save and load complex data.
andrewm@0 192 }
andrewm@0 193 void CompressorAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
andrewm@0 194 {
andrewm@0 195 // Use this to restore your parameters from this memory block, whose contents will have been created by the getStateInformation() call.
andrewm@0 196 }
andrewm@0 197 // This creates new instances of the plugin..
andrewm@0 198 AudioProcessor* JUCE_CALLTYPE createPluginFilter()
andrewm@0 199 {
andrewm@0 200 return new CompressorAudioProcessor();
andrewm@0 201 }
andrewm@0 202 int CompressorAudioProcessor::round(float inn)
andrewm@0 203 {
andrewm@0 204 if (inn > 0) return (int) (inn + 0.5);
andrewm@0 205 else return (int) (inn - 0.5);
andrewm@0 206 }
andrewm@0 207 const String CompressorAudioProcessor::getName() const
andrewm@0 208 {
andrewm@0 209 return JucePlugin_Name;
andrewm@0 210 }
andrewm@0 211 int CompressorAudioProcessor::getNumParameters()
andrewm@0 212 {
andrewm@0 213 return 0;
andrewm@0 214 }
andrewm@0 215 float CompressorAudioProcessor::getParameter (int index)
andrewm@0 216 {
andrewm@0 217 return 0.0f;
andrewm@0 218 }
andrewm@0 219 void CompressorAudioProcessor::setParameter (int index, float newValue)
andrewm@0 220 {
andrewm@0 221 }
andrewm@0 222 const String CompressorAudioProcessor::getParameterName (int index)
andrewm@0 223 {
andrewm@0 224 return String::empty;
andrewm@0 225 }
andrewm@0 226 const String CompressorAudioProcessor::getParameterText (int index)
andrewm@0 227 {
andrewm@0 228 return String::empty;
andrewm@0 229 }
andrewm@0 230 const String CompressorAudioProcessor::getInputChannelName (int channelIndex) const
andrewm@0 231 {
andrewm@0 232 return String (channelIndex + 1);
andrewm@0 233 }
andrewm@0 234 const String CompressorAudioProcessor::getOutputChannelName (int channelIndex) const
andrewm@0 235 {
andrewm@0 236 return String (channelIndex + 1);
andrewm@0 237 }
andrewm@0 238 bool CompressorAudioProcessor::isInputChannelStereoPair (int index) const
andrewm@0 239 {
andrewm@0 240 return true;
andrewm@0 241 }
andrewm@0 242 bool CompressorAudioProcessor::isOutputChannelStereoPair (int index) const
andrewm@0 243 {
andrewm@0 244 return true;
andrewm@0 245 }
andrewm@0 246 bool CompressorAudioProcessor::silenceInProducesSilenceOut() const
andrewm@0 247 {
andrewm@0 248 #if JucePlugin_SilenceInProducesSilenceOut
andrewm@0 249 return true;
andrewm@0 250 #else
andrewm@0 251 return false;
andrewm@0 252 #endif
andrewm@0 253 }
andrewm@0 254
andrewm@0 255 double CompressorAudioProcessor::getTailLengthSeconds() const
andrewm@0 256 {
andrewm@0 257 return 0.0;
andrewm@0 258 }
andrewm@0 259 bool CompressorAudioProcessor::acceptsMidi() const
andrewm@0 260 {
andrewm@0 261 #if JucePlugin_WantsMidiInput
andrewm@0 262 return true;
andrewm@0 263 #else
andrewm@0 264 return false;
andrewm@0 265 #endif
andrewm@0 266 }
andrewm@0 267 bool CompressorAudioProcessor::producesMidi() const
andrewm@0 268 {
andrewm@0 269 #if JucePlugin_ProducesMidiOutput
andrewm@0 270 return true;
andrewm@0 271 #else
andrewm@0 272 return false;
andrewm@0 273 #endif
andrewm@0 274 }
andrewm@0 275 int CompressorAudioProcessor::getNumPrograms()
andrewm@0 276 {
andrewm@0 277 return 0;
andrewm@0 278 }
andrewm@0 279 int CompressorAudioProcessor::getCurrentProgram()
andrewm@0 280 {
andrewm@0 281 return 0;
andrewm@0 282 }
andrewm@0 283 void CompressorAudioProcessor::setCurrentProgram (int index)
andrewm@0 284 {
andrewm@0 285 }
andrewm@0 286 const String CompressorAudioProcessor::getProgramName (int index)
andrewm@0 287 {
andrewm@0 288 return String::empty;
andrewm@0 289 }
andrewm@0 290 void CompressorAudioProcessor::changeProgramName (int index, const String& newName)
andrewm@0 291 {
andrewm@0 292 }