annotate 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
rev   line source
f@0 1 //
f@0 2 // AccessiblePeakMeter.h
f@0 3 //
f@0 4 // Author: Fiore Martin
f@0 5 // Started from IPlugMultiTargets example in WDL-OL, by Oli Larkin - https://github.com/olilarkin/wdl-ol
f@0 6 //
f@0 7 // Licensed under the Cockos WDL License, see README.txt
f@0 8 //
f@0 9
f@0 10 #ifndef __ACCESSIBLEPEAKMETER__
f@0 11 #define __ACCESSIBLEPEAKMETER__
f@0 12
f@0 13 #include "IPlug_include_in_plug_hdr.h"
f@0 14 #include "stk/include/SineWave.h"
f@0 15 #include "stk/include/Envelope.h"
f@0 16 #include "stk/include/ADSR.h"
f@0 17 #include "stk/include/RtAudio.h"
f@0 18 #include "stk/include/RtWvOut.h"
f@0 19
f@0 20 #include <thread>
f@0 21 #include <mutex>
f@0 22
f@0 23
f@0 24 const int DAC_BUFFER_SIZE = 64;
f@0 25 const int SONIFICATION_TYPE_CLIPPING = 1;
f@0 26 const int SONIFICATION_TYPE_CONTINUOUS = 0;
f@0 27 const double BEEP_TIME = 0.2;
f@0 28 const int MAX_CHANNELS = 2;
f@0 29
f@0 30 /*
f@0 31 This is a slightly hacked version of the AccessiblePeakMeter. The sonification is sent to
f@0 32 the defualt audio card rather than to the plugin output. The input audio signal is still
f@0 33 routed to the plugin out put with nomodification besides the amplitude, modified according
f@0 34 to the dry parameter.
f@0 35
f@0 36 When Reset() is called for the first time on the plugin, a new thread is spawned.
f@0 37 The VST plugin then continuously shares information about the input audio with the thread.
f@0 38 The thread continously polls this information and plays the sonification on the default audio interface.
f@0 39
f@0 40 DacRoutine() : is the function execute by the new thread
f@0 41 DacSynced : is the struct with all shared variables between the new thread and the VST plugin
f@0 42 Sonification: is the structure with all the sonification stuff. In this version it is only
f@0 43 accessed by the new thread.
f@0 44
f@0 45 DacThread struct does RAAI on the resource "thread"
f@0 46
f@0 47 */
f@0 48
f@0 49
f@0 50
f@0 51 /* DacRouting is the function executed by the thread that plays the sonification to the dac */
f@0 52 void DacRoutine();
f@0 53
f@0 54 /* the sonification struct contains all the variables for sonification.
f@0 55 It is accessed exclusively by the sonification thread */
f@0 56 struct Sonification {
f@0 57 stk::SineWave ugen[MAX_CHANNELS];
f@0 58
f@0 59 /* resets all the ugens. Type and ugen freq are not affected by reset
f@0 60 as well as sample rate, when srate is less than 0 */
f@0 61 void reset(double srate = -1.0){
f@0 62 for (int i = 0; i < MAX_CHANNELS; i++){
f@0 63 ugen[i].reset();
f@0 64
f@0 65 /* continous sonification */
f@0 66 continous.isOn[i] = true;
f@0 67 stk::Envelope & coe = continous.envelope[i];
f@0 68 coe.setValue(1.0); // setValue also sets the target
f@0 69 coe.setTime(0.2);
f@0 70
f@0 71 /* clipping sonification */
f@0 72 clipping.maxDiff[i] = 0.0;
f@0 73 stk::ADSR & cle = clipping.envelope[i];
f@0 74 cle.setValue(0.0);
f@0 75 cle.setReleaseTime(BEEP_TIME);
f@0 76 cle.setAttackTime(0.01);
f@0 77 cle.setSustainLevel(1);
f@0 78
f@0 79 /*
f@0 80 the sample is fixed to 44100 when the handle to the soundcard is created
f@0 81 the sonification is independent from changes in the daw sample rate anyway
f@0 82 if (srate > 0.0){
f@0 83 ugen[i].setSampleRate(srate);
f@0 84 coe.setSampleRate(srate);
f@0 85 cle.setSampleRate(srate);
f@0 86 }
f@0 87 */
f@0 88 }
f@0 89 }
f@0 90
f@0 91 struct Continous {
f@0 92 stk::Envelope envelope[MAX_CHANNELS];
f@0 93 bool isOn[MAX_CHANNELS];
f@0 94 } continous;
f@0 95
f@0 96 struct Clipping {
f@0 97 double maxDiff[MAX_CHANNELS];
f@0 98 stk::ADSR envelope[MAX_CHANNELS];
f@0 99 } clipping;
f@0 100
f@0 101 Sonification() {
f@0 102 reset();
f@0 103 }
f@0 104 } sSonification;
f@0 105
f@0 106 /* this structure is used to pass information back and forth between
f@0 107 the puginthread and the sonification thread, with direct access to the sound card */
f@0 108 struct DacSynced {
f@0 109 bool die;
f@0 110 double wet;
f@0 111 double sonifFreq[MAX_CHANNELS];
f@0 112 int type;
f@0 113 double maxClippingDiff[MAX_CHANNELS];
f@0 114 int sonificationType;
f@0 115 DacSynced()
f@0 116 : die(false),
f@0 117 wet(0.5),
f@0 118 sonificationType( SONIFICATION_TYPE_CLIPPING )
f@0 119 {
f@0 120 for (int i = 0; i < MAX_CHANNELS; i++){
f@0 121 sonifFreq[i] = 0.0;
f@0 122 maxClippingDiff[i] = 0.0;
f@0 123 }
f@0 124 }
f@0 125 } sDacSynced;
f@0 126
f@0 127
f@0 128
f@0 129 /* mutex to sync the vst plugin thread with the thread
f@0 130 that writes directly into the soundcard (DacThread)
f@0 131 */
f@0 132 std::mutex sDacMutex;
f@0 133
f@0 134
f@0 135 /*sPrevSonificationType keeps track of the sonification type. Useful for DacThread
f@0 136 to assess whether the sonification has changed from the last loop cycle */
f@0 137 int sPrevSonificationType = SONIFICATION_TYPE_CLIPPING;
f@0 138
f@0 139 struct DacThread {
f@0 140 std::thread t;
f@0 141 bool started = false;
f@0 142
f@0 143 /* when this struct goes out of scope (user *
f@0 144 * exits daw) The thread is stopped and joined. */
f@0 145 ~DacThread(){
f@0 146 sDacMutex.lock();
f@0 147 sDacSynced.die = true;
f@0 148 sDacMutex.unlock();
f@0 149
f@0 150 if (t.joinable())
f@0 151 t.join();
f@0 152 }
f@0 153
f@0 154 } sDacThread;
f@0 155
f@0 156 class AccessiblePeakMeter : public IPlug
f@0 157 {
f@0 158 public:
f@0 159
f@0 160 AccessiblePeakMeter(IPlugInstanceInfo instanceInfo);
f@0 161 ~AccessiblePeakMeter();
f@0 162
f@0 163 void Reset();
f@0 164 void OnParamChange(int paramIdx);
f@0 165
f@0 166 void ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames);
f@0 167 bool HostRequestingAboutBox();
f@0 168
f@0 169 static const double DRY_DEFAULT;
f@0 170 static const double WET_DEFAULT;
f@0 171 static const int SONIFICATION_TYPE_DEFAULT;
f@0 172 static const double METERDECAY_DEFAULT;
f@0 173 static const double THRESHOLD_DEFAULT;
f@0 174 static const double BEEP_TIME;
f@0 175 static const double DB_RANGE;
f@0 176 static const double SONIFICATION_RANGE;
f@0 177 static const int NO_BEEP;
f@0 178 static const int NUM_PRESETS = 2;
f@0 179 static const double MIN_SONIFICATION_FREQ;
f@0 180 static const int NUM_KNOB_FRAMES;
f@0 181 static const double CLIPPING_CEILING_SNAP;
f@0 182
f@0 183 private:
f@0 184 /* parameters on the GUI */
f@0 185 double mDry;
f@0 186 double mWet;
f@0 187 double mMeterDecayRate;
f@0 188 double mThreshold;
f@0 189
f@0 190 double mSampleRate;
f@0 191
f@0 192 double mPrevPeak[MAX_CHANNELS];
f@0 193 int mMeterIdx[MAX_CHANNELS];
f@0 194
f@0 195 int mSonificationType;
f@0 196
f@0 197 void addContinuousSonification(double** inputs, double** outputs, int nFrames);
f@0 198 void addClippingSonification(double** inputs, double** outputs, int nFrames);
f@0 199 };
f@0 200
f@0 201 #endif //__ACCESSIBLEPEAKMETER__