/* ========================================
* Air - Air.h
* Copyright (c) 2016 airwindows, All rights reserved
* ======================================== */
#ifndef __Air_H
#include "Air.h"
#endif
void Air::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames)
{
float* in1 = inputs[0];
float* in2 = inputs[1];
float* out1 = outputs[0];
float* out2 = outputs[1];
double hiIntensity = -pow(((A*2.0)-1.0),3)*2;
double tripletintensity = -pow(((B*2.0)-1.0),3);
double airIntensity = -pow(((C*2.0)-1.0),3)/2;
double filterQ = 2.1-D;
double output = E;
double wet = F;
double dry = 1.0-wet;
long double inputSampleL;
long double inputSampleR;
double drySampleL;
double drySampleR;
double correctionL;
double correctionR;
while (--sampleFrames >= 0)
{
inputSampleL = *in1;
inputSampleR = *in2;
if (inputSampleL<1.2e-38 && -inputSampleL<1.2e-38) {
static int noisesource = 0;
//this declares a variable before anything else is compiled. It won't keep assigning
//it to 0 for every sample, it's as if the declaration doesn't exist in this context,
//but it lets me add this denormalization fix in a single place rather than updating
//it in three different locations. The variable isn't thread-safe but this is only
//a random seed and we can share it with whatever.
noisesource = noisesource % 1700021; noisesource++;
int residue = noisesource * noisesource;
residue = residue % 170003; residue *= residue;
residue = residue % 17011; residue *= residue;
residue = residue % 1709; residue *= residue;
residue = residue % 173; residue *= residue;
residue = residue % 17;
double applyresidue = residue;
applyresidue *= 0.00000001;
applyresidue *= 0.00000001;
inputSampleL = applyresidue;
}
if (inputSampleR<1.2e-38 && -inputSampleR<1.2e-38) {
static int noisesource = 0;
noisesource = noisesource % 1700021; noisesource++;
int residue = noisesource * noisesource;
residue = residue % 170003; residue *= residue;
residue = residue % 17011; residue *= residue;
residue = residue % 1709; residue *= residue;
residue = residue % 173; residue *= residue;
residue = residue % 17;
double applyresidue = residue;
applyresidue *= 0.00000001;
applyresidue *= 0.00000001;
inputSampleR = applyresidue;
//this denormalization routine produces a white noise at -300 dB which the noise
//shaping will interact with to produce a bipolar output, but the noise is actually
//all positive. That should stop any variables from going denormal, and the routine
//only kicks in if digital black is input. As a final touch, if you save to 24-bit
//the silence will return to being digital black again.
}
drySampleL = inputSampleL;
drySampleR = inputSampleR;
correctionL = 0.0;
correctionR = 0.0; //from here on down, please add L and R to the code
if (count < 1 || count > 3) count = 1;
tripletFactorL = tripletPrevL - inputSampleL;
tripletFactorR = tripletPrevR - inputSampleR;
switch (count)
{
case 1:
tripletAL += tripletFactorL;
tripletCL -= tripletFactorL;
tripletFactorL = tripletAL * tripletintensity;
tripletPrevL = tripletMidL;
tripletMidL = inputSampleL;
tripletAR += tripletFactorR;
tripletCR -= tripletFactorR;
tripletFactorR = tripletAR * tripletintensity;
tripletPrevR = tripletMidR;
tripletMidR = inputSampleR;
break;
case 2:
tripletBL += tripletFactorL;
tripletAL -= tripletFactorL;
tripletFactorL = tripletBL * tripletintensity;
tripletPrevL = tripletMidL;
tripletMidL = inputSampleL;
tripletBR += tripletFactorR;
tripletAR -= tripletFactorR;
tripletFactorR = tripletBR * tripletintensity;
tripletPrevR = tripletMidR;
tripletMidR = inputSampleR;
break;
case 3:
tripletCL += tripletFactorL;
tripletBL -= tripletFactorL;
tripletFactorL = tripletCL * tripletintensity;
tripletPrevL = tripletMidL;
tripletMidL = inputSampleL;
tripletCR += tripletFactorR;
tripletBR -= tripletFactorR;
tripletFactorR = tripletCR * tripletintensity;
tripletPrevR = tripletMidR;
tripletMidR = inputSampleR;
break;
}
tripletAL /= filterQ;
tripletBL /= filterQ;
tripletCL /= filterQ;
correctionL = correctionL + tripletFactorL;
tripletAR /= filterQ;
tripletBR /= filterQ;
tripletCR /= filterQ;
correctionR = correctionR + tripletFactorR;
count++;
//finished Triplet section- 15K
if (flop)
{
airFactorAL = airPrevAL - inputSampleL;
airFactorAR = airPrevAR - inputSampleR;
if (flipA)
{
airEvenAL += airFactorAL;
airOddAL -= airFactorAL;
airFactorAL = airEvenAL * airIntensity;
airEvenAR += airFactorAR;
airOddAR -= airFactorAR;
airFactorAR = airEvenAR * airIntensity;
}
else
{
airOddAL += airFactorAL;
airEvenAL -= airFactorAL;
airFactorAL = airOddAL * airIntensity;
airOddAR += airFactorAR;
airEvenAR -= airFactorAR;
airFactorAR = airOddAR * airIntensity;
}
airOddAL = (airOddAL - ((airOddAL - airEvenAL)/256.0)) / filterQ;
airEvenAL = (airEvenAL - ((airEvenAL - airOddAL)/256.0)) / filterQ;
airPrevAL = inputSampleL;
correctionL = correctionL + airFactorAL;
airOddAR = (airOddAR - ((airOddAR - airEvenAR)/256.0)) / filterQ;
airEvenAR = (airEvenAR - ((airEvenAR - airOddAR)/256.0)) / filterQ;
airPrevAR = inputSampleR;
correctionR = correctionR + airFactorAR;
flipA = !flipA;
}
else
{
airFactorBL = airPrevBL - inputSampleL;
airFactorBR = airPrevBR - inputSampleR;
if (flipB)
{
airEvenBL += airFactorBL;
airOddBL -= airFactorBL;
airFactorBL = airEvenBL * airIntensity;
airEvenBR += airFactorBR;
airOddBR -= airFactorBR;
airFactorBR = airEvenBR * airIntensity;
}
else
{
airOddBL += airFactorBL;
airEvenBL -= airFactorBL;
airFactorBL = airOddBL * airIntensity;
airOddBR += airFactorBR;
airEvenBR -= airFactorBR;
airFactorBR = airOddBR * airIntensity;
}
airOddBL = (airOddBL - ((airOddBL - airEvenBL)/256.0)) / filterQ;
airEvenBL = (airEvenBL - ((airEvenBL - airOddBL)/256.0)) / filterQ;
airPrevBL = inputSampleL;
correctionL = correctionL + airFactorBL;
airOddBR = (airOddBR - ((airOddBR - airEvenBR)/256.0)) / filterQ;
airEvenBR = (airEvenBR - ((airEvenBR - airOddBR)/256.0)) / filterQ;
airPrevBR = inputSampleR;
correctionR = correctionR + airFactorBR;
flipB = !flipB;
}
//11K one
airFactorCL = airPrevCL - inputSampleL;
airFactorCR = airPrevCR - inputSampleR;
if (flop)
{
airEvenCL += airFactorCL;
airOddCL -= airFactorCL;
airFactorCL = airEvenCL * hiIntensity;
airEvenCR += airFactorCR;
airOddCR -= airFactorCR;
airFactorCR = airEvenCR * hiIntensity;
}
else
{
airOddCL += airFactorCL;
airEvenCL -= airFactorCL;
airFactorCL = airOddCL * hiIntensity;
airOddCR += airFactorCR;
airEvenCR -= airFactorCR;
airFactorCR = airOddCR * hiIntensity;
}
airOddCL = (airOddCL - ((airOddCL - airEvenCL)/256.0)) / filterQ;
airEvenCL = (airEvenCL - ((airEvenCL - airOddCL)/256.0)) / filterQ;
airPrevCL = inputSampleL;
correctionL = correctionL + airFactorCL;
airOddCR = (airOddCR - ((airOddCR - airEvenCR)/256.0)) / filterQ;
airEvenCR = (airEvenCR - ((airEvenCR - airOddCR)/256.0)) / filterQ;
airPrevCR = inputSampleR;
correctionR = correctionR + airFactorCR;
flop = !flop;
inputSampleL += correctionL;
inputSampleR += correctionR;
if (output < 1.0) {
inputSampleL *= output;
inputSampleR *= output;
}
if (wet < 1.0) {
inputSampleL = (drySampleL*dry)+(inputSampleL*wet);
inputSampleR = (drySampleR*dry)+(inputSampleR*wet);
}
//nice little output stage template: if we have another scale of floating point
//number, we really don't want to meaninglessly multiply that by 1.0.
//stereo 32 bit dither, made small and tidy.
int expon; frexpf((float)inputSampleL, &expon);
long double dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
inputSampleL += (dither-fpNShapeL); fpNShapeL = dither;
frexpf((float)inputSampleR, &expon);
dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
inputSampleR += (dither-fpNShapeR); fpNShapeR = dither;
//end 32 bit dither
*out1 = inputSampleL;
*out2 = inputSampleR;
*in1++;
*in2++;
*out1++;
*out2++;
}
}
void Air::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames)
{
double* in1 = inputs[0];
double* in2 = inputs[1];
double* out1 = outputs[0];
double* out2 = outputs[1];
double hiIntensity = -pow(((A*2.0)-1.0),3)*2;
double tripletintensity = -pow(((B*2.0)-1.0),3);
double airIntensity = -pow(((C*2.0)-1.0),3)/2;
double filterQ = 2.1-D;
double output = E;
double wet = F;
double dry = 1.0-wet;
long double inputSampleL;
long double inputSampleR;
double drySampleL;
double drySampleR;
double correctionL;
double correctionR;
while (--sampleFrames >= 0)
{
inputSampleL = *in1;
inputSampleR = *in2;
if (inputSampleL<1.2e-38 && -inputSampleL<1.2e-38) {
static int noisesource = 0;
//this declares a variable before anything else is compiled. It won't keep assigning
//it to 0 for every sample, it's as if the declaration doesn't exist in this context,
//but it lets me add this denormalization fix in a single place rather than updating
//it in three different locations. The variable isn't thread-safe but this is only
//a random seed and we can share it with whatever.
noisesource = noisesource % 1700021; noisesource++;
int residue = noisesource * noisesource;
residue = residue % 170003; residue *= residue;
residue = residue % 17011; residue *= residue;
residue = residue % 1709; residue *= residue;
residue = residue % 173; residue *= residue;
residue = residue % 17;
double applyresidue = residue;
applyresidue *= 0.00000001;
applyresidue *= 0.00000001;
inputSampleL = applyresidue;
}
if (inputSampleR<1.2e-38 && -inputSampleR<1.2e-38) {
static int noisesource = 0;
noisesource = noisesource % 1700021; noisesource++;
int residue = noisesource * noisesource;
residue = residue % 170003; residue *= residue;
residue = residue % 17011; residue *= residue;
residue = residue % 1709; residue *= residue;
residue = residue % 173; residue *= residue;
residue = residue % 17;
double applyresidue = residue;
applyresidue *= 0.00000001;
applyresidue *= 0.00000001;
inputSampleR = applyresidue;
//this denormalization routine produces a white noise at -300 dB which the noise
//shaping will interact with to produce a bipolar output, but the noise is actually
//all positive. That should stop any variables from going denormal, and the routine
//only kicks in if digital black is input. As a final touch, if you save to 24-bit
//the silence will return to being digital black again.
}
drySampleL = inputSampleL;
drySampleR = inputSampleR;
correctionL = 0.0;
correctionR = 0.0; //from here on down, please add L and R to the code
if (count < 1 || count > 3) count = 1;
tripletFactorL = tripletPrevL - inputSampleL;
tripletFactorR = tripletPrevR - inputSampleR;
switch (count)
{
case 1:
tripletAL += tripletFactorL;
tripletCL -= tripletFactorL;
tripletFactorL = tripletAL * tripletintensity;
tripletPrevL = tripletMidL;
tripletMidL = inputSampleL;
tripletAR += tripletFactorR;
tripletCR -= tripletFactorR;
tripletFactorR = tripletAR * tripletintensity;
tripletPrevR = tripletMidR;
tripletMidR = inputSampleR;
break;
case 2:
tripletBL += tripletFactorL;
tripletAL -= tripletFactorL;
tripletFactorL = tripletBL * tripletintensity;
tripletPrevL = tripletMidL;
tripletMidL = inputSampleL;
tripletBR += tripletFactorR;
tripletAR -= tripletFactorR;
tripletFactorR = tripletBR * tripletintensity;
tripletPrevR = tripletMidR;
tripletMidR = inputSampleR;
break;
case 3:
tripletCL += tripletFactorL;
tripletBL -= tripletFactorL;
tripletFactorL = tripletCL * tripletintensity;
tripletPrevL = tripletMidL;
tripletMidL = inputSampleL;
tripletCR += tripletFactorR;
tripletBR -= tripletFactorR;
tripletFactorR = tripletCR * tripletintensity;
tripletPrevR = tripletMidR;
tripletMidR = inputSampleR;
break;
}
tripletAL /= filterQ;
tripletBL /= filterQ;
tripletCL /= filterQ;
correctionL = correctionL + tripletFactorL;
tripletAR /= filterQ;
tripletBR /= filterQ;
tripletCR /= filterQ;
correctionR = correctionR + tripletFactorR;
count++;
//finished Triplet section- 15K
if (flop)
{
airFactorAL = airPrevAL - inputSampleL;
airFactorAR = airPrevAR - inputSampleR;
if (flipA)
{
airEvenAL += airFactorAL;
airOddAL -= airFactorAL;
airFactorAL = airEvenAL * airIntensity;
airEvenAR += airFactorAR;
airOddAR -= airFactorAR;
airFactorAR = airEvenAR * airIntensity;
}
else
{
airOddAL += airFactorAL;
airEvenAL -= airFactorAL;
airFactorAL = airOddAL * airIntensity;
airOddAR += airFactorAR;
airEvenAR -= airFactorAR;
airFactorAR = airOddAR * airIntensity;
}
airOddAL = (airOddAL - ((airOddAL - airEvenAL)/256.0)) / filterQ;
airEvenAL = (airEvenAL - ((airEvenAL - airOddAL)/256.0)) / filterQ;
airPrevAL = inputSampleL;
correctionL = correctionL + airFactorAL;
airOddAR = (airOddAR - ((airOddAR - airEvenAR)/256.0)) / filterQ;
airEvenAR = (airEvenAR - ((airEvenAR - airOddAR)/256.0)) / filterQ;
airPrevAR = inputSampleR;
correctionR = correctionR + airFactorAR;
flipA = !flipA;
}
else
{
airFactorBL = airPrevBL - inputSampleL;
airFactorBR = airPrevBR - inputSampleR;
if (flipB)
{
airEvenBL += airFactorBL;
airOddBL -= airFactorBL;
airFactorBL = airEvenBL * airIntensity;
airEvenBR += airFactorBR;
airOddBR -= airFactorBR;
airFactorBR = airEvenBR * airIntensity;
}
else
{
airOddBL += airFactorBL;
airEvenBL -= airFactorBL;
airFactorBL = airOddBL * airIntensity;
airOddBR += airFactorBR;
airEvenBR -= airFactorBR;
airFactorBR = airOddBR * airIntensity;
}
airOddBL = (airOddBL - ((airOddBL - airEvenBL)/256.0)) / filterQ;
airEvenBL = (airEvenBL - ((airEvenBL - airOddBL)/256.0)) / filterQ;
airPrevBL = inputSampleL;
correctionL = correctionL + airFactorBL;
airOddBR = (airOddBR - ((airOddBR - airEvenBR)/256.0)) / filterQ;
airEvenBR = (airEvenBR - ((airEvenBR - airOddBR)/256.0)) / filterQ;
airPrevBR = inputSampleR;
correctionR = correctionR + airFactorBR;
flipB = !flipB;
}
//11K one
airFactorCL = airPrevCL - inputSampleL;
airFactorCR = airPrevCR - inputSampleR;
if (flop)
{
airEvenCL += airFactorCL;
airOddCL -= airFactorCL;
airFactorCL = airEvenCL * hiIntensity;
airEvenCR += airFactorCR;
airOddCR -= airFactorCR;
airFactorCR = airEvenCR * hiIntensity;
}
else
{
airOddCL += airFactorCL;
airEvenCL -= airFactorCL;
airFactorCL = airOddCL * hiIntensity;
airOddCR += airFactorCR;
airEvenCR -= airFactorCR;
airFactorCR = airOddCR * hiIntensity;
}
airOddCL = (airOddCL - ((airOddCL - airEvenCL)/256.0)) / filterQ;
airEvenCL = (airEvenCL - ((airEvenCL - airOddCL)/256.0)) / filterQ;
airPrevCL = inputSampleL;
correctionL = correctionL + airFactorCL;
airOddCR = (airOddCR - ((airOddCR - airEvenCR)/256.0)) / filterQ;
airEvenCR = (airEvenCR - ((airEvenCR - airOddCR)/256.0)) / filterQ;
airPrevCR = inputSampleR;
correctionR = correctionR + airFactorCR;
flop = !flop;
inputSampleL += correctionL;
inputSampleR += correctionR;
if (output < 1.0) {
inputSampleL *= output;
inputSampleR *= output;
}
if (wet < 1.0) {
inputSampleL = (drySampleL*dry)+(inputSampleL*wet);
inputSampleR = (drySampleR*dry)+(inputSampleR*wet);
}
//nice little output stage template: if we have another scale of floating point
//number, we really don't want to meaninglessly multiply that by 1.0.
//stereo 64 bit dither, made small and tidy.
int expon; frexp((double)inputSampleL, &expon);
long double dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
dither /= 536870912.0; //needs this to scale to 64 bit zone
inputSampleL += (dither-fpNShapeL); fpNShapeL = dither;
frexp((double)inputSampleR, &expon);
dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
dither /= 536870912.0; //needs this to scale to 64 bit zone
inputSampleR += (dither-fpNShapeR); fpNShapeR = dither;
//end 64 bit dither
*out1 = inputSampleL;
*out2 = inputSampleR;
*in1++;
*in2++;
*out1++;
*out2++;
}
}