diff options
Diffstat (limited to 'plugins/MacVST/StudioTan/source/StudioTanProc.cpp')
-rwxr-xr-x | plugins/MacVST/StudioTan/source/StudioTanProc.cpp | 564 |
1 files changed, 564 insertions, 0 deletions
diff --git a/plugins/MacVST/StudioTan/source/StudioTanProc.cpp b/plugins/MacVST/StudioTan/source/StudioTanProc.cpp new file mode 100755 index 0000000..3258f7b --- /dev/null +++ b/plugins/MacVST/StudioTan/source/StudioTanProc.cpp @@ -0,0 +1,564 @@ +/* ======================================== + * StudioTan - StudioTan.h + * Copyright (c) 2016 airwindows, All rights reserved + * ======================================== */ + +#ifndef __StudioTan_H +#include "StudioTan.h" +#endif + +void StudioTan::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) +{ + float* in1 = inputs[0]; + float* in2 = inputs[1]; + float* out1 = outputs[0]; + float* out2 = outputs[1]; + + bool highres = true; //for 24 bit: false for 16 bit + bool brightfloor = true; //for Studio Tan: false for Dither Me Timbers + bool benford = true; //for Not Just Another Dither: false for newer two + bool cutbins = false; //for NJAD: only attenuate bins if one gets very full + switch ((VstInt32)( A * 5.999 )) + { + case 0: benford = false; break; //Studio Tan 24 + case 1: benford = false; brightfloor = false; break; //Dither Me Timbers 24 + case 2: break; //Not Just Another Dither 24 + case 3: benford = false; highres = false; break; //Studio Tan 16 + case 4: benford = false; brightfloor = false; highres = false; break; //Dither Me Timbers 16 + case 5: highres = false; break; //Not Just Another Dither 16 + } + + while (--sampleFrames >= 0) + { + long double inputSampleL; + long double outputSampleL; + long double drySampleL; + long double inputSampleR; + long double outputSampleR; + long double drySampleR; + + if (highres) { + inputSampleL = *in1 * 8388608.0; + inputSampleR = *in2 * 8388608.0; + } else { + inputSampleL = *in1 * 32768.0; + inputSampleR = *in2 * 32768.0; + } + //shared input stage + + if (benford) { + //begin Not Just Another Dither + drySampleL = inputSampleL; + drySampleR = inputSampleR; + inputSampleL -= noiseShapingL; + inputSampleR -= noiseShapingR; + + cutbins = false; + long double benfordize; //we get to re-use this for each channel + + //begin left channel NJAD + benfordize = floor(inputSampleL); + while (benfordize >= 1.0) {benfordize /= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + int hotbinA = floor(benfordize); + //hotbin becomes the Benford bin value for this number floored + long double totalA = 0; + if ((hotbinA > 0) && (hotbinA < 10)) + { + bynL[hotbinA] += 1; + if (bynL[hotbinA] > 982) cutbins = true; + totalA += (301-bynL[1]); + totalA += (176-bynL[2]); + totalA += (125-bynL[3]); + totalA += (97-bynL[4]); + totalA += (79-bynL[5]); + totalA += (67-bynL[6]); + totalA += (58-bynL[7]); + totalA += (51-bynL[8]); + totalA += (46-bynL[9]); + bynL[hotbinA] -= 1; + } else {hotbinA = 10;} + //produce total number- smaller is closer to Benford real + + benfordize = ceil(inputSampleL); + while (benfordize >= 1.0) {benfordize /= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + int hotbinB = floor(benfordize); + //hotbin becomes the Benford bin value for this number ceiled + long double totalB = 0; + if ((hotbinB > 0) && (hotbinB < 10)) + { + bynL[hotbinB] += 1; + if (bynL[hotbinB] > 982) cutbins = true; + totalB += (301-bynL[1]); + totalB += (176-bynL[2]); + totalB += (125-bynL[3]); + totalB += (97-bynL[4]); + totalB += (79-bynL[5]); + totalB += (67-bynL[6]); + totalB += (58-bynL[7]); + totalB += (51-bynL[8]); + totalB += (46-bynL[9]); + bynL[hotbinB] -= 1; + } else {hotbinB = 10;} + //produce total number- smaller is closer to Benford real + + if (totalA < totalB) + { + bynL[hotbinA] += 1; + outputSampleL = floor(inputSampleL); + } + else + { + bynL[hotbinB] += 1; + outputSampleL = floor(inputSampleL+1); + } + //assign the relevant one to the delay line + //and floor/ceil signal accordingly + if (cutbins) { + bynL[1] *= 0.99; + bynL[2] *= 0.99; + bynL[3] *= 0.99; + bynL[4] *= 0.99; + bynL[5] *= 0.99; + bynL[6] *= 0.99; + bynL[7] *= 0.99; + bynL[8] *= 0.99; + bynL[9] *= 0.99; + bynL[10] *= 0.99; //catchall for garbage data + } + noiseShapingL += outputSampleL - drySampleL; + //end left channel NJAD + + //begin right channel NJAD + cutbins = false; + benfordize = floor(inputSampleR); + while (benfordize >= 1.0) {benfordize /= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + hotbinA = floor(benfordize); + //hotbin becomes the Benford bin value for this number floored + totalA = 0; + if ((hotbinA > 0) && (hotbinA < 10)) + { + bynR[hotbinA] += 1; + if (bynR[hotbinA] > 982) cutbins = true; + totalA += (301-bynR[1]); + totalA += (176-bynR[2]); + totalA += (125-bynR[3]); + totalA += (97-bynR[4]); + totalA += (79-bynR[5]); + totalA += (67-bynR[6]); + totalA += (58-bynR[7]); + totalA += (51-bynR[8]); + totalA += (46-bynR[9]); + bynR[hotbinA] -= 1; + } else {hotbinA = 10;} + //produce total number- smaller is closer to Benford real + + benfordize = ceil(inputSampleR); + while (benfordize >= 1.0) {benfordize /= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + hotbinB = floor(benfordize); + //hotbin becomes the Benford bin value for this number ceiled + totalB = 0; + if ((hotbinB > 0) && (hotbinB < 10)) + { + bynR[hotbinB] += 1; + if (bynR[hotbinB] > 982) cutbins = true; + totalB += (301-bynR[1]); + totalB += (176-bynR[2]); + totalB += (125-bynR[3]); + totalB += (97-bynR[4]); + totalB += (79-bynR[5]); + totalB += (67-bynR[6]); + totalB += (58-bynR[7]); + totalB += (51-bynR[8]); + totalB += (46-bynR[9]); + bynR[hotbinB] -= 1; + } else {hotbinB = 10;} + //produce total number- smaller is closer to Benford real + + if (totalA < totalB) + { + bynR[hotbinA] += 1; + outputSampleR = floor(inputSampleR); + } + else + { + bynR[hotbinB] += 1; + outputSampleR = floor(inputSampleR+1); + } + //assign the relevant one to the delay line + //and floor/ceil signal accordingly + if (cutbins) { + bynR[1] *= 0.99; + bynR[2] *= 0.99; + bynR[3] *= 0.99; + bynR[4] *= 0.99; + bynR[5] *= 0.99; + bynR[6] *= 0.99; + bynR[7] *= 0.99; + bynR[8] *= 0.99; + bynR[9] *= 0.99; + bynR[10] *= 0.99; //catchall for garbage data + } + noiseShapingR += outputSampleR - drySampleR; + //end right channel NJAD + + //end Not Just Another Dither + } else { + //begin StudioTan or Dither Me Timbers + if (brightfloor) { + lastSampleL -= (noiseShapingL*0.8); + lastSampleR -= (noiseShapingR*0.8); + if ((lastSampleL+lastSampleL) <= (inputSampleL+lastSample2L)) outputSampleL = floor(lastSampleL); //StudioTan + else outputSampleL = floor(lastSampleL+1.0); //round down or up based on whether it softens treble angles + if ((lastSampleR+lastSampleR) <= (inputSampleR+lastSample2R)) outputSampleR = floor(lastSampleR); //StudioTan + else outputSampleR = floor(lastSampleR+1.0); //round down or up based on whether it softens treble angles + } else { + lastSampleL -= (noiseShapingL*0.11); + lastSampleR -= (noiseShapingR*0.11); + if ((lastSampleL+lastSampleL) >= (inputSampleL+lastSample2L)) outputSampleL = floor(lastSampleL); //DitherMeTimbers + else outputSampleL = floor(lastSampleL+1.0); //round down or up based on whether it softens treble angles + if ((lastSampleR+lastSampleR) >= (inputSampleR+lastSample2R)) outputSampleR = floor(lastSampleR); //DitherMeTimbers + else outputSampleR = floor(lastSampleR+1.0); //round down or up based on whether it softens treble angles + } + noiseShapingL += outputSampleL; + noiseShapingL -= lastSampleL; //apply noise shaping + lastSample2L = lastSampleL; + lastSampleL = inputSampleL; //we retain three samples in a row + + noiseShapingR += outputSampleR; + noiseShapingR -= lastSampleR; //apply noise shaping + lastSample2R = lastSampleR; + lastSampleR = inputSampleR; //we retain three samples in a row + //end StudioTan or Dither Me Timbers + } + + //shared output stage + long double noiseSuppressL = fabs(inputSampleL); + if (noiseShapingL > noiseSuppressL) noiseShapingL = noiseSuppressL; + if (noiseShapingL < -noiseSuppressL) noiseShapingL = -noiseSuppressL; + + long double noiseSuppressR = fabs(inputSampleR); + if (noiseShapingR > noiseSuppressR) noiseShapingR = noiseSuppressR; + if (noiseShapingR < -noiseSuppressR) noiseShapingR = -noiseSuppressR; + + float ironBarL; + float ironBarR; + if (highres) { + ironBarL = outputSampleL / 8388608.0; + ironBarR = outputSampleR / 8388608.0; + } else { + ironBarL = outputSampleL / 32768.0; + ironBarR = outputSampleR / 32768.0; + } + + if (ironBarL > 1.0) ironBarL = 1.0; + if (ironBarL < -1.0) ironBarL = -1.0; + if (ironBarR > 1.0) ironBarR = 1.0; + if (ironBarR < -1.0) ironBarR = -1.0; + + *out1 = ironBarL; + *out2 = ironBarR; + + *in1++; + *in2++; + *out1++; + *out2++; + } +} + +void StudioTan::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames) +{ + double* in1 = inputs[0]; + double* in2 = inputs[1]; + double* out1 = outputs[0]; + double* out2 = outputs[1]; + + bool highres = true; //for 24 bit: false for 16 bit + bool brightfloor = true; //for Studio Tan: false for Dither Me Timbers + bool benford = true; //for Not Just Another Dither: false for newer two + bool cutbins = false; //for NJAD: only attenuate bins if one gets very full + switch ((VstInt32)( A * 5.999 )) + { + case 0: benford = false; break; //Studio Tan 24 + case 1: benford = false; brightfloor = false; break; //Dither Me Timbers 24 + case 2: break; //Not Just Another Dither 24 + case 3: benford = false; highres = false; break; //Studio Tan 16 + case 4: benford = false; brightfloor = false; highres = false; break; //Dither Me Timbers 16 + case 5: highres = false; break; //Not Just Another Dither 16 + } + + while (--sampleFrames >= 0) + { + long double inputSampleL; + long double outputSampleL; + long double drySampleL; + long double inputSampleR; + long double outputSampleR; + long double drySampleR; + + if (highres) { + inputSampleL = *in1 * 8388608.0; + inputSampleR = *in2 * 8388608.0; + } else { + inputSampleL = *in1 * 32768.0; + inputSampleR = *in2 * 32768.0; + } + //shared input stage + + if (benford) { + //begin Not Just Another Dither + drySampleL = inputSampleL; + drySampleR = inputSampleR; + inputSampleL -= noiseShapingL; + inputSampleR -= noiseShapingR; + + cutbins = false; + long double benfordize; //we get to re-use this for each channel + + //begin left channel NJAD + benfordize = floor(inputSampleL); + while (benfordize >= 1.0) {benfordize /= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + int hotbinA = floor(benfordize); + //hotbin becomes the Benford bin value for this number floored + long double totalA = 0; + if ((hotbinA > 0) && (hotbinA < 10)) + { + bynL[hotbinA] += 1; + if (bynL[hotbinA] > 982) cutbins = true; + totalA += (301-bynL[1]); + totalA += (176-bynL[2]); + totalA += (125-bynL[3]); + totalA += (97-bynL[4]); + totalA += (79-bynL[5]); + totalA += (67-bynL[6]); + totalA += (58-bynL[7]); + totalA += (51-bynL[8]); + totalA += (46-bynL[9]); + bynL[hotbinA] -= 1; + } else {hotbinA = 10;} + //produce total number- smaller is closer to Benford real + + benfordize = ceil(inputSampleL); + while (benfordize >= 1.0) {benfordize /= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + int hotbinB = floor(benfordize); + //hotbin becomes the Benford bin value for this number ceiled + long double totalB = 0; + if ((hotbinB > 0) && (hotbinB < 10)) + { + bynL[hotbinB] += 1; + if (bynL[hotbinB] > 982) cutbins = true; + totalB += (301-bynL[1]); + totalB += (176-bynL[2]); + totalB += (125-bynL[3]); + totalB += (97-bynL[4]); + totalB += (79-bynL[5]); + totalB += (67-bynL[6]); + totalB += (58-bynL[7]); + totalB += (51-bynL[8]); + totalB += (46-bynL[9]); + bynL[hotbinB] -= 1; + } else {hotbinB = 10;} + //produce total number- smaller is closer to Benford real + + if (totalA < totalB) + { + bynL[hotbinA] += 1; + outputSampleL = floor(inputSampleL); + } + else + { + bynL[hotbinB] += 1; + outputSampleL = floor(inputSampleL+1); + } + //assign the relevant one to the delay line + //and floor/ceil signal accordingly + if (cutbins) { + bynL[1] *= 0.99; + bynL[2] *= 0.99; + bynL[3] *= 0.99; + bynL[4] *= 0.99; + bynL[5] *= 0.99; + bynL[6] *= 0.99; + bynL[7] *= 0.99; + bynL[8] *= 0.99; + bynL[9] *= 0.99; + bynL[10] *= 0.99; //catchall for garbage data + } + noiseShapingL += outputSampleL - drySampleL; + //end left channel NJAD + + //begin right channel NJAD + cutbins = false; + benfordize = floor(inputSampleR); + while (benfordize >= 1.0) {benfordize /= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + hotbinA = floor(benfordize); + //hotbin becomes the Benford bin value for this number floored + totalA = 0; + if ((hotbinA > 0) && (hotbinA < 10)) + { + bynR[hotbinA] += 1; + if (bynR[hotbinA] > 982) cutbins = true; + totalA += (301-bynR[1]); + totalA += (176-bynR[2]); + totalA += (125-bynR[3]); + totalA += (97-bynR[4]); + totalA += (79-bynR[5]); + totalA += (67-bynR[6]); + totalA += (58-bynR[7]); + totalA += (51-bynR[8]); + totalA += (46-bynR[9]); + bynR[hotbinA] -= 1; + } else {hotbinA = 10;} + //produce total number- smaller is closer to Benford real + + benfordize = ceil(inputSampleR); + while (benfordize >= 1.0) {benfordize /= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + if (benfordize < 1.0) {benfordize *= 10;} + hotbinB = floor(benfordize); + //hotbin becomes the Benford bin value for this number ceiled + totalB = 0; + if ((hotbinB > 0) && (hotbinB < 10)) + { + bynR[hotbinB] += 1; + if (bynR[hotbinB] > 982) cutbins = true; + totalB += (301-bynR[1]); + totalB += (176-bynR[2]); + totalB += (125-bynR[3]); + totalB += (97-bynR[4]); + totalB += (79-bynR[5]); + totalB += (67-bynR[6]); + totalB += (58-bynR[7]); + totalB += (51-bynR[8]); + totalB += (46-bynR[9]); + bynR[hotbinB] -= 1; + } else {hotbinB = 10;} + //produce total number- smaller is closer to Benford real + + if (totalA < totalB) + { + bynR[hotbinA] += 1; + outputSampleR = floor(inputSampleR); + } + else + { + bynR[hotbinB] += 1; + outputSampleR = floor(inputSampleR+1); + } + //assign the relevant one to the delay line + //and floor/ceil signal accordingly + if (cutbins) { + bynR[1] *= 0.99; + bynR[2] *= 0.99; + bynR[3] *= 0.99; + bynR[4] *= 0.99; + bynR[5] *= 0.99; + bynR[6] *= 0.99; + bynR[7] *= 0.99; + bynR[8] *= 0.99; + bynR[9] *= 0.99; + bynR[10] *= 0.99; //catchall for garbage data + } + noiseShapingR += outputSampleR - drySampleR; + //end right channel NJAD + + //end Not Just Another Dither + } else { + //begin StudioTan or Dither Me Timbers + if (brightfloor) { + lastSampleL -= (noiseShapingL*0.8); + lastSampleR -= (noiseShapingR*0.8); + if ((lastSampleL+lastSampleL) <= (inputSampleL+lastSample2L)) outputSampleL = floor(lastSampleL); //StudioTan + else outputSampleL = floor(lastSampleL+1.0); //round down or up based on whether it softens treble angles + if ((lastSampleR+lastSampleR) <= (inputSampleR+lastSample2R)) outputSampleR = floor(lastSampleR); //StudioTan + else outputSampleR = floor(lastSampleR+1.0); //round down or up based on whether it softens treble angles + } else { + lastSampleL -= (noiseShapingL*0.11); + lastSampleR -= (noiseShapingR*0.11); + if ((lastSampleL+lastSampleL) >= (inputSampleL+lastSample2L)) outputSampleL = floor(lastSampleL); //DitherMeTimbers + else outputSampleL = floor(lastSampleL+1.0); //round down or up based on whether it softens treble angles + if ((lastSampleR+lastSampleR) >= (inputSampleR+lastSample2R)) outputSampleR = floor(lastSampleR); //DitherMeTimbers + else outputSampleR = floor(lastSampleR+1.0); //round down or up based on whether it softens treble angles + } + noiseShapingL += outputSampleL; + noiseShapingL -= lastSampleL; //apply noise shaping + lastSample2L = lastSampleL; + lastSampleL = inputSampleL; //we retain three samples in a row + + noiseShapingR += outputSampleR; + noiseShapingR -= lastSampleR; //apply noise shaping + lastSample2R = lastSampleR; + lastSampleR = inputSampleR; //we retain three samples in a row + //end StudioTan or Dither Me Timbers + } + + //shared output stage + long double noiseSuppressL = fabs(inputSampleL); + if (noiseShapingL > noiseSuppressL) noiseShapingL = noiseSuppressL; + if (noiseShapingL < -noiseSuppressL) noiseShapingL = -noiseSuppressL; + + long double noiseSuppressR = fabs(inputSampleR); + if (noiseShapingR > noiseSuppressR) noiseShapingR = noiseSuppressR; + if (noiseShapingR < -noiseSuppressR) noiseShapingR = -noiseSuppressR; + + double ironBarL; + double ironBarR; + if (highres) { + ironBarL = outputSampleL / 8388608.0; + ironBarR = outputSampleR / 8388608.0; + } else { + ironBarL = outputSampleL / 32768.0; + ironBarR = outputSampleR / 32768.0; + } + + if (ironBarL > 1.0) ironBarL = 1.0; + if (ironBarL < -1.0) ironBarL = -1.0; + if (ironBarR > 1.0) ironBarR = 1.0; + if (ironBarR < -1.0) ironBarR = -1.0; + + *out1 = ironBarL; + *out2 = ironBarR; + + *in1++; + *in2++; + *out1++; + *out2++; + } +} |