diff --git a/libs/airwindows b/libs/airwindows index 7ff0412..5ee0c57 160000 --- a/libs/airwindows +++ b/libs/airwindows @@ -1 +1 @@ -Subproject commit 7ff04123cced168b31f60595d4dcbfebfb8dbf7e +Subproject commit 5ee0c5711feb2de9da0858600893aeecbdbe91fc diff --git a/res/awpdoc/ZOutputStage.txt b/res/awpdoc/ZOutputStage.txt new file mode 100644 index 0000000..ae42e1f --- /dev/null +++ b/res/awpdoc/ZOutputStage.txt @@ -0,0 +1,19 @@ +# ZOutputStage is the output clipping from the Emu e6400 style Z filters. + +So I didn't get asked for this, exactly. + +I got asked for the exciter setting out of the Emu e6400 Ultra. And this isn't it. + +But I did have an exciter (and so have you, as it's in the plugin collection.) I'm sure it's weirder and twitchier than the Emu one, but it does exist. It just won't sound anything like that sampler, because the sampler has a lot of hardware on the analog outs, as well as being probably a totally different algorithm than mine, one that I have no idea how it's done. + +Wait a second. + +The reason I got asked for this was, drum and bass guys in the UK wanted to add some insane grind and energy, to basically synth waves. And I don't have the algo for that… but my exciter is nothing if not insane, and I did an output stage on the Z filters. That would apply exactly the same to an exciter, or anything else. I'd just do it as a simple distortion, except that rather than being a normal distortion it'd use the special filtering used in the Z filters to get that 'frizz' on the edges of clipped sounds that I clearly saw in the recordings of the real e6400. If it did that on distorting filters, it would do the same on an exciter, or anything. + +And so I did :) + +This goes after… well, anything. Whatever you like. Turn it up past 0.1 to distort, just like the Z filters. Turn the output way down because it's really hot. Apply to whatever digital mayhem you can wreak, and it should act a little more like it's coming off that sampler. + +See ya next week :) + + diff --git a/src/ModuleAdd.h b/src/ModuleAdd.h index cb574e8..ecb6872 100644 --- a/src/ModuleAdd.h +++ b/src/ModuleAdd.h @@ -182,6 +182,10 @@ int Console8SubHype_unused = AirwinRegistry::registerAirwindow({"Console8SubHype int Console8SubIn_unused = AirwinRegistry::registerAirwindow({"Console8SubIn", "Consoles", 89, "Console8SubIn moves to a channel/submix/buss topology and adds analog simulation.", airwin2rack::Console8SubIn::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/Console8SubOut.h" int Console8SubOut_unused = AirwinRegistry::registerAirwindow({"Console8SubOut", "Consoles", 90, "Console8SubOut moves to a channel/submix/buss topology and adds analog simulation.", airwin2rack::Console8SubOut::kNumParameters, []() { return std::make_unique(0); }}); +#include "autogen_airwin/ConsoleLABuss.h" +int ConsoleLABuss_unused = AirwinRegistry::registerAirwindow({"ConsoleLABuss", "Unclassified", -1, "", airwin2rack::ConsoleLABuss::kNumParameters, []() { return std::make_unique(0); }}); +#include "autogen_airwin/ConsoleLAChannel.h" +int ConsoleLAChannel_unused = AirwinRegistry::registerAirwindow({"ConsoleLAChannel", "Unclassified", -1, "", airwin2rack::ConsoleLAChannel::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/ConsoleMCBuss.h" int ConsoleMCBuss_unused = AirwinRegistry::registerAirwindow({"ConsoleMCBuss", "Consoles", 114, "ConsoleMCBuss is the initial, bright take on the MCI console.", airwin2rack::ConsoleMCBuss::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/ConsoleMCChannel.h" @@ -450,6 +454,8 @@ int NotJustAnotherDither_unused = AirwinRegistry::registerAirwindow({"NotJustAno int OneCornerClip_unused = AirwinRegistry::registerAirwindow({"OneCornerClip", "Clipping", 74, "OneCornerClip is an ultimate full-bandwidth clipper.", airwin2rack::OneCornerClip::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/OrbitKick.h" int OrbitKick_unused = AirwinRegistry::registerAirwindow({"OrbitKick", "Bass", 35, "OrbitKick is a bass generator and kick drum reinforcer.", airwin2rack::OrbitKick::kNumParameters, []() { return std::make_unique(0); }}); +#include "autogen_airwin/Overheads.h" +int Overheads_unused = AirwinRegistry::registerAirwindow({"Overheads", "Unclassified", -1, "", airwin2rack::Overheads::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/PDBuss.h" int PDBuss_unused = AirwinRegistry::registerAirwindow({"PDBuss", "Consoles", 105, "PDBuss is Console5 and PurestDrive, sittin’ in a tree… (i.e. both at once, on channels and buss)", airwin2rack::PDBuss::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/PDChannel.h" @@ -729,7 +735,7 @@ int ZNotch_unused = AirwinRegistry::registerAirwindow({"ZNotch", "XYZ Filters", #include "autogen_airwin/ZNotch2.h" int ZNotch2_unused = AirwinRegistry::registerAirwindow({"ZNotch2", "XYZ Filters", 353, "ZNotch2 acts more like the Emu e6400 Ultra phaser in motion, with control smoothing.", airwin2rack::ZNotch2::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/ZOutputStage.h" -int ZOutputStage_unused = AirwinRegistry::registerAirwindow({"ZOutputStage", "Unclassified", -1, "", airwin2rack::ZOutputStage::kNumParameters, []() { return std::make_unique(0); }}); +int ZOutputStage_unused = AirwinRegistry::registerAirwindow({"ZOutputStage", "Unclassified", -1, "ZOutputStage is the output clipping from the Emu e6400 style Z filters.", airwin2rack::ZOutputStage::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/ZRegion.h" int ZRegion_unused = AirwinRegistry::registerAirwindow({"ZRegion", "XYZ Filters", 359, "ZRegion is an Emu e6400 style Airwindows Region filter.", airwin2rack::ZRegion::kNumParameters, []() { return std::make_unique(0); }}); #include "autogen_airwin/ZRegion2.h" diff --git a/src/autogen_airwin/CMakeLists.txt b/src/autogen_airwin/CMakeLists.txt index de4f10d..91e1c02 100644 --- a/src/autogen_airwin/CMakeLists.txt +++ b/src/autogen_airwin/CMakeLists.txt @@ -183,6 +183,10 @@ set(AIRWIN_SOURCES src/autogen_airwin/Console8SubInProc.cpp src/autogen_airwin/Console8SubOut.cpp src/autogen_airwin/Console8SubOutProc.cpp + src/autogen_airwin/ConsoleLABuss.cpp + src/autogen_airwin/ConsoleLABussProc.cpp + src/autogen_airwin/ConsoleLAChannel.cpp + src/autogen_airwin/ConsoleLAChannelProc.cpp src/autogen_airwin/ConsoleMCBuss.cpp src/autogen_airwin/ConsoleMCBussProc.cpp src/autogen_airwin/ConsoleMCChannel.cpp @@ -451,6 +455,8 @@ set(AIRWIN_SOURCES src/autogen_airwin/OneCornerClipProc.cpp src/autogen_airwin/OrbitKick.cpp src/autogen_airwin/OrbitKickProc.cpp + src/autogen_airwin/Overheads.cpp + src/autogen_airwin/OverheadsProc.cpp src/autogen_airwin/PDBuss.cpp src/autogen_airwin/PDBussProc.cpp src/autogen_airwin/PDChannel.cpp diff --git a/src/autogen_airwin/ConsoleLABuss.cpp b/src/autogen_airwin/ConsoleLABuss.cpp new file mode 100644 index 0000000..acef18d --- /dev/null +++ b/src/autogen_airwin/ConsoleLABuss.cpp @@ -0,0 +1,117 @@ +/* ======================================== + * ConsoleLABuss - ConsoleLABuss.h + * Copyright (c) airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __ConsoleLABuss_H +#include "ConsoleLABuss.h" +#endif +namespace airwin2rack::ConsoleLABuss { + +AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new ConsoleLABuss(audioMaster);} + +ConsoleLABuss::ConsoleLABuss(audioMasterCallback audioMaster) : + AudioEffectX(audioMaster, kNumPrograms, kNumParameters) +{ + A = 1.0; + + lastSinewL = lastSinewR = 0.0; + subAL = subAR = subBL = subBR = subCL = subCR = 0.0; + gainA = gainB = 1.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 +} + +ConsoleLABuss::~ConsoleLABuss() {} +VstInt32 ConsoleLABuss::getVendorVersion () {return 1000;} +void ConsoleLABuss::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);} +void ConsoleLABuss::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; +} + +void ConsoleLABuss::setParameter(VstInt32 index, float value) { + switch (index) { + case kParamA: A = value; break; + default: break; // unknown parameter, shouldn't happen! + } +} + +float ConsoleLABuss::getParameter(VstInt32 index) { + switch (index) { + case kParamA: return A; 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 ConsoleLABuss::getParameterName(VstInt32 index, char *text) { + switch (index) { + case kParamA: vst_strncpy (text, "Master", kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } //this is our labels for displaying in the VST host +} + +void ConsoleLABuss::getParameterDisplay(VstInt32 index, char *text) { + switch (index) { + case kParamA: float2string (A, text, kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } //this displays the values and handles 'popups' where it's discrete choices +} + +void ConsoleLABuss::getParameterLabel(VstInt32 index, char *text) { + switch (index) { + case kParamA: vst_strncpy (text, "", kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } +} + +VstInt32 ConsoleLABuss::canDo(char *text) +{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know + +bool ConsoleLABuss::getEffectName(char* name) { + vst_strncpy(name, "ConsoleLABuss", kVstMaxProductStrLen); return true; +} + +VstPlugCategory ConsoleLABuss::getPlugCategory() {return kPlugCategEffect;} + +bool ConsoleLABuss::getProductString(char* text) { + vst_strncpy (text, "airwindows ConsoleLABuss", kVstMaxProductStrLen); return true; +} + +bool ConsoleLABuss::getVendorString(char* text) { + vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true; +} +bool ConsoleLABuss::parameterTextToValue(VstInt32 index, const char *text, float &value) { + switch(index) { + case kParamA: { auto b = string2float(text, value); return b; break; } + + } + return false; +} +bool ConsoleLABuss::canConvertParameterTextToValue(VstInt32 index) { + switch(index) { + case kParamA: return true; + + } + return false; +} +} // end namespace diff --git a/src/autogen_airwin/ConsoleLABuss.h b/src/autogen_airwin/ConsoleLABuss.h new file mode 100644 index 0000000..19e634f --- /dev/null +++ b/src/autogen_airwin/ConsoleLABuss.h @@ -0,0 +1,78 @@ +/* ======================================== + * ConsoleLABuss - ConsoleLABuss.h + * Created 8/12/11 by SPIAdmin + * Copyright (c) Airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __ConsoleLABuss_ConsoleLABuss_H +#define __ConsoleLABuss_ConsoleLABuss_H + +#ifndef __audioeffect__ +#include "../airwin2rackbase.h" +#endif + +#include +#include +#include + +namespace airwin2rack::ConsoleLABuss { +enum { + kParamA = 0, + kNumParameters = 1 +}; // + +const int kNumPrograms = 0; +const int kNumInputs = 2; +const int kNumOutputs = 2; +const unsigned long kUniqueId = 'clab'; //Change this to what the AU identity is! + +class ConsoleLABuss : + public AudioEffectX +{ +public: + ConsoleLABuss(audioMasterCallback audioMaster); + ~ConsoleLABuss(); + 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 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 + // Added by the perl as inverses + virtual bool parameterTextToValue(VstInt32 index, const char *text, float &value); + virtual bool canConvertParameterTextToValue(VstInt32 index); + virtual VstInt32 canDo(char *text); +private: + char _programName[kVstMaxProgNameLen + 1]; + std::set< std::string > _canDo; + + uint32_t fpdL; + uint32_t fpdR; + //default stuff + + double lastSinewL; + double lastSinewR; + + double subAL; + double subAR; + double subBL; + double subBR; + double subCL; + double subCR; + + double gainA; + double gainB; //smoothed master fader for channel, from Z2 series filter code + + float A; +}; + +#endif +} // end namespace diff --git a/src/autogen_airwin/ConsoleLABussProc.cpp b/src/autogen_airwin/ConsoleLABussProc.cpp new file mode 100644 index 0000000..fe5201a --- /dev/null +++ b/src/autogen_airwin/ConsoleLABussProc.cpp @@ -0,0 +1,272 @@ +/* ======================================== + * ConsoleLABuss - ConsoleLABuss.h + * Copyright (c) airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __ConsoleLABuss_H +#include "ConsoleLABuss.h" +#endif +namespace airwin2rack::ConsoleLABuss { + +void ConsoleLABuss::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) +{ + float* in1 = inputs[0]; + float* in2 = inputs[1]; + float* out1 = outputs[0]; + float* out2 = outputs[1]; + + VstInt32 inFramesToProcess = sampleFrames; //vst doesn't give us this as a separate variable so we'll make it + double overallscale = 1.0; + overallscale /= 44100.0; + overallscale *= getSampleRate(); + + gainA = gainB; + gainB = sqrt(A); //smoothed master fader from Z2 filters + //this will be applied three times: this is to make the various tone alterations + //hit differently at different master fader drive levels. + //in particular, backing off the master fader tightens the super lows + //but opens up the modified Sinew, because more of the attentuation happens before + //you even get to slew clipping :) and if the fader is not active, it bypasses completely. + + double threshSinew = 0.718/overallscale; + double subTrim = 0.0011 / overallscale; + + while (--sampleFrames >= 0) + { + double inputSampleL = *in1; + double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-23) inputSampleL = fpdL * 1.18e-17; + if (fabs(inputSampleR)<1.18e-23) inputSampleR = fpdR * 1.18e-17; + + double temp = (double)sampleFrames/inFramesToProcess; + double gain = (gainA*temp)+(gainB*(1.0-temp)); + //setting up smoothed master fader + + //begin SubTight section + double subSampleL = inputSampleL * subTrim; + double subSampleR = inputSampleR * subTrim; + + double scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subAL+(sin(subAL-subSampleL)*scale)); + subAL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subAR+(sin(subAR-subSampleR)*scale)); + subAR = subSampleR*scale; + scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subBL+(sin(subBL-subSampleL)*scale)); + subBL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subBR+(sin(subBR-subSampleR)*scale)); + subBR = subSampleR*scale; + scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subCL+(sin(subCL-subSampleL)*scale)); + subCL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subCR+(sin(subCR-subSampleR)*scale)); + subCR = subSampleR*scale; + if (subSampleL > 0.25) subSampleL = 0.25; + if (subSampleL < -0.25) subSampleL = -0.25; + if (subSampleR > 0.25) subSampleR = 0.25; + if (subSampleR < -0.25) subSampleR = -0.25; + inputSampleL -= (subSampleL*16.0); + inputSampleR -= (subSampleR*16.0); + //end SubTight section + + if (gain < 1.0) { + inputSampleL *= gain; + inputSampleR *= gain; + } //if using the master fader, we are going to attenuate three places. + //subtight is always fully engaged: tighten response when restraining full console + + //begin ConsoleZeroBuss which is the one we choose for ConsoleLA + if (inputSampleL > 2.8) inputSampleL = 2.8; + if (inputSampleL < -2.8) inputSampleL = -2.8; + if (inputSampleL > 0.0) inputSampleL = (inputSampleL*2.0)/(3.0-inputSampleL); + else inputSampleL = -(inputSampleL*-2.0)/(3.0+inputSampleL); + + if (inputSampleR > 2.8) inputSampleR = 2.8; + if (inputSampleR < -2.8) inputSampleR = -2.8; + if (inputSampleR > 0.0) inputSampleR = (inputSampleR*2.0)/(3.0-inputSampleR); + else inputSampleR = -(inputSampleR*-2.0)/(3.0+inputSampleR); + //ConsoleZero Buss + + if (gain < 1.0) { + inputSampleL *= gain; + inputSampleR *= gain; + } //if using the master fader, we are going to attenuate three places. + //after C0Buss but before EverySlew: allow highs to come out a bit more + //when pulling back master fader. Less drive equals more open + + temp = inputSampleL; + double clamp = inputSampleL - lastSinewL; + if (lastSinewL > 1.0) lastSinewL = 1.0; + if (lastSinewL < -1.0) lastSinewL = -1.0; + double sinew = threshSinew * cos(lastSinewL); + if (clamp > sinew) temp = lastSinewL + sinew; + if (-clamp > sinew) temp = lastSinewL - sinew; + inputSampleL = lastSinewL = temp; + temp = inputSampleR; + clamp = inputSampleR - lastSinewR; + if (lastSinewR > 1.0) lastSinewR = 1.0; + if (lastSinewR < -1.0) lastSinewR = -1.0; + sinew = threshSinew * cos(lastSinewR); + if (clamp > sinew) temp = lastSinewR + sinew; + if (-clamp > sinew) temp = lastSinewR - sinew; + inputSampleR = lastSinewR = temp; + + if (gain < 1.0) { + inputSampleL *= gain; + inputSampleR *= gain; + } //if using the master fader, we are going to attenuate three places. + //after EverySlew fades the total output sound: least change in tone here. + + //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 ConsoleLABuss::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames) +{ + double* in1 = inputs[0]; + double* in2 = inputs[1]; + double* out1 = outputs[0]; + double* out2 = outputs[1]; + + VstInt32 inFramesToProcess = sampleFrames; //vst doesn't give us this as a separate variable so we'll make it + double overallscale = 1.0; + overallscale /= 44100.0; + overallscale *= getSampleRate(); + + gainA = gainB; + gainB = sqrt(A); //smoothed master fader from Z2 filters + //this will be applied three times: this is to make the various tone alterations + //hit differently at different master fader drive levels. + //in particular, backing off the master fader tightens the super lows + //but opens up the modified Sinew, because more of the attentuation happens before + //you even get to slew clipping :) and if the fader is not active, it bypasses completely. + + double threshSinew = 0.718/overallscale; + double subTrim = 0.0011 / overallscale; + + while (--sampleFrames >= 0) + { + double inputSampleL = *in1; + double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-23) inputSampleL = fpdL * 1.18e-17; + if (fabs(inputSampleR)<1.18e-23) inputSampleR = fpdR * 1.18e-17; + + double temp = (double)sampleFrames/inFramesToProcess; + double gain = (gainA*temp)+(gainB*(1.0-temp)); + //setting up smoothed master fader + + //begin SubTight section + double subSampleL = inputSampleL * subTrim; + double subSampleR = inputSampleR * subTrim; + + double scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subAL+(sin(subAL-subSampleL)*scale)); + subAL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subAR+(sin(subAR-subSampleR)*scale)); + subAR = subSampleR*scale; + scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subBL+(sin(subBL-subSampleL)*scale)); + subBL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subBR+(sin(subBR-subSampleR)*scale)); + subBR = subSampleR*scale; + scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subCL+(sin(subCL-subSampleL)*scale)); + subCL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subCR+(sin(subCR-subSampleR)*scale)); + subCR = subSampleR*scale; + if (subSampleL > 0.25) subSampleL = 0.25; + if (subSampleL < -0.25) subSampleL = -0.25; + if (subSampleR > 0.25) subSampleR = 0.25; + if (subSampleR < -0.25) subSampleR = -0.25; + inputSampleL -= (subSampleL*16.0); + inputSampleR -= (subSampleR*16.0); + //end SubTight section + + if (gain < 1.0) { + inputSampleL *= gain; + inputSampleR *= gain; + } //if using the master fader, we are going to attenuate three places. + //subtight is always fully engaged: tighten response when restraining full console + + //begin ConsoleZeroBuss which is the one we choose for ConsoleLA + if (inputSampleL > 2.8) inputSampleL = 2.8; + if (inputSampleL < -2.8) inputSampleL = -2.8; + if (inputSampleL > 0.0) inputSampleL = (inputSampleL*2.0)/(3.0-inputSampleL); + else inputSampleL = -(inputSampleL*-2.0)/(3.0+inputSampleL); + + if (inputSampleR > 2.8) inputSampleR = 2.8; + if (inputSampleR < -2.8) inputSampleR = -2.8; + if (inputSampleR > 0.0) inputSampleR = (inputSampleR*2.0)/(3.0-inputSampleR); + else inputSampleR = -(inputSampleR*-2.0)/(3.0+inputSampleR); + //ConsoleZero Buss + + if (gain < 1.0) { + inputSampleL *= gain; + inputSampleR *= gain; + } //if using the master fader, we are going to attenuate three places. + //after C0Buss but before EverySlew: allow highs to come out a bit more + //when pulling back master fader. Less drive equals more open + + temp = inputSampleL; + double clamp = inputSampleL - lastSinewL; + if (lastSinewL > 1.0) lastSinewL = 1.0; + if (lastSinewL < -1.0) lastSinewL = -1.0; + double sinew = threshSinew * cos(lastSinewL); + if (clamp > sinew) temp = lastSinewL + sinew; + if (-clamp > sinew) temp = lastSinewL - sinew; + inputSampleL = lastSinewL = temp; + temp = inputSampleR; + clamp = inputSampleR - lastSinewR; + if (lastSinewR > 1.0) lastSinewR = 1.0; + if (lastSinewR < -1.0) lastSinewR = -1.0; + sinew = threshSinew * cos(lastSinewR); + if (clamp > sinew) temp = lastSinewR + sinew; + if (-clamp > sinew) temp = lastSinewR - sinew; + inputSampleR = lastSinewR = temp; + + if (gain < 1.0) { + inputSampleL *= gain; + inputSampleR *= gain; + } //if using the master fader, we are going to attenuate three places. + //after EverySlew fades the total output sound: least change in tone here. + + //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 diff --git a/src/autogen_airwin/ConsoleLAChannel.cpp b/src/autogen_airwin/ConsoleLAChannel.cpp new file mode 100644 index 0000000..90dd84c --- /dev/null +++ b/src/autogen_airwin/ConsoleLAChannel.cpp @@ -0,0 +1,153 @@ +/* ======================================== + * ConsoleLAChannel - ConsoleLAChannel.h + * Copyright (c) airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __ConsoleLAChannel_H +#include "ConsoleLAChannel.h" +#endif +namespace airwin2rack::ConsoleLAChannel { + +AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new ConsoleLAChannel(audioMaster);} + +ConsoleLAChannel::ConsoleLAChannel(audioMasterCallback audioMaster) : + AudioEffectX(audioMaster, kNumPrograms, kNumParameters) +{ + A = 0.5; + B = 0.5; + C = 0.5; + D = 0.5; + E = 0.5; + + for(int count = 0; count < 222; count++) {hullL[count] = 0.0; hullR[count] = 0.0;} + hullp = 1; + for (int x = 0; x < 21; x++) pearB[x] = 0.0; + subAL = subAR = subBL = subBR = subCL = subCR = 0.0; + midA = midB = 0.0; + bassA = bassB = 0.0; + gainA = gainB = 1.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 +} + +ConsoleLAChannel::~ConsoleLAChannel() {} +VstInt32 ConsoleLAChannel::getVendorVersion () {return 1000;} +void ConsoleLAChannel::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);} +void ConsoleLAChannel::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; +} + +void ConsoleLAChannel::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: break; // unknown parameter, shouldn't happen! + } +} + +float ConsoleLAChannel::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 ConsoleLAChannel::getParameterName(VstInt32 index, char *text) { + switch (index) { + case kParamA: vst_strncpy (text, "Treble", kVstMaxParamStrLen); break; + case kParamB: vst_strncpy (text, "Mid", kVstMaxParamStrLen); break; + case kParamC: vst_strncpy (text, "Bass", kVstMaxParamStrLen); break; + case kParamD: vst_strncpy (text, "Pan", kVstMaxParamStrLen); break; + case kParamE: vst_strncpy (text, "Fader", kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } //this is our labels for displaying in the VST host +} + +void ConsoleLAChannel::getParameterDisplay(VstInt32 index, char *text) { + switch (index) { + case kParamA: float2string (A, text, kVstMaxParamStrLen); break; + case kParamB: float2string (B, text, kVstMaxParamStrLen); break; + case kParamC: float2string (C, text, kVstMaxParamStrLen); break; + case kParamD: float2string (D, text, kVstMaxParamStrLen); break; + case kParamE: float2string (E, text, kVstMaxParamStrLen); break; + default: break; // unknown parameter, shouldn't happen! + } //this displays the values and handles 'popups' where it's discrete choices +} + +void ConsoleLAChannel::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! + } +} + +VstInt32 ConsoleLAChannel::canDo(char *text) +{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know + +bool ConsoleLAChannel::getEffectName(char* name) { + vst_strncpy(name, "ConsoleLAChannel", kVstMaxProductStrLen); return true; +} + +VstPlugCategory ConsoleLAChannel::getPlugCategory() {return kPlugCategEffect;} + +bool ConsoleLAChannel::getProductString(char* text) { + vst_strncpy (text, "airwindows ConsoleLAChannel", kVstMaxProductStrLen); return true; +} + +bool ConsoleLAChannel::getVendorString(char* text) { + vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true; +} +bool ConsoleLAChannel::parameterTextToValue(VstInt32 index, const char *text, float &value) { + switch(index) { + case kParamA: { auto b = string2float(text, value); return b; break; } + case kParamB: { auto b = string2float(text, value); return b; break; } + case kParamC: { auto b = string2float(text, value); return b; break; } + case kParamD: { auto b = string2float(text, value); return b; break; } + case kParamE: { auto b = string2float(text, value); return b; break; } + + } + return false; +} +bool ConsoleLAChannel::canConvertParameterTextToValue(VstInt32 index) { + switch(index) { + case kParamA: return true; + case kParamB: return true; + case kParamC: return true; + case kParamD: return true; + case kParamE: return true; + + } + return false; +} +} // end namespace diff --git a/src/autogen_airwin/ConsoleLAChannel.h b/src/autogen_airwin/ConsoleLAChannel.h new file mode 100644 index 0000000..5e08721 --- /dev/null +++ b/src/autogen_airwin/ConsoleLAChannel.h @@ -0,0 +1,91 @@ +/* ======================================== + * ConsoleLAChannel - ConsoleLAChannel.h + * Created 8/12/11 by SPIAdmin + * Copyright (c) Airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __ConsoleLAChannel_ConsoleLAChannel_H +#define __ConsoleLAChannel_ConsoleLAChannel_H + +#ifndef __audioeffect__ +#include "../airwin2rackbase.h" +#endif + +#include +#include +#include + +namespace airwin2rack::ConsoleLAChannel { +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 = 'clac'; //Change this to what the AU identity is! + +class ConsoleLAChannel : + public AudioEffectX +{ +public: + ConsoleLAChannel(audioMasterCallback audioMaster); + ~ConsoleLAChannel(); + 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 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 + // Added by the perl as inverses + virtual bool parameterTextToValue(VstInt32 index, const char *text, float &value); + virtual bool canConvertParameterTextToValue(VstInt32 index); + virtual VstInt32 canDo(char *text); +private: + char _programName[kVstMaxProgNameLen + 1]; + std::set< std::string > _canDo; + + uint32_t fpdL; + uint32_t fpdR; + //default stuff + + double subAL; + double subAR; + double subBL; + double subBR; + double subCL; + double subCR; + double hullL[225]; + double hullR[225]; + int hullp; + double pearB[22]; + double midA; + double midB; + double bassA; + double bassB; + double gainA; + double gainB; //smoothed master fader for channel, from Z2 series filter code + + float A; + float B; + float C; + float D; + float E; //parameters. Always 0-1, and we scale/alter them elsewhere. + +}; + +#endif +} // end namespace diff --git a/src/autogen_airwin/ConsoleLAChannelProc.cpp b/src/autogen_airwin/ConsoleLAChannelProc.cpp new file mode 100644 index 0000000..a105f8f --- /dev/null +++ b/src/autogen_airwin/ConsoleLAChannelProc.cpp @@ -0,0 +1,626 @@ +/* ======================================== + * ConsoleLAChannel - ConsoleLAChannel.h + * Copyright (c) airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __ConsoleLAChannel_H +#include "ConsoleLAChannel.h" +#endif +namespace airwin2rack::ConsoleLAChannel { + +void ConsoleLAChannel::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) +{ + float* in1 = inputs[0]; + float* in2 = inputs[1]; + float* out1 = outputs[0]; + float* out2 = outputs[1]; + + VstInt32 inFramesToProcess = sampleFrames; //vst doesn't give us this as a separate variable so we'll make it + double overallscale = 1.0; + overallscale /= 44100.0; + overallscale *= getSampleRate(); + int cycleEnd = floor(overallscale); + if (cycleEnd < 1) cycleEnd = 1; + if (cycleEnd > 4) cycleEnd = 4; + + int limit = 4*cycleEnd; + double divisor = 2.0/limit; + + double treble = (A*6.0)-3.0; + midA = midB; + midB = (B*6.0)-3.0; + bassA = bassB; + bassB = (C*6.0)-3.0; + //these should stack to go up to -3.0 to 3.0 + if (treble < 0.0) treble /= 3.0; + if (midB < 0.0) midB /= 3.0; + if (bassB < 0.0) bassB /= 3.0; + //and then become -1.0 to 3.0; + //there will be successive sin/cos stages w. dry/wet in these + double freqMid = 0.024; + switch (cycleEnd) + { + case 1: //base sample rate, no change + break; + case 2: //96k tier + freqMid = 0.012; + break; + case 3: //192k tier + freqMid = 0.006; + break; + } + + + int bitshiftL = 0; + int bitshiftR = 0; + double panControl = (D*2.0)-1.0; //-1.0 to 1.0 + double panAttenuation = (1.0-fabs(panControl)); + int panBits = 20; //start centered + if (panAttenuation > 0.0) panBits = floor(1.0 / panAttenuation); + if (panControl > 0.25) bitshiftL += panBits; + if (panControl < -0.25) bitshiftR += panBits; + if (bitshiftL < 0) bitshiftL = 0; if (bitshiftL > 17) bitshiftL = 17; + if (bitshiftR < 0) bitshiftR = 0; if (bitshiftR > 17) bitshiftR = 17; + double gainL = 1.0; + double gainR = 1.0; + switch (bitshiftL) + { + case 17: gainL = 0.0; break; + case 16: gainL = 0.0000152587890625; break; + case 15: gainL = 0.000030517578125; break; + case 14: gainL = 0.00006103515625; break; + case 13: gainL = 0.0001220703125; break; + case 12: gainL = 0.000244140625; break; + case 11: gainL = 0.00048828125; break; + case 10: gainL = 0.0009765625; break; + case 9: gainL = 0.001953125; break; + case 8: gainL = 0.00390625; break; + case 7: gainL = 0.0078125; break; + case 6: gainL = 0.015625; break; + case 5: gainL = 0.03125; break; + case 4: gainL = 0.0625; break; + case 3: gainL = 0.125; break; + case 2: gainL = 0.25; break; + case 1: gainL = 0.5; break; + case 0: break; + } + switch (bitshiftR) + { + case 17: gainR = 0.0; break; + case 16: gainR = 0.0000152587890625; break; + case 15: gainR = 0.000030517578125; break; + case 14: gainR = 0.00006103515625; break; + case 13: gainR = 0.0001220703125; break; + case 12: gainR = 0.000244140625; break; + case 11: gainR = 0.00048828125; break; + case 10: gainR = 0.0009765625; break; + case 9: gainR = 0.001953125; break; + case 8: gainR = 0.00390625; break; + case 7: gainR = 0.0078125; break; + case 6: gainR = 0.015625; break; + case 5: gainR = 0.03125; break; + case 4: gainR = 0.0625; break; + case 3: gainR = 0.125; break; + case 2: gainR = 0.25; break; + case 1: gainR = 0.5; break; + case 0: break; + } + + gainA = gainB; + gainB = E*2.0; //smoothed master fader from Z2 filters + //BitShiftGain pre gain trim goes here + + double subTrim = 0.0011 / overallscale; + + while (--sampleFrames >= 0) + { + double inputSampleL = *in1; + double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-23) inputSampleL = fpdL * 1.18e-17; + if (fabs(inputSampleR)<1.18e-23) inputSampleR = fpdR * 1.18e-17; + + double temp = (double)sampleFrames/inFramesToProcess; + double gain = (gainA*temp)+(gainB*(1.0-temp)); + double mid = (midA*temp)+(midB*(1.0-temp)); + double bass = (bassA*temp)+(bassB*(1.0-temp)); + + //begin Hull2 Treble + hullp--; if (hullp < 0) hullp += 60; + hullL[hullp] = hullL[hullp+60] = inputSampleL; + hullR[hullp] = hullR[hullp+60] = inputSampleR; + + int x = hullp; + double bassL = 0.0; + double bassR = 0.0; + while (x < hullp+(limit/2)) { + bassL += hullL[x] * divisor; + bassR += hullR[x] * divisor; + x++; + } + bassL += bassL * 0.125; + bassR += bassR * 0.125; + while (x < hullp+limit) { + bassL -= hullL[x] * 0.125 * divisor; + bassR -= hullR[x] * 0.125 * divisor; + x++; + } + hullL[hullp+20] = hullL[hullp+80] = bassL; + hullR[hullp+20] = hullR[hullp+80] = bassR; + x = hullp+20; + bassL = bassR = 0.0; + while (x < hullp+20+(limit/2)) { + bassL += hullL[x] * divisor; + bassR += hullR[x] * divisor; + x++; + } + bassL += bassL * 0.125; + bassR += bassR * 0.125; + while (x < hullp+20+limit) { + bassL -= hullL[x] * 0.125 * divisor; + bassR -= hullR[x] * 0.125 * divisor; + x++; + } + hullL[hullp+40] = hullL[hullp+100] = bassL; + hullR[hullp+40] = hullR[hullp+100] = bassR; + x = hullp+40; + bassL = bassR = 0.0; + while (x < hullp+40+(limit/2)) { + bassL += hullL[x] * divisor; + bassR += hullR[x] * divisor; + x++; + } + bassL += bassL * 0.125; + bassR += bassR * 0.125; + while (x < hullp+40+limit) { + bassL -= hullL[x] * 0.125 * divisor; + bassR -= hullR[x] * 0.125 * divisor; + x++; + } + double trebleL = inputSampleL - bassL; inputSampleL = bassL; + double trebleR = inputSampleR - bassR; inputSampleR = bassR; + //end Hull2 treble + + //begin Pear filter stages + //at this point 'bass' is actually still mid and bass + double slew = ((bassL - pearB[0]) + pearB[1])*freqMid*0.5; + pearB[0] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[0] + pearB[1])); + pearB[1] = slew; slew = ((bassR - pearB[2]) + pearB[3])*freqMid*0.5; + pearB[2] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[2] + pearB[3])); + pearB[3] = slew; slew = ((bassL - pearB[4]) + pearB[5])*freqMid*0.5; + pearB[4] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[4] + pearB[5])); + pearB[5] = slew; slew = ((bassR - pearB[6]) + pearB[7])*freqMid*0.5; + pearB[6] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[6] + pearB[7])); + pearB[7] = slew; slew = ((bassL - pearB[8]) + pearB[9])*freqMid*0.5; + pearB[8] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[8] + pearB[9])); + pearB[9] = slew; slew = ((bassR - pearB[10]) + pearB[11])*freqMid*0.5; + pearB[10] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[10] + pearB[11])); + pearB[11] = slew; slew = ((bassL - pearB[12]) + pearB[13])*freqMid*0.5; + pearB[12] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[12] + pearB[13])); + pearB[13] = slew; slew = ((bassR - pearB[14]) + pearB[15])*freqMid*0.5; + pearB[14] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[14] + pearB[15])); + pearB[15] = slew; slew = ((bassL - pearB[16]) + pearB[17])*freqMid*0.5; + pearB[16] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[16] + pearB[17])); + pearB[17] = slew; slew = ((bassR - pearB[18]) + pearB[19])*freqMid*0.5; + pearB[18] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[18] + pearB[19])); + pearB[19] = slew; + double midL = inputSampleL - bassL; + double midR = inputSampleR - bassR; + //we now have three bands out of hull and pear filters + + double w = 0.0; //filter into bands, apply the sin/cos to each band + if (treble > 0.0) { + w = treble; if (w > 1.0) w = 1.0; + trebleL = (trebleL*(1.0-w)) + (sin(trebleL*M_PI_2)*treble); + trebleR = (trebleR*(1.0-w)) + (sin(trebleR*M_PI_2)*treble); + } + if (treble < 0.0) { + if (trebleL > 1.0) trebleL = 1.0; if (trebleL < -1.0) trebleL = -1.0; + if (trebleR > 1.0) trebleR = 1.0; if (trebleR < -1.0) trebleR = -1.0; + w = -treble; if (w > 1.0) w = 1.0; + if (trebleL > 0) trebleL = (trebleL*(1.0-w))+((1.0-cos(trebleL*w))*(1.0-w)); + else trebleL = (trebleL*(1.0-w))+((-1.0+cos(-trebleL*w))*(1.0-w)); + if (trebleR > 0) trebleR = (trebleR*(1.0-w))+((1.0-cos(trebleR*w))*(1.0-w)); + else trebleR = (trebleR*(1.0-w))+((-1.0+cos(-trebleR*w))*(1.0-w)); + } //cosine stages for EQ or expansion + + if (midL > 1.0) midL = 1.0; if (midL < -1.0) midL = -1.0; + if (midR > 1.0) midR = 1.0; if (midR < -1.0) midR = -1.0; + if (mid > 0.0) { + w = mid; if (w > 1.0) w = 1.0; + midL = (midL*(1.0-w)) + (sin(midL*M_PI_2)*mid); + midR = (midR*(1.0-w)) + (sin(midR*M_PI_2)*mid); + } + if (mid < 0.0) { + w = -mid; if (w > 1.0) w = 1.0; + if (midL > 0) midL = (midL*(1.0-w))+((1.0-cos(midL*w))*(1.0-w)); + else midL = (midL*(1.0-w))+((-1.0+cos(-midL*w))*(1.0-w)); + if (midR > 0) midR = (midR*(1.0-w))+((1.0-cos(midR*w))*(1.0-w)); + else midR = (midR*(1.0-w))+((-1.0+cos(-midR*w))*(1.0-w)); + } //cosine stages for EQ or expansion + + if (bassL > 1.0) bassL = 1.0; if (bassL < -1.0) bassL = -1.0; + if (bassR > 1.0) bassR = 1.0; if (bassR < -1.0) bassR = -1.0; + if (bass > 0.0) { + w = bass; if (w > 1.0) w = 1.0; + bassL = (bassL*(1.0-w)) + (sin(bassL*M_PI_2)*bass); + bassR = (bassR*(1.0-w)) + (sin(bassR*M_PI_2)*bass); + } + if (bass < 0.0) { + w = -bass; if (w > 1.0) w = 1.0; + if (bassL > 0) bassL = (bassL*(1.0-w))+((1.0-cos(bassL*w))*(1.0-w)); + else bassL = (bassL*(1.0-w))+((-1.0+cos(-bassL*w))*(1.0-w)); + if (bassR > 0) bassR = (bassR*(1.0-w))+((1.0-cos(bassR*w))*(1.0-w)); + else bassR = (bassR*(1.0-w))+((-1.0+cos(-bassR*w))*(1.0-w)); + } //cosine stages for EQ or expansion + + inputSampleL = (bassL + midL + trebleL)*gainL*gain; + inputSampleR = (bassR + midR + trebleR)*gainR*gain; + //applies BitShiftPan pan section, and smoothed fader gain + + //begin SubTight section + double subSampleL = inputSampleL * subTrim; + double subSampleR = inputSampleR * subTrim; + + double scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subAL+(sin(subAL-subSampleL)*scale)); + subAL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subAR+(sin(subAR-subSampleR)*scale)); + subAR = subSampleR*scale; + scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subBL+(sin(subBL-subSampleL)*scale)); + subBL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subBR+(sin(subBR-subSampleR)*scale)); + subBR = subSampleR*scale; + scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subCL+(sin(subCL-subSampleL)*scale)); + subCL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subCR+(sin(subCR-subSampleR)*scale)); + subCR = subSampleR*scale; + if (subSampleL > 0.25) subSampleL = 0.25; + if (subSampleL < -0.25) subSampleL = -0.25; + if (subSampleR > 0.25) subSampleR = 0.25; + if (subSampleR < -0.25) subSampleR = -0.25; + inputSampleL += (subSampleL*16.0); + inputSampleR += (subSampleR*16.0); + //end SubTight section + + //begin Console7 Channel processing + if (inputSampleL > 1.097) inputSampleL = 1.097; + if (inputSampleL < -1.097) inputSampleL = -1.097; + if (inputSampleR > 1.097) inputSampleR = 1.097; + if (inputSampleR < -1.097) inputSampleR = -1.097; + inputSampleL = ((sin(inputSampleL*fabs(inputSampleL))/((fabs(inputSampleL) == 0.0) ?1:fabs(inputSampleL)))*0.8)+(sin(inputSampleL)*0.2); + inputSampleR = ((sin(inputSampleR*fabs(inputSampleR))/((fabs(inputSampleR) == 0.0) ?1:fabs(inputSampleR)))*0.8)+(sin(inputSampleR)*0.2); + //this is a version of Spiral blended 80/20 with regular Density. + //It's blending between two different harmonics in the overtones of the algorithm + + //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 ConsoleLAChannel::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames) +{ + double* in1 = inputs[0]; + double* in2 = inputs[1]; + double* out1 = outputs[0]; + double* out2 = outputs[1]; + + VstInt32 inFramesToProcess = sampleFrames; //vst doesn't give us this as a separate variable so we'll make it + double overallscale = 1.0; + overallscale /= 44100.0; + overallscale *= getSampleRate(); + int cycleEnd = floor(overallscale); + if (cycleEnd < 1) cycleEnd = 1; + if (cycleEnd > 4) cycleEnd = 4; + + int limit = 4*cycleEnd; + double divisor = 2.0/limit; + + double treble = (A*6.0)-3.0; + midA = midB; + midB = (B*6.0)-3.0; + bassA = bassB; + bassB = (C*6.0)-3.0; + //these should stack to go up to -3.0 to 3.0 + if (treble < 0.0) treble /= 3.0; + if (midB < 0.0) midB /= 3.0; + if (bassB < 0.0) bassB /= 3.0; + //and then become -1.0 to 3.0; + //there will be successive sin/cos stages w. dry/wet in these + double freqMid = 0.024; + switch (cycleEnd) + { + case 1: //base sample rate, no change + break; + case 2: //96k tier + freqMid = 0.012; + break; + case 3: //192k tier + freqMid = 0.006; + break; + } + + + int bitshiftL = 0; + int bitshiftR = 0; + double panControl = (D*2.0)-1.0; //-1.0 to 1.0 + double panAttenuation = (1.0-fabs(panControl)); + int panBits = 20; //start centered + if (panAttenuation > 0.0) panBits = floor(1.0 / panAttenuation); + if (panControl > 0.25) bitshiftL += panBits; + if (panControl < -0.25) bitshiftR += panBits; + if (bitshiftL < 0) bitshiftL = 0; if (bitshiftL > 17) bitshiftL = 17; + if (bitshiftR < 0) bitshiftR = 0; if (bitshiftR > 17) bitshiftR = 17; + double gainL = 1.0; + double gainR = 1.0; + switch (bitshiftL) + { + case 17: gainL = 0.0; break; + case 16: gainL = 0.0000152587890625; break; + case 15: gainL = 0.000030517578125; break; + case 14: gainL = 0.00006103515625; break; + case 13: gainL = 0.0001220703125; break; + case 12: gainL = 0.000244140625; break; + case 11: gainL = 0.00048828125; break; + case 10: gainL = 0.0009765625; break; + case 9: gainL = 0.001953125; break; + case 8: gainL = 0.00390625; break; + case 7: gainL = 0.0078125; break; + case 6: gainL = 0.015625; break; + case 5: gainL = 0.03125; break; + case 4: gainL = 0.0625; break; + case 3: gainL = 0.125; break; + case 2: gainL = 0.25; break; + case 1: gainL = 0.5; break; + case 0: break; + } + switch (bitshiftR) + { + case 17: gainR = 0.0; break; + case 16: gainR = 0.0000152587890625; break; + case 15: gainR = 0.000030517578125; break; + case 14: gainR = 0.00006103515625; break; + case 13: gainR = 0.0001220703125; break; + case 12: gainR = 0.000244140625; break; + case 11: gainR = 0.00048828125; break; + case 10: gainR = 0.0009765625; break; + case 9: gainR = 0.001953125; break; + case 8: gainR = 0.00390625; break; + case 7: gainR = 0.0078125; break; + case 6: gainR = 0.015625; break; + case 5: gainR = 0.03125; break; + case 4: gainR = 0.0625; break; + case 3: gainR = 0.125; break; + case 2: gainR = 0.25; break; + case 1: gainR = 0.5; break; + case 0: break; + } + + gainA = gainB; + gainB = E*2.0; //smoothed master fader from Z2 filters + //BitShiftGain pre gain trim goes here + + double subTrim = 0.0011 / overallscale; + + while (--sampleFrames >= 0) + { + double inputSampleL = *in1; + double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-23) inputSampleL = fpdL * 1.18e-17; + if (fabs(inputSampleR)<1.18e-23) inputSampleR = fpdR * 1.18e-17; + + double temp = (double)sampleFrames/inFramesToProcess; + double gain = (gainA*temp)+(gainB*(1.0-temp)); + double mid = (midA*temp)+(midB*(1.0-temp)); + double bass = (bassA*temp)+(bassB*(1.0-temp)); + + //begin Hull2 Treble + hullp--; if (hullp < 0) hullp += 60; + hullL[hullp] = hullL[hullp+60] = inputSampleL; + hullR[hullp] = hullR[hullp+60] = inputSampleR; + + int x = hullp; + double bassL = 0.0; + double bassR = 0.0; + while (x < hullp+(limit/2)) { + bassL += hullL[x] * divisor; + bassR += hullR[x] * divisor; + x++; + } + bassL += bassL * 0.125; + bassR += bassR * 0.125; + while (x < hullp+limit) { + bassL -= hullL[x] * 0.125 * divisor; + bassR -= hullR[x] * 0.125 * divisor; + x++; + } + hullL[hullp+20] = hullL[hullp+80] = bassL; + hullR[hullp+20] = hullR[hullp+80] = bassR; + x = hullp+20; + bassL = bassR = 0.0; + while (x < hullp+20+(limit/2)) { + bassL += hullL[x] * divisor; + bassR += hullR[x] * divisor; + x++; + } + bassL += bassL * 0.125; + bassR += bassR * 0.125; + while (x < hullp+20+limit) { + bassL -= hullL[x] * 0.125 * divisor; + bassR -= hullR[x] * 0.125 * divisor; + x++; + } + hullL[hullp+40] = hullL[hullp+100] = bassL; + hullR[hullp+40] = hullR[hullp+100] = bassR; + x = hullp+40; + bassL = bassR = 0.0; + while (x < hullp+40+(limit/2)) { + bassL += hullL[x] * divisor; + bassR += hullR[x] * divisor; + x++; + } + bassL += bassL * 0.125; + bassR += bassR * 0.125; + while (x < hullp+40+limit) { + bassL -= hullL[x] * 0.125 * divisor; + bassR -= hullR[x] * 0.125 * divisor; + x++; + } + double trebleL = inputSampleL - bassL; inputSampleL = bassL; + double trebleR = inputSampleR - bassR; inputSampleR = bassR; + //end Hull2 treble + + //begin Pear filter stages + //at this point 'bass' is actually still mid and bass + double slew = ((bassL - pearB[0]) + pearB[1])*freqMid*0.5; + pearB[0] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[0] + pearB[1])); + pearB[1] = slew; slew = ((bassR - pearB[2]) + pearB[3])*freqMid*0.5; + pearB[2] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[2] + pearB[3])); + pearB[3] = slew; slew = ((bassL - pearB[4]) + pearB[5])*freqMid*0.5; + pearB[4] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[4] + pearB[5])); + pearB[5] = slew; slew = ((bassR - pearB[6]) + pearB[7])*freqMid*0.5; + pearB[6] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[6] + pearB[7])); + pearB[7] = slew; slew = ((bassL - pearB[8]) + pearB[9])*freqMid*0.5; + pearB[8] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[8] + pearB[9])); + pearB[9] = slew; slew = ((bassR - pearB[10]) + pearB[11])*freqMid*0.5; + pearB[10] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[10] + pearB[11])); + pearB[11] = slew; slew = ((bassL - pearB[12]) + pearB[13])*freqMid*0.5; + pearB[12] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[12] + pearB[13])); + pearB[13] = slew; slew = ((bassR - pearB[14]) + pearB[15])*freqMid*0.5; + pearB[14] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[14] + pearB[15])); + pearB[15] = slew; slew = ((bassL - pearB[16]) + pearB[17])*freqMid*0.5; + pearB[16] = bassL = (freqMid * bassL) + ((1.0-freqMid) * (pearB[16] + pearB[17])); + pearB[17] = slew; slew = ((bassR - pearB[18]) + pearB[19])*freqMid*0.5; + pearB[18] = bassR = (freqMid * bassR) + ((1.0-freqMid) * (pearB[18] + pearB[19])); + pearB[19] = slew; + double midL = inputSampleL - bassL; + double midR = inputSampleR - bassR; + //we now have three bands out of hull and pear filters + + double w = 0.0; //filter into bands, apply the sin/cos to each band + if (treble > 0.0) { + w = treble; if (w > 1.0) w = 1.0; + trebleL = (trebleL*(1.0-w)) + (sin(trebleL*M_PI_2)*treble); + trebleR = (trebleR*(1.0-w)) + (sin(trebleR*M_PI_2)*treble); + } + if (treble < 0.0) { + if (trebleL > 1.0) trebleL = 1.0; if (trebleL < -1.0) trebleL = -1.0; + if (trebleR > 1.0) trebleR = 1.0; if (trebleR < -1.0) trebleR = -1.0; + w = -treble; if (w > 1.0) w = 1.0; + if (trebleL > 0) trebleL = (trebleL*(1.0-w))+((1.0-cos(trebleL*w))*(1.0-w)); + else trebleL = (trebleL*(1.0-w))+((-1.0+cos(-trebleL*w))*(1.0-w)); + if (trebleR > 0) trebleR = (trebleR*(1.0-w))+((1.0-cos(trebleR*w))*(1.0-w)); + else trebleR = (trebleR*(1.0-w))+((-1.0+cos(-trebleR*w))*(1.0-w)); + } //cosine stages for EQ or expansion + + if (midL > 1.0) midL = 1.0; if (midL < -1.0) midL = -1.0; + if (midR > 1.0) midR = 1.0; if (midR < -1.0) midR = -1.0; + if (mid > 0.0) { + w = mid; if (w > 1.0) w = 1.0; + midL = (midL*(1.0-w)) + (sin(midL*M_PI_2)*mid); + midR = (midR*(1.0-w)) + (sin(midR*M_PI_2)*mid); + } + if (mid < 0.0) { + w = -mid; if (w > 1.0) w = 1.0; + if (midL > 0) midL = (midL*(1.0-w))+((1.0-cos(midL*w))*(1.0-w)); + else midL = (midL*(1.0-w))+((-1.0+cos(-midL*w))*(1.0-w)); + if (midR > 0) midR = (midR*(1.0-w))+((1.0-cos(midR*w))*(1.0-w)); + else midR = (midR*(1.0-w))+((-1.0+cos(-midR*w))*(1.0-w)); + } //cosine stages for EQ or expansion + + if (bassL > 1.0) bassL = 1.0; if (bassL < -1.0) bassL = -1.0; + if (bassR > 1.0) bassR = 1.0; if (bassR < -1.0) bassR = -1.0; + if (bass > 0.0) { + w = bass; if (w > 1.0) w = 1.0; + bassL = (bassL*(1.0-w)) + (sin(bassL*M_PI_2)*bass); + bassR = (bassR*(1.0-w)) + (sin(bassR*M_PI_2)*bass); + } + if (bass < 0.0) { + w = -bass; if (w > 1.0) w = 1.0; + if (bassL > 0) bassL = (bassL*(1.0-w))+((1.0-cos(bassL*w))*(1.0-w)); + else bassL = (bassL*(1.0-w))+((-1.0+cos(-bassL*w))*(1.0-w)); + if (bassR > 0) bassR = (bassR*(1.0-w))+((1.0-cos(bassR*w))*(1.0-w)); + else bassR = (bassR*(1.0-w))+((-1.0+cos(-bassR*w))*(1.0-w)); + } //cosine stages for EQ or expansion + + inputSampleL = (bassL + midL + trebleL)*gainL*gain; + inputSampleR = (bassR + midR + trebleR)*gainR*gain; + //applies BitShiftPan pan section, and smoothed fader gain + + //begin SubTight section + double subSampleL = inputSampleL * subTrim; + double subSampleR = inputSampleR * subTrim; + + double scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subAL+(sin(subAL-subSampleL)*scale)); + subAL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subAR+(sin(subAR-subSampleR)*scale)); + subAR = subSampleR*scale; + scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subBL+(sin(subBL-subSampleL)*scale)); + subBL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subBR+(sin(subBR-subSampleR)*scale)); + subBR = subSampleR*scale; + scale = 0.5+fabs(subSampleL*0.5); + subSampleL = (subCL+(sin(subCL-subSampleL)*scale)); + subCL = subSampleL*scale; + scale = 0.5+fabs(subSampleR*0.5); + subSampleR = (subCR+(sin(subCR-subSampleR)*scale)); + subCR = subSampleR*scale; + if (subSampleL > 0.25) subSampleL = 0.25; + if (subSampleL < -0.25) subSampleL = -0.25; + if (subSampleR > 0.25) subSampleR = 0.25; + if (subSampleR < -0.25) subSampleR = -0.25; + inputSampleL += (subSampleL*16.0); + inputSampleR += (subSampleR*16.0); + //end SubTight section + + //begin Console7 Channel processing + if (inputSampleL > 1.097) inputSampleL = 1.097; + if (inputSampleL < -1.097) inputSampleL = -1.097; + if (inputSampleR > 1.097) inputSampleR = 1.097; + if (inputSampleR < -1.097) inputSampleR = -1.097; + inputSampleL = ((sin(inputSampleL*fabs(inputSampleL))/((fabs(inputSampleL) == 0.0) ?1:fabs(inputSampleL)))*0.8)+(sin(inputSampleL)*0.2); + inputSampleR = ((sin(inputSampleR*fabs(inputSampleR))/((fabs(inputSampleR) == 0.0) ?1:fabs(inputSampleR)))*0.8)+(sin(inputSampleR)*0.2); + //this is a version of Spiral blended 80/20 with regular Density. + //It's blending between two different harmonics in the overtones of the algorithm + + //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 diff --git a/src/autogen_airwin/Overheads.cpp b/src/autogen_airwin/Overheads.cpp new file mode 100644 index 0000000..fb6c27b --- /dev/null +++ b/src/autogen_airwin/Overheads.cpp @@ -0,0 +1,133 @@ +/* ======================================== + * Overheads - Overheads.h + * Copyright (c) airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __Overheads_H +#include "Overheads.h" +#endif +namespace airwin2rack::Overheads { + +AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {return new Overheads(audioMaster);} + +Overheads::Overheads(audioMasterCallback audioMaster) : + AudioEffectX(audioMaster, kNumPrograms, kNumParameters) +{ + A = 0.0; + B = 0.5; + C = 1.0; + + ovhGain = 1.0; + for(int count = 0; count < 129; count++) {ovhL[count] = 0.0; ovhR[count] = 0.0;} + ovhCount = 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 +} + +Overheads::~Overheads() {} +VstInt32 Overheads::getVendorVersion () {return 1000;} +void Overheads::setProgramName(char *name) {vst_strncpy (_programName, name, kVstMaxProgNameLen);} +void Overheads::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; +} + +void Overheads::setParameter(VstInt32 index, float value) { + switch (index) { + case kParamA: A = value; break; + case kParamB: B = value; break; + case kParamC: C = value; break; + default: break; // unknown parameter, shouldn't happen! + } +} + +float Overheads::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 Overheads::getParameterName(VstInt32 index, char *text) { + switch (index) { + case kParamA: vst_strncpy (text, "Compr", kVstMaxParamStrLen); break; + case kParamB: vst_strncpy (text, "Sharp", kVstMaxParamStrLen); break; + case kParamC: 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 Overheads::getParameterDisplay(VstInt32 index, char *text) { + switch (index) { + case kParamA: float2string (A, text, kVstMaxParamStrLen); break; + 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 Overheads::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 Overheads::canDo(char *text) +{ return (_canDo.find(text) == _canDo.end()) ? -1: 1; } // 1 = yes, -1 = no, 0 = don't know + +bool Overheads::getEffectName(char* name) { + vst_strncpy(name, "Overheads", kVstMaxProductStrLen); return true; +} + +VstPlugCategory Overheads::getPlugCategory() {return kPlugCategEffect;} + +bool Overheads::getProductString(char* text) { + vst_strncpy (text, "airwindows Overheads", kVstMaxProductStrLen); return true; +} + +bool Overheads::getVendorString(char* text) { + vst_strncpy (text, "airwindows", kVstMaxVendorStrLen); return true; +} +bool Overheads::parameterTextToValue(VstInt32 index, const char *text, float &value) { + switch(index) { + case kParamA: { auto b = string2float(text, value); return b; break; } + case kParamB: { auto b = string2float(text, value); return b; break; } + case kParamC: { auto b = string2float(text, value); return b; break; } + + } + return false; +} +bool Overheads::canConvertParameterTextToValue(VstInt32 index) { + switch(index) { + case kParamA: return true; + case kParamB: return true; + case kParamC: return true; + + } + return false; +} +} // end namespace diff --git a/src/autogen_airwin/Overheads.h b/src/autogen_airwin/Overheads.h new file mode 100644 index 0000000..014ae4a --- /dev/null +++ b/src/autogen_airwin/Overheads.h @@ -0,0 +1,75 @@ +/* ======================================== + * Overheads - Overheads.h + * Created 8/12/11 by SPIAdmin + * Copyright (c) Airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __Overheads_Overheads_H +#define __Overheads_Overheads_H + +#ifndef __audioeffect__ +#include "../airwin2rackbase.h" +#endif + +#include +#include +#include + +namespace airwin2rack::Overheads { +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 = 'over'; //Change this to what the AU identity is! + +class Overheads : + public AudioEffectX +{ +public: + Overheads(audioMasterCallback audioMaster); + ~Overheads(); + 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 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 + // Added by the perl as inverses + virtual bool parameterTextToValue(VstInt32 index, const char *text, float &value); + virtual bool canConvertParameterTextToValue(VstInt32 index); + virtual VstInt32 canDo(char *text); +private: + char _programName[kVstMaxProgNameLen + 1]; + std::set< std::string > _canDo; + + uint32_t fpdL; + uint32_t fpdR; + //default stuff + + float A; + float B; + float C; + + double ovhGain; + double ovhL[130]; + double ovhR[130]; + int ovhCount; + +}; + +#endif +} // end namespace diff --git a/src/autogen_airwin/OverheadsProc.cpp b/src/autogen_airwin/OverheadsProc.cpp new file mode 100644 index 0000000..5994407 --- /dev/null +++ b/src/autogen_airwin/OverheadsProc.cpp @@ -0,0 +1,130 @@ +/* ======================================== + * Overheads - Overheads.h + * Copyright (c) airwindows, Airwindows uses the MIT license + * ======================================== */ + +#ifndef __Overheads_H +#include "Overheads.h" +#endif +namespace airwin2rack::Overheads { + +void Overheads::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 ovhTrim = pow(A,3); + ovhTrim += 1.0; ovhTrim *= ovhTrim; + int offset = (pow(B,7) * 16.0 * overallscale)+1; + double wet = C; + + while (--sampleFrames >= 0) + { + double inputSampleL = *in1; + double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-23) inputSampleL = fpdL * 1.18e-17; + if (fabs(inputSampleR)<1.18e-23) inputSampleR = fpdR * 1.18e-17; + double drySampleL = inputSampleL; + double drySampleR = inputSampleR; + + //begin Overheads compressor + inputSampleL *= ovhTrim; inputSampleR *= ovhTrim; + ovhCount--; if (ovhCount < 0 || ovhCount > 128) ovhCount = 128; ovhL[ovhCount] = inputSampleL; ovhR[ovhCount] = inputSampleR; + double ovhClamp = sin(fabs(inputSampleL - ovhL[(ovhCount+offset)-(((ovhCount+offset) > 128)?129:0)])*(ovhTrim-1.0)*64.0); + ovhGain *= (1.0 - ovhClamp); ovhGain += ((1.0-ovhClamp) * ovhClamp); + ovhClamp = sin(fabs(inputSampleR - ovhR[(ovhCount+offset)-(((ovhCount+offset) > 128)?129:0)])*(ovhTrim-1.0)*64.0); + ovhGain *= (1.0 - ovhClamp); ovhGain += ((1.0-ovhClamp) * ovhClamp); + if (ovhGain > 1.0) ovhGain = 1.0; if (ovhGain < 0.0) ovhGain = 0.0; + inputSampleL *= ovhGain; inputSampleR *= ovhGain; + //end Overheads compressor + + if (wet !=1.0) { + inputSampleL = (inputSampleL * wet) + (drySampleL * (1.0-wet)); + inputSampleR = (inputSampleR * wet) + (drySampleR * (1.0-wet)); + } + + //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 Overheads::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 ovhTrim = pow(A,3); + ovhTrim += 1.0; ovhTrim *= ovhTrim; + int offset = (pow(B,7) * 16.0 * overallscale)+1; + double wet = C; + + while (--sampleFrames >= 0) + { + double inputSampleL = *in1; + double inputSampleR = *in2; + if (fabs(inputSampleL)<1.18e-23) inputSampleL = fpdL * 1.18e-17; + if (fabs(inputSampleR)<1.18e-23) inputSampleR = fpdR * 1.18e-17; + double drySampleL = inputSampleL; + double drySampleR = inputSampleR; + + //begin Overheads compressor + inputSampleL *= ovhTrim; inputSampleR *= ovhTrim; + ovhCount--; if (ovhCount < 0 || ovhCount > 128) ovhCount = 128; ovhL[ovhCount] = inputSampleL; ovhR[ovhCount] = inputSampleR; + double ovhClamp = sin(fabs(inputSampleL - ovhL[(ovhCount+offset)-(((ovhCount+offset) > 128)?129:0)])*(ovhTrim-1.0)*64.0); + ovhGain *= (1.0 - ovhClamp); ovhGain += ((1.0-ovhClamp) * ovhClamp); + ovhClamp = sin(fabs(inputSampleR - ovhR[(ovhCount+offset)-(((ovhCount+offset) > 128)?129:0)])*(ovhTrim-1.0)*64.0); + ovhGain *= (1.0 - ovhClamp); ovhGain += ((1.0-ovhClamp) * ovhClamp); + if (ovhGain > 1.0) ovhGain = 1.0; if (ovhGain < 0.0) ovhGain = 0.0; + inputSampleL *= ovhGain; inputSampleR *= ovhGain; + //end Overheads compressor + + if (wet !=1.0) { + inputSampleL = (inputSampleL * wet) + (drySampleL * (1.0-wet)); + inputSampleR = (inputSampleR * wet) + (drySampleR * (1.0-wet)); + } + + //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