diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AccessiblePeakMeter.h	Sat Jun 13 15:08:10 2015 +0100
@@ -0,0 +1,201 @@
+// 
+// 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__