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