| 
							- /*
 -  * Power Juice Plugin
 -  * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz
 -  *
 -  * This program is free software; you can redistribute it and/or
 -  * modify it under the terms of the GNU General Public License as
 -  * published by the Free Software Foundation; either version 2 of
 -  * the License, or any later version.
 -  *
 -  * This program is distributed in the hope that it will be useful,
 -  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 -  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 -  * GNU General Public License for more details.
 -  *
 -  * For a full copy of the GNU General Public License see the doc/GPL.txt file.
 -  */
 - 
 - #include "PowerJuicePlugin.hpp"
 - //#include <cstring>
 - #include <cstdlib>
 - 
 - START_NAMESPACE_DISTRHO
 - 
 - // -----------------------------------------------------------------------
 - 
 - PowerJuicePlugin::PowerJuicePlugin()
 -     : Plugin(paramCount, 1, 0) // 1 program, 0 states
 - {
 -     // set default values
 -     d_setProgram(0);
 - 
 -     // reset
 -     d_deactivate();
 - }
 - 
 - PowerJuicePlugin::~PowerJuicePlugin()
 - {
 - 	free(lookaheadStack.data);
 - 	free(RMSStack.data);
 - }
 - 
 - // -----------------------------------------------------------------------
 - // Init
 - 
 - void PowerJuicePlugin::d_initParameter(uint32_t index, Parameter& parameter)
 - {
 -     switch (index)
 -     {
 -     case paramAttack:
 -         parameter.hints      = PARAMETER_IS_AUTOMABLE;
 -         parameter.name       = "Attack";
 -         parameter.symbol     = "att";
 -         parameter.unit       = "ms";
 -         parameter.ranges.def = 20.0f;
 -         parameter.ranges.min = 0.1f;
 -         parameter.ranges.max = 1000.0f;
 -         break;
 -     case paramRelease:
 -         parameter.hints      = PARAMETER_IS_AUTOMABLE;
 -         parameter.name       = "Release";
 -         parameter.symbol     = "rel";
 -         parameter.unit       = "ms";
 -         parameter.ranges.def = 200.0f;
 -         parameter.ranges.min = 0.1f;
 -         parameter.ranges.max = 1000.0f;
 -         break;
 -     case paramThreshold:
 -         parameter.hints      = PARAMETER_IS_AUTOMABLE;
 -         parameter.name       = "Threshold";
 -         parameter.symbol     = "thr";
 -         parameter.unit       = "dB";
 -         parameter.ranges.def = 0.0f;
 -         parameter.ranges.min = -60.0f;
 -         parameter.ranges.max = 0.0f;
 -         break;
 -     case paramRatio:
 -         parameter.hints      = PARAMETER_IS_AUTOMABLE;
 -         parameter.name       = "Ratio";
 -         parameter.symbol     = "rat";
 -         parameter.unit       = "";
 -         parameter.ranges.def = 1.0f;
 -         parameter.ranges.min = 1.0f;
 -         parameter.ranges.max = 10.0f;
 -         break;
 -     case paramMakeup:
 -         parameter.hints      = PARAMETER_IS_AUTOMABLE;
 -         parameter.name       = "Make-Up";
 -         parameter.symbol     = "mak";
 -         parameter.unit       = "";
 -         parameter.ranges.def = 0.0f;
 -         parameter.ranges.min = 0.0f;
 -         parameter.ranges.max = 20.0f;
 -         break;
 -     case paramMix:
 -         parameter.hints      = PARAMETER_IS_AUTOMABLE;
 -         parameter.name       = "Mix";
 -         parameter.symbol     = "Mix";
 -         parameter.unit       = "";
 -         parameter.ranges.def = 1.0f;
 -         parameter.ranges.min = 0.0f;
 -         parameter.ranges.max = 1.0f;
 -         break;
 - 
 -     }
 - }
 - 
 - void PowerJuicePlugin::d_initProgramName(uint32_t index, d_string& programName)
 - {
 -     if (index != 0)
 -         return;
 - 
 -     programName = "Default";
 - }
 - 
 - // -----------------------------------------------------------------------
 - // Internal data
 - 
 - float PowerJuicePlugin::d_getParameterValue(uint32_t index) const
 - {
 -     switch (index)
 -     {
 -     case paramAttack:
 -         return attack;
 -     case paramRelease:
 -         return release;
 -     case paramThreshold:
 -         return threshold;
 -     case paramRatio:
 -         return ratio;
 -     case paramMakeup:
 -         return makeup;
 -     case paramMix:
 -         return mix;
 -     default:
 -         return 0.0f;
 -     }
 - }
 - 
 - void PowerJuicePlugin::d_setParameterValue(uint32_t index, float value)
 - {
 -     switch (index)
 -     {
 -     case paramAttack:
 -         attack = value;
 -         attackSamples = d_getSampleRate()*(attack/1000.0f);
 -         break;
 -     case paramRelease:
 -         release = value;
 -         releaseSamples = d_getSampleRate()*(release/1000.0f);
 -         break;
 -     case paramThreshold:
 -         threshold = value;
 -         break;
 -     case paramRatio:
 -         ratio = value;
 -         break;
 -     case paramMakeup:
 -         makeup = value;
 -         makeupFloat = fromDB(makeup);
 -         break;
 -     case paramMix:
 -         mix = value;
 -         break;
 -     }
 - }
 - 
 - void PowerJuicePlugin::d_setProgram(uint32_t index)
 - {
 -     if (index != 0)
 -         return;
 - 
 -     /* Default parameter values */
 -     attack = 20.0f;
 -     release = 200.0f;
 -     threshold = 0.0f;
 -     ratio = 1.0f;
 -     makeup = 0.0f;
 -     mix = 1.0f;
 - 
 -     makeupFloat = fromDB(makeup);
 -     attackSamples = d_getSampleRate()*(attack/1000.0f);
 -     releaseSamples = d_getSampleRate()*(release/1000.0f);
 - 
 - 	
 - 
 -     w = 563; //waveform plane size, size of the plane in pixels;
 -     w2 = 1126; //wavefowm array
 -     h = 121; //waveform plane height
 -     x = 27; //waveform plane positions
 -     y = 53;
 -     dc = 113; //0DC line y position
 - 	
 -     /* Default variable values */
 -     averageCounter = 0;
 -     inputMax = 0.0f;
 - 
 -     balancer = 1.0f;
 -     GR = 1.0f;
 - 
 - 	newRepaint = false;
 - 
 -     input.start = 0;
 -     rms.start = 0;
 -     gainReduction.start = 0;
 -     RMSStack.start = 0;
 -     lookaheadStack.start = 0;
 -     repaintSkip = 0;
 -     
 -     
 -     kFloatRMSStackCount = 400.0f/44100.0f*d_getSampleRate();
 -     RMSStack.data = (float*) calloc(kFloatRMSStackCount, sizeof(float));
 -     
 -     kFloatLookaheadStackCount = 800.0f/44100.0f*d_getSampleRate();
 -     lookaheadStack.data = (float*) calloc(kFloatLookaheadStackCount, sizeof(float));
 -     
 -     refreshSkip= 300.0f/44100.0f*d_getSampleRate();
 -     
 -     std::memset(rms.data, 0, sizeof(float)*kFloatStackCount);
 -     std::memset(gainReduction.data, 0, sizeof(float)*kFloatStackCount);
 -     std::memset(RMSStack.data, 0, sizeof(float)*kFloatRMSStackCount);
 -     std::memset(lookaheadStack.data, 0, sizeof(float)*kFloatLookaheadStackCount);
 -     
 - 	for (int j=0; j < kFloatStackCount; ++j)
 - 		history.rms[j] = h +y;
 - 	for (int j=0; j < kFloatStackCount; ++j) 
 - 		history.gainReduction[j] = h +y;
 - 
 -     d_activate();
 -     
 - }
 - 
 - float PowerJuicePlugin::getRMSHistory(int n) {
 -     return history.rms[n];
 - }
 - 
 - bool PowerJuicePlugin::repaintNeeded() {
 - 	return newRepaint;
 - }
 - 
 - float PowerJuicePlugin::getGainReductionHistory(int n) {
 - 	if (n == kFloatStackCount-1) {
 - 		newRepaint = false;
 - 		//printf("falsing!\n");
 - 	}
 -     return history.gainReduction[n];
 - }
 - 
 - // -----------------------------------------------------------------------
 - // Process
 - 
 - void PowerJuicePlugin::d_activate()
 - {
 - }
 - 
 - void PowerJuicePlugin::d_deactivate()
 - {
 -     // all values to zero
 - }
 - 
 - void PowerJuicePlugin::d_run(const float** inputs, float** outputs, uint32_t frames)
 - {
 -     const float* in = inputs[0];
 -     float* out = outputs[0];
 -     float sum;
 -     float data;
 -     float difference;
 - 
 - 
 -     for (uint32_t i=0; i < frames; i++) {
 - 
 -         sum = 0.0f;
 -         data = 0.0f;
 -         difference = 0;
 -         //sanitizeDenormal(in[i]); // FIXME - you cannot modify inputs
 - 
 -         /*   compute last RMS   */
 - 
 -         //store audio samples in an RMS buffer line
 -         RMSStack.data[RMSStack.start++] = in[i];
 - 	   
 -         if (RMSStack.start == kFloatRMSStackCount)
 -                 RMSStack.start = 0;
 -         //compute RMS over last kFloatRMSStackCount samples
 -         for (int j=0; j < kFloatRMSStackCount; ++j) {
 -             data = RMSStack.data[(RMSStack.start+j) % kFloatRMSStackCount];
 -             sum += data * data;
 -         }
 - 	   
 -         //root mean SQUARE
 -           float RMS = sqrt(sum / kFloatRMSStackCount);
 -         sanitizeDenormal(RMS);
 - 		
 - 
 -         /*   compute gain reduction if needed   */
 -         float RMSDB = toDB(RMS);
 - 	   
 -         if (RMSDB>threshold) {
 -             //attack stage
 -             float difference = (RMSDB-threshold);
 - 		  
 -             //sanitizeDenormal(difference);
 -             targetGR = difference - difference/ratio;
 -             if (targetGR>difference/(ratio/4.0f)) {
 -                 targetGR = difference - difference/(ratio*1.5f);
 -                 //more power!
 -             }
 - 		  //
 -             if (GR<targetGR) {
 -                 //approach targetGR at attackSamples rate
 -                 GR -= (GR-targetGR)/(attackSamples);
 -             } else {
 -                 //approach targetGR at releaseSamples rate
 -                 GR -= (GR-targetGR)/releaseSamples;
 -             }
 - 		  
 -             sanitizeDenormal(GR);
 -         } else {
 -             //release stage
 -             //approach targetGR at releaseSamples rate, targetGR = 0.0f
 -             GR -= GR/releaseSamples;
 -         }
 - 		
 -         //store audio in lookahead buffer
 - 	   
 -         lookaheadStack.data[lookaheadStack.start++] = in[i];
 - 	   //printf("rms\n");
 -         if (lookaheadStack.start == kFloatLookaheadStackCount)
 -                 lookaheadStack.start = 0;
 - 		
 -         if (++averageCounter >= refreshSkip) {
 - 		  
 -             //add relevant values to the shared memory
 -             rms.data[rms.start++] = RMSDB;
 -             gainReduction.data[gainReduction.start++] = GR;
 - 		  
 - 
 -             //rewind stack reading heads if needed
 -             if (rms.start == kFloatStackCount)
 -                 rms.start = 0;
 -             if (gainReduction.start == kFloatStackCount)
 -                 gainReduction.start = 0;
 - 
 - 
 -             //saving in gfx format, for speed
 -             //share memory
 - 
 -             for (int j=0; j < kFloatStackCount; ++j)
 -                 history.rms[j] = -toIEC(rms.data[(rms.start+j) % kFloatStackCount])/200*h +h +y;
 -             for (int j=0; j < kFloatStackCount; ++j) {
 -                 history.gainReduction[j] = -toIEC(-gainReduction.data[(gainReduction.start+j) % kFloatStackCount])/200*h +h +y;
 - 			
 - 		  }
 - 			
 - 			repaintSkip++;
 - 			if (repaintSkip>5) {
 - 				repaintSkip = 0;
 - 				newRepaint = true;
 - 			}
 - 			
 -             averageCounter = 0;
 -             inputMax = 0.0f;
 -         }
 - 
 -         /* compress, mix, done. */
 -         float compressedSignal = in[i]*fromDB(-GR);
 -         out[i] = (compressedSignal*makeupFloat*mix)+in[i]*(1-mix);
 -     }
 - }
 - 
 - // -----------------------------------------------------------------------
 - 
 - Plugin* createPlugin()
 - {
 -     return new PowerJuicePlugin();
 - }
 - 
 - // -----------------------------------------------------------------------
 - 
 - END_NAMESPACE_DISTRHO
 
 
  |