From b0027d12906d43550c78f52962196e19ab3a4c31 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 5 Sep 2021 20:27:00 -0400 Subject: [PATCH] Add Mackity and MackEQ Airwindows FX (#4998) Closes #4996 --- libs/airwindows/CMakeLists.txt | 6 + .../src/AirWinBaseClass_pluginRegistry.cpp | 5 + libs/airwindows/src/MackEQ.cpp | 181 +++++++ libs/airwindows/src/MackEQ.h | 94 ++++ libs/airwindows/src/MackEQProc.cpp | 457 ++++++++++++++++++ libs/airwindows/src/Mackity.cpp | 147 ++++++ libs/airwindows/src/Mackity.h | 77 +++ libs/airwindows/src/MackityProc.cpp | 217 +++++++++ 8 files changed, 1184 insertions(+) create mode 100644 libs/airwindows/src/MackEQ.cpp create mode 100644 libs/airwindows/src/MackEQ.h create mode 100644 libs/airwindows/src/MackEQProc.cpp create mode 100644 libs/airwindows/src/Mackity.cpp create mode 100644 libs/airwindows/src/Mackity.h create mode 100644 libs/airwindows/src/MackityProc.cpp diff --git a/libs/airwindows/CMakeLists.txt b/libs/airwindows/CMakeLists.txt index 4c858a942da..1b43daeeb77 100644 --- a/libs/airwindows/CMakeLists.txt +++ b/libs/airwindows/CMakeLists.txt @@ -96,6 +96,12 @@ add_library(${PROJECT_NAME} src/Loud.cpp src/Loud.h src/LoudProc.cpp + src/Mackity.cpp + src/Mackity.h + src/MackityProc.cpp + src/MackEQ.cpp + src/MackEQ.h + src/MackEQProc.cpp src/MatrixVerb.cpp src/MatrixVerb.h src/MatrixVerbProc.cpp diff --git a/libs/airwindows/src/AirWinBaseClass_pluginRegistry.cpp b/libs/airwindows/src/AirWinBaseClass_pluginRegistry.cpp index 257ba4fd039..34d5edf534b 100644 --- a/libs/airwindows/src/AirWinBaseClass_pluginRegistry.cpp +++ b/libs/airwindows/src/AirWinBaseClass_pluginRegistry.cpp @@ -30,6 +30,8 @@ #include "IronOxide5.h" #include "Logical4.h" #include "Loud.h" +#include "Mackity.h" +#include "MackEQ.h" #include "MatrixVerb.h" #include "Melt.h" #include "Mojo.h" @@ -166,6 +168,9 @@ std::vector AirWinBaseClass::pluginRegistry() reg.emplace_back(create, id++, 440, gnStereo, "Triple Spread" ); reg.emplace_back(create, id++, 223, gnAmbience, "Chamber" ); + + reg.emplace_back(create, id++, 355, gnSaturation, "Mackity" ); + reg.emplace_back(create, id++, 430, gnFilter, "MackEQ" ); return reg; } diff --git a/libs/airwindows/src/MackEQ.cpp b/libs/airwindows/src/MackEQ.cpp new file mode 100644 index 00000000000..782a579efc6 --- /dev/null +++ b/libs/airwindows/src/MackEQ.cpp @@ -0,0 +1,181 @@ +/* ======================================== + * MackEQ - MackEQ.h + * Copyright (c) 2016 airwindows, All rights reserved + * ======================================== */ + +#ifndef __MackEQ_H +#include "MackEQ.h" +#endif + +namespace MackEQ { + + +// AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new MackEQ(audioMaster);} + +MackEQ::MackEQ(audioMasterCallback audioMaster) : + AudioEffectX(audioMaster, kNumPrograms, kNumParameters) +{ + A = 0.1; + B = 0.5; + C = 0.5; + D = 1.0; + E = 1.0; + + iirSampleAL = 0.0; + iirSampleBL = 0.0; + iirSampleCL = 0.0; + iirSampleDL = 0.0; + iirSampleEL = 0.0; + iirSampleFL = 0.0; + iirSampleAR = 0.0; + iirSampleBR = 0.0; + iirSampleCR = 0.0; + iirSampleDR = 0.0; + iirSampleER = 0.0; + iirSampleFR = 0.0; + for (int x = 0; x < 15; x++) {biquadA[x] = 0.0; biquadB[x] = 0.0; biquadC[x] = 0.0; biquadD[x] = 0.0;} + + fpdL = 1.0; while (fpdL < 16386) fpdL = rand()*UINT32_MAX; + fpdR = 1.0; while (fpdR < 16386) fpdR = rand()*UINT32_MAX; + //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 +} + +MackEQ::~MackEQ() {} +VstInt32 MackEQ::getVendorVersion () {return 1000;} +void MackEQ::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);} +void MackEQ::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 MackEQ::getChunk (void** data, bool isPreset) +{ + float *chunkData = (float *)calloc(kNumParameters, sizeof(float)); + chunkData[0] = A; + chunkData[1] = B; + chunkData[2] = C; + chunkData[3] = D; + chunkData[4] = E; + /* 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 MackEQ::setChunk (void* data, VstInt32 byteSize, bool isPreset) +{ + float *chunkData = (float *)data; + A = pinParameter(chunkData[0]); + B = pinParameter(chunkData[1]); + C = pinParameter(chunkData[2]); + D = pinParameter(chunkData[3]); + E = pinParameter(chunkData[4]); + /* 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 MackEQ::setParameter(VstInt32 index, float value) { + switch (index) { + case kParamA: A = value; break; + case kParamB: B = value; break; + case kParamC: C = value; break; + case kParamD: D = value; break; + case kParamE: E = value; break; + default: throw; // unknown parameter, shouldn't happen! + } +} + +float MackEQ::getParameter(VstInt32 index) { + switch (index) { + case kParamA: return A; break; + case kParamB: return B; break; + case kParamC: return C; break; + case kParamD: return D; break; + case kParamE: return E; 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 MackEQ::getParameterName(VstInt32 index, char *text) { + switch (index) { + case kParamA: vst_strncpy (text, "Trim", kVstMaxParamStrLen); break; + case kParamB: vst_strncpy (text, "Hi", kVstMaxParamStrLen); break; + case kParamC: vst_strncpy (text, "Lo", kVstMaxParamStrLen); break; + case kParamD: vst_strncpy (text, "Gain", kVstMaxParamStrLen); break; + case kParamE: vst_strncpy (text, "Dry/Wet", kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } //this is our labels for displaying in the VST host +} + +void MackEQ::getParameterDisplay(VstInt32 index, char *text, float extVal, bool isExternal) { + switch (index) { + case kParamA: float2string (EXTV(A) * 100, text, kVstMaxParamStrLen); break; + case kParamB: float2string (EXTV(B) * 100, text, kVstMaxParamStrLen); break; + case kParamC: float2string (EXTV(C) * 100, text, kVstMaxParamStrLen); break; + case kParamD: float2string (EXTV(D) * 100, text, kVstMaxParamStrLen); break; + case kParamE: float2string (EXTV(E) * 100, text, kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } //this displays the values and handles 'popups' where it's discrete choices +} + +void MackEQ::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; + case kParamD: vst_strncpy (text, "%", kVstMaxParamStrLen); break; + case kParamE: vst_strncpy (text, "%", kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } +} + + +bool MackEQ::parseParameterValueFromString(VstInt32 index, const char *str, float &f) +{ + auto v = std::atof(str); + f = v / 100.0; + return true; +} + +VstInt32 MackEQ::canDo(char *text) +{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know + +bool MackEQ::getEffectName(char* name) { + vst_strncpy(name, "MackEQ", kVstMaxProductStrLen); return true; +} + +VstPlugCategory MackEQ::getPlugCategory() {return kPlugCategEffect;} + +bool MackEQ::getProductString(char* text) { + vst_strncpy (text, "airwindows MackEQ", kVstMaxProductStrLen); return true; +} + +bool MackEQ::getVendorString(char* text) { + vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true; +} + + +} // end namespace MackEQ + diff --git a/libs/airwindows/src/MackEQ.h b/libs/airwindows/src/MackEQ.h new file mode 100644 index 00000000000..b9dfd09d995 --- /dev/null +++ b/libs/airwindows/src/MackEQ.h @@ -0,0 +1,94 @@ +/* ======================================== + * MackEQ - MackEQ.h + * Created 8/12/11 by SPIAdmin + * Copyright (c) 2011 __MyCompanyName__, All rights reserved + * ======================================== */ + +#ifndef __MackEQ_H +#define __MackEQ_H + +#ifndef __audioeffect__ +#include "airwindows/AirWinBaseClass.h" +#endif + +#include +#include +#include + +namespace MackEQ { + +enum { + kParamA = 0, + kParamB = 1, + kParamC = 2, + kParamD = 3, + kParamE = 4, + kNumParameters = 5 +}; // + +const int kNumPrograms = 0; +const int kNumInputs = 2; +const int kNumOutputs = 2; +const unsigned long kUniqueId = 'mkeq'; //Change this to what the AU identity is! + +class MackEQ : + public AudioEffectX +{ +public: + MackEQ(audioMasterCallback audioMaster); + ~MackEQ(); + 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, float extVal, bool isExternal); // text description of the current value + virtual bool parseParameterValueFromString(VstInt32 index, const char *str, float &f); + + virtual VstInt32 canDo(char *text); +private: + char _programName[kVstMaxProgNameLen + 1]; + std::set< std::string > _canDo; + + long double iirSampleAL; + long double iirSampleBL; + long double iirSampleCL; + long double iirSampleDL; + long double iirSampleEL; + long double iirSampleFL; + long double iirSampleAR; + long double iirSampleBR; + long double iirSampleCR; + long double iirSampleDR; + long double iirSampleER; + long double iirSampleFR; + long double biquadA[15]; + long double biquadB[15]; + long double biquadC[15]; + long double biquadD[15]; + + uint32_t fpdL; + uint32_t fpdR; + //default stuff + + float A; + float B; + float C; + float D; + float E; //parameters. Always 0-1, and we scale/alter them elsewhere. + +}; + +} // end namespace MackEQ + +#endif diff --git a/libs/airwindows/src/MackEQProc.cpp b/libs/airwindows/src/MackEQProc.cpp new file mode 100644 index 00000000000..faeb76f5ace --- /dev/null +++ b/libs/airwindows/src/MackEQProc.cpp @@ -0,0 +1,457 @@ +/* ======================================== + * MackEQ - MackEQ.h + * Copyright (c) 2016 airwindows, All rights reserved + * ======================================== */ + +#ifndef __MackEQ_H +#include "MackEQ.h" +#endif + +namespace MackEQ { + + +void MackEQ::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) +{ + float* in1 = inputs[0]; + float* in2 = inputs[1]; + float* out1 = outputs[0]; + float* out2 = outputs[1]; + + double overallscale = 1.0; + overallscale /= 44100.0; + overallscale *= getSampleRate(); + + double inTrim = A*10.0; + inTrim *= inTrim; + + double gainHigh = pow(B,2)*4.0; + double outHigh = sqrt(B); + double gainBass = pow(C,2)*4.0; + double outBass = sqrt(C); + double outPad = D; + double wet = E; + + double iirAmountA = 0.001860867/overallscale; + double iirAmountB = 0.000287496/overallscale; + double iirBassMid = 0.159/overallscale; + double iirMidHigh = 0.236/overallscale; + + biquadD[0] = biquadC[0] = biquadB[0] = biquadA[0] = 19160.0 / getSampleRate(); + biquadA[1] = 0.431684981684982; + biquadB[1] = 1.1582298; + biquadC[1] = 0.657027382751269; + biquadD[1] = 1.076210852946577; + + double K = tan(M_PI * biquadA[0]); //lowpass + double norm = 1.0 / (1.0 + K / biquadA[1] + K * K); + biquadA[2] = K * K * norm; + biquadA[3] = 2.0 * biquadA[2]; + biquadA[4] = biquadA[2]; + biquadA[5] = 2.0 * (K * K - 1.0) * norm; + biquadA[6] = (1.0 - K / biquadA[1] + K * K) * norm; + + K = tan(M_PI * biquadB[0]); + norm = 1.0 / (1.0 + K / biquadB[1] + K * K); + biquadB[2] = K * K * norm; + biquadB[3] = 2.0 * biquadB[2]; + biquadB[4] = biquadB[2]; + biquadB[5] = 2.0 * (K * K - 1.0) * norm; + biquadB[6] = (1.0 - K / biquadB[1] + K * K) * norm; + + K = tan(M_PI * biquadC[0]); + norm = 1.0 / (1.0 + K / biquadC[1] + K * K); + biquadC[2] = K * K * norm; + biquadC[3] = 2.0 * biquadC[2]; + biquadC[4] = biquadC[2]; + biquadC[5] = 2.0 * (K * K - 1.0) * norm; + biquadC[6] = (1.0 - K / biquadC[1] + K * K) * norm; + + K = tan(M_PI * biquadD[0]); + norm = 1.0 / (1.0 + K / biquadD[1] + K * K); + biquadD[2] = K * K * norm; + biquadD[3] = 2.0 * biquadD[2]; + biquadD[4] = biquadD[2]; + biquadD[5] = 2.0 * (K * K - 1.0) * norm; + biquadD[6] = (1.0 - K / biquadD[1] + K * K) * norm; + + while (--sampleFrames >= 0) + { + long double inputSampleL = *in1; + long double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-37) inputSampleL = fpdL * 1.18e-37; + if (fabs(inputSampleR)<1.18e-37) inputSampleR = fpdR * 1.18e-37; + long double drySampleL = inputSampleL; + long double drySampleR = inputSampleR; + + if (fabs(iirSampleAL)<1.18e-37) iirSampleAL = 0.0; + iirSampleAL = (iirSampleAL * (1.0 - iirAmountA)) + (inputSampleL * iirAmountA); + inputSampleL -= iirSampleAL; + if (fabs(iirSampleAR)<1.18e-37) iirSampleAR = 0.0; + iirSampleAR = (iirSampleAR * (1.0 - iirAmountA)) + (inputSampleR * iirAmountA); + inputSampleR -= iirSampleAR; + + if (inTrim != 1.0) {inputSampleL *= inTrim; inputSampleR *= inTrim;} + + //begin Mackity input stage + long double outSampleL = biquadA[2]*inputSampleL+biquadA[3]*biquadA[7]+biquadA[4]*biquadA[8]-biquadA[5]*biquadA[9]-biquadA[6]*biquadA[10]; + biquadA[8] = biquadA[7]; biquadA[7] = inputSampleL; inputSampleL = outSampleL; biquadA[10] = biquadA[9]; biquadA[9] = inputSampleL; //DF1 left + + long double outSampleR = biquadA[2]*inputSampleR+biquadA[3]*biquadA[11]+biquadA[4]*biquadA[12]-biquadA[5]*biquadA[13]-biquadA[6]*biquadA[14]; + biquadA[12] = biquadA[11]; biquadA[11] = inputSampleR; inputSampleR = outSampleR; biquadA[14] = biquadA[13]; biquadA[13] = inputSampleR; //DF1 right + + if (inputSampleL > 1.0) inputSampleL = 1.0; + if (inputSampleL < -1.0) inputSampleL = -1.0; + inputSampleL -= pow(inputSampleL,5)*0.1768; + if (inputSampleR > 1.0) inputSampleR = 1.0; + if (inputSampleR < -1.0) inputSampleR = -1.0; + inputSampleR -= pow(inputSampleR,5)*0.1768; + + outSampleL = biquadB[2]*inputSampleL+biquadB[3]*biquadB[7]+biquadB[4]*biquadB[8]-biquadB[5]*biquadB[9]-biquadB[6]*biquadB[10]; + biquadB[8] = biquadB[7]; biquadB[7] = inputSampleL; inputSampleL = outSampleL; biquadB[10] = biquadB[9]; biquadB[9] = inputSampleL; //DF1 left + + outSampleR = biquadB[2]*inputSampleR+biquadB[3]*biquadB[11]+biquadB[4]*biquadB[12]-biquadB[5]*biquadB[13]-biquadB[6]*biquadB[14]; + biquadB[12] = biquadB[11]; biquadB[11] = inputSampleR; inputSampleR = outSampleR; biquadB[14] = biquadB[13]; biquadB[13] = inputSampleR; //DF1 right + + if (fabs(iirSampleBL)<1.18e-37) iirSampleBL = 0.0; + iirSampleBL = (iirSampleBL * (1.0 - iirAmountB)) + (inputSampleL * iirAmountB); + inputSampleL -= iirSampleBL; + if (fabs(iirSampleBR)<1.18e-37) iirSampleBR = 0.0; + iirSampleBR = (iirSampleBR * (1.0 - iirAmountB)) + (inputSampleR * iirAmountB); + inputSampleR -= iirSampleBR; + //end Mackity input stage + + //begin EQ section + if (fabs(iirSampleCL)<1.18e-37) iirSampleCL = 0.0; + iirSampleCL = (iirSampleCL * (1.0 - iirBassMid)) + (inputSampleL * iirBassMid); + if (fabs(iirSampleCR)<1.18e-37) iirSampleCR = 0.0; + iirSampleCR = (iirSampleCR * (1.0 - iirBassMid)) + (inputSampleR * iirBassMid); + + long double bassSampleL = iirSampleCL; + long double midSampleL = inputSampleL - bassSampleL; + long double bassSampleR = iirSampleCR; + long double midSampleR = inputSampleR - bassSampleR; + + if (gainBass != 1.0) {bassSampleL *= gainBass; bassSampleR *= gainBass;} + + if (bassSampleL > 1.0) bassSampleL = 1.0; + if (bassSampleL < -1.0) bassSampleL = -1.0; + bassSampleL -= pow(bassSampleL,5)*0.1768; + if (bassSampleR > 1.0) bassSampleR = 1.0; + if (bassSampleR < -1.0) bassSampleR = -1.0; + bassSampleR -= pow(bassSampleR,5)*0.1768; + + if (fabs(iirSampleDL)<1.18e-37) iirSampleDL = 0.0; + iirSampleDL = (iirSampleDL * (1.0 - iirBassMid)) + (bassSampleL * iirBassMid); + bassSampleL = iirSampleDL; + if (fabs(iirSampleDR)<1.18e-37) iirSampleDR = 0.0; + iirSampleDR = (iirSampleDR * (1.0 - iirBassMid)) + (bassSampleR * iirBassMid); + bassSampleR = iirSampleDR; + //we've taken the bass sample, made the mids from it, distorted it + //and hit it with another pole of darkening. + //mid sample is still normal from undistorted bass + + if (fabs(iirSampleEL)<1.18e-37) iirSampleEL = 0.0; + iirSampleEL = (iirSampleEL * (1.0 - iirMidHigh)) + (midSampleL * iirMidHigh); + long double highSampleL = midSampleL - iirSampleEL; + midSampleL = iirSampleEL; + if (fabs(iirSampleER)<1.18e-37) iirSampleER = 0.0; + iirSampleER = (iirSampleER * (1.0 - iirMidHigh)) + (midSampleR * iirMidHigh); + long double highSampleR = midSampleR - iirSampleER; + midSampleR = iirSampleER; + //here is where we make the high sample out of the mid, and take highs + //away from the mid. + + if (fabs(iirSampleFL)<1.18e-37) iirSampleFL = 0.0; + iirSampleFL = (iirSampleFL * (1.0 - iirMidHigh)) + (highSampleL * iirMidHigh); + highSampleL -= iirSampleFL; + if (fabs(iirSampleFR)<1.18e-37) iirSampleFR = 0.0; + iirSampleFR = (iirSampleFR * (1.0 - iirMidHigh)) + (highSampleR * iirMidHigh); + highSampleR -= iirSampleFR; + + if (gainHigh != 1.0) {highSampleL *= gainHigh; highSampleR *= gainHigh;} + + if (highSampleL > 1.0) highSampleL = 1.0; + if (highSampleL < -1.0) highSampleL = -1.0; + highSampleL -= pow(highSampleL,5)*0.1768; + if (highSampleR > 1.0) highSampleR = 1.0; + if (highSampleR < -1.0) highSampleR = -1.0; + highSampleR -= pow(highSampleR,5)*0.1768; + //highpassing HighSample another stage, before distorting it + + inputSampleL = ((bassSampleL*outBass) + midSampleL + (highSampleL*outHigh))*4.0; + inputSampleR = ((bassSampleR*outBass) + midSampleR + (highSampleR*outHigh))*4.0; + //end EQ section + + outSampleL = biquadC[2]*inputSampleL+biquadC[3]*biquadC[7]+biquadC[4]*biquadC[8]-biquadC[5]*biquadC[9]-biquadC[6]*biquadC[10]; + biquadC[8] = biquadC[7]; biquadC[7] = inputSampleL; inputSampleL = outSampleL; biquadC[10] = biquadC[9]; biquadC[9] = inputSampleL; //DF1 left + + outSampleR = biquadC[2]*inputSampleR+biquadC[3]*biquadC[11]+biquadC[4]*biquadC[12]-biquadC[5]*biquadC[13]-biquadC[6]*biquadC[14]; + biquadC[12] = biquadC[11]; biquadC[11] = inputSampleR; inputSampleR = outSampleR; biquadC[14] = biquadC[13]; biquadC[13] = inputSampleR; //DF1 right + + if (inputSampleL > 1.0) inputSampleL = 1.0; + if (inputSampleL < -1.0) inputSampleL = -1.0; + inputSampleL -= pow(inputSampleL,5)*0.1768; + if (inputSampleR > 1.0) inputSampleR = 1.0; + if (inputSampleR < -1.0) inputSampleR = -1.0; + inputSampleR -= pow(inputSampleR,5)*0.1768; + + outSampleL = biquadD[2]*inputSampleL+biquadD[3]*biquadD[7]+biquadD[4]*biquadD[8]-biquadD[5]*biquadD[9]-biquadD[6]*biquadD[10]; + biquadD[8] = biquadD[7]; biquadD[7] = inputSampleL; inputSampleL = outSampleL; biquadD[10] = biquadD[9]; biquadD[9] = inputSampleL; //DF1 left + + outSampleR = biquadD[2]*inputSampleR+biquadD[3]*biquadD[11]+biquadD[4]*biquadD[12]-biquadD[5]*biquadD[13]-biquadD[6]*biquadD[14]; + biquadD[12] = biquadD[11]; biquadD[11] = inputSampleR; inputSampleR = outSampleR; biquadD[14] = biquadD[13]; biquadD[13] = inputSampleR; //DF1 right + + if (outPad != 1.0) { + inputSampleL *= outPad; + inputSampleR *= outPad; + } + + if (wet !=1.0) { + inputSampleL = (inputSampleL * wet) + (drySampleL * (1.0-wet)); + inputSampleR = (inputSampleR * wet) + (drySampleR * (1.0-wet)); + } + //Dry/Wet control, defaults to the last slider + + //begin 32 bit stereo floating point dither + int expon; frexpf((float)inputSampleL, &expon); + fpdL ^= fpdL << 13; fpdL ^= fpdL >> 17; fpdL ^= fpdL << 5; + inputSampleL += ((double(fpdL)-uint32_t(0x7fffffff)) * 5.5e-36l * pow(2,expon+62)); + frexpf((float)inputSampleR, &expon); + fpdR ^= fpdR << 13; fpdR ^= fpdR >> 17; fpdR ^= fpdR << 5; + inputSampleR += ((double(fpdR)-uint32_t(0x7fffffff)) * 5.5e-36l * pow(2,expon+62)); + //end 32 bit stereo floating point dither + + *out1 = inputSampleL; + *out2 = inputSampleR; + + in1++; + in2++; + out1++; + out2++; + } +} + +void MackEQ::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames) +{ + double* in1 = inputs[0]; + double* in2 = inputs[1]; + double* out1 = outputs[0]; + double* out2 = outputs[1]; + + double overallscale = 1.0; + overallscale /= 44100.0; + overallscale *= getSampleRate(); + + double inTrim = A*10.0; + inTrim *= inTrim; + + double gainHigh = pow(B,2)*4.0; + double outHigh = sqrt(B); + double gainBass = pow(C,2)*4.0; + double outBass = sqrt(C); + double outPad = D; + double wet = E; + + double iirAmountA = 0.001860867/overallscale; + double iirAmountB = 0.000287496/overallscale; + double iirBassMid = 0.159/overallscale; + double iirMidHigh = 0.236/overallscale; + + biquadD[0] = biquadC[0] = biquadB[0] = biquadA[0] = 19160.0 / getSampleRate(); + biquadA[1] = 0.431684981684982; + biquadB[1] = 1.1582298; + biquadC[1] = 0.657027382751269; + biquadD[1] = 1.076210852946577; + + double K = tan(M_PI * biquadA[0]); //lowpass + double norm = 1.0 / (1.0 + K / biquadA[1] + K * K); + biquadA[2] = K * K * norm; + biquadA[3] = 2.0 * biquadA[2]; + biquadA[4] = biquadA[2]; + biquadA[5] = 2.0 * (K * K - 1.0) * norm; + biquadA[6] = (1.0 - K / biquadA[1] + K * K) * norm; + + K = tan(M_PI * biquadB[0]); + norm = 1.0 / (1.0 + K / biquadB[1] + K * K); + biquadB[2] = K * K * norm; + biquadB[3] = 2.0 * biquadB[2]; + biquadB[4] = biquadB[2]; + biquadB[5] = 2.0 * (K * K - 1.0) * norm; + biquadB[6] = (1.0 - K / biquadB[1] + K * K) * norm; + + K = tan(M_PI * biquadC[0]); + norm = 1.0 / (1.0 + K / biquadC[1] + K * K); + biquadC[2] = K * K * norm; + biquadC[3] = 2.0 * biquadC[2]; + biquadC[4] = biquadC[2]; + biquadC[5] = 2.0 * (K * K - 1.0) * norm; + biquadC[6] = (1.0 - K / biquadC[1] + K * K) * norm; + + K = tan(M_PI * biquadD[0]); + norm = 1.0 / (1.0 + K / biquadD[1] + K * K); + biquadD[2] = K * K * norm; + biquadD[3] = 2.0 * biquadD[2]; + biquadD[4] = biquadD[2]; + biquadD[5] = 2.0 * (K * K - 1.0) * norm; + biquadD[6] = (1.0 - K / biquadD[1] + K * K) * norm; + + while (--sampleFrames >= 0) + { + long double inputSampleL = *in1; + long double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-43) inputSampleL = fpdL * 1.18e-43; + if (fabs(inputSampleR)<1.18e-43) inputSampleR = fpdR * 1.18e-43; + long double drySampleL = inputSampleL; + long double drySampleR = inputSampleR; + + if (fabs(iirSampleAL)<1.18e-37) iirSampleAL = 0.0; + iirSampleAL = (iirSampleAL * (1.0 - iirAmountA)) + (inputSampleL * iirAmountA); + inputSampleL -= iirSampleAL; + if (fabs(iirSampleAR)<1.18e-37) iirSampleAR = 0.0; + iirSampleAR = (iirSampleAR * (1.0 - iirAmountA)) + (inputSampleR * iirAmountA); + inputSampleR -= iirSampleAR; + + if (inTrim != 1.0) {inputSampleL *= inTrim; inputSampleR *= inTrim;} + + //begin Mackity input stage + long double outSampleL = biquadA[2]*inputSampleL+biquadA[3]*biquadA[7]+biquadA[4]*biquadA[8]-biquadA[5]*biquadA[9]-biquadA[6]*biquadA[10]; + biquadA[8] = biquadA[7]; biquadA[7] = inputSampleL; inputSampleL = outSampleL; biquadA[10] = biquadA[9]; biquadA[9] = inputSampleL; //DF1 left + + long double outSampleR = biquadA[2]*inputSampleR+biquadA[3]*biquadA[11]+biquadA[4]*biquadA[12]-biquadA[5]*biquadA[13]-biquadA[6]*biquadA[14]; + biquadA[12] = biquadA[11]; biquadA[11] = inputSampleR; inputSampleR = outSampleR; biquadA[14] = biquadA[13]; biquadA[13] = inputSampleR; //DF1 right + + if (inputSampleL > 1.0) inputSampleL = 1.0; + if (inputSampleL < -1.0) inputSampleL = -1.0; + inputSampleL -= pow(inputSampleL,5)*0.1768; + if (inputSampleR > 1.0) inputSampleR = 1.0; + if (inputSampleR < -1.0) inputSampleR = -1.0; + inputSampleR -= pow(inputSampleR,5)*0.1768; + + outSampleL = biquadB[2]*inputSampleL+biquadB[3]*biquadB[7]+biquadB[4]*biquadB[8]-biquadB[5]*biquadB[9]-biquadB[6]*biquadB[10]; + biquadB[8] = biquadB[7]; biquadB[7] = inputSampleL; inputSampleL = outSampleL; biquadB[10] = biquadB[9]; biquadB[9] = inputSampleL; //DF1 left + + outSampleR = biquadB[2]*inputSampleR+biquadB[3]*biquadB[11]+biquadB[4]*biquadB[12]-biquadB[5]*biquadB[13]-biquadB[6]*biquadB[14]; + biquadB[12] = biquadB[11]; biquadB[11] = inputSampleR; inputSampleR = outSampleR; biquadB[14] = biquadB[13]; biquadB[13] = inputSampleR; //DF1 right + + if (fabs(iirSampleBL)<1.18e-37) iirSampleBL = 0.0; + iirSampleBL = (iirSampleBL * (1.0 - iirAmountB)) + (inputSampleL * iirAmountB); + inputSampleL -= iirSampleBL; + if (fabs(iirSampleBR)<1.18e-37) iirSampleBR = 0.0; + iirSampleBR = (iirSampleBR * (1.0 - iirAmountB)) + (inputSampleR * iirAmountB); + inputSampleR -= iirSampleBR; + //end Mackity input stage + + //begin EQ section + if (fabs(iirSampleCL)<1.18e-37) iirSampleCL = 0.0; + iirSampleCL = (iirSampleCL * (1.0 - iirBassMid)) + (inputSampleL * iirBassMid); + if (fabs(iirSampleCR)<1.18e-37) iirSampleCR = 0.0; + iirSampleCR = (iirSampleCR * (1.0 - iirBassMid)) + (inputSampleR * iirBassMid); + + long double bassSampleL = iirSampleCL; + long double midSampleL = inputSampleL - bassSampleL; + long double bassSampleR = iirSampleCR; + long double midSampleR = inputSampleR - bassSampleR; + + if (gainBass != 1.0) {bassSampleL *= gainBass; bassSampleR *= gainBass;} + + if (bassSampleL > 1.0) bassSampleL = 1.0; + if (bassSampleL < -1.0) bassSampleL = -1.0; + bassSampleL -= pow(bassSampleL,5)*0.1768; + if (bassSampleR > 1.0) bassSampleR = 1.0; + if (bassSampleR < -1.0) bassSampleR = -1.0; + bassSampleR -= pow(bassSampleR,5)*0.1768; + + if (fabs(iirSampleDL)<1.18e-37) iirSampleDL = 0.0; + iirSampleDL = (iirSampleDL * (1.0 - iirBassMid)) + (bassSampleL * iirBassMid); + bassSampleL = iirSampleDL; + if (fabs(iirSampleDR)<1.18e-37) iirSampleDR = 0.0; + iirSampleDR = (iirSampleDR * (1.0 - iirBassMid)) + (bassSampleR * iirBassMid); + bassSampleR = iirSampleDR; + //we've taken the bass sample, made the mids from it, distorted it + //and hit it with another pole of darkening. + //mid sample is still normal from undistorted bass + + if (fabs(iirSampleEL)<1.18e-37) iirSampleEL = 0.0; + iirSampleEL = (iirSampleEL * (1.0 - iirMidHigh)) + (midSampleL * iirMidHigh); + long double highSampleL = midSampleL - iirSampleEL; + midSampleL = iirSampleEL; + if (fabs(iirSampleER)<1.18e-37) iirSampleER = 0.0; + iirSampleER = (iirSampleER * (1.0 - iirMidHigh)) + (midSampleR * iirMidHigh); + long double highSampleR = midSampleR - iirSampleER; + midSampleR = iirSampleER; + //here is where we make the high sample out of the mid, and take highs + //away from the mid. + + if (fabs(iirSampleFL)<1.18e-37) iirSampleFL = 0.0; + iirSampleFL = (iirSampleFL * (1.0 - iirMidHigh)) + (highSampleL * iirMidHigh); + highSampleL -= iirSampleFL; + if (fabs(iirSampleFR)<1.18e-37) iirSampleFR = 0.0; + iirSampleFR = (iirSampleFR * (1.0 - iirMidHigh)) + (highSampleR * iirMidHigh); + highSampleR -= iirSampleFR; + + if (gainHigh != 1.0) {highSampleL *= gainHigh; highSampleR *= gainHigh;} + + if (highSampleL > 1.0) highSampleL = 1.0; + if (highSampleL < -1.0) highSampleL = -1.0; + highSampleL -= pow(highSampleL,5)*0.1768; + if (highSampleR > 1.0) highSampleR = 1.0; + if (highSampleR < -1.0) highSampleR = -1.0; + highSampleR -= pow(highSampleR,5)*0.1768; + //highpassing HighSample another stage, before distorting it + + inputSampleL = ((bassSampleL*outBass) + midSampleL + (highSampleL*outHigh))*4.0; + inputSampleR = ((bassSampleR*outBass) + midSampleR + (highSampleR*outHigh))*4.0; + //end EQ section + + outSampleL = biquadC[2]*inputSampleL+biquadC[3]*biquadC[7]+biquadC[4]*biquadC[8]-biquadC[5]*biquadC[9]-biquadC[6]*biquadC[10]; + biquadC[8] = biquadC[7]; biquadC[7] = inputSampleL; inputSampleL = outSampleL; biquadC[10] = biquadC[9]; biquadC[9] = inputSampleL; //DF1 left + + outSampleR = biquadC[2]*inputSampleR+biquadC[3]*biquadC[11]+biquadC[4]*biquadC[12]-biquadC[5]*biquadC[13]-biquadC[6]*biquadC[14]; + biquadC[12] = biquadC[11]; biquadC[11] = inputSampleR; inputSampleR = outSampleR; biquadC[14] = biquadC[13]; biquadC[13] = inputSampleR; //DF1 right + + if (inputSampleL > 1.0) inputSampleL = 1.0; + if (inputSampleL < -1.0) inputSampleL = -1.0; + inputSampleL -= pow(inputSampleL,5)*0.1768; + if (inputSampleR > 1.0) inputSampleR = 1.0; + if (inputSampleR < -1.0) inputSampleR = -1.0; + inputSampleR -= pow(inputSampleR,5)*0.1768; + + outSampleL = biquadD[2]*inputSampleL+biquadD[3]*biquadD[7]+biquadD[4]*biquadD[8]-biquadD[5]*biquadD[9]-biquadD[6]*biquadD[10]; + biquadD[8] = biquadD[7]; biquadD[7] = inputSampleL; inputSampleL = outSampleL; biquadD[10] = biquadD[9]; biquadD[9] = inputSampleL; //DF1 left + + outSampleR = biquadD[2]*inputSampleR+biquadD[3]*biquadD[11]+biquadD[4]*biquadD[12]-biquadD[5]*biquadD[13]-biquadD[6]*biquadD[14]; + biquadD[12] = biquadD[11]; biquadD[11] = inputSampleR; inputSampleR = outSampleR; biquadD[14] = biquadD[13]; biquadD[13] = inputSampleR; //DF1 right + + if (outPad != 1.0) { + inputSampleL *= outPad; + inputSampleR *= outPad; + } + + if (wet !=1.0) { + inputSampleL = (inputSampleL * wet) + (drySampleL * (1.0-wet)); + inputSampleR = (inputSampleR * wet) + (drySampleR * (1.0-wet)); + } + //Dry/Wet control, defaults to the last slider + + //begin 64 bit stereo floating point dither + int expon; frexp((double)inputSampleL, &expon); + fpdL ^= fpdL << 13; fpdL ^= fpdL >> 17; fpdL ^= fpdL << 5; + inputSampleL += ((double(fpdL)-uint32_t(0x7fffffff)) * 1.1e-44l * pow(2,expon+62)); + frexp((double)inputSampleR, &expon); + fpdR ^= fpdR << 13; fpdR ^= fpdR >> 17; fpdR ^= fpdR << 5; + inputSampleR += ((double(fpdR)-uint32_t(0x7fffffff)) * 1.1e-44l * pow(2,expon+62)); + //end 64 bit stereo floating point dither + + *out1 = inputSampleL; + *out2 = inputSampleR; + + in1++; + in2++; + out1++; + out2++; + } +} + + +} // end namespace MackEQ + diff --git a/libs/airwindows/src/Mackity.cpp b/libs/airwindows/src/Mackity.cpp new file mode 100644 index 00000000000..3d14ff618f7 --- /dev/null +++ b/libs/airwindows/src/Mackity.cpp @@ -0,0 +1,147 @@ +/* ======================================== + * Mackity - Mackity.h + * Copyright (c) 2016 airwindows, All rights reserved + * ======================================== */ + +#ifndef __Mackity_H +#include "Mackity.h" +#endif + +namespace Mackity { + + +// AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new Mackity(audioMaster);} + +Mackity::Mackity(audioMasterCallback audioMaster) : + AudioEffectX(audioMaster, kNumPrograms, kNumParameters) +{ + A = 0.1; + B = 1.0; + + iirSampleAL = 0.0; + iirSampleBL = 0.0; + iirSampleAR = 0.0; + iirSampleBR = 0.0; + for (int x = 0; x < 15; x++) {biquadA[x] = 0.0; biquadB[x] = 0.0;} + + fpdL = 1.0; while (fpdL < 16386) fpdL = rand()*UINT32_MAX; + fpdR = 1.0; while (fpdR < 16386) fpdR = rand()*UINT32_MAX; + //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 +} + +Mackity::~Mackity() {} +VstInt32 Mackity::getVendorVersion () {return 1000;} +void Mackity::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);} +void Mackity::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 Mackity::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 Mackity::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 Mackity::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 Mackity::getParameter(VstInt32 index) { + 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 Mackity::getParameterName(VstInt32 index, char *text) { + switch (index) { + case kParamA: vst_strncpy (text, "In Trim", kVstMaxParamStrLen); break; + case kParamB: vst_strncpy (text, "Out Pad", kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } //this is our labels for displaying in the VST host +} + +void Mackity::getParameterDisplay(VstInt32 index, char *text, float extVal, bool isExternal) { + switch (index) { + case kParamA: float2string (EXTV(A) * 100, text, kVstMaxParamStrLen); break; + case kParamB: float2string (EXTV(B) * 100, text, kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } //this displays the values and handles 'popups' where it's discrete choices +} + +void Mackity::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 Mackity::canDo(char *text) +{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know + +bool Mackity::getEffectName(char* name) { + vst_strncpy(name, "Mackity", kVstMaxProductStrLen); return true; +} + +VstPlugCategory Mackity::getPlugCategory() {return kPlugCategEffect;} + +bool Mackity::getProductString(char* text) { + vst_strncpy (text, "airwindows Mackity", kVstMaxProductStrLen); return true; +} + +bool Mackity::getVendorString(char* text) { + vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true; +} + +bool Mackity::parseParameterValueFromString(VstInt32 index, const char *str, float &f) +{ + auto v = std::atof(str); + f = v / 100.0; + return true; +} + +} // end namespace Mackity + diff --git a/libs/airwindows/src/Mackity.h b/libs/airwindows/src/Mackity.h new file mode 100644 index 00000000000..c02479048f5 --- /dev/null +++ b/libs/airwindows/src/Mackity.h @@ -0,0 +1,77 @@ +/* ======================================== + * Mackity - Mackity.h + * Created 8/12/11 by SPIAdmin + * Copyright (c) 2011 __MyCompanyName__, All rights reserved + * ======================================== */ + +#ifndef __Mackity_H +#define __Mackity_H + +#ifndef __audioeffect__ +#include "airwindows/AirWinBaseClass.h" +#endif + +#include +#include +#include + +namespace Mackity { + +enum { + kParamA = 0, + kParamB = 1, + kNumParameters = 2 +}; // + +const int kNumPrograms = 0; +const int kNumInputs = 2; +const int kNumOutputs = 2; +const unsigned long kUniqueId = 'mkty'; //Change this to what the AU identity is! + +class Mackity : + public AudioEffectX +{ +public: + Mackity(audioMasterCallback audioMaster); + ~Mackity(); + 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, float extVal, bool isExternal); // text description of the current value + virtual bool parseParameterValueFromString(VstInt32 index, const char *str, float &f); + virtual VstInt32 canDo(char *text); +private: + char _programName[kVstMaxProgNameLen + 1]; + std::set< std::string > _canDo; + + + long double iirSampleAL; + long double iirSampleBL; + long double iirSampleAR; + long double iirSampleBR; + long double biquadA[15]; + long double biquadB[15]; + + uint32_t fpdL; + uint32_t fpdR; + //default stuff + + float A; + float B; +}; + +} // end namespace Mackity + +#endif diff --git a/libs/airwindows/src/MackityProc.cpp b/libs/airwindows/src/MackityProc.cpp new file mode 100644 index 00000000000..9f56afb49a3 --- /dev/null +++ b/libs/airwindows/src/MackityProc.cpp @@ -0,0 +1,217 @@ +/* ======================================== + * Mackity - Mackity.h + * Copyright (c) 2016 airwindows, All rights reserved + * ======================================== */ + +#ifndef __Mackity_H +#include "Mackity.h" +#endif + +namespace Mackity { + + +void Mackity::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) +{ + float* in1 = inputs[0]; + float* in2 = inputs[1]; + float* out1 = outputs[0]; + float* out2 = outputs[1]; + + double overallscale = 1.0; + overallscale /= 44100.0; + overallscale *= getSampleRate(); + + double inTrim = A*10.0; + double outPad = B; + inTrim *= inTrim; + + double iirAmountA = 0.001860867/overallscale; + double iirAmountB = 0.000287496/overallscale; + + biquadB[0] = biquadA[0] = 19160.0 / getSampleRate(); + biquadA[1] = 0.431684981684982; + biquadB[1] = 1.1582298; + + double K = tan(M_PI * biquadA[0]); //lowpass + double norm = 1.0 / (1.0 + K / biquadA[1] + K * K); + biquadA[2] = K * K * norm; + biquadA[3] = 2.0 * biquadA[2]; + biquadA[4] = biquadA[2]; + biquadA[5] = 2.0 * (K * K - 1.0) * norm; + biquadA[6] = (1.0 - K / biquadA[1] + K * K) * norm; + + K = tan(M_PI * biquadB[0]); + norm = 1.0 / (1.0 + K / biquadB[1] + K * K); + biquadB[2] = K * K * norm; + biquadB[3] = 2.0 * biquadB[2]; + biquadB[4] = biquadB[2]; + biquadB[5] = 2.0 * (K * K - 1.0) * norm; + biquadB[6] = (1.0 - K / biquadB[1] + K * K) * norm; + + while (--sampleFrames >= 0) + { + long double inputSampleL = *in1; + long double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-37) inputSampleL = fpdL * 1.18e-37; + if (fabs(inputSampleR)<1.18e-37) inputSampleR = fpdR * 1.18e-37; + + if (fabs(iirSampleAL)<1.18e-37) iirSampleAL = 0.0; + iirSampleAL = (iirSampleAL * (1.0 - iirAmountA)) + (inputSampleL * iirAmountA); + inputSampleL -= iirSampleAL; + if (fabs(iirSampleAR)<1.18e-37) iirSampleAR = 0.0; + iirSampleAR = (iirSampleAR * (1.0 - iirAmountA)) + (inputSampleR * iirAmountA); + inputSampleR -= iirSampleAR; + + if (inTrim != 1.0) {inputSampleL *= inTrim; inputSampleR *= inTrim;} + + long double outSampleL = biquadA[2]*inputSampleL+biquadA[3]*biquadA[7]+biquadA[4]*biquadA[8]-biquadA[5]*biquadA[9]-biquadA[6]*biquadA[10]; + biquadA[8] = biquadA[7]; biquadA[7] = inputSampleL; inputSampleL = outSampleL; biquadA[10] = biquadA[9]; biquadA[9] = inputSampleL; //DF1 left + + long double outSampleR = biquadA[2]*inputSampleR+biquadA[3]*biquadA[11]+biquadA[4]*biquadA[12]-biquadA[5]*biquadA[13]-biquadA[6]*biquadA[14]; + biquadA[12] = biquadA[11]; biquadA[11] = inputSampleR; inputSampleR = outSampleR; biquadA[14] = biquadA[13]; biquadA[13] = inputSampleR; //DF1 right + + if (inputSampleL > 1.0) inputSampleL = 1.0; + if (inputSampleL < -1.0) inputSampleL = -1.0; + inputSampleL -= pow(inputSampleL,5)*0.1768; + if (inputSampleR > 1.0) inputSampleR = 1.0; + if (inputSampleR < -1.0) inputSampleR = -1.0; + inputSampleR -= pow(inputSampleR,5)*0.1768; + + outSampleL = biquadB[2]*inputSampleL+biquadB[3]*biquadB[7]+biquadB[4]*biquadB[8]-biquadB[5]*biquadB[9]-biquadB[6]*biquadB[10]; + biquadB[8] = biquadB[7]; biquadB[7] = inputSampleL; inputSampleL = outSampleL; biquadB[10] = biquadB[9]; biquadB[9] = inputSampleL; //DF1 left + + outSampleR = biquadB[2]*inputSampleR+biquadB[3]*biquadB[11]+biquadB[4]*biquadB[12]-biquadB[5]*biquadB[13]-biquadB[6]*biquadB[14]; + biquadB[12] = biquadB[11]; biquadB[11] = inputSampleR; inputSampleR = outSampleR; biquadB[14] = biquadB[13]; biquadB[13] = inputSampleR; //DF1 right + + if (fabs(iirSampleBL)<1.18e-37) iirSampleBL = 0.0; + iirSampleBL = (iirSampleBL * (1.0 - iirAmountB)) + (inputSampleL * iirAmountB); + inputSampleL -= iirSampleBL; + if (fabs(iirSampleBR)<1.18e-37) iirSampleBR = 0.0; + iirSampleBR = (iirSampleBR * (1.0 - iirAmountB)) + (inputSampleR * iirAmountB); + inputSampleR -= iirSampleBR; + + if (outPad != 1.0) {inputSampleL *= outPad; inputSampleR *= outPad;} + + //begin 32 bit stereo floating point dither + int expon; frexpf((float)inputSampleL, &expon); + fpdL ^= fpdL << 13; fpdL ^= fpdL >> 17; fpdL ^= fpdL << 5; + inputSampleL += ((double(fpdL)-uint32_t(0x7fffffff)) * 5.5e-36l * pow(2,expon+62)); + frexpf((float)inputSampleR, &expon); + fpdR ^= fpdR << 13; fpdR ^= fpdR >> 17; fpdR ^= fpdR << 5; + inputSampleR += ((double(fpdR)-uint32_t(0x7fffffff)) * 5.5e-36l * pow(2,expon+62)); + //end 32 bit stereo floating point dither + + *out1 = inputSampleL; + *out2 = inputSampleR; + + in1++; + in2++; + out1++; + out2++; + } +} + +void Mackity::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames) +{ + double* in1 = inputs[0]; + double* in2 = inputs[1]; + double* out1 = outputs[0]; + double* out2 = outputs[1]; + + double overallscale = 1.0; + overallscale /= 44100.0; + overallscale *= getSampleRate(); + + double inTrim = A*10.0; + double outPad = B; + inTrim *= inTrim; + + double iirAmountA = 0.001860867/overallscale; + double iirAmountB = 0.000287496/overallscale; + + biquadB[0] = biquadA[0] = 19160.0 / getSampleRate(); + biquadA[1] = 0.431684981684982; + biquadB[1] = 1.1582298; + + double K = tan(M_PI * biquadA[0]); //lowpass + double norm = 1.0 / (1.0 + K / biquadA[1] + K * K); + biquadA[2] = K * K * norm; + biquadA[3] = 2.0 * biquadA[2]; + biquadA[4] = biquadA[2]; + biquadA[5] = 2.0 * (K * K - 1.0) * norm; + biquadA[6] = (1.0 - K / biquadA[1] + K * K) * norm; + + K = tan(M_PI * biquadB[0]); + norm = 1.0 / (1.0 + K / biquadB[1] + K * K); + biquadB[2] = K * K * norm; + biquadB[3] = 2.0 * biquadB[2]; + biquadB[4] = biquadB[2]; + biquadB[5] = 2.0 * (K * K - 1.0) * norm; + biquadB[6] = (1.0 - K / biquadB[1] + K * K) * norm; + + while (--sampleFrames >= 0) + { + long double inputSampleL = *in1; + long double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-43) inputSampleL = fpdL * 1.18e-43; + if (fabs(inputSampleR)<1.18e-43) inputSampleR = fpdR * 1.18e-43; + + if (fabs(iirSampleAL)<1.18e-37) iirSampleAL = 0.0; + iirSampleAL = (iirSampleAL * (1.0 - iirAmountA)) + (inputSampleL * iirAmountA); + inputSampleL -= iirSampleAL; + if (fabs(iirSampleAR)<1.18e-37) iirSampleAR = 0.0; + iirSampleAR = (iirSampleAR * (1.0 - iirAmountA)) + (inputSampleR * iirAmountA); + inputSampleR -= iirSampleAR; + + if (inTrim != 1.0) {inputSampleL *= inTrim; inputSampleR *= inTrim;} + + long double outSampleL = biquadA[2]*inputSampleL+biquadA[3]*biquadA[7]+biquadA[4]*biquadA[8]-biquadA[5]*biquadA[9]-biquadA[6]*biquadA[10]; + biquadA[8] = biquadA[7]; biquadA[7] = inputSampleL; inputSampleL = outSampleL; biquadA[10] = biquadA[9]; biquadA[9] = inputSampleL; //DF1 left + + long double outSampleR = biquadA[2]*inputSampleR+biquadA[3]*biquadA[11]+biquadA[4]*biquadA[12]-biquadA[5]*biquadA[13]-biquadA[6]*biquadA[14]; + biquadA[12] = biquadA[11]; biquadA[11] = inputSampleR; inputSampleR = outSampleR; biquadA[14] = biquadA[13]; biquadA[13] = inputSampleR; //DF1 right + + if (inputSampleL > 1.0) inputSampleL = 1.0; + if (inputSampleL < -1.0) inputSampleL = -1.0; + inputSampleL -= pow(inputSampleL,5)*0.1768; + if (inputSampleR > 1.0) inputSampleR = 1.0; + if (inputSampleR < -1.0) inputSampleR = -1.0; + inputSampleR -= pow(inputSampleR,5)*0.1768; + + outSampleL = biquadB[2]*inputSampleL+biquadB[3]*biquadB[7]+biquadB[4]*biquadB[8]-biquadB[5]*biquadB[9]-biquadB[6]*biquadB[10]; + biquadB[8] = biquadB[7]; biquadB[7] = inputSampleL; inputSampleL = outSampleL; biquadB[10] = biquadB[9]; biquadB[9] = inputSampleL; //DF1 left + + outSampleR = biquadB[2]*inputSampleR+biquadB[3]*biquadB[11]+biquadB[4]*biquadB[12]-biquadB[5]*biquadB[13]-biquadB[6]*biquadB[14]; + biquadB[12] = biquadB[11]; biquadB[11] = inputSampleR; inputSampleR = outSampleR; biquadB[14] = biquadB[13]; biquadB[13] = inputSampleR; //DF1 right + + if (fabs(iirSampleBL)<1.18e-37) iirSampleBL = 0.0; + iirSampleBL = (iirSampleBL * (1.0 - iirAmountB)) + (inputSampleL * iirAmountB); + inputSampleL -= iirSampleBL; + if (fabs(iirSampleBR)<1.18e-37) iirSampleBR = 0.0; + iirSampleBR = (iirSampleBR * (1.0 - iirAmountB)) + (inputSampleR * iirAmountB); + inputSampleR -= iirSampleBR; + + if (outPad != 1.0) {inputSampleL *= outPad; inputSampleR *= outPad;} + + //begin 64 bit stereo floating point dither + int expon; frexp((double)inputSampleL, &expon); + fpdL ^= fpdL << 13; fpdL ^= fpdL >> 17; fpdL ^= fpdL << 5; + inputSampleL += ((double(fpdL)-uint32_t(0x7fffffff)) * 1.1e-44l * pow(2,expon+62)); + frexp((double)inputSampleR, &expon); + fpdR ^= fpdR << 13; fpdR ^= fpdR >> 17; fpdR ^= fpdR << 5; + inputSampleR += ((double(fpdR)-uint32_t(0x7fffffff)) * 1.1e-44l * pow(2,expon+62)); + //end 64 bit stereo floating point dither + + *out1 = inputSampleL; + *out2 = inputSampleR; + + in1++; + in2++; + out1++; + out2++; + } +} + + +} // end namespace Mackity +