f@0: // f@0: // AccessiblePeakMeter.h f@0: // f@0: // Author: Fiore Martin f@0: // Started from IPlugMultiTargets example in WDL-OL, by Oli Larkin - https://github.com/olilarkin/wdl-ol f@0: // f@0: // Licensed under the Cockos WDL License, see README.txt f@0: // f@0: f@0: f@0: #ifndef __ACCESSIBLEPEAKMETER__ f@0: #define __ACCESSIBLEPEAKMETER__ f@0: f@0: #include "IPlug_include_in_plug_hdr.h" f@0: f@0: #include "stk/include/SineWave.h" f@0: #include "stk/include/Envelope.h" f@0: #include "stk/include/ADSR.h" f@0: f@0: f@0: class AccessiblePeakMeter : public IPlug f@0: { f@0: public: f@0: f@0: AccessiblePeakMeter(IPlugInstanceInfo instanceInfo); f@0: ~AccessiblePeakMeter(); f@0: f@0: void Reset(); f@0: void OnParamChange(int paramIdx); f@0: void ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames); f@0: bool HostRequestingAboutBox(); f@0: f@0: private: f@0: static const double DRYWET_DEFAULT; f@2: static const int SONIFICATION_TYPE_DEFAULT; f@0: static const double METERDECAY_DEFAULT; f@0: static const double THRESHOLD_DEFAULT; f@0: static const double BEEP_TIME; f@0: static const double DB_RANGE; f@0: static const double SONIFICATION_RANGE; f@0: static const int SONIFICATION_TYPE_CLIPPING; f@0: static const int SONIFICATION_TYPE_CONTINUOUS; f@0: static const int MAX_CHANNELS = 2; f@0: static const int NUM_PRESETS; f@0: static const double MIN_SONIFICATION_FREQ; f@0: static const int NUM_KNOB_FRAMES; f@0: static const double CLIPPING_CEILING_SNAP; f@0: f@0: /* parameters on GUI */ f@0: double mDry; f@0: double mWet; f@0: double mMeterDecayRate; f@0: double mThreshold; f@0: f@0: double mSampleRate; f@0: f@0: /* paramters for peak level meter */ f@0: double mPrevPeak[MAX_CHANNELS]; f@0: int mMeterIdx[MAX_CHANNELS]; f@0: f@0: /* struct Sonification is the sonification engine. It has two substructures containing f@0: data specific to each type (clipping/continuous) f@0: */ f@0: struct Sonification { f@0: int type; // type of sonification : clipping - continous f@0: stk::SineWave ugen[MAX_CHANNELS]; // generator for both types of sonification f@0: f@0: struct Continous { f@0: /* this envelope is to turn off the countinuous sonification smoothly f@0: without clicks. It's always 1, unless the sonification is being turned off. f@0: */ f@0: stk::Envelope envelope[MAX_CHANNELS]; f@0: bool isOn[MAX_CHANNELS]; f@0: } continous; f@0: f@0: struct Clipping { f@0: /* max diff is used to keep the pitch more consistent over different blocks f@0: with maxDiff the beep sounds better cause is not constantly pitch modulated */ f@0: double maxDiff[MAX_CHANNELS]; f@0: stk::ADSR envelope[MAX_CHANNELS]; f@0: } clipping; f@0: f@0: /* resets all the ugens. When srate is less than 0, type and ugen freq are f@0: not affected by resetas well as sample rate. f@0: */ f@0: void reset(double srate = -1.0){ f@0: f@0: for (int i = 0; i < MAX_CHANNELS; i++){ f@0: f@0: ugen[i].reset(); f@0: f@0: continous.isOn[i] = true; f@0: stk::Envelope & coe = continous.envelope[i]; f@0: coe.setValue(1.0); // setValue also sets the target to the value f@0: coe.setTime(0.2); f@0: f@0: clipping.maxDiff[i] = 0.0; f@0: stk::ADSR & cle = clipping.envelope[i]; f@0: cle.setValue(0.0); f@0: cle.setReleaseTime(BEEP_TIME); f@0: cle.setAttackTime(0.01); f@0: cle.setSustainLevel(1); f@0: f@0: if (srate > 0.0){ f@0: ugen[i].setSampleRate(srate); f@0: coe.setSampleRate(srate); f@0: cle.setSampleRate(srate); f@0: } f@0: } f@0: } f@0: f@2: Sonification() : type(SONIFICATION_TYPE_DEFAULT) { f@0: reset(); f@0: } f@0: f@0: } mSonification; f@0: f@0: /* adds continous sonification on top of the original audio signal */ f@0: void addContinuousSonification(double** inputs, double** outputs, int nFrames); f@0: /* adds clipping sonification on top of the original audio signal */ f@0: void addClippingSonification(double** inputs, double** outputs, int nFrames); f@0: /* for dry/wet mix */ f@0: inline double mix(double dry, double wet) const{ f@0: return dry * mDry + wet * mWet; f@0: } f@0: }; f@0: f@0: f@0: #endif //__ACCESSIBLEPEAKMETER__