aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/LinuxVST
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/LinuxVST')
-rwxr-xr-xplugins/LinuxVST/src/Beam/Beam.cpp142
-rwxr-xr-xplugins/LinuxVST/src/Beam/Beam.h67
-rwxr-xr-xplugins/LinuxVST/src/Beam/BeamProc.cpp266
-rwxr-xr-xplugins/LinuxVST/src/Dark/Dark.cpp2
-rwxr-xr-xplugins/LinuxVST/src/Dark/DarkProc.cpp20
-rwxr-xr-xplugins/LinuxVST/src/NotJustAnotherDither/.vs/Console4Channel64/v14/.suobin32768 -> 0 bytes
-rwxr-xr-xplugins/LinuxVST/src/NotJustAnotherDither/.vs/VSTProject/v14/.suobin23040 -> 0 bytes
-rwxr-xr-xplugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.cpp56
-rwxr-xr-xplugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.h10
-rwxr-xr-xplugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDitherProc.cpp556
10 files changed, 735 insertions, 384 deletions
diff --git a/plugins/LinuxVST/src/Beam/Beam.cpp b/plugins/LinuxVST/src/Beam/Beam.cpp
new file mode 100755
index 0000000..183b5e5
--- /dev/null
+++ b/plugins/LinuxVST/src/Beam/Beam.cpp
@@ -0,0 +1,142 @@
+/* ========================================
+ * Beam - Beam.h
+ * Copyright (c) 2016 airwindows, All rights reserved
+ * ======================================== */
+
+#ifndef __Beam_H
+#include "Beam.h"
+#endif
+
+AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new Beam(audioMaster);}
+
+Beam::Beam(audioMasterCallback audioMaster) :
+ AudioEffectX(audioMaster, kNumPrograms, kNumParameters)
+{
+ A = 1.0;
+ B = 0.5;
+ C = 0.0;
+ for(int count = 0; count < 99; count++) {
+ lastSampleL[count] = 0;
+ lastSampleR[count] = 0;
+ }
+ fpd = 17;
+ //this is reset: values being initialized only once. Startup values, whatever they are.
+
+ _canDo.insert("plugAsChannelInsert"); // plug-in can be used as a channel insert effect.
+ _canDo.insert("plugAsSend"); // plug-in can be used as a send effect.
+ _canDo.insert("x2in2out");
+ setNumInputs(kNumInputs);
+ setNumOutputs(kNumOutputs);
+ setUniqueID(kUniqueId);
+ canProcessReplacing(); // supports output replacing
+ canDoubleReplacing(); // supports double precision processing
+ programsAreChunks(true);
+ vst_strncpy (_programName, "Default", kVstMaxProgNameLen); // default program name
+}
+
+Beam::~Beam() {}
+VstInt32 Beam::getVendorVersion () {return 1000;}
+void Beam::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);}
+void Beam::getProgramName(char *name) {vst_strncpy (name, _programName, kVstMaxProgNameLen);}
+//airwindows likes to ignore this stuff. Make your own programs, and make a different plugin rather than
+//trying to do versioning and preventing people from using older versions. Maybe they like the old one!
+
+static float pinParameter(float data)
+{
+ if (data < 0.0f) return 0.0f;
+ if (data > 1.0f) return 1.0f;
+ return data;
+}
+
+VstInt32 Beam::getChunk (void** data, bool isPreset)
+{
+ float *chunkData = (float *)calloc(kNumParameters, sizeof(float));
+ chunkData[0] = A;
+ chunkData[1] = B;
+ chunkData[2] = C;
+ /* Note: The way this is set up, it will break if you manage to save settings on an Intel
+ machine and load them on a PPC Mac. However, it's fine if you stick to the machine you
+ started with. */
+
+ *data = chunkData;
+ return kNumParameters * sizeof(float);
+}
+
+VstInt32 Beam::setChunk (void* data, VstInt32 byteSize, bool isPreset)
+{
+ float *chunkData = (float *)data;
+ A = pinParameter(chunkData[0]);
+ B = pinParameter(chunkData[1]);
+ C = pinParameter(chunkData[2]);
+ /* We're ignoring byteSize as we found it to be a filthy liar */
+
+ /* calculate any other fields you need here - you could copy in
+ code from setParameter() here. */
+ return 0;
+}
+
+void Beam::setParameter(VstInt32 index, float value) {
+ switch (index) {
+ case kParamA: A = value; break;
+ case kParamB: B = value; break;
+ case kParamC: C = value; break;
+ default: throw; // unknown parameter, shouldn't happen!
+ }
+}
+
+float Beam::getParameter(VstInt32 index) {
+ switch (index) {
+ case kParamA: return A; break;
+ case kParamB: return B; break;
+ case kParamC: return C; break;
+ default: break; // unknown parameter, shouldn't happen!
+ } return 0.0; //we only need to update the relevant name, this is simple to manage
+}
+
+void Beam::getParameterName(VstInt32 index, char *text) {
+ switch (index) {
+ case kParamA: vst_strncpy (text, "Quant", kVstMaxParamStrLen); break;
+ case kParamB: vst_strncpy (text, "Focus", kVstMaxParamStrLen); break;
+ case kParamC: vst_strncpy (text, "DeRez", kVstMaxParamStrLen); break;
+ default: break; // unknown parameter, shouldn't happen!
+ } //this is our labels for displaying in the VST host
+}
+
+void Beam::getParameterDisplay(VstInt32 index, char *text) {
+ switch (index) {
+ case kParamA: switch((VstInt32)( A * 1.999 )) //0 to almost edge of # of params
+ { case 0: vst_strncpy (text, "CD 16", kVstMaxParamStrLen); break;
+ case 1: vst_strncpy (text, "HD 24", kVstMaxParamStrLen); break;
+ default: break; // unknown parameter, shouldn't happen!
+ } break; //completed consoletype 'popup' parameter, exit
+ case kParamB: float2string (B, text, kVstMaxParamStrLen); break;
+ case kParamC: float2string (C, text, kVstMaxParamStrLen); break;
+ default: break; // unknown parameter, shouldn't happen!
+ } //this displays the values and handles 'popups' where it's discrete choices
+}
+
+void Beam::getParameterLabel(VstInt32 index, char *text) {
+ switch (index) {
+ case kParamA: vst_strncpy (text, "", kVstMaxParamStrLen); break;
+ case kParamB: vst_strncpy (text, "", kVstMaxParamStrLen); break;
+ case kParamC: vst_strncpy (text, "", kVstMaxParamStrLen); break;
+ default: break; // unknown parameter, shouldn't happen!
+ }
+}
+
+VstInt32 Beam::canDo(char *text)
+{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know
+
+bool Beam::getEffectName(char* name) {
+ vst_strncpy(name, "Beam", kVstMaxProductStrLen); return true;
+}
+
+VstPlugCategory Beam::getPlugCategory() {return kPlugCategEffect;}
+
+bool Beam::getProductString(char* text) {
+ vst_strncpy (text, "airwindows Beam", kVstMaxProductStrLen); return true;
+}
+
+bool Beam::getVendorString(char* text) {
+ vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true;
+}
diff --git a/plugins/LinuxVST/src/Beam/Beam.h b/plugins/LinuxVST/src/Beam/Beam.h
new file mode 100755
index 0000000..30e1ccd
--- /dev/null
+++ b/plugins/LinuxVST/src/Beam/Beam.h
@@ -0,0 +1,67 @@
+/* ========================================
+ * Beam - Beam.h
+ * Created 8/12/11 by SPIAdmin
+ * Copyright (c) 2011 __MyCompanyName__, All rights reserved
+ * ======================================== */
+
+#ifndef __Beam_H
+#define __Beam_H
+
+#ifndef __audioeffect__
+#include "audioeffectx.h"
+#endif
+
+#include <set>
+#include <string>
+#include <math.h>
+
+enum {
+ kParamA = 0,
+ kParamB = 1,
+ kParamC = 2,
+ kNumParameters = 3
+}; //
+
+const int kNumPrograms = 0;
+const int kNumInputs = 2;
+const int kNumOutputs = 2;
+const unsigned long kUniqueId = 'beam'; //Change this to what the AU identity is!
+
+class Beam :
+ public AudioEffectX
+{
+public:
+ Beam(audioMasterCallback audioMaster);
+ ~Beam();
+ virtual bool getEffectName(char* name); // The plug-in name
+ virtual VstPlugCategory getPlugCategory(); // The general category for the plug-in
+ virtual bool getProductString(char* text); // This is a unique plug-in string provided by Steinberg
+ virtual bool getVendorString(char* text); // Vendor info
+ virtual VstInt32 getVendorVersion(); // Version number
+ virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames);
+ virtual void processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames);
+ virtual void getProgramName(char *name); // read the name from the host
+ virtual void setProgramName(char *name); // changes the name of the preset displayed in the host
+ virtual VstInt32 getChunk (void** data, bool isPreset);
+ virtual VstInt32 setChunk (void* data, VstInt32 byteSize, bool isPreset);
+ virtual float getParameter(VstInt32 index); // get the parameter value at the specified index
+ virtual void setParameter(VstInt32 index, float value); // set the parameter at index to value
+ virtual void getParameterLabel(VstInt32 index, char *text); // label for the parameter (eg dB)
+ virtual void getParameterName(VstInt32 index, char *text); // name of the parameter
+ virtual void getParameterDisplay(VstInt32 index, char *text); // text description of the current value
+ virtual VstInt32 canDo(char *text);
+private:
+ char _programName[kVstMaxProgNameLen + 1];
+ std::set< std::string > _canDo;
+
+ float lastSampleL[100];
+ float lastSampleR[100];
+ uint32_t fpd;
+ //default stuff
+
+ float A;
+ float B;
+ float C;
+};
+
+#endif
diff --git a/plugins/LinuxVST/src/Beam/BeamProc.cpp b/plugins/LinuxVST/src/Beam/BeamProc.cpp
new file mode 100755
index 0000000..5871eb5
--- /dev/null
+++ b/plugins/LinuxVST/src/Beam/BeamProc.cpp
@@ -0,0 +1,266 @@
+/* ========================================
+ * Beam - Beam.h
+ * Copyright (c) 2016 airwindows, All rights reserved
+ * ======================================== */
+
+#ifndef __Beam_H
+#include "Beam.h"
+#endif
+
+void Beam::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames)
+{
+ float* in1 = inputs[0];
+ float* in2 = inputs[1];
+ float* out1 = outputs[0];
+ float* out2 = outputs[1];
+
+ int processing = (VstInt32)( A * 1.999 );
+ float sonority = B * 1.618033988749894848204586;
+ double overallscale = 1.0;
+ overallscale /= 44100.0;
+ overallscale *= getSampleRate();
+ int depth = (int)(17.0*overallscale);
+ if (depth < 3) depth = 3;
+ if (depth > 98) depth = 98;
+ bool highres = false;
+ if (processing == 1) highres = true;
+ float scaleFactor;
+ if (highres) scaleFactor = 8388608.0;
+ else scaleFactor = 32768.0;
+ float derez = C;
+ if (derez > 0.0) scaleFactor *= pow(1.0-derez,6);
+ if (scaleFactor < 0.0001) scaleFactor = 0.0001;
+ float outScale = scaleFactor;
+ if (outScale < 8.0) outScale = 8.0;
+
+ while (--sampleFrames >= 0)
+ {
+ long double inputSampleL = *in1;
+ long double inputSampleR = *in2;
+ if (fabs(inputSampleL)<1.18e-37) inputSampleL = fpd * 1.18e-37;
+ fpd ^= fpd << 13; fpd ^= fpd >> 17; fpd ^= fpd << 5;
+ if (fabs(inputSampleR)<1.18e-37) inputSampleR = fpd * 1.18e-37;
+ fpd ^= fpd << 13; fpd ^= fpd >> 17; fpd ^= fpd << 5;
+
+ inputSampleL *= scaleFactor;
+ inputSampleR *= scaleFactor;
+ //0-1 is now one bit, now we dither
+
+ //We are doing it first Left, then Right, because the loops may run faster if
+ //they aren't too jammed full of variables. This means re-running code.
+
+ //begin left
+ int quantA = floor(inputSampleL);
+ int quantB = floor(inputSampleL+1.0);
+ //to do this style of dither, we quantize in either direction and then
+ //do a reconstruction of what the result will be for each choice.
+ //We then evaluate which one we like, and keep a history of what we previously had
+
+ float expectedSlewA = 0;
+ for(int x = 0; x < depth; x++) {
+ expectedSlewA += (lastSampleL[x+1] - lastSampleL[x]);
+ }
+ float expectedSlewB = expectedSlewA;
+ expectedSlewA += (lastSampleL[0] - quantA);
+ expectedSlewB += (lastSampleL[0] - quantB);
+ //now we have a collection of all slews, averaged and left at total scale
+
+ float clamp = sonority;
+ if (fabs(inputSampleL) < sonority) clamp = fabs(inputSampleL);
+
+ float testA = fabs(fabs(expectedSlewA)-clamp);
+ float testB = fabs(fabs(expectedSlewB)-clamp);
+ //doing this means the result will be lowest when it's reaching the target slope across
+ //the desired time range, either positively or negatively. Should produce the same target
+ //at whatever sample rate, as high rate stuff produces smaller increments.
+
+ if (testA < testB) inputSampleL = quantA;
+ else inputSampleL = quantB;
+ //select whichever one departs LEAST from the vector of averaged
+ //reconstructed previous final samples. This will force a kind of dithering
+ //as it'll make the output end up as smooth as possible
+
+ for(int x = depth; x >=0; x--) {
+ lastSampleL[x+1] = lastSampleL[x];
+ }
+ lastSampleL[0] = inputSampleL;
+ //end left
+
+ //begin right
+ quantA = floor(inputSampleR);
+ quantB = floor(inputSampleR+1.0);
+ //to do this style of dither, we quantize in either direction and then
+ //do a reconstruction of what the result will be for each choice.
+ //We then evaluate which one we like, and keep a history of what we previously had
+
+ expectedSlewA = 0;
+ for(int x = 0; x < depth; x++) {
+ expectedSlewA += (lastSampleR[x+1] - lastSampleR[x]);
+ }
+ expectedSlewB = expectedSlewA;
+ expectedSlewA += (lastSampleR[0] - quantA);
+ expectedSlewB += (lastSampleR[0] - quantB);
+ //now we have a collection of all slews, averaged and left at total scale
+
+ clamp = sonority;
+ if (fabs(inputSampleR) < sonority) clamp = fabs(inputSampleR);
+
+ testA = fabs(fabs(expectedSlewA)-clamp);
+ testB = fabs(fabs(expectedSlewB)-clamp);
+ //doing this means the result will be lowest when it's reaching the target slope across
+ //the desired time range, either positively or negatively. Should produce the same target
+ //at whatever sample rate, as high rate stuff produces smaller increments.
+
+ if (testA < testB) inputSampleR = quantA;
+ else inputSampleR = quantB;
+ //select whichever one departs LEAST from the vector of averaged
+ //reconstructed previous final samples. This will force a kind of dithering
+ //as it'll make the output end up as smooth as possible
+
+ for(int x = depth; x >=0; x--) {
+ lastSampleR[x+1] = lastSampleR[x];
+ }
+ lastSampleR[0] = inputSampleR;
+ //end right
+
+ inputSampleL /= outScale;
+ inputSampleR /= outScale;
+
+ *out1 = inputSampleL;
+ *out2 = inputSampleR;
+
+ *in1++;
+ *in2++;
+ *out1++;
+ *out2++;
+ }
+}
+
+void Beam::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames)
+{
+ double* in1 = inputs[0];
+ double* in2 = inputs[1];
+ double* out1 = outputs[0];
+ double* out2 = outputs[1];
+
+ int processing = (VstInt32)( A * 1.999 );
+ float sonority = B * 1.618033988749894848204586;
+ double overallscale = 1.0;
+ overallscale /= 44100.0;
+ overallscale *= getSampleRate();
+ int depth = (int)(17.0*overallscale);
+ if (depth < 3) depth = 3;
+ if (depth > 98) depth = 98;
+ bool highres = false;
+ if (processing == 1) highres = true;
+ float scaleFactor;
+ if (highres) scaleFactor = 8388608.0;
+ else scaleFactor = 32768.0;
+ float derez = C;
+ if (derez > 0.0) scaleFactor *= pow(1.0-derez,6);
+ if (scaleFactor < 0.0001) scaleFactor = 0.0001;
+ float outScale = scaleFactor;
+ if (outScale < 8.0) outScale = 8.0;
+
+ while (--sampleFrames >= 0)
+ {
+ long double inputSampleL = *in1;
+ long double inputSampleR = *in2;
+ if (fabs(inputSampleL)<1.18e-43) inputSampleL = fpd * 1.18e-43;
+ fpd ^= fpd << 13; fpd ^= fpd >> 17; fpd ^= fpd << 5;
+ if (fabs(inputSampleR)<1.18e-43) inputSampleR = fpd * 1.18e-43;
+ fpd ^= fpd << 13; fpd ^= fpd >> 17; fpd ^= fpd << 5;
+
+ inputSampleL *= scaleFactor;
+ inputSampleR *= scaleFactor;
+ //0-1 is now one bit, now we dither
+
+ //We are doing it first Left, then Right, because the loops may run faster if
+ //they aren't too jammed full of variables. This means re-running code.
+
+ //begin left
+ int quantA = floor(inputSampleL);
+ int quantB = floor(inputSampleL+1.0);
+ //to do this style of dither, we quantize in either direction and then
+ //do a reconstruction of what the result will be for each choice.
+ //We then evaluate which one we like, and keep a history of what we previously had
+
+ float expectedSlewA = 0;
+ for(int x = 0; x < depth; x++) {
+ expectedSlewA += (lastSampleL[x+1] - lastSampleL[x]);
+ }
+ float expectedSlewB = expectedSlewA;
+ expectedSlewA += (lastSampleL[0] - quantA);
+ expectedSlewB += (lastSampleL[0] - quantB);
+ //now we have a collection of all slews, averaged and left at total scale
+
+ float clamp = sonority;
+ if (fabs(inputSampleL) < sonority) clamp = fabs(inputSampleL);
+
+ float testA = fabs(fabs(expectedSlewA)-clamp);
+ float testB = fabs(fabs(expectedSlewB)-clamp);
+ //doing this means the result will be lowest when it's reaching the target slope across
+ //the desired time range, either positively or negatively. Should produce the same target
+ //at whatever sample rate, as high rate stuff produces smaller increments.
+
+ if (testA < testB) inputSampleL = quantA;
+ else inputSampleL = quantB;
+ //select whichever one departs LEAST from the vector of averaged
+ //reconstructed previous final samples. This will force a kind of dithering
+ //as it'll make the output end up as smooth as possible
+
+ for(int x = depth; x >=0; x--) {
+ lastSampleL[x+1] = lastSampleL[x];
+ }
+ lastSampleL[0] = inputSampleL;
+ //end left
+
+ //begin right
+ quantA = floor(inputSampleR);
+ quantB = floor(inputSampleR+1.0);
+ //to do this style of dither, we quantize in either direction and then
+ //do a reconstruction of what the result will be for each choice.
+ //We then evaluate which one we like, and keep a history of what we previously had
+
+ expectedSlewA = 0;
+ for(int x = 0; x < depth; x++) {
+ expectedSlewA += (lastSampleR[x+1] - lastSampleR[x]);
+ }
+ expectedSlewB = expectedSlewA;
+ expectedSlewA += (lastSampleR[0] - quantA);
+ expectedSlewB += (lastSampleR[0] - quantB);
+ //now we have a collection of all slews, averaged and left at total scale
+
+ clamp = sonority;
+ if (fabs(inputSampleR) < sonority) clamp = fabs(inputSampleR);
+
+ testA = fabs(fabs(expectedSlewA)-clamp);
+ testB = fabs(fabs(expectedSlewB)-clamp);
+ //doing this means the result will be lowest when it's reaching the target slope across
+ //the desired time range, either positively or negatively. Should produce the same target
+ //at whatever sample rate, as high rate stuff produces smaller increments.
+
+ if (testA < testB) inputSampleR = quantA;
+ else inputSampleR = quantB;
+ //select whichever one departs LEAST from the vector of averaged
+ //reconstructed previous final samples. This will force a kind of dithering
+ //as it'll make the output end up as smooth as possible
+
+ for(int x = depth; x >=0; x--) {
+ lastSampleR[x+1] = lastSampleR[x];
+ }
+ lastSampleR[0] = inputSampleR;
+ //end right
+
+ inputSampleL /= outScale;
+ inputSampleR /= outScale;
+
+ *out1 = inputSampleL;
+ *out2 = inputSampleR;
+
+ *in1++;
+ *in2++;
+ *out1++;
+ *out2++;
+ }
+}
diff --git a/plugins/LinuxVST/src/Dark/Dark.cpp b/plugins/LinuxVST/src/Dark/Dark.cpp
index bae0428..f652aa4 100755
--- a/plugins/LinuxVST/src/Dark/Dark.cpp
+++ b/plugins/LinuxVST/src/Dark/Dark.cpp
@@ -14,11 +14,11 @@ Dark::Dark(audioMasterCallback audioMaster) :
{
A = 1.0;
B = 0.0;
+ fpd = 17;
for(int count = 0; count < 99; count++) {
lastSampleL[count] = 0;
lastSampleR[count] = 0;
}
- fpd = 17;
//this is reset: values being initialized only once. Startup values, whatever they are.
_canDo.insert("plugAsChannelInsert"); // plug-in can be used as a channel insert effect.
diff --git a/plugins/LinuxVST/src/Dark/DarkProc.cpp b/plugins/LinuxVST/src/Dark/DarkProc.cpp
index 2aa85c4..955a53f 100755
--- a/plugins/LinuxVST/src/Dark/DarkProc.cpp
+++ b/plugins/LinuxVST/src/Dark/DarkProc.cpp
@@ -13,13 +13,14 @@ void Dark::processReplacing(float **inputs, float **outputs, VstInt32 sampleFram
float* in2 = inputs[1];
float* out1 = outputs[0];
float* out2 = outputs[1];
- int processing = (VstInt32)( A * 1.999 );
double overallscale = 1.0;
overallscale /= 44100.0;
overallscale *= getSampleRate();
int depth = (int)(17.0*overallscale);
if (depth < 3) depth = 3;
if (depth > 98) depth = 98;
+
+ int processing = (VstInt32)( A * 1.999 );
bool highres = false;
if (processing == 1) highres = true;
float scaleFactor;
@@ -28,6 +29,8 @@ void Dark::processReplacing(float **inputs, float **outputs, VstInt32 sampleFram
float derez = B;
if (derez > 0.0) scaleFactor *= pow(1.0-derez,6);
if (scaleFactor < 0.0001) scaleFactor = 0.0001;
+ float outScale = scaleFactor;
+ if (outScale < 8.0) outScale = 8.0;
while (--sampleFrames >= 0)
{
@@ -105,8 +108,8 @@ void Dark::processReplacing(float **inputs, float **outputs, VstInt32 sampleFram
lastSampleR[0] = inputSampleR;
//end right
- inputSampleL /= scaleFactor;
- inputSampleR /= scaleFactor;
+ inputSampleL /= outScale;
+ inputSampleR /= outScale;
*out1 = inputSampleL;
*out2 = inputSampleR;
@@ -125,13 +128,14 @@ void Dark::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sa
double* out1 = outputs[0];
double* out2 = outputs[1];
- int processing = (VstInt32)( A * 1.999 );
double overallscale = 1.0;
overallscale /= 44100.0;
overallscale *= getSampleRate();
int depth = (int)(17.0*overallscale);
if (depth < 3) depth = 3;
if (depth > 98) depth = 98;
+
+ int processing = (VstInt32)( A * 1.999 );
bool highres = false;
if (processing == 1) highres = true;
float scaleFactor;
@@ -139,7 +143,9 @@ void Dark::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sa
else scaleFactor = 32768.0;
float derez = B;
if (derez > 0.0) scaleFactor *= pow(1.0-derez,6);
- if (scaleFactor < 1.0) scaleFactor = 1.0;
+ if (scaleFactor < 0.0001) scaleFactor = 0.0001;
+ float outScale = scaleFactor;
+ if (outScale < 8.0) outScale = 8.0;
while (--sampleFrames >= 0)
{
@@ -217,8 +223,8 @@ void Dark::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sa
lastSampleR[0] = inputSampleR;
//end right
- inputSampleL /= scaleFactor;
- inputSampleR /= scaleFactor;
+ inputSampleL /= outScale;
+ inputSampleR /= outScale;
*out1 = inputSampleL;
*out2 = inputSampleR;
diff --git a/plugins/LinuxVST/src/NotJustAnotherDither/.vs/Console4Channel64/v14/.suo b/plugins/LinuxVST/src/NotJustAnotherDither/.vs/Console4Channel64/v14/.suo
deleted file mode 100755
index 777b846..0000000
--- a/plugins/LinuxVST/src/NotJustAnotherDither/.vs/Console4Channel64/v14/.suo
+++ /dev/null
Binary files differ
diff --git a/plugins/LinuxVST/src/NotJustAnotherDither/.vs/VSTProject/v14/.suo b/plugins/LinuxVST/src/NotJustAnotherDither/.vs/VSTProject/v14/.suo
deleted file mode 100755
index 0b83621..0000000
--- a/plugins/LinuxVST/src/NotJustAnotherDither/.vs/VSTProject/v14/.suo
+++ /dev/null
Binary files differ
diff --git a/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.cpp b/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.cpp
index 22a3cc7..7727b50 100755
--- a/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.cpp
+++ b/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.cpp
@@ -12,6 +12,9 @@ AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new N
NotJustAnotherDither::NotJustAnotherDither(audioMasterCallback audioMaster) :
AudioEffectX(audioMaster, kNumPrograms, kNumParameters)
{
+ A = 1.0;
+ B = 0.0;
+ fpd = 17;
bynL[0] = 1000;
bynL[1] = 301;
bynL[2] = 176;
@@ -58,31 +61,80 @@ void NotJustAnotherDither::getProgramName(char *name) {vst_strncpy (name, _progr
//airwindows likes to ignore this stuff. Make your own programs, and make a different plugin rather than
//trying to do versioning and preventing people from using older versions. Maybe they like the old one!
+static float pinParameter(float data)
+{
+ if (data < 0.0f) return 0.0f;
+ if (data > 1.0f) return 1.0f;
+ return data;
+}
VstInt32 NotJustAnotherDither::getChunk (void** data, bool isPreset)
{
+ float *chunkData = (float *)calloc(kNumParameters, sizeof(float));
+ chunkData[0] = A;
+ chunkData[1] = B;
+ /* Note: The way this is set up, it will break if you manage to save settings on an Intel
+ machine and load them on a PPC Mac. However, it's fine if you stick to the machine you
+ started with. */
+
+ *data = chunkData;
return kNumParameters * sizeof(float);
}
VstInt32 NotJustAnotherDither::setChunk (void* data, VstInt32 byteSize, bool isPreset)
{
+ float *chunkData = (float *)data;
+ A = pinParameter(chunkData[0]);
+ B = pinParameter(chunkData[1]);
+ /* We're ignoring byteSize as we found it to be a filthy liar */
+
+ /* calculate any other fields you need here - you could copy in
+ code from setParameter() here. */
return 0;
}
void NotJustAnotherDither::setParameter(VstInt32 index, float value) {
- }
+ switch (index) {
+ case kParamA: A = value; break;
+ case kParamB: B = value; break;
+ default: throw; // unknown parameter, shouldn't happen!
+ }
+}
float NotJustAnotherDither::getParameter(VstInt32 index) {
- return 0.0; //we only need to update the relevant name, this is simple to manage
+ switch (index) {
+ case kParamA: return A; break;
+ case kParamB: return B; break;
+ default: break; // unknown parameter, shouldn't happen!
+ } return 0.0; //we only need to update the relevant name, this is simple to manage
}
void NotJustAnotherDither::getParameterName(VstInt32 index, char *text) {
+ switch (index) {
+ case kParamA: vst_strncpy (text, "Quant", kVstMaxParamStrLen); break;
+ case kParamB: vst_strncpy (text, "DeRez", kVstMaxParamStrLen); break;
+ default: break; // unknown parameter, shouldn't happen!
+ } //this is our labels for displaying in the VST host
}
void NotJustAnotherDither::getParameterDisplay(VstInt32 index, char *text) {
+ switch (index) {
+ case kParamA: switch((VstInt32)( A * 1.999 )) //0 to almost edge of # of params
+ { case 0: vst_strncpy (text, "CD 16", kVstMaxParamStrLen); break;
+ case 1: vst_strncpy (text, "HD 24", kVstMaxParamStrLen); break;
+ default: break; // unknown parameter, shouldn't happen!
+ } break; //completed consoletype 'popup' parameter, exit
+ case kParamB: float2string (B, text, kVstMaxParamStrLen); break;
+ default: break; // unknown parameter, shouldn't happen!
+ } //this displays the values and handles 'popups' where it's discrete choices
}
void NotJustAnotherDither::getParameterLabel(VstInt32 index, char *text) {
+ switch (index) {
+ case kParamA: vst_strncpy (text, "", kVstMaxParamStrLen); break;
+ case kParamB: vst_strncpy (text, "", kVstMaxParamStrLen); break;
+ default: break; // unknown parameter, shouldn't happen!
+ }
}
VstInt32 NotJustAnotherDither::canDo(char *text)
diff --git a/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.h b/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.h
index 37abf4c..5ca0c0a 100755
--- a/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.h
+++ b/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDither.h
@@ -16,7 +16,9 @@
#include <math.h>
enum {
- kNumParameters = 0
+ kParamA = 0,
+ kParamB = 1,
+ kNumParameters = 2
}; //
const int kNumPrograms = 0;
@@ -55,7 +57,11 @@ private:
double bynR[13];
long double noiseShapingL;
long double noiseShapingR;
-
+ uint32_t fpd;
+ //default stuff
+
+ float A;
+ float B;
};
#endif
diff --git a/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDitherProc.cpp b/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDitherProc.cpp
index cbc6cc3..1a80711 100755
--- a/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDitherProc.cpp
+++ b/plugins/LinuxVST/src/NotJustAnotherDither/NotJustAnotherDitherProc.cpp
@@ -14,237 +14,143 @@ void NotJustAnotherDither::processReplacing(float **inputs, float **outputs, Vst
float* out1 = outputs[0];
float* out2 = outputs[1];
- long double inputSampleL;
- long double inputSampleR;
-
- double benfordize;
- int hotbinA;
- int hotbinB;
- double totalA;
- double totalB;
- float drySampleL;
- float drySampleR;
+ int processing = (VstInt32)( A * 1.999 );
+ bool highres = false;
+ if (processing == 1) highres = true;
+ float scaleFactor;
+ if (highres) scaleFactor = 8388608.0;
+ else scaleFactor = 32768.0;
+ float derez = B;
+ if (derez > 0.0) scaleFactor *= pow(1.0-derez,6);
+ if (scaleFactor < 0.0001) scaleFactor = 0.0001;
+ float outScale = scaleFactor;
+ if (outScale < 8.0) outScale = 8.0;
+
while (--sampleFrames >= 0)
{
- inputSampleL = *in1;
- inputSampleR = *in2;
- if (inputSampleL<1.2e-38 && -inputSampleL<1.2e-38) {
- static int noisesource = 0;
- //this declares a variable before anything else is compiled. It won't keep assigning
- //it to 0 for every sample, it's as if the declaration doesn't exist in this context,
- //but it lets me add this denormalization fix in a single place rather than updating
- //it in three different locations. The variable isn't thread-safe but this is only
- //a random seed and we can share it with whatever.
- noisesource = noisesource % 1700021; noisesource++;
- int residue = noisesource * noisesource;
- residue = residue % 170003; residue *= residue;
- residue = residue % 17011; residue *= residue;
- residue = residue % 1709; residue *= residue;
- residue = residue % 173; residue *= residue;
- residue = residue % 17;
- double applyresidue = residue;
- applyresidue *= 0.00000001;
- applyresidue *= 0.00000001;
- inputSampleL = applyresidue;
- }
- if (inputSampleR<1.2e-38 && -inputSampleR<1.2e-38) {
- static int noisesource = 0;
- noisesource = noisesource % 1700021; noisesource++;
- int residue = noisesource * noisesource;
- residue = residue % 170003; residue *= residue;
- residue = residue % 17011; residue *= residue;
- residue = residue % 1709; residue *= residue;
- residue = residue % 173; residue *= residue;
- residue = residue % 17;
- double applyresidue = residue;
- applyresidue *= 0.00000001;
- applyresidue *= 0.00000001;
- inputSampleR = applyresidue;
- //this denormalization routine produces a white noise at -300 dB which the noise
- //shaping will interact with to produce a bipolar output, but the noise is actually
- //all positive. That should stop any variables from going denormal, and the routine
- //only kicks in if digital black is input. As a final touch, if you save to 24-bit
- //the silence will return to being digital black again.
- }
- drySampleL = inputSampleL;
- drySampleR = inputSampleR;
+ long double inputSampleL = *in1;
+ long double inputSampleR = *in2;
+ if (fabs(inputSampleL)<1.18e-37) inputSampleL = fpd * 1.18e-37;
+ fpd ^= fpd << 13; fpd ^= fpd >> 17; fpd ^= fpd << 5;
+ if (fabs(inputSampleR)<1.18e-37) inputSampleR = fpd * 1.18e-37;
+ fpd ^= fpd << 13; fpd ^= fpd >> 17; fpd ^= fpd << 5;
+
+ inputSampleL *= scaleFactor;
+ inputSampleR *= scaleFactor;
+ //0-1 is now one bit, now we dither
+ //begin Not Just Another Dither
+ bool cutbinsL; cutbinsL = false;
+ bool cutbinsR; cutbinsR = false;
+ long double drySampleL; drySampleL = inputSampleL;
+ long double drySampleR; drySampleR = inputSampleR;
inputSampleL -= noiseShapingL;
inputSampleR -= noiseShapingR;
-
- inputSampleL *= 8388608.0;
- inputSampleR *= 8388608.0;
- //0-1 is now one bit, now we dither
-
- //begin L
- benfordize = floor(inputSampleL);
- while (benfordize >= 1.0) {benfordize /= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- hotbinA = floor(benfordize);
+
+ //NJAD L
+ long double benfordize; benfordize = floor(inputSampleL);
+ while (benfordize >= 1.0) benfordize /= 10;
+ while (benfordize < 1.0 && benfordize > 0.0000001) benfordize *= 10;
+ int hotbinA; hotbinA = floor(benfordize);
//hotbin becomes the Benford bin value for this number floored
- totalA = 0;
+ long double totalA; totalA = 0;
if ((hotbinA > 0) && (hotbinA < 10))
{
- bynL[hotbinA] += 1;
- totalA += (301-bynL[1]);
- totalA += (176-bynL[2]);
- totalA += (125-bynL[3]);
- totalA += (97-bynL[4]);
- totalA += (79-bynL[5]);
- totalA += (67-bynL[6]);
- totalA += (58-bynL[7]);
- totalA += (51-bynL[8]);
- totalA += (46-bynL[9]);
+ bynL[hotbinA] += 1; if (bynL[hotbinA] > 982) cutbinsL = true;
+ totalA += (301-bynL[1]); totalA += (176-bynL[2]); totalA += (125-bynL[3]);
+ totalA += (97-bynL[4]); totalA += (79-bynL[5]); totalA += (67-bynL[6]);
+ totalA += (58-bynL[7]); totalA += (51-bynL[8]); totalA += (46-bynL[9]);
bynL[hotbinA] -= 1;
- } else {hotbinA = 10;}
+ } else hotbinA = 10;
//produce total number- smaller is closer to Benford real
benfordize = ceil(inputSampleL);
- while (benfordize >= 1.0) {benfordize /= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- hotbinB = floor(benfordize);
+ while (benfordize >= 1.0) benfordize /= 10;
+ while (benfordize < 1.0 && benfordize > 0.0000001) benfordize *= 10;
+ int hotbinB; hotbinB = floor(benfordize);
//hotbin becomes the Benford bin value for this number ceiled
- totalB = 0;
+ long double totalB; totalB = 0;
if ((hotbinB > 0) && (hotbinB < 10))
{
- bynL[hotbinB] += 1;
- totalB += (301-bynL[1]);
- totalB += (176-bynL[2]);
- totalB += (125-bynL[3]);
- totalB += (97-bynL[4]);
- totalB += (79-bynL[5]);
- totalB += (67-bynL[6]);
- totalB += (58-bynL[7]);
- totalB += (51-bynL[8]);
- totalB += (46-bynL[9]);
+ bynL[hotbinB] += 1; if (bynL[hotbinB] > 982) cutbinsL = true;
+ totalB += (301-bynL[1]); totalB += (176-bynL[2]); totalB += (125-bynL[3]);
+ totalB += (97-bynL[4]); totalB += (79-bynL[5]); totalB += (67-bynL[6]);
+ totalB += (58-bynL[7]); totalB += (51-bynL[8]); totalB += (46-bynL[9]);
bynL[hotbinB] -= 1;
- } else {hotbinB = 10;}
+ } else hotbinB = 10;
//produce total number- smaller is closer to Benford real
- if (totalA < totalB)
- {
- bynL[hotbinA] += 1;
- inputSampleL = floor(inputSampleL);
- }
- else
- {
- bynL[hotbinB] += 1;
- inputSampleL = ceil(inputSampleL);
- }
+ long double outputSample;
+ if (totalA < totalB) {bynL[hotbinA] += 1; outputSample = floor(inputSampleL);}
+ else {bynL[hotbinB] += 1; outputSample = floor(inputSampleL+1);}
//assign the relevant one to the delay line
//and floor/ceil signal accordingly
+ if (cutbinsL) {
+ bynL[1] *= 0.99; bynL[2] *= 0.99; bynL[3] *= 0.99; bynL[4] *= 0.99; bynL[5] *= 0.99;
+ bynL[6] *= 0.99; bynL[7] *= 0.99; bynL[8] *= 0.99; bynL[9] *= 0.99; bynL[10] *= 0.99;
+ }
+ noiseShapingL += outputSample - drySampleL;
+ if (noiseShapingL > fabs(inputSampleL)) noiseShapingL = fabs(inputSampleL);
+ if (noiseShapingL < -fabs(inputSampleL)) noiseShapingL = -fabs(inputSampleL);
+ //finished NJAD L
- totalA = bynL[1] + bynL[2] + bynL[3] + bynL[4] + bynL[5] + bynL[6] + bynL[7] + bynL[8] + bynL[9];
- totalA /= 1000;
- if (totalA = 0) totalA = 1; // spotted by Laserbat: this 'scaling back' code doesn't. It always divides by the fallback of 1. Old NJAD doesn't scale back the things we're comparing against. Kept to retain known behavior, use the one in StudioTan and Monitoring for a tuned-as-intended NJAD.
- bynL[1] /= totalA;
- bynL[2] /= totalA;
- bynL[3] /= totalA;
- bynL[4] /= totalA;
- bynL[5] /= totalA;
- bynL[6] /= totalA;
- bynL[7] /= totalA;
- bynL[8] /= totalA;
- bynL[9] /= totalA;
- bynL[10] /= 2; //catchall for garbage data
- //end L
-
- //begin R
+ //NJAD R
benfordize = floor(inputSampleR);
- while (benfordize >= 1.0) {benfordize /= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
+ while (benfordize >= 1.0) benfordize /= 10;
+ while (benfordize < 1.0 && benfordize > 0.0000001) benfordize *= 10;
hotbinA = floor(benfordize);
//hotbin becomes the Benford bin value for this number floored
totalA = 0;
if ((hotbinA > 0) && (hotbinA < 10))
{
- bynR[hotbinA] += 1;
- totalA += (301-bynR[1]);
- totalA += (176-bynR[2]);
- totalA += (125-bynR[3]);
- totalA += (97-bynR[4]);
- totalA += (79-bynR[5]);
- totalA += (67-bynR[6]);
- totalA += (58-bynR[7]);
- totalA += (51-bynR[8]);
- totalA += (46-bynR[9]);
+ bynR[hotbinA] += 1; if (bynR[hotbinA] > 982) cutbinsR = true;
+ totalA += (301-bynR[1]); totalA += (176-bynR[2]); totalA += (125-bynR[3]);
+ totalA += (97-bynR[4]); totalA += (79-bynR[5]); totalA += (67-bynR[6]);
+ totalA += (58-bynR[7]); totalA += (51-bynR[8]); totalA += (46-bynR[9]);
bynR[hotbinA] -= 1;
- } else {hotbinA = 10;}
+ } else hotbinA = 10;
//produce total number- smaller is closer to Benford real
benfordize = ceil(inputSampleR);
- while (benfordize >= 1.0) {benfordize /= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
+ while (benfordize >= 1.0) benfordize /= 10;
+ while (benfordize < 1.0 && benfordize > 0.0000001) benfordize *= 10;
hotbinB = floor(benfordize);
//hotbin becomes the Benford bin value for this number ceiled
totalB = 0;
if ((hotbinB > 0) && (hotbinB < 10))
{
- bynR[hotbinB] += 1;
- totalB += (301-bynR[1]);
- totalB += (176-bynR[2]);
- totalB += (125-bynR[3]);
- totalB += (97-bynR[4]);
- totalB += (79-bynR[5]);
- totalB += (67-bynR[6]);
- totalB += (58-bynR[7]);
- totalB += (51-bynR[8]);
- totalB += (46-bynR[9]);
+ bynR[hotbinB] += 1; if (bynR[hotbinB] > 982) cutbinsR = true;
+ totalB += (301-bynR[1]); totalB += (176-bynR[2]); totalB += (125-bynR[3]);
+ totalB += (97-bynR[4]); totalB += (79-bynR[5]); totalB += (67-bynR[6]);
+ totalB += (58-bynR[7]); totalB += (51-bynR[8]); totalB += (46-bynR[9]);
bynR[hotbinB] -= 1;
- } else {hotbinB = 10;}
+ } else hotbinB = 10;
//produce total number- smaller is closer to Benford real
- if (totalA < totalB)
- {
- bynR[hotbinA] += 1;
- inputSampleR = floor(inputSampleR);
- }
- else
- {
- bynR[hotbinB] += 1;
- inputSampleR = ceil(inputSampleR);
- }
+ if (totalA < totalB) {bynR[hotbinA] += 1; outputSample = floor(inputSampleR);}
+ else {bynR[hotbinB] += 1; outputSample = floor(inputSampleR+1);}
//assign the relevant one to the delay line
//and floor/ceil signal accordingly
- totalA = bynR[1] + bynR[2] + bynR[3] + bynR[4] + bynR[5] + bynR[6] + bynR[7] + bynR[8] + bynR[9];
- totalA /= 1000;
- if (totalA = 0) totalA = 1; // spotted by Laserbat: this 'scaling back' code doesn't. It always divides by the fallback of 1. Old NJAD doesn't scale back the things we're comparing against. Kept to retain known behavior, use the one in StudioTan and Monitoring for a tuned-as-intended NJAD.
- bynR[1] /= totalA;
- bynR[2] /= totalA;
- bynR[3] /= totalA;
- bynR[4] /= totalA;
- bynR[5] /= totalA;
- bynR[6] /= totalA;
- bynR[7] /= totalA;
- bynR[8] /= totalA;
- bynR[9] /= totalA;
- bynR[10] /= 2; //catchall for garbage data
- //end R
+ if (cutbinsR) {
+ bynR[1] *= 0.99; bynR[2] *= 0.99; bynR[3] *= 0.99; bynR[4] *= 0.99; bynR[5] *= 0.99;
+ bynR[6] *= 0.99; bynR[7] *= 0.99; bynR[8] *= 0.99; bynR[9] *= 0.99; bynR[10] *= 0.99;
+ }
+ noiseShapingR += outputSample - drySampleR;
+ if (noiseShapingR > fabs(inputSampleR)) noiseShapingR = fabs(inputSampleR);
+ if (noiseShapingR < -fabs(inputSampleR)) noiseShapingR = -fabs(inputSampleR);
+ //finished NJAD R
+
- inputSampleL /= 8388608.0;
- inputSampleR /= 8388608.0;
-
- noiseShapingL += inputSampleL - drySampleL;
- noiseShapingR += inputSampleR - drySampleR;
+ inputSampleL /= outScale;
+ inputSampleR /= outScale;
+ if (inputSampleL > 1.0) inputSampleL = 1.0;
+ if (inputSampleL < -1.0) inputSampleL = -1.0;
+ if (inputSampleR > 1.0) inputSampleR = 1.0;
+ if (inputSampleR < -1.0) inputSampleR = -1.0;
+
*out1 = inputSampleL;
*out2 = inputSampleR;
@@ -262,237 +168,143 @@ void NotJustAnotherDither::processDoubleReplacing(double **inputs, double **outp
double* out1 = outputs[0];
double* out2 = outputs[1];
-
- long double inputSampleL;
- long double inputSampleR;
-
- double benfordize;
- int hotbinA;
- int hotbinB;
- double totalA;
- double totalB;
- double drySampleL;
- double drySampleR;
+ int processing = (VstInt32)( A * 1.999 );
+ bool highres = false;
+ if (processing == 1) highres = true;
+ float scaleFactor;
+ if (highres) scaleFactor = 8388608.0;
+ else scaleFactor = 32768.0;
+ float derez = B;
+ if (derez > 0.0) scaleFactor *= pow(1.0-derez,6);
+ if (scaleFactor < 0.0001) scaleFactor = 0.0001;
+ float outScale = scaleFactor;
+ if (outScale < 8.0) outScale = 8.0;
+
while (--sampleFrames >= 0)
{
- inputSampleL = *in1;
- inputSampleR = *in2;
- if (inputSampleL<1.2e-38 && -inputSampleL<1.2e-38) {
- static int noisesource = 0;
- //this declares a variable before anything else is compiled. It won't keep assigning
- //it to 0 for every sample, it's as if the declaration doesn't exist in this context,
- //but it lets me add this denormalization fix in a single place rather than updating
- //it in three different locations. The variable isn't thread-safe but this is only
- //a random seed and we can share it with whatever.
- noisesource = noisesource % 1700021; noisesource++;
- int residue = noisesource * noisesource;
- residue = residue % 170003; residue *= residue;
- residue = residue % 17011; residue *= residue;
- residue = residue % 1709; residue *= residue;
- residue = residue % 173; residue *= residue;
- residue = residue % 17;
- double applyresidue = residue;
- applyresidue *= 0.00000001;
- applyresidue *= 0.00000001;
- inputSampleL = applyresidue;
- }
- if (inputSampleR<1.2e-38 && -inputSampleR<1.2e-38) {
- static int noisesource = 0;
- noisesource = noisesource % 1700021; noisesource++;
- int residue = noisesource * noisesource;
- residue = residue % 170003; residue *= residue;
- residue = residue % 17011; residue *= residue;
- residue = residue % 1709; residue *= residue;
- residue = residue % 173; residue *= residue;
- residue = residue % 17;
- double applyresidue = residue;
- applyresidue *= 0.00000001;
- applyresidue *= 0.00000001;
- inputSampleR = applyresidue;
- //this denormalization routine produces a white noise at -300 dB which the noise
- //shaping will interact with to produce a bipolar output, but the noise is actually
- //all positive. That should stop any variables from going denormal, and the routine
- //only kicks in if digital black is input. As a final touch, if you save to 24-bit
- //the silence will return to being digital black again.
- }
- drySampleL = inputSampleL;
- drySampleR = inputSampleR;
-
- inputSampleL -= noiseShapingL;
- inputSampleR -= noiseShapingR;
+ long double inputSampleL = *in1;
+ long double inputSampleR = *in2;
+ if (fabs(inputSampleL)<1.18e-43) inputSampleL = fpd * 1.18e-43;
+ fpd ^= fpd << 13; fpd ^= fpd >> 17; fpd ^= fpd << 5;
+ if (fabs(inputSampleR)<1.18e-43) inputSampleR = fpd * 1.18e-43;
+ fpd ^= fpd << 13; fpd ^= fpd >> 17; fpd ^= fpd << 5;
- inputSampleL *= 8388608.0;
- inputSampleR *= 8388608.0;
+ inputSampleL *= scaleFactor;
+ inputSampleR *= scaleFactor;
//0-1 is now one bit, now we dither
- //begin L
- benfordize = floor(inputSampleL);
- while (benfordize >= 1.0) {benfordize /= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- hotbinA = floor(benfordize);
+ //begin Not Just Another Dither
+ bool cutbinsL; cutbinsL = false;
+ bool cutbinsR; cutbinsR = false;
+ long double drySampleL; drySampleL = inputSampleL;
+ long double drySampleR; drySampleR = inputSampleR;
+ inputSampleL -= noiseShapingL;
+ inputSampleR -= noiseShapingR;
+
+ //NJAD L
+ long double benfordize; benfordize = floor(inputSampleL);
+ while (benfordize >= 1.0) benfordize /= 10;
+ while (benfordize < 1.0 && benfordize > 0.0000001) benfordize *= 10;
+ int hotbinA; hotbinA = floor(benfordize);
//hotbin becomes the Benford bin value for this number floored
- totalA = 0;
+ long double totalA; totalA = 0;
if ((hotbinA > 0) && (hotbinA < 10))
{
- bynL[hotbinA] += 1;
- totalA += (301-bynL[1]);
- totalA += (176-bynL[2]);
- totalA += (125-bynL[3]);
- totalA += (97-bynL[4]);
- totalA += (79-bynL[5]);
- totalA += (67-bynL[6]);
- totalA += (58-bynL[7]);
- totalA += (51-bynL[8]);
- totalA += (46-bynL[9]);
+ bynL[hotbinA] += 1; if (bynL[hotbinA] > 982) cutbinsL = true;
+ totalA += (301-bynL[1]); totalA += (176-bynL[2]); totalA += (125-bynL[3]);
+ totalA += (97-bynL[4]); totalA += (79-bynL[5]); totalA += (67-bynL[6]);
+ totalA += (58-bynL[7]); totalA += (51-bynL[8]); totalA += (46-bynL[9]);
bynL[hotbinA] -= 1;
- } else {hotbinA = 10;}
+ } else hotbinA = 10;
//produce total number- smaller is closer to Benford real
benfordize = ceil(inputSampleL);
- while (benfordize >= 1.0) {benfordize /= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- hotbinB = floor(benfordize);
+ while (benfordize >= 1.0) benfordize /= 10;
+ while (benfordize < 1.0 && benfordize > 0.0000001) benfordize *= 10;
+ int hotbinB; hotbinB = floor(benfordize);
//hotbin becomes the Benford bin value for this number ceiled
- totalB = 0;
+ long double totalB; totalB = 0;
if ((hotbinB > 0) && (hotbinB < 10))
{
- bynL[hotbinB] += 1;
- totalB += (301-bynL[1]);
- totalB += (176-bynL[2]);
- totalB += (125-bynL[3]);
- totalB += (97-bynL[4]);
- totalB += (79-bynL[5]);
- totalB += (67-bynL[6]);
- totalB += (58-bynL[7]);
- totalB += (51-bynL[8]);
- totalB += (46-bynL[9]);
+ bynL[hotbinB] += 1; if (bynL[hotbinB] > 982) cutbinsL = true;
+ totalB += (301-bynL[1]); totalB += (176-bynL[2]); totalB += (125-bynL[3]);
+ totalB += (97-bynL[4]); totalB += (79-bynL[5]); totalB += (67-bynL[6]);
+ totalB += (58-bynL[7]); totalB += (51-bynL[8]); totalB += (46-bynL[9]);
bynL[hotbinB] -= 1;
- } else {hotbinB = 10;}
+ } else hotbinB = 10;
//produce total number- smaller is closer to Benford real
- if (totalA < totalB)
- {
- bynL[hotbinA] += 1;
- inputSampleL = floor(inputSampleL);
- }
- else
- {
- bynL[hotbinB] += 1;
- inputSampleL = ceil(inputSampleL);
- }
+ long double outputSampleL;
+ if (totalA < totalB) {bynL[hotbinA] += 1; outputSampleL = floor(inputSampleL);}
+ else {bynL[hotbinB] += 1; outputSampleL = floor(inputSampleL+1);}
//assign the relevant one to the delay line
//and floor/ceil signal accordingly
+ if (cutbinsL) {
+ bynL[1] *= 0.99; bynL[2] *= 0.99; bynL[3] *= 0.99; bynL[4] *= 0.99; bynL[5] *= 0.99;
+ bynL[6] *= 0.99; bynL[7] *= 0.99; bynL[8] *= 0.99; bynL[9] *= 0.99; bynL[10] *= 0.99;
+ }
+ noiseShapingL += outputSampleL - drySampleL;
+ if (noiseShapingL > fabs(inputSampleL)) noiseShapingL = fabs(inputSampleL);
+ if (noiseShapingL < -fabs(inputSampleL)) noiseShapingL = -fabs(inputSampleL);
+ //finished NJAD L
- totalA = bynL[1] + bynL[2] + bynL[3] + bynL[4] + bynL[5] + bynL[6] + bynL[7] + bynL[8] + bynL[9];
- totalA /= 1000;
- if (totalA = 0) totalA = 1; // spotted by Laserbat: this 'scaling back' code doesn't. It always divides by the fallback of 1. Old NJAD doesn't scale back the things we're comparing against. Kept to retain known behavior, use the one in StudioTan and Monitoring for a tuned-as-intended NJAD.
- bynL[1] /= totalA;
- bynL[2] /= totalA;
- bynL[3] /= totalA;
- bynL[4] /= totalA;
- bynL[5] /= totalA;
- bynL[6] /= totalA;
- bynL[7] /= totalA;
- bynL[8] /= totalA;
- bynL[9] /= totalA;
- bynL[10] /= 2; //catchall for garbage data
- //end L
-
- //begin R
+ //NJAD R
benfordize = floor(inputSampleR);
- while (benfordize >= 1.0) {benfordize /= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
+ while (benfordize >= 1.0) benfordize /= 10;
+ while (benfordize < 1.0 && benfordize > 0.0000001) benfordize *= 10;
hotbinA = floor(benfordize);
//hotbin becomes the Benford bin value for this number floored
totalA = 0;
if ((hotbinA > 0) && (hotbinA < 10))
{
- bynR[hotbinA] += 1;
- totalA += (301-bynR[1]);
- totalA += (176-bynR[2]);
- totalA += (125-bynR[3]);
- totalA += (97-bynR[4]);
- totalA += (79-bynR[5]);
- totalA += (67-bynR[6]);
- totalA += (58-bynR[7]);
- totalA += (51-bynR[8]);
- totalA += (46-bynR[9]);
+ bynR[hotbinA] += 1; if (bynR[hotbinA] > 982) cutbinsR = true;
+ totalA += (301-bynR[1]); totalA += (176-bynR[2]); totalA += (125-bynR[3]);
+ totalA += (97-bynR[4]); totalA += (79-bynR[5]); totalA += (67-bynR[6]);
+ totalA += (58-bynR[7]); totalA += (51-bynR[8]); totalA += (46-bynR[9]);
bynR[hotbinA] -= 1;
- } else {hotbinA = 10;}
+ } else hotbinA = 10;
//produce total number- smaller is closer to Benford real
benfordize = ceil(inputSampleR);
- while (benfordize >= 1.0) {benfordize /= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
- if (benfordize < 1.0) {benfordize *= 10;}
+ while (benfordize >= 1.0) benfordize /= 10;
+ while (benfordize < 1.0 && benfordize > 0.0000001) benfordize *= 10;
hotbinB = floor(benfordize);
//hotbin becomes the Benford bin value for this number ceiled
totalB = 0;
if ((hotbinB > 0) && (hotbinB < 10))
{
- bynR[hotbinB] += 1;
- totalB += (301-bynR[1]);
- totalB += (176-bynR[2]);
- totalB += (125-bynR[3]);
- totalB += (97-bynR[4]);
- totalB += (79-bynR[5]);
- totalB += (67-bynR[6]);
- totalB += (58-bynR[7]);
- totalB += (51-bynR[8]);
- totalB += (46-bynR[9]);
+ bynR[hotbinB] += 1; if (bynR[hotbinB] > 982) cutbinsR = true;
+ totalB += (301-bynR[1]); totalB += (176-bynR[2]); totalB += (125-bynR[3]);
+ totalB += (97-bynR[4]); totalB += (79-bynR[5]); totalB += (67-bynR[6]);
+ totalB += (58-bynR[7]); totalB += (51-bynR[8]); totalB += (46-bynR[9]);
bynR[hotbinB] -= 1;
- } else {hotbinB = 10;}
+ } else hotbinB = 10;
//produce total number- smaller is closer to Benford real
- if (totalA < totalB)
- {
- bynR[hotbinA] += 1;
- inputSampleR = floor(inputSampleR);
- }
- else
- {
- bynR[hotbinB] += 1;
- inputSampleR = ceil(inputSampleR);
- }
+ long double outputSampleR;
+ if (totalA < totalB) {bynR[hotbinA] += 1; outputSampleR = floor(inputSampleR);}
+ else {bynR[hotbinB] += 1; outputSampleR = floor(inputSampleR+1);}
//assign the relevant one to the delay line
//and floor/ceil signal accordingly
- totalA = bynR[1] + bynR[2] + bynR[3] + bynR[4] + bynR[5] + bynR[6] + bynR[7] + bynR[8] + bynR[9];
- totalA /= 1000;
- if (totalA = 0) totalA = 1; // spotted by Laserbat: this 'scaling back' code doesn't. It always divides by the fallback of 1. Old NJAD doesn't scale back the things we're comparing against. Kept to retain known behavior, use the one in StudioTan and Monitoring for a tuned-as-intended NJAD.
- bynR[1] /= totalA;
- bynR[2] /= totalA;
- bynR[3] /= totalA;
- bynR[4] /= totalA;
- bynR[5] /= totalA;
- bynR[6] /= totalA;
- bynR[7] /= totalA;
- bynR[8] /= totalA;
- bynR[9] /= totalA;
- bynR[10] /= 2; //catchall for garbage data
- //end R
+ if (cutbinsR) {
+ bynR[1] *= 0.99; bynR[2] *= 0.99; bynR[3] *= 0.99; bynR[4] *= 0.99; bynR[5] *= 0.99;
+ bynR[6] *= 0.99; bynR[7] *= 0.99; bynR[8] *= 0.99; bynR[9] *= 0.99; bynR[10] *= 0.99;
+ }
+ noiseShapingR += outputSampleR - drySampleR;
+ if (noiseShapingR > fabs(inputSampleR)) noiseShapingR = fabs(inputSampleR);
+ if (noiseShapingR < -fabs(inputSampleR)) noiseShapingR = -fabs(inputSampleR);
+ //finished NJAD R
+
- inputSampleL /= 8388608.0;
- inputSampleR /= 8388608.0;
+ inputSampleL = outputSampleL / outScale;
+ inputSampleR = outputSampleR / outScale;
- noiseShapingL += inputSampleL - drySampleL;
- noiseShapingR += inputSampleR - drySampleR;
+ if (inputSampleL > 1.0) inputSampleL = 1.0;
+ if (inputSampleL < -1.0) inputSampleL = -1.0;
+ if (inputSampleR > 1.0) inputSampleR = 1.0;
+ if (inputSampleR < -1.0) inputSampleR = -1.0;
*out1 = inputSampleL;
*out2 = inputSampleR;