aboutsummaryrefslogtreecommitdiffstats
path: root/src/mdaSpecMeter.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-08-12 00:20:16 +0000
committerDavid Robillard <d@drobilla.net>2008-08-12 00:20:16 +0000
commit102e899c331bd2ed9902467a077164e209c918f9 (patch)
treeb7fe5ec873582cc8a0fc0862f9da045d12b2259a /src/mdaSpecMeter.cpp
parent2b679f152e1c3104ac178b6c78ac0b1edf954ff6 (diff)
downloadmda.lv2-102e899c331bd2ed9902467a077164e209c918f9.tar.gz
mda.lv2-102e899c331bd2ed9902467a077164e209c918f9.tar.bz2
mda.lv2-102e899c331bd2ed9902467a077164e209c918f9.zip
VSTUI X11 port and embeddable GTK wrapper.
Build mdaSpecMeter and GUI. git-svn-id: http://svn.drobilla.net/lad/mda-lv2@1340 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/mdaSpecMeter.cpp')
-rw-r--r--src/mdaSpecMeter.cpp482
1 files changed, 482 insertions, 0 deletions
diff --git a/src/mdaSpecMeter.cpp b/src/mdaSpecMeter.cpp
new file mode 100644
index 0000000..7aae786
--- /dev/null
+++ b/src/mdaSpecMeter.cpp
@@ -0,0 +1,482 @@
+//
+// Plug-in: "MDA SpecMeter"
+//
+// Copyright(c)2002 Paul Kellett (maxim digital audio)
+//
+
+
+#include <stdio.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+
+#include "mdaSpecMeter.h"
+//#include "mdaSpecMeterGUI.h"
+//#include "AEffEditor.hpp"
+
+AudioEffect *
+createEffectInstance (audioMasterCallback audioMaster)
+{
+ return new mdaSpecMeter (audioMaster);
+}
+
+mdaSpecMeterProgram::mdaSpecMeterProgram ()
+{
+ param[_PARAM0] = 1.0;
+ strcpy (name, "MDA SpecMeter");
+}
+
+
+mdaSpecMeter::mdaSpecMeter (audioMasterCallback audioMaster):AudioEffectX (audioMaster, 1,
+ NPARAMS)
+{
+ //editor = new mdaSpecMeterGUI(this);
+
+ programs = new mdaSpecMeterProgram[numPrograms];
+ if (programs) {
+ setProgram (0);
+ }
+
+ setNumInputs (2);
+ setNumOutputs (2);
+ DECLARE_LVZ_DEPRECATED (canMono) ();
+ setUniqueID ("mdaSpecMeter");
+ canProcessReplacing ();
+
+ //initialise...
+ K = counter = 0;
+ kmax = 2048;
+ topband = 11;
+ iK = 1.0f / (float) kmax;
+ den = 1.0e-8f;
+
+ //buffer = new float[44100];
+
+ suspend ();
+}
+
+bool
+mdaSpecMeter::getProductString (char *text)
+{
+ strcpy (text, "MDA SpecMeter");
+ return true;
+}
+
+bool
+mdaSpecMeter::getVendorString (char *text)
+{
+ strcpy (text, "mda");
+ return true;
+}
+
+bool
+mdaSpecMeter::getEffectName (char *name)
+{
+ strcpy (name, "SpecMeter");
+ return true;
+}
+
+void
+mdaSpecMeter::suspend ()
+{
+ Lpeak = Rpeak = Lrms = Rrms = Corr = 0.0f;
+ lpeak = rpeak = lrms = rrms = corr = 0.0f;
+ Lhold = Rhold = 0.0f;
+ Lmin = Rmin = 0.0000001f;
+ for (long i = 0; i < 16; i++) {
+ band[0][i] = band[1][i] = 0.0f;
+ for (long j = 0; j < 6; j++)
+ lpp[j][i] = rpp[j][i] = 0.0f;
+ }
+
+ //memset(buffer, 0, size * sizeof (float));
+}
+
+void
+mdaSpecMeter::setSampleRate (float rate)
+{
+ AudioEffectX::setSampleRate (rate);
+ if (rate > 64000) {
+ topband = 12;
+ kmax = 4096;
+ } else {
+ topband = 11;
+ kmax = 2048;
+ }
+ iK = 1.0f / (float) kmax;
+}
+
+
+mdaSpecMeter::~mdaSpecMeter ()
+{
+ //if(buffer) delete [] buffer;
+ if (programs)
+ delete[]programs;
+}
+
+
+void
+mdaSpecMeter::setProgramName (char *name)
+{
+ strcpy (programs[curProgram].name, name);
+}
+
+void
+mdaSpecMeter::getProgramName (char *name)
+{
+ strcpy (name, programs[curProgram].name);
+}
+
+float
+mdaSpecMeter::getParameter (LvzInt32 index)
+{
+ return param[index];
+}
+
+void
+mdaSpecMeter::setProgram (LvzInt32 program)
+{
+ mdaSpecMeterProgram *p = &programs[program];
+ curProgram = program;
+ setProgramName (p->name);
+ for (long i = 0; i < NPARAMS; i++)
+ setParameter (i, p->param[i]);
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+void
+mdaSpecMeter::setParameter (LvzInt32 index, float value)
+{
+ mdaSpecMeterProgram *p = &programs[curProgram];
+ param[index] = p->param[index] = value;
+
+ switch (index) {
+ case _PARAM0:
+ gain = (float) pow (10.0f, 2.0f * param[index] - 1.0f);
+ break;
+
+ default:
+ break;
+ }
+
+ //if(editor) editor->postUpdate();
+}
+
+
+void
+mdaSpecMeter::getParameterName (LvzInt32 index, char *label)
+{
+ switch (index) {
+ case _PARAM0:
+ strcpy (label, "Gain");
+ break;
+ default:
+ strcpy (label, "");
+ }
+}
+
+
+void
+mdaSpecMeter::getParameterDisplay (LvzInt32 index, char *text)
+{
+ char string[16];
+
+ switch (index) {
+ case _PARAM0:
+ sprintf (string, "%.1f", 40.0f * param[index] - 20.0f);
+ break;
+ default:
+ sprintf (string, "%.0f", 0.0f * param[index]);
+ }
+ string[8] = 0;
+ strcpy (text, (char *) string);
+}
+
+
+void
+mdaSpecMeter::getParameterLabel (LvzInt32 index, char *label)
+{
+ switch (index) {
+ case _PARAM0:
+ strcpy (label, "Gain");
+ break;
+ default:
+ strcpy (label, "");
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+void
+mdaSpecMeter::process (float **inputs, float **outputs, LvzInt32 sampleFrames)
+{
+ float *in1 = inputs[0];
+ float *in2 = inputs[1];
+ float *out1 = outputs[0];
+ float *out2 = outputs[1];
+
+ den = -den;
+ float l, r, p, q, iN = iK;
+ long k = K, j0 = topband, mask, j;
+
+ while (--sampleFrames >= 0) {
+ l = *in1++;
+ r = *in2++;
+ *out1++ += l;
+ *out2++ += r;
+
+ l += den; //anti-denormal
+ r += den;
+
+ lrms += l * l; //RMS integrate
+ rrms += r * r;
+
+ p = (float) fabs (l);
+ if (p > lpeak)
+ lpeak = p; //peak detect
+ q = (float) fabs (r);
+ if (q > rpeak)
+ rpeak = q;
+ /*
+ if(p > 1.0e-8f && p < lmin) lmin = p; //'trough' detect
+ if(q > 1.0e-8f && q < rmin) rmin = q;
+ */
+ if ((l * r) > 0.0f)
+ corr += iN; //measure correlation
+
+ j = j0;
+ mask = k << 1;
+
+ do { //polyphase filter bank
+ p = lpp[0][j] + 0.208f * l;
+ lpp[0][j] = lpp[1][j];
+ lpp[1][j] = l - 0.208f * p;
+
+ q = lpp[2][j] + lpp[4][j] * 0.682f;
+ lpp[2][j] = lpp[3][j];
+ lpp[3][j] = lpp[4][j] - 0.682f * q;
+ lpp[4][j] = l;
+ lpp[5][j] += (float) fabs (p - q); //top octave
+ l = p + q; //lower octaves
+
+ p = rpp[0][j] + 0.208f * r;
+ rpp[0][j] = rpp[1][j];
+ rpp[1][j] = r - 0.208f * p;
+
+ q = rpp[2][j] + rpp[4][j] * 0.682f;
+ rpp[2][j] = rpp[3][j];
+ rpp[3][j] = rpp[4][j] - 0.682f * q;
+ rpp[4][j] = r;
+ rpp[5][j] += (float) fabs (p - q); //top octave
+ r = p + q; //lower octaves
+
+ j--;
+ mask >>= 1;
+ } while (mask & 1);
+
+ if (++k == kmax) {
+ k = 0;
+ counter++; //editor waits for this to change
+
+ if (lpeak == 0.0f)
+ Lpeak = Lrms = 0.0f;
+ else { ///add limits here!
+ if (lpeak > 2.0f)
+ lpeak = 2.0f;
+ if (lpeak >= Lpeak) {
+ Lpeak = lpeak;
+ Lhold = 2.0f * Lpeak;
+ } else {
+ Lhold *= 0.95f;
+ if (Lhold < Lpeak)
+ Lpeak = Lhold;
+ }
+ Lmin = lmin;
+ lmin *= 1.01f;
+ Lrms += 0.2f * (iN * lrms - Lrms);
+ }
+
+ if (rpeak == 0.0f)
+ Rpeak = Rrms = 0.0f;
+ else {
+ if (rpeak > 2.0f)
+ rpeak = 2.0f;
+ if (rpeak >= Rpeak) {
+ Rpeak = rpeak;
+ Rhold = 2.0f * Rpeak;
+ } else {
+ Rhold *= 0.95f;
+ if (Rhold < Rpeak)
+ Rpeak = Rhold;
+ }
+ Rmin = rmin;
+ rmin *= 1.01f;
+ Rrms += 0.2f * (iN * rrms - Rrms);
+ }
+
+ rpeak = lpeak = lrms = rrms = 0.0f;
+ Corr += 0.1f * (corr - Corr); //correlation
+ corr = SILENCE;
+
+ float dec = 0.08f;
+ for (j = 0; j < 13; j++) { //spectrum output
+ band[0][j] += dec * (iN * lpp[5][j] - band[0][j]);
+ if (band[0][j] > 2.0f)
+ band[0][j] = 2.0f;
+ else if (band[0][j] < 0.014f)
+ band[0][j] = 0.014f;
+
+ band[1][j] += dec * (iN * rpp[5][j] - band[1][j]);
+ if (band[1][j] > 2.0f)
+ band[1][j] = 2.0f;
+ else if (band[1][j] < 0.014f)
+ band[1][j] = 0.014f;
+
+ rpp[5][j] = lpp[5][j] = SILENCE;
+ dec = dec * 1.1f;
+ }
+ }
+ }
+
+ K = k;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+void
+mdaSpecMeter::processReplacing (float **inputs, float **outputs,
+ LvzInt32 sampleFrames)
+{
+ float *in1 = inputs[0];
+ float *in2 = inputs[1];
+ float *out1 = outputs[0];
+ float *out2 = outputs[1];
+
+ den = -den;
+ float l, r, p, q, iN = iK;
+ long k = K, j0 = topband, mask, j;
+
+ while (--sampleFrames >= 0) {
+ l = *in1++;
+ r = *in2++;
+ *out1++ = l;
+ *out2++ = r;
+
+ l += den; //anti-denormal
+ r += den;
+
+ lrms += l * l; //RMS integrate
+ rrms += r * r;
+
+ p = (float) fabs (l);
+ if (p > lpeak)
+ lpeak = p; //peak detect
+ q = (float) fabs (r);
+ if (q > rpeak)
+ rpeak = q;
+ /*
+ if(p > 1.0e-8f && p < lmin) lmin = p; //'trough' detect
+ if(q > 1.0e-8f && q < rmin) rmin = q;
+ */
+ if ((l * r) > 0.0f)
+ corr += iN; //measure correlation
+
+ j = j0;
+ mask = k << 1;
+
+ do { //polyphase filter bank
+ p = lpp[0][j] + 0.208f * l;
+ lpp[0][j] = lpp[1][j];
+ lpp[1][j] = l - 0.208f * p;
+
+ q = lpp[2][j] + lpp[4][j] * 0.682f;
+ lpp[2][j] = lpp[3][j];
+ lpp[3][j] = lpp[4][j] - 0.682f * q;
+ lpp[4][j] = l;
+ lpp[5][j] += (float) fabs (p - q); //top octave
+ l = p + q; //lower octaves
+
+ p = rpp[0][j] + 0.208f * r;
+ rpp[0][j] = rpp[1][j];
+ rpp[1][j] = r - 0.208f * p;
+
+ q = rpp[2][j] + rpp[4][j] * 0.682f;
+ rpp[2][j] = rpp[3][j];
+ rpp[3][j] = rpp[4][j] - 0.682f * q;
+ rpp[4][j] = r;
+ rpp[5][j] += (float) fabs (p - q); //top octave
+ r = p + q; //lower octaves
+
+ j--;
+ mask >>= 1;
+ } while (mask & 1);
+
+ if (++k == kmax) {
+ k = 0;
+ //counter++; //editor waits for this to change
+
+ if (lpeak == 0.0f)
+ Lpeak = Lrms = 0.0f;
+ else { ///add limits here!
+ if (lpeak > 2.0f)
+ lpeak = 2.0f;
+ if (lpeak >= Lpeak) {
+ Lpeak = lpeak;
+ Lhold = 2.0f * Lpeak;
+ } else {
+ Lhold *= 0.95f;
+ if (Lhold < Lpeak)
+ Lpeak = Lhold;
+ }
+ Lmin = lmin;
+ lmin *= 1.01f;
+ Lrms += 0.2f * (iN * lrms - Lrms);
+ }
+
+ if (rpeak == 0.0f)
+ Rpeak = Rrms = 0.0f;
+ else {
+ if (rpeak > 2.0f)
+ rpeak = 2.0f;
+ if (rpeak >= Rpeak) {
+ Rpeak = rpeak;
+ Rhold = 2.0f * Rpeak;
+ } else {
+ Rhold *= 0.95f;
+ if (Rhold < Rpeak)
+ Rpeak = Rhold;
+ }
+ Rmin = rmin;
+ rmin *= 1.01f;
+ Rrms += 0.2f * (iN * rrms - Rrms);
+ }
+
+ rpeak = lpeak = lrms = rrms = 0.0f;
+ Corr += 0.1f * (corr - Corr); //correlation
+ corr = SILENCE;
+
+ float dec = 0.08f;
+ for (j = 0; j < 13; j++) { //spectrum output
+ band[0][j] += dec * (iN * lpp[5][j] - band[0][j]);
+ if (band[0][j] > 2.0f)
+ band[0][j] = 2.0f;
+ else if (band[0][j] < 0.014f)
+ band[0][j] = 0.014f;
+
+ band[1][j] += dec * (iN * rpp[5][j] - band[1][j]);
+ if (band[1][j] > 2.0f)
+ band[1][j] = 2.0f;
+ else if (band[1][j] < 0.014f)
+ band[1][j] = 0.014f;
+
+ rpp[5][j] = lpp[5][j] = SILENCE;
+ dec = dec * 1.1f;
+ }
+
+ counter++; //editor waits for this to change
+ }
+ }
+
+ K = k;
+}