airwindows/plugins/MacSignedVST/MultiBandDistortion/source/MultiBandDistortionProc.cpp
2022-11-21 09:20:21 -05:00

498 lines
21 KiB
C++
Executable file

/* ========================================
* MultiBandDistortion - MultiBandDistortion.h
* Copyright (c) 2016 airwindows, Airwindows uses the MIT license
* ======================================== */
#ifndef __MultiBandDistortion_H
#include "MultiBandDistortion.h"
#endif
void MultiBandDistortion::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 iirAmount = pow(A,3)/overallscale;
double gainH = pow(10.0,(B*48.0)/20);
double thresholdH = D;
double hardnessH;
if (thresholdH < 1.0) hardnessH = 1.0 / (1.0-thresholdH);
else hardnessH = 999999999999999999999.0;
double gainL = pow(10.0,(C*48.0)/20);
double thresholdL = E;
double hardnessL;
if (thresholdL < 1.0) hardnessL = 1.0 / (1.0-thresholdL);
else hardnessL = 999999999999999999999.0;
double breakup = 1.5707963267949;
double bridgerectifier;
double outputH = F;
double outputL = G;
double outputD = H*0.597;
double outtrim = outputH + outputL + outputD;
outputH *= outtrim;
outputL *= outtrim;
outputD *= outtrim;
double outputGlobal = pow(10.0,((I-1.0)*48.0)/20);
double tempHL;
double tempLL;
double tempHR;
double tempLR;
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;
ataDrySampleL = inputSampleL;
ataHalfDrySampleL = ataHalfwaySampleL = (inputSampleL + ataLast1SampleL + ((-ataLast2SampleL + ataLast3SampleL) * ataUpsampleHighTweakL)) / 2.0;
ataLast3SampleL = ataLast2SampleL; ataLast2SampleL = ataLast1SampleL; ataLast1SampleL = inputSampleL;
//setting up oversampled special antialiasing
ataDrySampleR = inputSampleR;
ataHalfDrySampleR = ataHalfwaySampleR = (inputSampleR + ataLast1SampleR + ((-ataLast2SampleR + ataLast3SampleR) * ataUpsampleHighTweakR)) / 2.0;
ataLast3SampleR = ataLast2SampleR; ataLast2SampleR = ataLast1SampleR; ataLast1SampleR = inputSampleR;
//setting up oversampled special antialiasing
//pre-center code on inputSample and halfwaySample in parallel
//begin interpolated sample- change inputSample -> ataHalfwaySample, ataDrySample -> ataHalfDrySample
tempLL = iirSampleAL = (iirSampleAL * (1 - iirAmount)) + (ataHalfwaySampleL * iirAmount);
tempHL = ataHalfwaySampleL - iirSampleAL;
//highpass section
tempLR = iirSampleAR = (iirSampleAR * (1 - iirAmount)) + (ataHalfwaySampleR * iirAmount);
tempHR = ataHalfwaySampleR - iirSampleAR;
//highpass section
tempHL *= gainH;
if (fabs(tempHL) > thresholdH)
{
bridgerectifier = (fabs(tempHL)-thresholdH)*hardnessH;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessH;
//do the sine factor, scale back to proper amount
if (tempHL > 0) tempHL = bridgerectifier+thresholdH;
else tempHL = -(bridgerectifier+thresholdH);
}
tempHR *= gainH;
if (fabs(tempHR) > thresholdH)
{
bridgerectifier = (fabs(tempHR)-thresholdH)*hardnessH;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessH;
//do the sine factor, scale back to proper amount
if (tempHR > 0) tempHR = bridgerectifier+thresholdH;
else tempHR = -(bridgerectifier+thresholdH);
}
tempLL *= gainL;
if (fabs(tempLL) > thresholdL)
{
bridgerectifier = (fabs(tempLL)-thresholdL)*hardnessL;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessL;
//do the sine factor, scale back to proper amount
if (tempLL > 0) tempLL = bridgerectifier+thresholdL;
else tempLL = -(bridgerectifier+thresholdL);
}
tempLR *= gainL;
if (fabs(tempLR) > thresholdL)
{
bridgerectifier = (fabs(tempLR)-thresholdL)*hardnessL;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessL;
//do the sine factor, scale back to proper amount
if (tempLR > 0) tempLR = bridgerectifier+thresholdL;
else tempLR = -(bridgerectifier+thresholdL);
}
ataHalfwaySampleL = (tempLL * outputL) + (tempHL * outputH);
ataHalfwaySampleR = (tempLR * outputL) + (tempHR * outputH);
//end interpolated sample
//begin raw sample- inputSample and ataDrySample handled separately here
tempLL = iirSampleBL = (iirSampleBL * (1 - iirAmount)) + (inputSampleL * iirAmount);
tempHL = inputSampleL - iirSampleBL;
//highpass section
tempLR = iirSampleBR = (iirSampleBR * (1 - iirAmount)) + (inputSampleR * iirAmount);
tempHR = inputSampleR - iirSampleBR;
//highpass section
tempHL *= gainH;
if (fabs(tempHL) > thresholdH)
{
bridgerectifier = (fabs(tempHL)-thresholdH)*hardnessH;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessH;
//do the sine factor, scale back to proper amount
if (tempHL > 0) tempHL = bridgerectifier+thresholdH;
else tempHL = -(bridgerectifier+thresholdH);
}
tempHR *= gainH;
if (fabs(tempHR) > thresholdH)
{
bridgerectifier = (fabs(tempHR)-thresholdH)*hardnessH;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessH;
//do the sine factor, scale back to proper amount
if (tempHR > 0) tempHR = bridgerectifier+thresholdH;
else tempHR = -(bridgerectifier+thresholdH);
}
tempLL *= gainL;
if (fabs(tempLL) > thresholdL)
{
bridgerectifier = (fabs(tempLL)-thresholdL)*hardnessL;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessL;
//do the sine factor, scale back to proper amount
if (tempLL > 0) tempLL = bridgerectifier+thresholdL;
else tempLL = -(bridgerectifier+thresholdL);
}
tempLR *= gainL;
if (fabs(tempLR) > thresholdL)
{
bridgerectifier = (fabs(tempLR)-thresholdL)*hardnessL;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessL;
//do the sine factor, scale back to proper amount
if (tempLR > 0) tempLR = bridgerectifier+thresholdL;
else tempLR = -(bridgerectifier+thresholdL);
}
inputSampleL = (tempLL * outputL) + (tempHL * outputH);
inputSampleR = (tempLR * outputL) + (tempHR * outputH);
//end raw sample
//begin antialiasing section for halfway sample
ataCL = ataHalfwaySampleL - ataHalfDrySampleL;
if (ataFlip) {ataAL *= ataDecayL; ataBL *= ataDecayL; ataAL += ataCL; ataBL -= ataCL; ataCL = ataAL;}
else {ataBL *= ataDecayL; ataAL *= ataDecayL; ataBL += ataCL; ataAL -= ataCL; ataCL = ataBL;}
ataHalfDiffSampleL = (ataCL * ataDecayL);
//end antialiasing section for halfway sample L
ataCR = ataHalfwaySampleR - ataHalfDrySampleR;
if (ataFlip) {ataAR *= ataDecayR; ataBR *= ataDecayR; ataAR += ataCR; ataBR -= ataCR; ataCR = ataAR;}
else {ataBR *= ataDecayR; ataAR *= ataDecayR; ataBR += ataCR; ataAR -= ataCR; ataCR = ataBR;}
ataHalfDiffSampleR = (ataCR * ataDecayR);
//end antialiasing section for halfway sample R
//begin antialiasing section for raw sample
ataCL = inputSampleL - ataDrySampleL;
if (ataFlip) {ataAL *= ataDecayL; ataBL *= ataDecayL; ataAL += ataCL; ataBL -= ataCL; ataCL = ataAL;}
else {ataBL *= ataDecayL; ataAL *= ataDecayL; ataBL += ataCL; ataAL -= ataCL; ataCL = ataBL;}
ataDiffSampleL = (ataCL * ataDecayL);
//end antialiasing section for input sample L
ataCR = inputSampleR - ataDrySampleR;
if (ataFlip) {ataAR *= ataDecayR; ataBR *= ataDecayR; ataAR += ataCR; ataBR -= ataCR; ataCR = ataAR;}
else {ataBR *= ataDecayR; ataAR *= ataDecayR; ataBR += ataCR; ataAR -= ataCR; ataCR = ataBR;}
ataDiffSampleR = (ataCR * ataDecayR);
//end antialiasing section for input sample R
ataFlip = !ataFlip;
inputSampleL = ataDrySampleL*outputD; inputSampleL += (ataDiffSampleL + ataHalfDiffSampleL);
inputSampleR = ataDrySampleR*outputD; inputSampleR += (ataDiffSampleR + ataHalfDiffSampleR);
//apply processing as difference to non-oversampled raw input
inputSampleL *= outputGlobal;
inputSampleR *= outputGlobal;
//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 MultiBandDistortion::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 iirAmount = pow(A,3)/overallscale;
double gainH = pow(10.0,(B*48.0)/20);
double thresholdH = D;
double hardnessH;
if (thresholdH < 1.0) hardnessH = 1.0 / (1.0-thresholdH);
else hardnessH = 999999999999999999999.0;
double gainL = pow(10.0,(C*48.0)/20);
double thresholdL = E;
double hardnessL;
if (thresholdL < 1.0) hardnessL = 1.0 / (1.0-thresholdL);
else hardnessL = 999999999999999999999.0;
double breakup = 1.5707963267949;
double bridgerectifier;
double outputH = F;
double outputL = G;
double outputD = H*0.597;
double outtrim = outputH + outputL + outputD;
outputH *= outtrim;
outputL *= outtrim;
outputD *= outtrim;
double outputGlobal = pow(10.0,((I-1.0)*48.0)/20);
double tempHL;
double tempLL;
double tempHR;
double tempLR;
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;
ataDrySampleL = inputSampleL;
ataHalfDrySampleL = ataHalfwaySampleL = (inputSampleL + ataLast1SampleL + ((-ataLast2SampleL + ataLast3SampleL) * ataUpsampleHighTweakL)) / 2.0;
ataLast3SampleL = ataLast2SampleL; ataLast2SampleL = ataLast1SampleL; ataLast1SampleL = inputSampleL;
//setting up oversampled special antialiasing
ataDrySampleR = inputSampleR;
ataHalfDrySampleR = ataHalfwaySampleR = (inputSampleR + ataLast1SampleR + ((-ataLast2SampleR + ataLast3SampleR) * ataUpsampleHighTweakR)) / 2.0;
ataLast3SampleR = ataLast2SampleR; ataLast2SampleR = ataLast1SampleR; ataLast1SampleR = inputSampleR;
//setting up oversampled special antialiasing
//pre-center code on inputSample and halfwaySample in parallel
//begin interpolated sample- change inputSample -> ataHalfwaySample, ataDrySample -> ataHalfDrySample
tempLL = iirSampleAL = (iirSampleAL * (1 - iirAmount)) + (ataHalfwaySampleL * iirAmount);
tempHL = ataHalfwaySampleL - iirSampleAL;
//highpass section
tempLR = iirSampleAR = (iirSampleAR * (1 - iirAmount)) + (ataHalfwaySampleR * iirAmount);
tempHR = ataHalfwaySampleR - iirSampleAR;
//highpass section
tempHL *= gainH;
if (fabs(tempHL) > thresholdH)
{
bridgerectifier = (fabs(tempHL)-thresholdH)*hardnessH;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessH;
//do the sine factor, scale back to proper amount
if (tempHL > 0) tempHL = bridgerectifier+thresholdH;
else tempHL = -(bridgerectifier+thresholdH);
}
tempHR *= gainH;
if (fabs(tempHR) > thresholdH)
{
bridgerectifier = (fabs(tempHR)-thresholdH)*hardnessH;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessH;
//do the sine factor, scale back to proper amount
if (tempHR > 0) tempHR = bridgerectifier+thresholdH;
else tempHR = -(bridgerectifier+thresholdH);
}
tempLL *= gainL;
if (fabs(tempLL) > thresholdL)
{
bridgerectifier = (fabs(tempLL)-thresholdL)*hardnessL;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessL;
//do the sine factor, scale back to proper amount
if (tempLL > 0) tempLL = bridgerectifier+thresholdL;
else tempLL = -(bridgerectifier+thresholdL);
}
tempLR *= gainL;
if (fabs(tempLR) > thresholdL)
{
bridgerectifier = (fabs(tempLR)-thresholdL)*hardnessL;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessL;
//do the sine factor, scale back to proper amount
if (tempLR > 0) tempLR = bridgerectifier+thresholdL;
else tempLR = -(bridgerectifier+thresholdL);
}
ataHalfwaySampleL = (tempLL * outputL) + (tempHL * outputH);
ataHalfwaySampleR = (tempLR * outputL) + (tempHR * outputH);
//end interpolated sample
//begin raw sample- inputSample and ataDrySample handled separately here
tempLL = iirSampleBL = (iirSampleBL * (1 - iirAmount)) + (inputSampleL * iirAmount);
tempHL = inputSampleL - iirSampleBL;
//highpass section
tempLR = iirSampleBR = (iirSampleBR * (1 - iirAmount)) + (inputSampleR * iirAmount);
tempHR = inputSampleR - iirSampleBR;
//highpass section
tempHL *= gainH;
if (fabs(tempHL) > thresholdH)
{
bridgerectifier = (fabs(tempHL)-thresholdH)*hardnessH;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessH;
//do the sine factor, scale back to proper amount
if (tempHL > 0) tempHL = bridgerectifier+thresholdH;
else tempHL = -(bridgerectifier+thresholdH);
}
tempHR *= gainH;
if (fabs(tempHR) > thresholdH)
{
bridgerectifier = (fabs(tempHR)-thresholdH)*hardnessH;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessH;
//do the sine factor, scale back to proper amount
if (tempHR > 0) tempHR = bridgerectifier+thresholdH;
else tempHR = -(bridgerectifier+thresholdH);
}
tempLL *= gainL;
if (fabs(tempLL) > thresholdL)
{
bridgerectifier = (fabs(tempLL)-thresholdL)*hardnessL;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessL;
//do the sine factor, scale back to proper amount
if (tempLL > 0) tempLL = bridgerectifier+thresholdL;
else tempLL = -(bridgerectifier+thresholdL);
}
tempLR *= gainL;
if (fabs(tempLR) > thresholdL)
{
bridgerectifier = (fabs(tempLR)-thresholdL)*hardnessL;
//skip flat area if any, scale to distortion limit
if (bridgerectifier > breakup) bridgerectifier = breakup;
//max value for sine function, 'breakup' modeling for trashed console tone
//more hardness = more solidness behind breakup modeling. more softness, more 'grunge' and sag
bridgerectifier = sin(bridgerectifier)/hardnessL;
//do the sine factor, scale back to proper amount
if (tempLR > 0) tempLR = bridgerectifier+thresholdL;
else tempLR = -(bridgerectifier+thresholdL);
}
inputSampleL = (tempLL * outputL) + (tempHL * outputH);
inputSampleR = (tempLR * outputL) + (tempHR * outputH);
//end raw sample
//begin antialiasing section for halfway sample
ataCL = ataHalfwaySampleL - ataHalfDrySampleL;
if (ataFlip) {ataAL *= ataDecayL; ataBL *= ataDecayL; ataAL += ataCL; ataBL -= ataCL; ataCL = ataAL;}
else {ataBL *= ataDecayL; ataAL *= ataDecayL; ataBL += ataCL; ataAL -= ataCL; ataCL = ataBL;}
ataHalfDiffSampleL = (ataCL * ataDecayL);
//end antialiasing section for halfway sample L
ataCR = ataHalfwaySampleR - ataHalfDrySampleR;
if (ataFlip) {ataAR *= ataDecayR; ataBR *= ataDecayR; ataAR += ataCR; ataBR -= ataCR; ataCR = ataAR;}
else {ataBR *= ataDecayR; ataAR *= ataDecayR; ataBR += ataCR; ataAR -= ataCR; ataCR = ataBR;}
ataHalfDiffSampleR = (ataCR * ataDecayR);
//end antialiasing section for halfway sample R
//begin antialiasing section for raw sample
ataCL = inputSampleL - ataDrySampleL;
if (ataFlip) {ataAL *= ataDecayL; ataBL *= ataDecayL; ataAL += ataCL; ataBL -= ataCL; ataCL = ataAL;}
else {ataBL *= ataDecayL; ataAL *= ataDecayL; ataBL += ataCL; ataAL -= ataCL; ataCL = ataBL;}
ataDiffSampleL = (ataCL * ataDecayL);
//end antialiasing section for input sample L
ataCR = inputSampleR - ataDrySampleR;
if (ataFlip) {ataAR *= ataDecayR; ataBR *= ataDecayR; ataAR += ataCR; ataBR -= ataCR; ataCR = ataAR;}
else {ataBR *= ataDecayR; ataAR *= ataDecayR; ataBR += ataCR; ataAR -= ataCR; ataCR = ataBR;}
ataDiffSampleR = (ataCR * ataDecayR);
//end antialiasing section for input sample R
ataFlip = !ataFlip;
inputSampleL = ataDrySampleL*outputD; inputSampleL += (ataDiffSampleL + ataHalfDiffSampleL);
inputSampleR = ataDrySampleR*outputD; inputSampleR += (ataDiffSampleR + ataHalfDiffSampleR);
//apply processing as difference to non-oversampled raw input
inputSampleL *= outputGlobal;
inputSampleR *= outputGlobal;
//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++;
}
}