mirror of
https://github.com/airwindows/airwindows.git
synced 2026-05-16 06:05:55 -06:00
286 lines
12 KiB
C++
Executable file
286 lines
12 KiB
C++
Executable file
/* ========================================
|
|
* ZAcidLowpass - ZAcidLowpass.h
|
|
* Copyright (c) airwindows, Airwindows uses the MIT license
|
|
* ======================================== */
|
|
|
|
#ifndef __ZAcidLowpass_H
|
|
#include "ZAcidLowpass.h"
|
|
#endif
|
|
|
|
void ZAcidLowpass::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();
|
|
|
|
cutoffA = cutoffB;
|
|
cutoffB = pow(A,3.0)/overallscale;
|
|
cutoffB /= (2.0/pow(overallscale,0.5-((overallscale-1.0)*0.0375)));
|
|
if (cutoffB < 0.0001) cutoffB = 0.0001; if (cutoffB > 1.0) cutoffB = 1.0;
|
|
overA = overB;
|
|
overB = B;
|
|
underA = underB;
|
|
underB = C;
|
|
meltdownA = meltdownB;
|
|
meltdownB = D;
|
|
|
|
//opamp stuff
|
|
inTrimA = inTrimB;
|
|
inTrimB = E*10.0;
|
|
inTrimB *= inTrimB; inTrimB *= inTrimB;
|
|
outTrimA = outTrimB;
|
|
outTrimB = F;
|
|
|
|
double iirAmountA = 0.00069/overallscale;
|
|
biquadF[0] = biquadE[0] = 15500.0 / getSampleRate();
|
|
biquadF[1] = biquadE[1] = 0.935;
|
|
double K = tan(M_PI * biquadE[0]); //lowpass
|
|
double norm = 1.0 / (1.0 + K / biquadE[1] + K * K);
|
|
biquadE[2] = K * K * norm;
|
|
biquadE[3] = 2.0 * biquadE[2];
|
|
biquadE[4] = biquadE[2];
|
|
biquadE[5] = 2.0 * (K * K - 1.0) * norm;
|
|
biquadE[6] = (1.0 - K / biquadE[1] + K * K) * norm;
|
|
for (int x = 0; x < 7; x++) biquadF[x] = biquadE[x];
|
|
//end opamp stuff
|
|
|
|
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 cutoff = (cutoffA*temp)+(cutoffB*(1.0-temp));
|
|
double over = (overA*temp)+(overB*(1.0-temp));
|
|
double under = (underA*temp)+(underB*(1.0-temp));
|
|
double meltdown = (meltdownA*temp)+(meltdownB*(1.0-temp));
|
|
double inTrim = (inTrimA*temp)+(inTrimB*(1.0-temp));
|
|
double outTrim = (outTrimA*temp)+(outTrimB*(1.0-temp));
|
|
double acidTrim = 1.0-pow(cutoff*0.5,1.0/(cutoff*0.5));
|
|
|
|
bezA[bez_cycle] += cutoff;
|
|
bezA[bez_SampL] += (inputSampleL * cutoff);
|
|
bezA[bez_SampR] += (inputSampleR * cutoff);
|
|
|
|
if (bezA[bez_cycle] > 1.0) { //hit the end point and we do a reverb sample
|
|
bezA[bez_cycle] -= 1.0;
|
|
bezA[bez_DL] = bezA[bez_CL];
|
|
bezA[bez_CL] = bezA[bez_BL];
|
|
bezA[bez_BL] = bezA[bez_AL];
|
|
bezA[bez_AL] = (bezA[bez_SampL]*(1.0-meltdown))+(inputSampleL*meltdown);
|
|
bezA[bez_SampL] = 0.0;
|
|
bezA[bez_DR] = bezA[bez_CR];
|
|
bezA[bez_CR] = bezA[bez_BR];
|
|
bezA[bez_BR] = bezA[bez_AR];
|
|
bezA[bez_AR] = (bezA[bez_SampR]*(1.0-meltdown))+(inputSampleR*meltdown);
|
|
bezA[bez_SampR] = 0.0;
|
|
}
|
|
|
|
double X = bezA[bez_cycle]*acidTrim;
|
|
double midL = bezA[bez_DL] * pow(1.0-X,3.0);
|
|
midL += bezA[bez_CL] * 3.0 * pow(1.0-X,2.0) * X;
|
|
midL += bezA[bez_BL] * 3.0 * (1.0-X) * X * X;
|
|
midL += bezA[bez_AL] * pow(X,3.0);
|
|
inputSampleL = (midL*under) + ((inputSampleL - midL)*over);
|
|
|
|
double midR = bezA[bez_DR] * pow(1.0-X,3.0);
|
|
midR += bezA[bez_CR] * 3.0 * pow(1.0-X,2.0) * X;
|
|
midR += bezA[bez_BR] * 3.0 * (1.0-X) * X * X;
|
|
midR += bezA[bez_AR] * pow(X,3.0);
|
|
inputSampleR = (midR*under) + ((inputSampleR - midR)*over);
|
|
|
|
if (inTrim != 1.0) {inputSampleL *= inTrim; inputSampleR *= inTrim;}
|
|
|
|
//opamp stage
|
|
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;
|
|
|
|
double outSample = biquadE[2]*inputSampleL+biquadE[3]*biquadE[7]+biquadE[4]*biquadE[8]-biquadE[5]*biquadE[9]-biquadE[6]*biquadE[10];
|
|
biquadE[8] = biquadE[7]; biquadE[7] = inputSampleL; inputSampleL = outSample; biquadE[10] = biquadE[9]; biquadE[9] = inputSampleL; //DF1 left
|
|
|
|
outSample = biquadE[2]*inputSampleR+biquadE[3]*biquadE[11]+biquadE[4]*biquadE[12]-biquadE[5]*biquadE[13]-biquadE[6]*biquadE[14];
|
|
biquadE[12] = biquadE[11]; biquadE[11] = inputSampleR; inputSampleR = outSample; biquadE[14] = biquadE[13]; biquadE[13] = inputSampleR; //DF1 right
|
|
|
|
if (inputSampleL > 1.0) inputSampleL = 1.0; if (inputSampleL < -1.0) inputSampleL = -1.0;
|
|
inputSampleL -= (inputSampleL*inputSampleL*inputSampleL*inputSampleL*inputSampleL*0.1768);
|
|
if (inputSampleR > 1.0) inputSampleR = 1.0; if (inputSampleR < -1.0) inputSampleR = -1.0;
|
|
inputSampleR -= (inputSampleR*inputSampleR*inputSampleR*inputSampleR*inputSampleR*0.1768);
|
|
|
|
outSample = biquadF[2]*inputSampleL+biquadF[3]*biquadF[7]+biquadF[4]*biquadF[8]-biquadF[5]*biquadF[9]-biquadF[6]*biquadF[10];
|
|
biquadF[8] = biquadF[7]; biquadF[7] = inputSampleL; inputSampleL = outSample; biquadF[10] = biquadF[9]; biquadF[9] = inputSampleL; //DF1 left
|
|
|
|
outSample = biquadF[2]*inputSampleR+biquadF[3]*biquadF[11]+biquadF[4]*biquadF[12]-biquadF[5]*biquadF[13]-biquadF[6]*biquadF[14];
|
|
biquadF[12] = biquadF[11]; biquadF[11] = inputSampleR; inputSampleR = outSample; biquadF[14] = biquadF[13]; biquadF[13] = inputSampleR; //DF1 right
|
|
|
|
if (outTrim != 1.0) {inputSampleL *= outTrim; inputSampleR *= outTrim;}
|
|
//end opamp stage
|
|
|
|
//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 ZAcidLowpass::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();
|
|
|
|
cutoffA = cutoffB;
|
|
cutoffB = pow(A,3.0)/overallscale;
|
|
cutoffB /= (2.0/pow(overallscale,0.5-((overallscale-1.0)*0.0375)));
|
|
if (cutoffB < 0.0001) cutoffB = 0.0001; if (cutoffB > 1.0) cutoffB = 1.0;
|
|
overA = overB;
|
|
overB = B;
|
|
underA = underB;
|
|
underB = C;
|
|
meltdownA = meltdownB;
|
|
meltdownB = D;
|
|
|
|
//opamp stuff
|
|
inTrimA = inTrimB;
|
|
inTrimB = E*10.0;
|
|
inTrimB *= inTrimB; inTrimB *= inTrimB;
|
|
outTrimA = outTrimB;
|
|
outTrimB = F;
|
|
|
|
double iirAmountA = 0.00069/overallscale;
|
|
biquadF[0] = biquadE[0] = 15500.0 / getSampleRate();
|
|
biquadF[1] = biquadE[1] = 0.935;
|
|
double K = tan(M_PI * biquadE[0]); //lowpass
|
|
double norm = 1.0 / (1.0 + K / biquadE[1] + K * K);
|
|
biquadE[2] = K * K * norm;
|
|
biquadE[3] = 2.0 * biquadE[2];
|
|
biquadE[4] = biquadE[2];
|
|
biquadE[5] = 2.0 * (K * K - 1.0) * norm;
|
|
biquadE[6] = (1.0 - K / biquadE[1] + K * K) * norm;
|
|
for (int x = 0; x < 7; x++) biquadF[x] = biquadE[x];
|
|
//end opamp stuff
|
|
|
|
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 cutoff = (cutoffA*temp)+(cutoffB*(1.0-temp));
|
|
double over = (overA*temp)+(overB*(1.0-temp));
|
|
double under = (underA*temp)+(underB*(1.0-temp));
|
|
double meltdown = (meltdownA*temp)+(meltdownB*(1.0-temp));
|
|
double inTrim = (inTrimA*temp)+(inTrimB*(1.0-temp));
|
|
double outTrim = (outTrimA*temp)+(outTrimB*(1.0-temp));
|
|
double acidTrim = 1.0-pow(cutoff*0.5,1.0/(cutoff*0.5));
|
|
|
|
bezA[bez_cycle] += cutoff;
|
|
bezA[bez_SampL] += (inputSampleL * cutoff);
|
|
bezA[bez_SampR] += (inputSampleR * cutoff);
|
|
|
|
if (bezA[bez_cycle] > 1.0) { //hit the end point and we do a reverb sample
|
|
bezA[bez_cycle] -= 1.0;
|
|
bezA[bez_DL] = bezA[bez_CL];
|
|
bezA[bez_CL] = bezA[bez_BL];
|
|
bezA[bez_BL] = bezA[bez_AL];
|
|
bezA[bez_AL] = (bezA[bez_SampL]*(1.0-meltdown))+(inputSampleL*meltdown);
|
|
bezA[bez_SampL] = 0.0;
|
|
bezA[bez_DR] = bezA[bez_CR];
|
|
bezA[bez_CR] = bezA[bez_BR];
|
|
bezA[bez_BR] = bezA[bez_AR];
|
|
bezA[bez_AR] = (bezA[bez_SampR]*(1.0-meltdown))+(inputSampleR*meltdown);
|
|
bezA[bez_SampR] = 0.0;
|
|
}
|
|
|
|
double X = bezA[bez_cycle]*acidTrim;
|
|
double midL = bezA[bez_DL] * pow(1.0-X,3.0);
|
|
midL += bezA[bez_CL] * 3.0 * pow(1.0-X,2.0) * X;
|
|
midL += bezA[bez_BL] * 3.0 * (1.0-X) * X * X;
|
|
midL += bezA[bez_AL] * pow(X,3.0);
|
|
inputSampleL = (midL*under) + ((inputSampleL - midL)*over);
|
|
|
|
double midR = bezA[bez_DR] * pow(1.0-X,3.0);
|
|
midR += bezA[bez_CR] * 3.0 * pow(1.0-X,2.0) * X;
|
|
midR += bezA[bez_BR] * 3.0 * (1.0-X) * X * X;
|
|
midR += bezA[bez_AR] * pow(X,3.0);
|
|
inputSampleR = (midR*under) + ((inputSampleR - midR)*over);
|
|
|
|
if (inTrim != 1.0) {inputSampleL *= inTrim; inputSampleR *= inTrim;}
|
|
|
|
//opamp stage
|
|
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;
|
|
|
|
double outSample = biquadE[2]*inputSampleL+biquadE[3]*biquadE[7]+biquadE[4]*biquadE[8]-biquadE[5]*biquadE[9]-biquadE[6]*biquadE[10];
|
|
biquadE[8] = biquadE[7]; biquadE[7] = inputSampleL; inputSampleL = outSample; biquadE[10] = biquadE[9]; biquadE[9] = inputSampleL; //DF1 left
|
|
|
|
outSample = biquadE[2]*inputSampleR+biquadE[3]*biquadE[11]+biquadE[4]*biquadE[12]-biquadE[5]*biquadE[13]-biquadE[6]*biquadE[14];
|
|
biquadE[12] = biquadE[11]; biquadE[11] = inputSampleR; inputSampleR = outSample; biquadE[14] = biquadE[13]; biquadE[13] = inputSampleR; //DF1 right
|
|
|
|
if (inputSampleL > 1.0) inputSampleL = 1.0; if (inputSampleL < -1.0) inputSampleL = -1.0;
|
|
inputSampleL -= (inputSampleL*inputSampleL*inputSampleL*inputSampleL*inputSampleL*0.1768);
|
|
if (inputSampleR > 1.0) inputSampleR = 1.0; if (inputSampleR < -1.0) inputSampleR = -1.0;
|
|
inputSampleR -= (inputSampleR*inputSampleR*inputSampleR*inputSampleR*inputSampleR*0.1768);
|
|
|
|
outSample = biquadF[2]*inputSampleL+biquadF[3]*biquadF[7]+biquadF[4]*biquadF[8]-biquadF[5]*biquadF[9]-biquadF[6]*biquadF[10];
|
|
biquadF[8] = biquadF[7]; biquadF[7] = inputSampleL; inputSampleL = outSample; biquadF[10] = biquadF[9]; biquadF[9] = inputSampleL; //DF1 left
|
|
|
|
outSample = biquadF[2]*inputSampleR+biquadF[3]*biquadF[11]+biquadF[4]*biquadF[12]-biquadF[5]*biquadF[13]-biquadF[6]*biquadF[14];
|
|
biquadF[12] = biquadF[11]; biquadF[11] = inputSampleR; inputSampleR = outSample; biquadF[14] = biquadF[13]; biquadF[13] = inputSampleR; //DF1 right
|
|
|
|
if (outTrim != 1.0) {inputSampleL *= outTrim; inputSampleR *= outTrim;}
|
|
//end opamp stage
|
|
|
|
//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++;
|
|
}
|
|
}
|