annotate effects/distortion/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 Distortion: distortion effect using different characteristic curves
andrewm@0 10 See textbook Chapter 7: Overdrive, Distortion and Fuzz
andrewm@0 11
andrewm@0 12 Code by Brecht De Man, Joshua Reiss and Andrew McPherson
andrewm@0 13
andrewm@0 14 When using this code (or a modified version thereof), please cite:
andrewm@0 15
andrewm@0 16 Brecht De Man and Joshua D. Reiss, "Adaptive Control of Amplitude
andrewm@0 17 Distortion Effects," 53rd Conference of the Audio Engineering Society,
andrewm@0 18 2014.
andrewm@0 19
andrewm@0 20 ---
andrewm@0 21
andrewm@0 22 This program is free software: you can redistribute it and/or modify
andrewm@0 23 it under the terms of the GNU General Public License as published by
andrewm@0 24 the Free Software Foundation, either version 3 of the License, or
andrewm@0 25 (at your option) any later version.
andrewm@0 26
andrewm@0 27 This program is distributed in the hope that it will be useful,
andrewm@0 28 but WITHOUT ANY WARRANTY; without even the implied warranty of
andrewm@0 29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
andrewm@0 30 GNU General Public License for more details.
andrewm@0 31
andrewm@0 32 You should have received a copy of the GNU General Public License
andrewm@0 33 along with this program. If not, see <http://www.gnu.org/licenses/>.
andrewm@0 34 */
andrewm@0 35
andrewm@0 36 #include "PluginProcessor.h"
andrewm@0 37 #include "PluginEditor.h"
andrewm@0 38
andrewm@0 39 #if JUCE_INTEL
andrewm@0 40 #define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0;
andrewm@0 41 #else
andrewm@0 42 #define JUCE_SNAP_TO_ZERO(n)
andrewm@0 43 #endif
andrewm@0 44
andrewm@0 45 DistortionAudioProcessor::DistortionAudioProcessor()
andrewm@0 46 :
andrewm@0 47 _numChannels (1)
andrewm@0 48 ,_numSamples (1) // dummy - will be set in prepareToPlay
andrewm@0 49 ,_sampleRate (1) // dummy - will be set in prepareToPlay
andrewm@0 50 ,_typeNumber (_hardClipping) // standard
andrewm@0 51 ,_currentTrackBuffer (1,1)
andrewm@0 52 ,_lastUIWidth (850)
andrewm@0 53 ,_lastUIHeight (650)
andrewm@0 54
andrewm@0 55 {
andrewm@0 56 Reset();
andrewm@0 57 }
andrewm@0 58
andrewm@0 59 DistortionAudioProcessor::~DistortionAudioProcessor()
andrewm@0 60 {
andrewm@0 61 }
andrewm@0 62
andrewm@0 63 //-----------------------------------------------------------------------------
andrewm@0 64 // P R E P A R E T O P L A Y
andrewm@0 65 void DistortionAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
andrewm@0 66 {
andrewm@0 67 // If sample rate/block size changes or straight after construction
andrewm@0 68 if (_numSamples != samplesPerBlock || _sampleRate != sampleRate)
andrewm@0 69 {
andrewm@0 70 _sampleRate = sampleRate;
andrewm@0 71 _numSamples = samplesPerBlock;
andrewm@0 72 _numChannels = getNumInputChannels();
andrewm@0 73 }
andrewm@0 74 }
andrewm@0 75
andrewm@0 76
andrewm@0 77 //-----------------------------------------------------------------------------
andrewm@0 78 // P R O C E S S B L O C K
andrewm@0 79 void DistortionAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
andrewm@0 80 {
andrewm@0 81 float gain = powf(10.0f, _gainIndB/20.f);
andrewm@0 82
andrewm@0 83
andrewm@0 84 for (int channel = 0; channel < _numChannels; ++channel)
andrewm@0 85 {
andrewm@0 86 // Apply gain
andrewm@0 87 buffer.applyGain(channel, 0, buffer.getNumSamples(), gain);
andrewm@0 88
andrewm@0 89 // Put track audio data into _currentTrackBuffer
andrewm@0 90 float * originalData = new float;
b@1 91 originalData = buffer.getWritePointer(channel);
andrewm@0 92
andrewm@0 93 // Apply distortion (sample per sample)
andrewm@0 94 switch (_typeNumber) {
andrewm@0 95 case _hardClipping:
andrewm@0 96 {
andrewm@0 97 float threshold = 0.5f;
andrewm@0 98 for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
andrewm@0 99 {
andrewm@0 100 if(originalData[sample] > threshold) // positive hard clipping
andrewm@0 101 {
andrewm@0 102 originalData[sample] = threshold;
andrewm@0 103 }
andrewm@0 104 else
andrewm@0 105 {
andrewm@0 106 if(originalData[sample] < - threshold) // negative hard clipping
andrewm@0 107 {
andrewm@0 108 originalData[sample] = - threshold;
andrewm@0 109 }
andrewm@0 110 }
andrewm@0 111 }
andrewm@0 112 break;
andrewm@0 113 }
andrewm@0 114
andrewm@0 115 case _softClipping:
andrewm@0 116 {
andrewm@0 117 float threshold1 = 1.0f/3.0f;
andrewm@0 118 float threshold2 = 2.0f/3.0f;
andrewm@0 119 for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
andrewm@0 120 {
andrewm@0 121 if(originalData[sample] > threshold1)
andrewm@0 122 {
andrewm@0 123 if(originalData[sample] > threshold2) // positive clipping
andrewm@0 124 {
andrewm@0 125 originalData[sample] = 1.0f;
andrewm@0 126 }
andrewm@0 127 else // soft knee (positive)
andrewm@0 128 {
andrewm@0 129 originalData[sample] = (3.0f - (2.0f - 3.0f*originalData[sample])*(2.0f - 3.0f*originalData[sample]))/3.0f;
andrewm@0 130 }
andrewm@0 131 }
andrewm@0 132 else
andrewm@0 133 {
andrewm@0 134 if(originalData[sample] < -threshold1)
andrewm@0 135 {
andrewm@0 136 if(originalData[sample] < -threshold2) // negative clipping
andrewm@0 137 {
andrewm@0 138 originalData[sample] = -1.0f;
andrewm@0 139 }
andrewm@0 140 else // soft knee (negative)
andrewm@0 141 {
andrewm@0 142 originalData[sample] = - (3.0f - (2.0f + 3.0f*originalData[sample])*(2.0f + 3.0f*originalData[sample]))/3.0f;
andrewm@0 143 }
andrewm@0 144 }
andrewm@0 145 else // linear region (-1/3..1/3)
andrewm@0 146 {
andrewm@0 147 originalData[sample] *= 2.0f;
andrewm@0 148 }
andrewm@0 149 }
andrewm@0 150
andrewm@0 151 originalData[sample] /= 2.0f; // divide all by 2 to compensate for extra 6 dB gain boost
andrewm@0 152 }
andrewm@0 153 break;
andrewm@0 154 }
andrewm@0 155
andrewm@0 156 case _softClippingExp:
andrewm@0 157 {
andrewm@0 158 for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
andrewm@0 159 {
andrewm@0 160 if (originalData[sample] > 0.0f) // positive
andrewm@0 161 {
andrewm@0 162 originalData[sample] = 1.0f - expf(-originalData[sample]);
andrewm@0 163 }
andrewm@0 164 else // negative
andrewm@0 165 {
andrewm@0 166 originalData[sample] = - 1.0f + expf(originalData[sample]);
andrewm@0 167 }
andrewm@0 168 }
andrewm@0 169 break;
andrewm@0 170 }
andrewm@0 171
andrewm@0 172 case _fullWaveRectifier:
andrewm@0 173 {
andrewm@0 174 for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
andrewm@0 175 {
andrewm@0 176 originalData[sample] = fabs(originalData[sample]);
andrewm@0 177 }
andrewm@0 178 break;
andrewm@0 179 }
andrewm@0 180
andrewm@0 181 case _halfWaveRectifier:
andrewm@0 182 {
andrewm@0 183 for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
andrewm@0 184 {
andrewm@0 185 originalData[sample] = 0.5f*(fabs(originalData[sample])+originalData[sample]);
andrewm@0 186 }
andrewm@0 187 break;
andrewm@0 188 }
andrewm@0 189
andrewm@0 190 default:
andrewm@0 191 break;
andrewm@0 192 }
andrewm@0 193 }
andrewm@0 194 }
andrewm@0 195
andrewm@0 196
andrewm@0 197 //-----------------------------------------------------------------------------
andrewm@0 198 // R E S E T
andrewm@0 199 void DistortionAudioProcessor::Reset()
andrewm@0 200 {
andrewm@0 201 _gainIndB = 0.0f;
andrewm@0 202 _typeNumber = _hardClipping;
andrewm@0 203 }
andrewm@0 204
andrewm@0 205
andrewm@0 206 //-----------------------------------------------------------------------------
andrewm@0 207 //
andrewm@0 208 void DistortionAudioProcessor::releaseResources()
andrewm@0 209 {
andrewm@0 210 // When playback stops, you can use this to free up any spare memory, etc.
andrewm@0 211 }
andrewm@0 212
andrewm@0 213
andrewm@0 214 bool DistortionAudioProcessor::hasEditor() const
andrewm@0 215 {
andrewm@0 216 return true; // (change this to false if you choose to not supply an editor)
andrewm@0 217 }
andrewm@0 218
andrewm@0 219 AudioProcessorEditor* DistortionAudioProcessor::createEditor()
andrewm@0 220 {
andrewm@0 221 return new DistortionAudioProcessorEditor (this);
andrewm@0 222 }
andrewm@0 223
andrewm@0 224
andrewm@0 225 //==============================================================================
andrewm@0 226 void DistortionAudioProcessor::getStateInformation (MemoryBlock& destData)
andrewm@0 227 {
andrewm@0 228 // SAVE STATE INFO
andrewm@0 229 XmlElement xml("Distortion_XML");
andrewm@0 230
andrewm@0 231 // Knobs
andrewm@0 232 xml.setAttribute("_gain" ,_gainIndB);
andrewm@0 233
andrewm@0 234 // Combo box
andrewm@0 235 xml.setAttribute("_type" ,(int) _typeNumber);
andrewm@0 236
andrewm@0 237 // then use this helper function to stuff it into the binary blob and return it..
andrewm@0 238 copyXmlToBinary(xml, destData);
andrewm@0 239 }
andrewm@0 240
andrewm@0 241 void DistortionAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
andrewm@0 242 {
andrewm@0 243 // LOAD STATE INFO
andrewm@0 244 ScopedPointer<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));
andrewm@0 245
andrewm@0 246 // make sure that it's actually our type of XML object..
andrewm@0 247 if(xmlState->hasTagName("Distortion_XML"))
andrewm@0 248 {
andrewm@0 249
andrewm@0 250 // Knobs
andrewm@0 251 _gainIndB = (float) xmlState->getDoubleAttribute("_gain",true);
andrewm@0 252
andrewm@0 253 //Combo box
andrewm@0 254 _typeNumber = (DistortionAudioProcessor::Types) xmlState->getIntAttribute("_type",true);
andrewm@0 255 }
andrewm@0 256 }
andrewm@0 257
andrewm@0 258 // This creates new instances of the plugin..
andrewm@0 259 AudioProcessor* JUCE_CALLTYPE createPluginFilter()
andrewm@0 260 {
andrewm@0 261 return new DistortionAudioProcessor();
andrewm@0 262 }
andrewm@0 263
andrewm@0 264 const String DistortionAudioProcessor::getName() const
andrewm@0 265 {
andrewm@0 266 return JucePlugin_Name;
andrewm@0 267 }
andrewm@0 268
andrewm@0 269 bool DistortionAudioProcessor::silenceInProducesSilenceOut() const
andrewm@0 270 {
andrewm@0 271 return true;
andrewm@0 272 }
andrewm@0 273
andrewm@0 274 int DistortionAudioProcessor::getNumParameters()
andrewm@0 275 {
andrewm@0 276 return _PARAMtotalNumParams;
andrewm@0 277 }
andrewm@0 278
andrewm@0 279 float DistortionAudioProcessor::getParameter (int index) // externally accessible
andrewm@0 280 {
andrewm@0 281 switch (index)
andrewm@0 282 {
andrewm@0 283 case _PARAMdeviceReset: return 0.0f;
andrewm@0 284 case _PARAMgain: return (GetGainIndB());
andrewm@0 285 case _PARAMtype: return (GetType());
andrewm@0 286 default: return 0.0f;
andrewm@0 287 }
andrewm@0 288 }
andrewm@0 289
andrewm@0 290 void DistortionAudioProcessor::setParameter (int index, float newValue) // externally accessible
andrewm@0 291 {
andrewm@0 292 switch (index)
andrewm@0 293 {
andrewm@0 294 case _PARAMdeviceReset:
andrewm@0 295 Reset();
andrewm@0 296 break;
andrewm@0 297 case _PARAMgain:
andrewm@0 298 SetGainIndB(newValue);
andrewm@0 299 break;
andrewm@0 300 case _PARAMtype:
andrewm@0 301 SetType((DistortionAudioProcessor::Types) roundFloatToInt(newValue*_numberOfTypes));
andrewm@0 302 break;
andrewm@0 303 default:
andrewm@0 304 break;
andrewm@0 305 }
andrewm@0 306 }
andrewm@0 307
andrewm@0 308 const String DistortionAudioProcessor::getParameterName (int index) // externally accessible
andrewm@0 309 {
andrewm@0 310 switch (index)
andrewm@0 311 {
andrewm@0 312 case _PARAMdeviceReset: return "Reset";
andrewm@0 313 case _PARAMgain: return "Gain (dB)";
andrewm@0 314 case _PARAMtype: return "Type";
andrewm@0 315 default: break;
andrewm@0 316 }
andrewm@0 317 return String::empty;
andrewm@0 318 }
andrewm@0 319
andrewm@0 320 const String DistortionAudioProcessor::getParameterText (int index)
andrewm@0 321 {
andrewm@0 322 return String (getParameter (index), 2);
andrewm@0 323 }
andrewm@0 324
andrewm@0 325 const String DistortionAudioProcessor::getInputChannelName (int channelIndex) const
andrewm@0 326 {
andrewm@0 327 return String (channelIndex + 1);
andrewm@0 328 }
andrewm@0 329
andrewm@0 330 const String DistortionAudioProcessor::getOutputChannelName (int channelIndex) const
andrewm@0 331 {
andrewm@0 332 return String (channelIndex + 1);
andrewm@0 333 }
andrewm@0 334
andrewm@0 335 bool DistortionAudioProcessor::isInputChannelStereoPair (int index) const
andrewm@0 336 {
andrewm@0 337 return true;
andrewm@0 338 }
andrewm@0 339
andrewm@0 340 bool DistortionAudioProcessor::isOutputChannelStereoPair (int index) const
andrewm@0 341 {
andrewm@0 342 return true;
andrewm@0 343 }
andrewm@0 344
andrewm@0 345 bool DistortionAudioProcessor::acceptsMidi() const
andrewm@0 346 {
andrewm@0 347 #if JucePlugin_WantsMidiInput
andrewm@0 348 return true;
andrewm@0 349 #else
andrewm@0 350 return false;
andrewm@0 351 #endif
andrewm@0 352 }
andrewm@0 353
andrewm@0 354 bool DistortionAudioProcessor::producesMidi() const
andrewm@0 355 {
andrewm@0 356 #if JucePlugin_ProducesMidiOutput
andrewm@0 357 return true;
andrewm@0 358 #else
andrewm@0 359 return false;
andrewm@0 360 #endif
andrewm@0 361 }
andrewm@0 362
andrewm@0 363 int DistortionAudioProcessor::getNumPrograms()
andrewm@0 364 {
andrewm@0 365 return 0;
andrewm@0 366 }
andrewm@0 367
andrewm@0 368 int DistortionAudioProcessor::getCurrentProgram()
andrewm@0 369 {
andrewm@0 370 return 0;
andrewm@0 371 }
andrewm@0 372
andrewm@0 373 void DistortionAudioProcessor::setCurrentProgram (int index)
andrewm@0 374 {
andrewm@0 375 }
andrewm@0 376
andrewm@0 377 const String DistortionAudioProcessor::getProgramName (int index)
andrewm@0 378 {
andrewm@0 379 return String::empty;
andrewm@0 380 }
andrewm@0 381
andrewm@0 382 void DistortionAudioProcessor::changeProgramName (int index, const String& newName)
andrewm@0 383 {
andrewm@0 384 }