aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/MacAU/Ditherbox/Ditherbox.cpp
diff options
context:
space:
mode:
authorChris Johnson <jinx6568@sover.net>2018-09-03 16:35:36 -0400
committerChris Johnson <jinx6568@sover.net>2018-09-03 16:35:36 -0400
commit3dd30d920a374ba31994f784fadd5ee130752247 (patch)
tree4a8350099d829390fc1e75234875ff76a82ec9e9 /plugins/MacAU/Ditherbox/Ditherbox.cpp
parentb4f55328448d087a68e6f658638fb3d38d86be12 (diff)
downloadairwindows-lv2-port-3dd30d920a374ba31994f784fadd5ee130752247.tar.gz
airwindows-lv2-port-3dd30d920a374ba31994f784fadd5ee130752247.tar.bz2
airwindows-lv2-port-3dd30d920a374ba31994f784fadd5ee130752247.zip
Ditherbox update
Diffstat (limited to 'plugins/MacAU/Ditherbox/Ditherbox.cpp')
-rwxr-xr-xplugins/MacAU/Ditherbox/Ditherbox.cpp118
1 files changed, 98 insertions, 20 deletions
diff --git a/plugins/MacAU/Ditherbox/Ditherbox.cpp b/plugins/MacAU/Ditherbox/Ditherbox.cpp
index 6cd002b..a4b1edf 100755
--- a/plugins/MacAU/Ditherbox/Ditherbox.cpp
+++ b/plugins/MacAU/Ditherbox/Ditherbox.cpp
@@ -83,6 +83,9 @@ ComponentResult Ditherbox::GetParameterValueStrings(AudioUnitScope inScope,
kMenuItem_Truncate,
kMenuItem_Flat,
kMenuItem_TPDF,
+ kMenuItem_Paul,
+ kMenuItem_DoublePaul,
+ kMenuItem_Tape,
kMenuItem_Quadratic,
kMenuItem_TenNines,
kMenuItem_Contingent,
@@ -91,6 +94,9 @@ ComponentResult Ditherbox::GetParameterValueStrings(AudioUnitScope inScope,
kMenuItem_TruncateHR,
kMenuItem_FlatHR,
kMenuItem_TPDFHR,
+ kMenuItem_PaulHR,
+ kMenuItem_DoublePaulHR,
+ kMenuItem_TapeHR,
kMenuItem_QuadraticHR,
kMenuItem_TenNinesHR,
kMenuItem_ContingentHR,
@@ -298,13 +304,39 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
Float32 drySample; //should be the same as what the native DAW buss is
- if (dtype > 8){highRes = true; dtype -= 8;}
+ if (dtype > 11){highRes = true; dtype -= 11;}
- if (dtype > 8){dithering = false; highRes = false;}
+ if (dtype > 11){dithering = false; highRes = false;}
//follow up by switching high res back off for the monitoring
while (nSampleFrames-- > 0) {
- drySample = inputSample = *sourceP;
+ inputSample = *sourceP;
+ if (inputSample<1.2e-38 && -inputSample<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;
+ inputSample = 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.
+ }
+ drySample = inputSample;
+
sourceP += inNumChannels;
if (dtype == 8) inputSample -= noiseShaping;
@@ -327,16 +359,62 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
//flat dither
break;
- case 3:
- inputSample += (rand()/(double)RAND_MAX);
- inputSample += (rand()/(double)RAND_MAX);
- inputSample -= 1.0;
- inputSample = floor(inputSample);
- //TPDF dither
- break;
-
-
- case 4:
+ case 3:
+ inputSample += (rand()/(double)RAND_MAX);
+ inputSample += (rand()/(double)RAND_MAX);
+ inputSample -= 1.0;
+ inputSample = floor(inputSample);
+ //TPDF dither
+ break;
+
+ case 4:
+ currentDither = (rand()/(double)RAND_MAX);
+ inputSample += currentDither;
+ inputSample -= lastSample;
+ inputSample = floor(inputSample);
+ lastSample = currentDither;
+ //Paul dither
+ break;
+
+ case 5:
+ ns[9] = ns[8]; ns[8] = ns[7]; ns[7] = ns[6]; ns[6] = ns[5];
+ ns[5] = ns[4]; ns[4] = ns[3]; ns[3] = ns[2]; ns[2] = ns[1];
+ ns[1] = ns[0]; ns[0] = (rand()/(double)RAND_MAX);
+
+ currentDither = (ns[0] * 0.061);
+ currentDither -= (ns[1] * 0.11);
+ currentDither += (ns[8] * 0.126);
+ currentDither -= (ns[7] * 0.23);
+ currentDither += (ns[2] * 0.25);
+ currentDither -= (ns[3] * 0.43);
+ currentDither += (ns[6] * 0.5);
+ currentDither -= ns[5];
+ currentDither += ns[4];
+ //this sounds different from doing it in order of sample position
+ //cumulative tiny errors seem to build up even at this buss depth
+ //considerably more pronounced at 32 bit float.
+ //Therefore we add the most significant components LAST.
+ //trying to keep values on like exponents of the floating point value.
+ inputSample += currentDither;
+
+ inputSample = floor(inputSample);
+ //DoublePaul dither
+ break;
+
+ case 6:
+ currentDither = (rand()/(double)RAND_MAX);
+ inputSample += currentDither;
+ inputSample -= ns[4];
+ inputSample = floor(inputSample);
+ ns[4] = ns[3];
+ ns[3] = ns[2];
+ ns[2] = ns[1];
+ ns[1] = currentDither;
+ //Tape dither
+ break;
+
+
+ case 7:
Position += 1;
//Note- uses integer overflow as a 'mod' operator
hotbinA = Position * Position;
@@ -356,7 +434,7 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
//Quadratic dither
break;
- case 5:
+ case 8:
absSample = ((rand()/(double)RAND_MAX) - 0.5);
ns[0] += absSample; ns[0] /= 2; absSample -= ns[0];
absSample += ((rand()/(double)RAND_MAX) - 0.5);
@@ -406,7 +484,7 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
//TenNines dither
break;
- case 6:
+ case 9:
if (inputSample > 0) inputSample += 0.383;
if (inputSample < 0) inputSample -= 0.383;
//adjusting to permit more information drug outta the noisefloor
@@ -428,7 +506,7 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
//and does a teeny parallel-compression thing when almost at digital black.
break;
- case 7:
+ case 10:
if (inputSample > 0) inputSample += (0.3333333333);
if (inputSample < 0) inputSample -= (0.3333333333);
@@ -508,7 +586,7 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
byn[10] /= 2; //catchall for garbage data
break;
- case 8: //this one is the Not Just Another Dither
+ case 11: //this one is the Not Just Another Dither
benfordize = floor(inputSample);
while (benfordize >= 1.0) {benfordize /= 10;}
@@ -590,7 +668,7 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
byn[10] /= 2; //catchall for garbage data
break;
- case 9:
+ case 12:
//slew only
outputSample = (inputSample - lastSample)*trim;
lastSample = inputSample;
@@ -599,7 +677,7 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
inputSample = outputSample;
break;
- case 10:
+ case 13:
//subs only
gain = gaintarget;
inputSample *= gain; gain = ((gain-1)*0.75)+1;
@@ -708,7 +786,7 @@ void Ditherbox::DitherboxKernel::Process( const Float32 *inSourceP,
if (inputSample < -1.0) inputSample = -1.0;
break;
- case 11:
+ case 14:
//silhouette
bridgerectifier = fabs(inputSample)*1.57079633;
if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;