mirror of
https://github.com/airwindows/airwindows.git
synced 2026-05-15 14:16:00 -06:00
874 lines
No EOL
28 KiB
C++
Executable file
874 lines
No EOL
28 KiB
C++
Executable file
/* ========================================
|
|
* AQuickVoiceClip - AQuickVoiceClip.h
|
|
* Copyright (c) 2016 airwindows, All rights reserved
|
|
* ======================================== */
|
|
|
|
#ifndef __AQuickVoiceClip_H
|
|
#include "AQuickVoiceClip.h"
|
|
#endif
|
|
|
|
void AQuickVoiceClip::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 softness = 0.484416;
|
|
double hardness = 1.0 - softness;
|
|
double iirAmount = ((pow(A,3)*2070)+30)/8000.0;
|
|
iirAmount /= overallscale;
|
|
double altAmount = (1.0 - iirAmount);
|
|
double cancelnew = 0.0682276;
|
|
double cancelold = 1.0 - cancelnew;
|
|
double lpSpeed = 0.0009;
|
|
double cliplevel = 0.98;
|
|
double refclip = 0.5; //preset to cut out gain quite a lot. 91%? no touchy unless clip
|
|
|
|
double LmaxRecent;
|
|
bool LclipOnset;
|
|
double LpassThrough;
|
|
double LoutputSample;
|
|
double LdrySample;
|
|
|
|
double RmaxRecent;
|
|
bool RclipOnset;
|
|
double RpassThrough;
|
|
double RoutputSample;
|
|
double RdrySample;
|
|
|
|
|
|
long double inputSampleL;
|
|
long double inputSampleR;
|
|
|
|
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.
|
|
}
|
|
LpassThrough = LataDrySample = inputSampleL;
|
|
RpassThrough = RataDrySample = inputSampleR;
|
|
|
|
LataHalfDrySample = LataHalfwaySample = (inputSampleL + LataLast1Sample + (LataLast2Sample*ataK1) + (LataLast3Sample*ataK2) + (LataLast4Sample*ataK6) + (LataLast5Sample*ataK7) + (LataLast6Sample*ataK8)) / 2.0;
|
|
LataLast6Sample = LataLast5Sample; LataLast5Sample = LataLast4Sample; LataLast4Sample = LataLast3Sample; LataLast3Sample = LataLast2Sample; LataLast2Sample = LataLast1Sample; LataLast1Sample = inputSampleL;
|
|
//setting up oversampled special antialiasing
|
|
RataHalfDrySample = RataHalfwaySample = (inputSampleR + RataLast1Sample + (RataLast2Sample*ataK1) + (RataLast3Sample*ataK2) + (RataLast4Sample*ataK6) + (RataLast5Sample*ataK7) + (RataLast6Sample*ataK8)) / 2.0;
|
|
RataLast6Sample = RataLast5Sample; RataLast5Sample = RataLast4Sample; RataLast4Sample = RataLast3Sample; RataLast3Sample = RataLast2Sample; RataLast2Sample = RataLast1Sample; RataLast1Sample = inputSampleR;
|
|
//setting up oversampled special antialiasing
|
|
LclipOnset = false;
|
|
RclipOnset = false;
|
|
|
|
|
|
LmaxRecent = fabs( LataLast6Sample );
|
|
if (fabs( LataLast5Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast5Sample );
|
|
if (fabs( LataLast4Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast4Sample );
|
|
if (fabs( LataLast3Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast3Sample );
|
|
if (fabs( LataLast2Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast2Sample );
|
|
if (fabs( LataLast1Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast1Sample );
|
|
if (fabs( inputSampleL ) > LmaxRecent ) LmaxRecent = fabs( inputSampleL );
|
|
//this gives us something that won't cut out in zero crossings, to interpolate with
|
|
|
|
RmaxRecent = fabs( RataLast6Sample );
|
|
if (fabs( RataLast5Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast5Sample );
|
|
if (fabs( RataLast4Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast4Sample );
|
|
if (fabs( RataLast3Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast3Sample );
|
|
if (fabs( RataLast2Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast2Sample );
|
|
if (fabs( RataLast1Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast1Sample );
|
|
if (fabs( inputSampleR ) > RmaxRecent ) RmaxRecent = fabs( inputSampleR );
|
|
//this gives us something that won't cut out in zero crossings, to interpolate with
|
|
|
|
LmaxRecent *= 2.0;
|
|
RmaxRecent *= 2.0;
|
|
//by refclip this is 1.0 and fully into the antialiasing
|
|
if (LmaxRecent > 1.0) LmaxRecent = 1.0;
|
|
if (RmaxRecent > 1.0) RmaxRecent = 1.0;
|
|
//and it tops out at 1. Higher means more antialiasing, lower blends into passThrough without antialiasing
|
|
|
|
LataHalfwaySample -= Loverall;
|
|
RataHalfwaySample -= Roverall;
|
|
//subtract dist-cancel from input after getting raw input, before doing anything
|
|
|
|
LdrySample = LataHalfwaySample;
|
|
RdrySample = RataHalfwaySample;
|
|
|
|
|
|
//begin L channel for the clipper
|
|
if (LlastSample >= refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LataHalfwaySample < refclip)
|
|
{
|
|
LlastSample = ((refclip*hardness) + (LataHalfwaySample * softness));
|
|
}
|
|
else LlastSample = refclip;
|
|
}
|
|
|
|
if (LlastSample <= -refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LataHalfwaySample > -refclip)
|
|
{
|
|
LlastSample = ((-refclip*hardness) + (LataHalfwaySample * softness));
|
|
}
|
|
else LlastSample = -refclip;
|
|
}
|
|
|
|
if (LataHalfwaySample > refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LlastSample < refclip)
|
|
{
|
|
LataHalfwaySample = ((refclip*hardness) + (LlastSample * softness));
|
|
}
|
|
else LataHalfwaySample = refclip;
|
|
}
|
|
|
|
if (LataHalfwaySample < -refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LlastSample > -refclip)
|
|
{
|
|
LataHalfwaySample = ((-refclip*hardness) + (LlastSample * softness));
|
|
}
|
|
else LataHalfwaySample = -refclip;
|
|
}
|
|
///end L channel for the clipper
|
|
|
|
//begin R channel for the clipper
|
|
if (RlastSample >= refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RataHalfwaySample < refclip)
|
|
{
|
|
RlastSample = ((refclip*hardness) + (RataHalfwaySample * softness));
|
|
}
|
|
else RlastSample = refclip;
|
|
}
|
|
|
|
if (RlastSample <= -refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RataHalfwaySample > -refclip)
|
|
{
|
|
RlastSample = ((-refclip*hardness) + (RataHalfwaySample * softness));
|
|
}
|
|
else RlastSample = -refclip;
|
|
}
|
|
|
|
if (RataHalfwaySample > refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RlastSample < refclip)
|
|
{
|
|
RataHalfwaySample = ((refclip*hardness) + (RlastSample * softness));
|
|
}
|
|
else RataHalfwaySample = refclip;
|
|
}
|
|
|
|
if (RataHalfwaySample < -refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RlastSample > -refclip)
|
|
{
|
|
RataHalfwaySample = ((-refclip*hardness) + (RlastSample * softness));
|
|
}
|
|
else RataHalfwaySample = -refclip;
|
|
}
|
|
///end R channel for the clipper
|
|
|
|
LoutputSample = LlastSample;
|
|
RoutputSample = RlastSample;
|
|
|
|
LlastSample = LataHalfwaySample;
|
|
RlastSample = RataHalfwaySample;
|
|
|
|
LataHalfwaySample = LoutputSample;
|
|
RataHalfwaySample = RoutputSample;
|
|
//swap around in a circle for one final ADClip,
|
|
//this time not tracking overshoot anymore
|
|
//end interpolated sample
|
|
//begin raw sample- inputSample and ataDrySample handled separately here
|
|
|
|
inputSampleL -= Loverall;
|
|
inputSampleR -= Roverall;
|
|
//subtract dist-cancel from input after getting raw input, before doing anything
|
|
|
|
LdrySample = inputSampleL;
|
|
RdrySample = inputSampleR;
|
|
|
|
//begin second L clip
|
|
if (LlastSample >= refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (inputSampleL < refclip)
|
|
{
|
|
LlastSample = ((refclip*hardness) + (inputSampleL * softness));
|
|
}
|
|
else LlastSample = refclip;
|
|
}
|
|
|
|
if (LlastSample <= -refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (inputSampleL > -refclip)
|
|
{
|
|
LlastSample = ((-refclip*hardness) + (inputSampleL * softness));
|
|
}
|
|
else LlastSample = -refclip;
|
|
}
|
|
|
|
if (inputSampleL > refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LlastSample < refclip)
|
|
{
|
|
inputSampleL = ((refclip*hardness) + (LlastSample * softness));
|
|
}
|
|
else inputSampleL = refclip;
|
|
}
|
|
|
|
if (inputSampleL < -refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LlastSample > -refclip)
|
|
{
|
|
inputSampleL = ((-refclip*hardness) + (LlastSample * softness));
|
|
}
|
|
else inputSampleL = -refclip;
|
|
}
|
|
//end second L clip
|
|
|
|
//begin second R clip
|
|
if (RlastSample >= refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (inputSampleR < refclip)
|
|
{
|
|
RlastSample = ((refclip*hardness) + (inputSampleR * softness));
|
|
}
|
|
else RlastSample = refclip;
|
|
}
|
|
|
|
if (RlastSample <= -refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (inputSampleR > -refclip)
|
|
{
|
|
RlastSample = ((-refclip*hardness) + (inputSampleR * softness));
|
|
}
|
|
else RlastSample = -refclip;
|
|
}
|
|
|
|
if (inputSampleR > refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RlastSample < refclip)
|
|
{
|
|
inputSampleR = ((refclip*hardness) + (RlastSample * softness));
|
|
}
|
|
else inputSampleR = refclip;
|
|
}
|
|
|
|
if (inputSampleR < -refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RlastSample > -refclip)
|
|
{
|
|
inputSampleR = ((-refclip*hardness) + (RlastSample * softness));
|
|
}
|
|
else inputSampleR = -refclip;
|
|
}
|
|
//end second R clip
|
|
|
|
LoutputSample = LlastSample;
|
|
RoutputSample = RlastSample;
|
|
LlastSample = inputSampleL;
|
|
RlastSample = inputSampleR;
|
|
inputSampleL = LoutputSample;
|
|
inputSampleR = RoutputSample;
|
|
|
|
LataHalfDrySample = (LataDrySample*ataK3)+(LataHalfDrySample*ataK4);
|
|
LataHalfDiffSample = (LataHalfwaySample - LataHalfDrySample)/2.0;
|
|
LataLastDiffSample = LataDiffSample*ataK5;
|
|
LataDiffSample = (inputSampleL - LataDrySample)/2.0;
|
|
LataDiffSample += LataHalfDiffSample;
|
|
LataDiffSample -= LataLastDiffSample;
|
|
inputSampleL = LataDrySample;
|
|
inputSampleL += LataDiffSample;
|
|
|
|
RataHalfDrySample = (RataDrySample*ataK3)+(RataHalfDrySample*ataK4);
|
|
RataHalfDiffSample = (RataHalfwaySample - RataHalfDrySample)/2.0;
|
|
RataLastDiffSample = RataDiffSample*ataK5;
|
|
RataDiffSample = (inputSampleR - RataDrySample)/2.0;
|
|
RataDiffSample += RataHalfDiffSample;
|
|
RataDiffSample -= RataLastDiffSample;
|
|
inputSampleR = RataDrySample;
|
|
inputSampleR += RataDiffSample;
|
|
|
|
Loverall = (Loverall * cancelold) + (LataDiffSample * cancelnew);
|
|
Roverall = (Roverall * cancelold) + (RataDiffSample * cancelnew);
|
|
//apply all the diffs to a lowpassed IIR
|
|
|
|
|
|
if (flip)
|
|
{
|
|
LiirSampleA = (LiirSampleA * altAmount) + (inputSampleL * iirAmount);
|
|
inputSampleL -= LiirSampleA;
|
|
LiirSampleC = (LiirSampleC * altAmount) + (LpassThrough * iirAmount);
|
|
LpassThrough -= LiirSampleC;
|
|
|
|
RiirSampleA = (RiirSampleA * altAmount) + (inputSampleR * iirAmount);
|
|
inputSampleR -= RiirSampleA;
|
|
RiirSampleC = (RiirSampleC * altAmount) + (RpassThrough * iirAmount);
|
|
RpassThrough -= RiirSampleC;
|
|
}
|
|
else
|
|
{
|
|
LiirSampleB = (LiirSampleB * altAmount) + (inputSampleL * iirAmount);
|
|
inputSampleL -= LiirSampleB;
|
|
LiirSampleD = (LiirSampleD * altAmount) + (LpassThrough * iirAmount);
|
|
LpassThrough -= LiirSampleD;
|
|
|
|
RiirSampleB = (RiirSampleB * altAmount) + (inputSampleR * iirAmount);
|
|
inputSampleR -= RiirSampleB;
|
|
RiirSampleD = (RiirSampleD * altAmount) + (RpassThrough * iirAmount);
|
|
RpassThrough -= RiirSampleD;
|
|
}
|
|
flip = !flip;
|
|
//highpass section
|
|
|
|
LlastOut3Sample = LlastOut2Sample;
|
|
LlastOut2Sample = LlastOutSample;
|
|
LlastOutSample = inputSampleL;
|
|
|
|
RlastOut3Sample = RlastOut2Sample;
|
|
RlastOut2Sample = RlastOutSample;
|
|
RlastOutSample = inputSampleR;
|
|
|
|
|
|
LlpDepth -= lpSpeed;
|
|
RlpDepth -= lpSpeed;
|
|
|
|
if (LlpDepth > 0.0)
|
|
{
|
|
if (LlpDepth > 1.0) LlpDepth = 1.0;
|
|
inputSampleL *= (1.0-LlpDepth);
|
|
inputSampleL += (((LlastOutSample + LlastOut2Sample + LlastOut3Sample) / 3.6)*LlpDepth);
|
|
}
|
|
|
|
if (RlpDepth > 0.0)
|
|
{
|
|
if (RlpDepth > 1.0) RlpDepth = 1.0;
|
|
inputSampleR *= (1.0-RlpDepth);
|
|
inputSampleR += (((RlastOutSample + RlastOut2Sample + RlastOut3Sample) / 3.6)*RlpDepth);
|
|
}
|
|
|
|
if (LlpDepth < 0.0) LlpDepth = 0.0;
|
|
if (RlpDepth < 0.0) RlpDepth = 0.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
|
|
|
|
inputSampleL *= (1.0-LmaxRecent);
|
|
inputSampleR *= (1.0-RmaxRecent);
|
|
inputSampleL += (LpassThrough * LmaxRecent);
|
|
inputSampleR += (RpassThrough * RmaxRecent);
|
|
//there's our raw signal, without antialiasing. Brings up low level stuff and softens more when hot
|
|
|
|
if (inputSampleL > cliplevel) inputSampleL = cliplevel;
|
|
if (inputSampleL < -cliplevel) inputSampleL = -cliplevel;
|
|
if (inputSampleR > cliplevel) inputSampleR = cliplevel;
|
|
if (inputSampleR < -cliplevel) inputSampleR = -cliplevel;
|
|
//final iron bar
|
|
|
|
|
|
*out1 = inputSampleL;
|
|
*out2 = inputSampleR;
|
|
|
|
*in1++;
|
|
*in2++;
|
|
*out1++;
|
|
*out2++;
|
|
}
|
|
}
|
|
|
|
void AQuickVoiceClip::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 softness = 0.484416;
|
|
double hardness = 1.0 - softness;
|
|
double iirAmount = ((pow(A,3)*2070)+30)/8000.0;
|
|
iirAmount /= overallscale;
|
|
double altAmount = (1.0 - iirAmount);
|
|
double cancelnew = 0.0682276;
|
|
double cancelold = 1.0 - cancelnew;
|
|
double lpSpeed = 0.0009;
|
|
double cliplevel = 0.98;
|
|
double refclip = 0.5; //preset to cut out gain quite a lot. 91%? no touchy unless clip
|
|
|
|
double LmaxRecent;
|
|
bool LclipOnset;
|
|
double LpassThrough;
|
|
double LoutputSample;
|
|
double LdrySample;
|
|
|
|
double RmaxRecent;
|
|
bool RclipOnset;
|
|
double RpassThrough;
|
|
double RoutputSample;
|
|
double RdrySample;
|
|
|
|
|
|
long double inputSampleL;
|
|
long double inputSampleR;
|
|
|
|
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.
|
|
}
|
|
LpassThrough = LataDrySample = inputSampleL;
|
|
RpassThrough = RataDrySample = inputSampleR;
|
|
|
|
LataHalfDrySample = LataHalfwaySample = (inputSampleL + LataLast1Sample + (LataLast2Sample*ataK1) + (LataLast3Sample*ataK2) + (LataLast4Sample*ataK6) + (LataLast5Sample*ataK7) + (LataLast6Sample*ataK8)) / 2.0;
|
|
LataLast6Sample = LataLast5Sample; LataLast5Sample = LataLast4Sample; LataLast4Sample = LataLast3Sample; LataLast3Sample = LataLast2Sample; LataLast2Sample = LataLast1Sample; LataLast1Sample = inputSampleL;
|
|
//setting up oversampled special antialiasing
|
|
RataHalfDrySample = RataHalfwaySample = (inputSampleR + RataLast1Sample + (RataLast2Sample*ataK1) + (RataLast3Sample*ataK2) + (RataLast4Sample*ataK6) + (RataLast5Sample*ataK7) + (RataLast6Sample*ataK8)) / 2.0;
|
|
RataLast6Sample = RataLast5Sample; RataLast5Sample = RataLast4Sample; RataLast4Sample = RataLast3Sample; RataLast3Sample = RataLast2Sample; RataLast2Sample = RataLast1Sample; RataLast1Sample = inputSampleR;
|
|
//setting up oversampled special antialiasing
|
|
LclipOnset = false;
|
|
RclipOnset = false;
|
|
|
|
|
|
LmaxRecent = fabs( LataLast6Sample );
|
|
if (fabs( LataLast5Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast5Sample );
|
|
if (fabs( LataLast4Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast4Sample );
|
|
if (fabs( LataLast3Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast3Sample );
|
|
if (fabs( LataLast2Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast2Sample );
|
|
if (fabs( LataLast1Sample ) > LmaxRecent ) LmaxRecent = fabs( LataLast1Sample );
|
|
if (fabs( inputSampleL ) > LmaxRecent ) LmaxRecent = fabs( inputSampleL );
|
|
//this gives us something that won't cut out in zero crossings, to interpolate with
|
|
|
|
RmaxRecent = fabs( RataLast6Sample );
|
|
if (fabs( RataLast5Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast5Sample );
|
|
if (fabs( RataLast4Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast4Sample );
|
|
if (fabs( RataLast3Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast3Sample );
|
|
if (fabs( RataLast2Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast2Sample );
|
|
if (fabs( RataLast1Sample ) > RmaxRecent ) RmaxRecent = fabs( RataLast1Sample );
|
|
if (fabs( inputSampleR ) > RmaxRecent ) RmaxRecent = fabs( inputSampleR );
|
|
//this gives us something that won't cut out in zero crossings, to interpolate with
|
|
|
|
LmaxRecent *= 2.0;
|
|
RmaxRecent *= 2.0;
|
|
//by refclip this is 1.0 and fully into the antialiasing
|
|
if (LmaxRecent > 1.0) LmaxRecent = 1.0;
|
|
if (RmaxRecent > 1.0) RmaxRecent = 1.0;
|
|
//and it tops out at 1. Higher means more antialiasing, lower blends into passThrough without antialiasing
|
|
|
|
LataHalfwaySample -= Loverall;
|
|
RataHalfwaySample -= Roverall;
|
|
//subtract dist-cancel from input after getting raw input, before doing anything
|
|
|
|
LdrySample = LataHalfwaySample;
|
|
RdrySample = RataHalfwaySample;
|
|
|
|
|
|
//begin L channel for the clipper
|
|
if (LlastSample >= refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LataHalfwaySample < refclip)
|
|
{
|
|
LlastSample = ((refclip*hardness) + (LataHalfwaySample * softness));
|
|
}
|
|
else LlastSample = refclip;
|
|
}
|
|
|
|
if (LlastSample <= -refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LataHalfwaySample > -refclip)
|
|
{
|
|
LlastSample = ((-refclip*hardness) + (LataHalfwaySample * softness));
|
|
}
|
|
else LlastSample = -refclip;
|
|
}
|
|
|
|
if (LataHalfwaySample > refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LlastSample < refclip)
|
|
{
|
|
LataHalfwaySample = ((refclip*hardness) + (LlastSample * softness));
|
|
}
|
|
else LataHalfwaySample = refclip;
|
|
}
|
|
|
|
if (LataHalfwaySample < -refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LlastSample > -refclip)
|
|
{
|
|
LataHalfwaySample = ((-refclip*hardness) + (LlastSample * softness));
|
|
}
|
|
else LataHalfwaySample = -refclip;
|
|
}
|
|
///end L channel for the clipper
|
|
|
|
//begin R channel for the clipper
|
|
if (RlastSample >= refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RataHalfwaySample < refclip)
|
|
{
|
|
RlastSample = ((refclip*hardness) + (RataHalfwaySample * softness));
|
|
}
|
|
else RlastSample = refclip;
|
|
}
|
|
|
|
if (RlastSample <= -refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RataHalfwaySample > -refclip)
|
|
{
|
|
RlastSample = ((-refclip*hardness) + (RataHalfwaySample * softness));
|
|
}
|
|
else RlastSample = -refclip;
|
|
}
|
|
|
|
if (RataHalfwaySample > refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RlastSample < refclip)
|
|
{
|
|
RataHalfwaySample = ((refclip*hardness) + (RlastSample * softness));
|
|
}
|
|
else RataHalfwaySample = refclip;
|
|
}
|
|
|
|
if (RataHalfwaySample < -refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RlastSample > -refclip)
|
|
{
|
|
RataHalfwaySample = ((-refclip*hardness) + (RlastSample * softness));
|
|
}
|
|
else RataHalfwaySample = -refclip;
|
|
}
|
|
///end R channel for the clipper
|
|
|
|
LoutputSample = LlastSample;
|
|
RoutputSample = RlastSample;
|
|
|
|
LlastSample = LataHalfwaySample;
|
|
RlastSample = RataHalfwaySample;
|
|
|
|
LataHalfwaySample = LoutputSample;
|
|
RataHalfwaySample = RoutputSample;
|
|
//swap around in a circle for one final ADClip,
|
|
//this time not tracking overshoot anymore
|
|
//end interpolated sample
|
|
//begin raw sample- inputSample and ataDrySample handled separately here
|
|
|
|
inputSampleL -= Loverall;
|
|
inputSampleR -= Roverall;
|
|
//subtract dist-cancel from input after getting raw input, before doing anything
|
|
|
|
LdrySample = inputSampleL;
|
|
RdrySample = inputSampleR;
|
|
|
|
//begin second L clip
|
|
if (LlastSample >= refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (inputSampleL < refclip)
|
|
{
|
|
LlastSample = ((refclip*hardness) + (inputSampleL * softness));
|
|
}
|
|
else LlastSample = refclip;
|
|
}
|
|
|
|
if (LlastSample <= -refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (inputSampleL > -refclip)
|
|
{
|
|
LlastSample = ((-refclip*hardness) + (inputSampleL * softness));
|
|
}
|
|
else LlastSample = -refclip;
|
|
}
|
|
|
|
if (inputSampleL > refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LlastSample < refclip)
|
|
{
|
|
inputSampleL = ((refclip*hardness) + (LlastSample * softness));
|
|
}
|
|
else inputSampleL = refclip;
|
|
}
|
|
|
|
if (inputSampleL < -refclip)
|
|
{
|
|
LlpDepth += 0.1;
|
|
if (LlastSample > -refclip)
|
|
{
|
|
inputSampleL = ((-refclip*hardness) + (LlastSample * softness));
|
|
}
|
|
else inputSampleL = -refclip;
|
|
}
|
|
//end second L clip
|
|
|
|
//begin second R clip
|
|
if (RlastSample >= refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (inputSampleR < refclip)
|
|
{
|
|
RlastSample = ((refclip*hardness) + (inputSampleR * softness));
|
|
}
|
|
else RlastSample = refclip;
|
|
}
|
|
|
|
if (RlastSample <= -refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (inputSampleR > -refclip)
|
|
{
|
|
RlastSample = ((-refclip*hardness) + (inputSampleR * softness));
|
|
}
|
|
else RlastSample = -refclip;
|
|
}
|
|
|
|
if (inputSampleR > refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RlastSample < refclip)
|
|
{
|
|
inputSampleR = ((refclip*hardness) + (RlastSample * softness));
|
|
}
|
|
else inputSampleR = refclip;
|
|
}
|
|
|
|
if (inputSampleR < -refclip)
|
|
{
|
|
RlpDepth += 0.1;
|
|
if (RlastSample > -refclip)
|
|
{
|
|
inputSampleR = ((-refclip*hardness) + (RlastSample * softness));
|
|
}
|
|
else inputSampleR = -refclip;
|
|
}
|
|
//end second R clip
|
|
|
|
LoutputSample = LlastSample;
|
|
RoutputSample = RlastSample;
|
|
LlastSample = inputSampleL;
|
|
RlastSample = inputSampleR;
|
|
inputSampleL = LoutputSample;
|
|
inputSampleR = RoutputSample;
|
|
|
|
LataHalfDrySample = (LataDrySample*ataK3)+(LataHalfDrySample*ataK4);
|
|
LataHalfDiffSample = (LataHalfwaySample - LataHalfDrySample)/2.0;
|
|
LataLastDiffSample = LataDiffSample*ataK5;
|
|
LataDiffSample = (inputSampleL - LataDrySample)/2.0;
|
|
LataDiffSample += LataHalfDiffSample;
|
|
LataDiffSample -= LataLastDiffSample;
|
|
inputSampleL = LataDrySample;
|
|
inputSampleL += LataDiffSample;
|
|
|
|
RataHalfDrySample = (RataDrySample*ataK3)+(RataHalfDrySample*ataK4);
|
|
RataHalfDiffSample = (RataHalfwaySample - RataHalfDrySample)/2.0;
|
|
RataLastDiffSample = RataDiffSample*ataK5;
|
|
RataDiffSample = (inputSampleR - RataDrySample)/2.0;
|
|
RataDiffSample += RataHalfDiffSample;
|
|
RataDiffSample -= RataLastDiffSample;
|
|
inputSampleR = RataDrySample;
|
|
inputSampleR += RataDiffSample;
|
|
|
|
Loverall = (Loverall * cancelold) + (LataDiffSample * cancelnew);
|
|
Roverall = (Roverall * cancelold) + (RataDiffSample * cancelnew);
|
|
//apply all the diffs to a lowpassed IIR
|
|
|
|
|
|
if (flip)
|
|
{
|
|
LiirSampleA = (LiirSampleA * altAmount) + (inputSampleL * iirAmount);
|
|
inputSampleL -= LiirSampleA;
|
|
LiirSampleC = (LiirSampleC * altAmount) + (LpassThrough * iirAmount);
|
|
LpassThrough -= LiirSampleC;
|
|
|
|
RiirSampleA = (RiirSampleA * altAmount) + (inputSampleR * iirAmount);
|
|
inputSampleR -= RiirSampleA;
|
|
RiirSampleC = (RiirSampleC * altAmount) + (RpassThrough * iirAmount);
|
|
RpassThrough -= RiirSampleC;
|
|
}
|
|
else
|
|
{
|
|
LiirSampleB = (LiirSampleB * altAmount) + (inputSampleL * iirAmount);
|
|
inputSampleL -= LiirSampleB;
|
|
LiirSampleD = (LiirSampleD * altAmount) + (LpassThrough * iirAmount);
|
|
LpassThrough -= LiirSampleD;
|
|
|
|
RiirSampleB = (RiirSampleB * altAmount) + (inputSampleR * iirAmount);
|
|
inputSampleR -= RiirSampleB;
|
|
RiirSampleD = (RiirSampleD * altAmount) + (RpassThrough * iirAmount);
|
|
RpassThrough -= RiirSampleD;
|
|
}
|
|
flip = !flip;
|
|
//highpass section
|
|
|
|
LlastOut3Sample = LlastOut2Sample;
|
|
LlastOut2Sample = LlastOutSample;
|
|
LlastOutSample = inputSampleL;
|
|
|
|
RlastOut3Sample = RlastOut2Sample;
|
|
RlastOut2Sample = RlastOutSample;
|
|
RlastOutSample = inputSampleR;
|
|
|
|
|
|
LlpDepth -= lpSpeed;
|
|
RlpDepth -= lpSpeed;
|
|
|
|
if (LlpDepth > 0.0)
|
|
{
|
|
if (LlpDepth > 1.0) LlpDepth = 1.0;
|
|
inputSampleL *= (1.0-LlpDepth);
|
|
inputSampleL += (((LlastOutSample + LlastOut2Sample + LlastOut3Sample) / 3.6)*LlpDepth);
|
|
}
|
|
|
|
if (RlpDepth > 0.0)
|
|
{
|
|
if (RlpDepth > 1.0) RlpDepth = 1.0;
|
|
inputSampleR *= (1.0-RlpDepth);
|
|
inputSampleR += (((RlastOutSample + RlastOut2Sample + RlastOut3Sample) / 3.6)*RlpDepth);
|
|
}
|
|
|
|
if (LlpDepth < 0.0) LlpDepth = 0.0;
|
|
if (RlpDepth < 0.0) RlpDepth = 0.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
|
|
|
|
inputSampleL *= (1.0-LmaxRecent);
|
|
inputSampleR *= (1.0-RmaxRecent);
|
|
inputSampleL += (LpassThrough * LmaxRecent);
|
|
inputSampleR += (RpassThrough * RmaxRecent);
|
|
//there's our raw signal, without antialiasing. Brings up low level stuff and softens more when hot
|
|
|
|
if (inputSampleL > cliplevel) inputSampleL = cliplevel;
|
|
if (inputSampleL < -cliplevel) inputSampleL = -cliplevel;
|
|
if (inputSampleR > cliplevel) inputSampleR = cliplevel;
|
|
if (inputSampleR < -cliplevel) inputSampleR = -cliplevel;
|
|
//final iron bar
|
|
|
|
|
|
*out1 = inputSampleL;
|
|
*out2 = inputSampleR;
|
|
|
|
*in1++;
|
|
*in2++;
|
|
*out1++;
|
|
*out2++;
|
|
}
|
|
} |