Mercurial > hg > apm2s
view AccessiblePeakMeter.h @ 0:4606bd505630 tip
first import
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Sat, 13 Jun 2015 15:08:10 +0100 |
parents | |
children |
line wrap: on
line source
// // AccessiblePeakMeter.h // // Author: Fiore Martin // Started from IPlugMultiTargets example in WDL-OL, by Oli Larkin - https://github.com/olilarkin/wdl-ol // // Licensed under the Cockos WDL License, see README.txt // #ifndef __ACCESSIBLEPEAKMETER__ #define __ACCESSIBLEPEAKMETER__ #include "IPlug_include_in_plug_hdr.h" #include "stk/include/SineWave.h" #include "stk/include/Envelope.h" #include "stk/include/ADSR.h" #include "stk/include/RtAudio.h" #include "stk/include/RtWvOut.h" #include <thread> #include <mutex> const int DAC_BUFFER_SIZE = 64; const int SONIFICATION_TYPE_CLIPPING = 1; const int SONIFICATION_TYPE_CONTINUOUS = 0; const double BEEP_TIME = 0.2; const int MAX_CHANNELS = 2; /* This is a slightly hacked version of the AccessiblePeakMeter. The sonification is sent to the defualt audio card rather than to the plugin output. The input audio signal is still routed to the plugin out put with nomodification besides the amplitude, modified according to the dry parameter. When Reset() is called for the first time on the plugin, a new thread is spawned. The VST plugin then continuously shares information about the input audio with the thread. The thread continously polls this information and plays the sonification on the default audio interface. DacRoutine() : is the function execute by the new thread DacSynced : is the struct with all shared variables between the new thread and the VST plugin Sonification: is the structure with all the sonification stuff. In this version it is only accessed by the new thread. DacThread struct does RAAI on the resource "thread" */ /* DacRouting is the function executed by the thread that plays the sonification to the dac */ void DacRoutine(); /* the sonification struct contains all the variables for sonification. It is accessed exclusively by the sonification thread */ struct Sonification { stk::SineWave ugen[MAX_CHANNELS]; /* resets all the ugens. Type and ugen freq are not affected by reset as well as sample rate, when srate is less than 0 */ void reset(double srate = -1.0){ for (int i = 0; i < MAX_CHANNELS; i++){ ugen[i].reset(); /* continous sonification */ continous.isOn[i] = true; stk::Envelope & coe = continous.envelope[i]; coe.setValue(1.0); // setValue also sets the target coe.setTime(0.2); /* clipping sonification */ clipping.maxDiff[i] = 0.0; stk::ADSR & cle = clipping.envelope[i]; cle.setValue(0.0); cle.setReleaseTime(BEEP_TIME); cle.setAttackTime(0.01); cle.setSustainLevel(1); /* the sample is fixed to 44100 when the handle to the soundcard is created the sonification is independent from changes in the daw sample rate anyway if (srate > 0.0){ ugen[i].setSampleRate(srate); coe.setSampleRate(srate); cle.setSampleRate(srate); } */ } } struct Continous { stk::Envelope envelope[MAX_CHANNELS]; bool isOn[MAX_CHANNELS]; } continous; struct Clipping { double maxDiff[MAX_CHANNELS]; stk::ADSR envelope[MAX_CHANNELS]; } clipping; Sonification() { reset(); } } sSonification; /* this structure is used to pass information back and forth between the puginthread and the sonification thread, with direct access to the sound card */ struct DacSynced { bool die; double wet; double sonifFreq[MAX_CHANNELS]; int type; double maxClippingDiff[MAX_CHANNELS]; int sonificationType; DacSynced() : die(false), wet(0.5), sonificationType( SONIFICATION_TYPE_CLIPPING ) { for (int i = 0; i < MAX_CHANNELS; i++){ sonifFreq[i] = 0.0; maxClippingDiff[i] = 0.0; } } } sDacSynced; /* mutex to sync the vst plugin thread with the thread that writes directly into the soundcard (DacThread) */ std::mutex sDacMutex; /*sPrevSonificationType keeps track of the sonification type. Useful for DacThread to assess whether the sonification has changed from the last loop cycle */ int sPrevSonificationType = SONIFICATION_TYPE_CLIPPING; struct DacThread { std::thread t; bool started = false; /* when this struct goes out of scope (user * * exits daw) The thread is stopped and joined. */ ~DacThread(){ sDacMutex.lock(); sDacSynced.die = true; sDacMutex.unlock(); if (t.joinable()) t.join(); } } sDacThread; class AccessiblePeakMeter : public IPlug { public: AccessiblePeakMeter(IPlugInstanceInfo instanceInfo); ~AccessiblePeakMeter(); void Reset(); void OnParamChange(int paramIdx); void ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames); bool HostRequestingAboutBox(); static const double DRY_DEFAULT; static const double WET_DEFAULT; static const int SONIFICATION_TYPE_DEFAULT; static const double METERDECAY_DEFAULT; static const double THRESHOLD_DEFAULT; static const double BEEP_TIME; static const double DB_RANGE; static const double SONIFICATION_RANGE; static const int NO_BEEP; static const int NUM_PRESETS = 2; static const double MIN_SONIFICATION_FREQ; static const int NUM_KNOB_FRAMES; static const double CLIPPING_CEILING_SNAP; private: /* parameters on the GUI */ double mDry; double mWet; double mMeterDecayRate; double mThreshold; double mSampleRate; double mPrevPeak[MAX_CHANNELS]; int mMeterIdx[MAX_CHANNELS]; int mSonificationType; void addContinuousSonification(double** inputs, double** outputs, int nFrames); void addClippingSonification(double** inputs, double** outputs, int nFrames); }; #endif //__ACCESSIBLEPEAKMETER__