1 /* ========================================
2 * Hombre - Hombre.h
3 * Copyright (c) 2016 airwindows, All rights reserved
4 * ======================================== */
5
6 #ifndef __Hombre_H
7 #include "Hombre.h"
8 #endif
9
10 namespace Hombre {
11
12
processReplacing(float ** inputs,float ** outputs,VstInt32 sampleFrames)13 void Hombre::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames)
14 {
15 float* in1 = inputs[0];
16 float* in2 = inputs[1];
17 float* out1 = outputs[0];
18 float* out2 = outputs[1];
19
20 double overallscale = 1.0;
21 overallscale /= 44100.0;
22 overallscale *= getSampleRate();
23
24 double target = A;
25 double offsetA;
26 double offsetB;
27 int widthA = (int)(1.0*overallscale);
28 int widthB = (int)(7.0*overallscale); //max 364 at 44.1, 792 at 96K
29 double wet = B;
30 double dry = 1.0 - wet;
31 double totalL;
32 double totalR;
33 int count;
34
35 long double inputSampleL;
36 long double inputSampleR;
37 double drySampleL;
38 double drySampleR;
39
40 while (--sampleFrames >= 0)
41 {
42 inputSampleL = *in1;
43 inputSampleR = *in2;
44 if (inputSampleL<1.2e-38 && -inputSampleL<1.2e-38) {
45 static int noisesource = 0;
46 //this declares a variable before anything else is compiled. It won't keep assigning
47 //it to 0 for every sample, it's as if the declaration doesn't exist in this context,
48 //but it lets me add this denormalization fix in a single place rather than updating
49 //it in three different locations. The variable isn't thread-safe but this is only
50 //a random seed and we can share it with whatever.
51 noisesource = noisesource % 1700021; noisesource++;
52 int residue = noisesource * noisesource;
53 residue = residue % 170003; residue *= residue;
54 residue = residue % 17011; residue *= residue;
55 residue = residue % 1709; residue *= residue;
56 residue = residue % 173; residue *= residue;
57 residue = residue % 17;
58 double applyresidue = residue;
59 applyresidue *= 0.00000001;
60 applyresidue *= 0.00000001;
61 inputSampleL = applyresidue;
62 }
63 if (inputSampleR<1.2e-38 && -inputSampleR<1.2e-38) {
64 static int noisesource = 0;
65 noisesource = noisesource % 1700021; noisesource++;
66 int residue = noisesource * noisesource;
67 residue = residue % 170003; residue *= residue;
68 residue = residue % 17011; residue *= residue;
69 residue = residue % 1709; residue *= residue;
70 residue = residue % 173; residue *= residue;
71 residue = residue % 17;
72 double applyresidue = residue;
73 applyresidue *= 0.00000001;
74 applyresidue *= 0.00000001;
75 inputSampleR = applyresidue;
76 //this denormalization routine produces a white noise at -300 dB which the noise
77 //shaping will interact with to produce a bipolar output, but the noise is actually
78 //all positive. That should stop any variables from going denormal, and the routine
79 //only kicks in if digital black is input. As a final touch, if you save to 24-bit
80 //the silence will return to being digital black again.
81 }
82 drySampleL = inputSampleL;
83 drySampleR = inputSampleR;
84
85 slide = (slide * 0.9997)+(target*0.0003);
86
87 offsetA = ((pow(slide,2)) * 77)+3.2;
88 offsetB = (3.85 * offsetA)+41;
89 offsetA *= overallscale;
90 offsetB *= overallscale;
91 //adjust for sample rate
92
93 if (gcount < 1 || gcount > 2000) {gcount = 2000;}
94 count = gcount;
95
96 pL[count+2000] = pL[count] = inputSampleL;
97 pR[count+2000] = pR[count] = inputSampleR;
98 //double buffer
99
100 count = (int)(gcount+floor(offsetA));
101
102 totalL = pL[count] * 0.391; //less as value moves away from .0
103 totalL += pL[count+widthA]; //we can assume always using this in one way or another?
104 totalL += pL[count+widthA+widthA] * 0.391; //greater as value moves away from .0
105
106 totalR = pR[count] * 0.391; //less as value moves away from .0
107 totalR += pR[count+widthA]; //we can assume always using this in one way or another?
108 totalR += pR[count+widthA+widthA] * 0.391; //greater as value moves away from .0
109
110 inputSampleL += ((totalL * 0.274));
111 inputSampleR += ((totalR * 0.274));
112
113 count = (int)(gcount+floor(offsetB));
114
115 totalL = pL[count] * 0.918; //less as value moves away from .0
116 totalL += pL[count+widthB]; //we can assume always using this in one way or another?
117 totalL += pL[count+widthB+widthB] * 0.918; //greater as value moves away from .0
118
119 totalR = pR[count] * 0.918; //less as value moves away from .0
120 totalR += pR[count+widthB]; //we can assume always using this in one way or another?
121 totalR += pR[count+widthB+widthB] * 0.918; //greater as value moves away from .0
122
123 inputSampleL -= ((totalL * 0.629));
124 inputSampleR -= ((totalR * 0.629));
125
126 inputSampleL /= 4;
127 inputSampleR /= 4;
128
129 gcount--;
130 //still scrolling through the samples, remember
131
132 if (wet !=1.0) {
133 inputSampleL = (inputSampleL * wet) + (drySampleL * dry);
134 inputSampleR = (inputSampleR * wet) + (drySampleR * dry);
135 }
136
137 //stereo 32 bit dither, made small and tidy.
138 int expon; frexpf((float)inputSampleL, &expon);
139 long double dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
140 inputSampleL += (dither-fpNShapeL); fpNShapeL = dither;
141 frexpf((float)inputSampleR, &expon);
142 dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
143 inputSampleR += (dither-fpNShapeR); fpNShapeR = dither;
144 //end 32 bit dither
145
146 *out1 = inputSampleL;
147 *out2 = inputSampleR;
148
149 in1++;
150 in2++;
151 out1++;
152 out2++;
153 }
154 }
155
processDoubleReplacing(double ** inputs,double ** outputs,VstInt32 sampleFrames)156 void Hombre::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames)
157 {
158 double* in1 = inputs[0];
159 double* in2 = inputs[1];
160 double* out1 = outputs[0];
161 double* out2 = outputs[1];
162
163 double overallscale = 1.0;
164 overallscale /= 44100.0;
165 overallscale *= getSampleRate();
166
167 double target = A;
168 double offsetA;
169 double offsetB;
170 int widthA = (int)(1.0*overallscale);
171 int widthB = (int)(7.0*overallscale); //max 364 at 44.1, 792 at 96K
172 double wet = B;
173 double dry = 1.0 - wet;
174 double totalL;
175 double totalR;
176 int count;
177
178 long double inputSampleL;
179 long double inputSampleR;
180 double drySampleL;
181 double drySampleR;
182
183 while (--sampleFrames >= 0)
184 {
185 inputSampleL = *in1;
186 inputSampleR = *in2;
187 if (inputSampleL<1.2e-38 && -inputSampleL<1.2e-38) {
188 static int noisesource = 0;
189 //this declares a variable before anything else is compiled. It won't keep assigning
190 //it to 0 for every sample, it's as if the declaration doesn't exist in this context,
191 //but it lets me add this denormalization fix in a single place rather than updating
192 //it in three different locations. The variable isn't thread-safe but this is only
193 //a random seed and we can share it with whatever.
194 noisesource = noisesource % 1700021; noisesource++;
195 int residue = noisesource * noisesource;
196 residue = residue % 170003; residue *= residue;
197 residue = residue % 17011; residue *= residue;
198 residue = residue % 1709; residue *= residue;
199 residue = residue % 173; residue *= residue;
200 residue = residue % 17;
201 double applyresidue = residue;
202 applyresidue *= 0.00000001;
203 applyresidue *= 0.00000001;
204 inputSampleL = applyresidue;
205 }
206 if (inputSampleR<1.2e-38 && -inputSampleR<1.2e-38) {
207 static int noisesource = 0;
208 noisesource = noisesource % 1700021; noisesource++;
209 int residue = noisesource * noisesource;
210 residue = residue % 170003; residue *= residue;
211 residue = residue % 17011; residue *= residue;
212 residue = residue % 1709; residue *= residue;
213 residue = residue % 173; residue *= residue;
214 residue = residue % 17;
215 double applyresidue = residue;
216 applyresidue *= 0.00000001;
217 applyresidue *= 0.00000001;
218 inputSampleR = applyresidue;
219 //this denormalization routine produces a white noise at -300 dB which the noise
220 //shaping will interact with to produce a bipolar output, but the noise is actually
221 //all positive. That should stop any variables from going denormal, and the routine
222 //only kicks in if digital black is input. As a final touch, if you save to 24-bit
223 //the silence will return to being digital black again.
224 }
225 drySampleL = inputSampleL;
226 drySampleR = inputSampleR;
227
228 slide = (slide * 0.9997)+(target*0.0003);
229
230 offsetA = ((pow(slide,2)) * 77)+3.2;
231 offsetB = (3.85 * offsetA)+41;
232 offsetA *= overallscale;
233 offsetB *= overallscale;
234 //adjust for sample rate
235
236 if (gcount < 1 || gcount > 2000) {gcount = 2000;}
237 count = gcount;
238
239 pL[count+2000] = pL[count] = inputSampleL;
240 pR[count+2000] = pR[count] = inputSampleR;
241 //double buffer
242
243 count = (int)(gcount+floor(offsetA));
244
245 totalL = pL[count] * 0.391; //less as value moves away from .0
246 totalL += pL[count+widthA]; //we can assume always using this in one way or another?
247 totalL += pL[count+widthA+widthA] * 0.391; //greater as value moves away from .0
248
249 totalR = pR[count] * 0.391; //less as value moves away from .0
250 totalR += pR[count+widthA]; //we can assume always using this in one way or another?
251 totalR += pR[count+widthA+widthA] * 0.391; //greater as value moves away from .0
252
253 inputSampleL += ((totalL * 0.274));
254 inputSampleR += ((totalR * 0.274));
255
256 count = (int)(gcount+floor(offsetB));
257
258 totalL = pL[count] * 0.918; //less as value moves away from .0
259 totalL += pL[count+widthB]; //we can assume always using this in one way or another?
260 totalL += pL[count+widthB+widthB] * 0.918; //greater as value moves away from .0
261
262 totalR = pR[count] * 0.918; //less as value moves away from .0
263 totalR += pR[count+widthB]; //we can assume always using this in one way or another?
264 totalR += pR[count+widthB+widthB] * 0.918; //greater as value moves away from .0
265
266 inputSampleL -= ((totalL * 0.629));
267 inputSampleR -= ((totalR * 0.629));
268
269 inputSampleL /= 4;
270 inputSampleR /= 4;
271
272 gcount--;
273 //still scrolling through the samples, remember
274
275 if (wet !=1.0) {
276 inputSampleL = (inputSampleL * wet) + (drySampleL * dry);
277 inputSampleR = (inputSampleR * wet) + (drySampleR * dry);
278 }
279
280 //stereo 64 bit dither, made small and tidy.
281 int expon; frexp((double)inputSampleL, &expon);
282 long double dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
283 dither /= 536870912.0; //needs this to scale to 64 bit zone
284 inputSampleL += (dither-fpNShapeL); fpNShapeL = dither;
285 frexp((double)inputSampleR, &expon);
286 dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
287 dither /= 536870912.0; //needs this to scale to 64 bit zone
288 inputSampleR += (dither-fpNShapeR); fpNShapeR = dither;
289 //end 64 bit dither
290
291 *out1 = inputSampleL;
292 *out2 = inputSampleR;
293
294 in1++;
295 in2++;
296 out1++;
297 out2++;
298 }
299 }
300
301 } // end namespace Hombre
302
303