1 /* ========================================
2 * DrumSlam - DrumSlam.h
3 * Copyright (c) 2016 airwindows, All rights reserved
4 * ======================================== */
5
6 #ifndef __DrumSlam_H
7 #include "DrumSlam.h"
8 #endif
9
10 namespace DrumSlam {
11
12
processReplacing(float ** inputs,float ** outputs,VstInt32 sampleFrames)13 void DrumSlam::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 double iirAmountL = 0.0819;
24 iirAmountL /= overallscale;
25 double iirAmountH = 0.377933067;
26 iirAmountH /= overallscale;
27 double drive = (A*3.0)+1.0;
28 double out = B;
29 double wet = C;
30 double dry = 1.0 - wet;
31
32 while (--sampleFrames >= 0)
33 {
34 long double inputSampleL = *in1;
35 long double inputSampleR = *in2;
36 if (inputSampleL<1.2e-38 && -inputSampleL<1.2e-38) {
37 static int noisesource = 0;
38 //this declares a variable before anything else is compiled. It won't keep assigning
39 //it to 0 for every sample, it's as if the declaration doesn't exist in this context,
40 //but it lets me add this denormalization fix in a single place rather than updating
41 //it in three different locations. The variable isn't thread-safe but this is only
42 //a random seed and we can share it with whatever.
43 noisesource = noisesource % 1700021; noisesource++;
44 int residue = noisesource * noisesource;
45 residue = residue % 170003; residue *= residue;
46 residue = residue % 17011; residue *= residue;
47 residue = residue % 1709; residue *= residue;
48 residue = residue % 173; residue *= residue;
49 residue = residue % 17;
50 double applyresidue = residue;
51 applyresidue *= 0.00000001;
52 applyresidue *= 0.00000001;
53 inputSampleL = applyresidue;
54 }
55 if (inputSampleR<1.2e-38 && -inputSampleR<1.2e-38) {
56 static int noisesource = 0;
57 noisesource = noisesource % 1700021; noisesource++;
58 int residue = noisesource * noisesource;
59 residue = residue % 170003; residue *= residue;
60 residue = residue % 17011; residue *= residue;
61 residue = residue % 1709; residue *= residue;
62 residue = residue % 173; residue *= residue;
63 residue = residue % 17;
64 double applyresidue = residue;
65 applyresidue *= 0.00000001;
66 applyresidue *= 0.00000001;
67 inputSampleR = applyresidue;
68 //this denormalization routine produces a white noise at -300 dB which the noise
69 //shaping will interact with to produce a bipolar output, but the noise is actually
70 //all positive. That should stop any variables from going denormal, and the routine
71 //only kicks in if digital black is input. As a final touch, if you save to 24-bit
72 //the silence will return to being digital black again.
73 }
74 long double drySampleL = inputSampleL;
75 long double drySampleR = inputSampleR;
76 long double lowSampleL;
77 long double lowSampleR;
78 long double midSampleL;
79 long double midSampleR;
80 long double highSampleL;
81 long double highSampleR;
82
83
84 inputSampleL *= drive;
85 inputSampleR *= drive;
86
87 if (fpFlip)
88 {
89 iirSampleAL = (iirSampleAL * (1 - iirAmountL)) + (inputSampleL * iirAmountL);
90 iirSampleBL = (iirSampleBL * (1 - iirAmountL)) + (iirSampleAL * iirAmountL);
91 lowSampleL = iirSampleBL;
92
93 iirSampleAR = (iirSampleAR * (1 - iirAmountL)) + (inputSampleR * iirAmountL);
94 iirSampleBR = (iirSampleBR * (1 - iirAmountL)) + (iirSampleAR * iirAmountL);
95 lowSampleR = iirSampleBR;
96
97 iirSampleEL = (iirSampleEL * (1 - iirAmountH)) + (inputSampleL * iirAmountH);
98 iirSampleFL = (iirSampleFL * (1 - iirAmountH)) + (iirSampleEL * iirAmountH);
99 midSampleL = iirSampleFL - iirSampleBL;
100
101 iirSampleER = (iirSampleER * (1 - iirAmountH)) + (inputSampleR * iirAmountH);
102 iirSampleFR = (iirSampleFR * (1 - iirAmountH)) + (iirSampleER * iirAmountH);
103 midSampleR = iirSampleFR - iirSampleBR;
104
105 highSampleL = inputSampleL - iirSampleFL;
106 highSampleR = inputSampleR - iirSampleFR;
107 }
108 else
109 {
110 iirSampleCL = (iirSampleCL * (1 - iirAmountL)) + (inputSampleL * iirAmountL);
111 iirSampleDL = (iirSampleDL * (1 - iirAmountL)) + (iirSampleCL * iirAmountL);
112 lowSampleL = iirSampleDL;
113
114 iirSampleCR = (iirSampleCR * (1 - iirAmountL)) + (inputSampleR * iirAmountL);
115 iirSampleDR = (iirSampleDR * (1 - iirAmountL)) + (iirSampleCR * iirAmountL);
116 lowSampleR = iirSampleDR;
117
118 iirSampleGL = (iirSampleGL * (1 - iirAmountH)) + (inputSampleL * iirAmountH);
119 iirSampleHL = (iirSampleHL * (1 - iirAmountH)) + (iirSampleGL * iirAmountH);
120 midSampleL = iirSampleHL - iirSampleDL;
121
122 iirSampleGR = (iirSampleGR * (1 - iirAmountH)) + (inputSampleR * iirAmountH);
123 iirSampleHR = (iirSampleHR * (1 - iirAmountH)) + (iirSampleGR * iirAmountH);
124 midSampleR = iirSampleHR - iirSampleDR;
125
126 highSampleL = inputSampleL - iirSampleHL;
127 highSampleR = inputSampleR - iirSampleHR;
128 }
129 fpFlip = !fpFlip;
130
131 //generate the tone bands we're using
132 if (lowSampleL > 1.0) {lowSampleL = 1.0;}
133 if (lowSampleL < -1.0) {lowSampleL = -1.0;}
134 if (lowSampleR > 1.0) {lowSampleR = 1.0;}
135 if (lowSampleR < -1.0) {lowSampleR = -1.0;}
136 lowSampleL -= (lowSampleL * (fabs(lowSampleL) * 0.448) * (fabs(lowSampleL) * 0.448) );
137 lowSampleR -= (lowSampleR * (fabs(lowSampleR) * 0.448) * (fabs(lowSampleR) * 0.448) );
138 lowSampleL *= drive;
139 lowSampleR *= drive;
140
141 if (highSampleL > 1.0) {highSampleL = 1.0;}
142 if (highSampleL < -1.0) {highSampleL = -1.0;}
143 if (highSampleR > 1.0) {highSampleR = 1.0;}
144 if (highSampleR < -1.0) {highSampleR = -1.0;}
145 highSampleL -= (highSampleL * (fabs(highSampleL) * 0.599) * (fabs(highSampleL) * 0.599) );
146 highSampleR -= (highSampleR * (fabs(highSampleR) * 0.599) * (fabs(highSampleR) * 0.599) );
147 highSampleL *= drive;
148 highSampleR *= drive;
149
150 midSampleL = midSampleL * drive;
151 midSampleR = midSampleR * drive;
152
153 long double skew = (midSampleL - lastSampleL);
154 lastSampleL = midSampleL;
155 //skew will be direction/angle
156 long double bridgerectifier = fabs(skew);
157 if (bridgerectifier > 3.1415926) bridgerectifier = 3.1415926;
158 //for skew we want it to go to zero effect again, so we use full range of the sine
159 bridgerectifier = sin(bridgerectifier);
160 if (skew > 0) skew = bridgerectifier*3.1415926;
161 else skew = -bridgerectifier*3.1415926;
162 //skew is now sined and clamped and then re-amplified again
163 skew *= midSampleL;
164 //cools off sparkliness and crossover distortion
165 skew *= 1.557079633;
166 //crank up the gain on this so we can make it sing
167 bridgerectifier = fabs(midSampleL);
168 bridgerectifier += skew;
169 if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
170 bridgerectifier = sin(bridgerectifier);
171 bridgerectifier *= drive;
172 bridgerectifier += skew;
173 if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
174 bridgerectifier = sin(bridgerectifier);
175 if (midSampleL > 0)
176 {
177 midSampleL = bridgerectifier;
178 }
179 else
180 {
181 midSampleL = -bridgerectifier;
182 }
183 //blend according to positive and negative controls, left
184
185 skew = (midSampleR - lastSampleR);
186 lastSampleR = midSampleR;
187 //skew will be direction/angle
188 bridgerectifier = fabs(skew);
189 if (bridgerectifier > 3.1415926) bridgerectifier = 3.1415926;
190 //for skew we want it to go to zero effect again, so we use full range of the sine
191 bridgerectifier = sin(bridgerectifier);
192 if (skew > 0) skew = bridgerectifier*3.1415926;
193 else skew = -bridgerectifier*3.1415926;
194 //skew is now sined and clamped and then re-amplified again
195 skew *= midSampleR;
196 //cools off sparkliness and crossover distortion
197 skew *= 1.557079633;
198 //crank up the gain on this so we can make it sing
199 bridgerectifier = fabs(midSampleR);
200 bridgerectifier += skew;
201 if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
202 bridgerectifier = sin(bridgerectifier);
203 bridgerectifier *= drive;
204 bridgerectifier += skew;
205 if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
206 bridgerectifier = sin(bridgerectifier);
207 if (midSampleR > 0)
208 {
209 midSampleR = bridgerectifier;
210 }
211 else
212 {
213 midSampleR = -bridgerectifier;
214 }
215 //blend according to positive and negative controls, right
216
217 inputSampleL = ((lowSampleL + midSampleL + highSampleL)/drive)*out;
218 inputSampleR = ((lowSampleR + midSampleR + highSampleR)/drive)*out;
219
220 if (wet !=1.0) {
221 inputSampleL = (inputSampleL * wet) + (drySampleL * dry);
222 inputSampleR = (inputSampleR * wet) + (drySampleR * dry);
223 }
224
225 //stereo 32 bit dither, made small and tidy.
226 int expon; frexpf((float)inputSampleL, &expon);
227 long double dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
228 inputSampleL += (dither-fpNShapeL); fpNShapeL = dither;
229 frexpf((float)inputSampleR, &expon);
230 dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
231 inputSampleR += (dither-fpNShapeR); fpNShapeR = dither;
232 //end 32 bit dither
233
234 *out1 = inputSampleL;
235 *out2 = inputSampleR;
236
237 in1++;
238 in2++;
239 out1++;
240 out2++;
241 }
242 }
243
processDoubleReplacing(double ** inputs,double ** outputs,VstInt32 sampleFrames)244 void DrumSlam::processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames)
245 {
246 double* in1 = inputs[0];
247 double* in2 = inputs[1];
248 double* out1 = outputs[0];
249 double* out2 = outputs[1];
250
251 double overallscale = 1.0;
252 overallscale /= 44100.0;
253 overallscale *= getSampleRate();
254 double iirAmountL = 0.0819;
255 iirAmountL /= overallscale;
256 double iirAmountH = 0.377933067;
257 iirAmountH /= overallscale;
258 double drive = (A*3.0)+1.0;
259 double out = B;
260 double wet = C;
261 double dry = 1.0 - wet;
262
263 while (--sampleFrames >= 0)
264 {
265 long double inputSampleL = *in1;
266 long double inputSampleR = *in2;
267 if (inputSampleL<1.2e-38 && -inputSampleL<1.2e-38) {
268 static int noisesource = 0;
269 //this declares a variable before anything else is compiled. It won't keep assigning
270 //it to 0 for every sample, it's as if the declaration doesn't exist in this context,
271 //but it lets me add this denormalization fix in a single place rather than updating
272 //it in three different locations. The variable isn't thread-safe but this is only
273 //a random seed and we can share it with whatever.
274 noisesource = noisesource % 1700021; noisesource++;
275 int residue = noisesource * noisesource;
276 residue = residue % 170003; residue *= residue;
277 residue = residue % 17011; residue *= residue;
278 residue = residue % 1709; residue *= residue;
279 residue = residue % 173; residue *= residue;
280 residue = residue % 17;
281 double applyresidue = residue;
282 applyresidue *= 0.00000001;
283 applyresidue *= 0.00000001;
284 inputSampleL = applyresidue;
285 }
286 if (inputSampleR<1.2e-38 && -inputSampleR<1.2e-38) {
287 static int noisesource = 0;
288 noisesource = noisesource % 1700021; noisesource++;
289 int residue = noisesource * noisesource;
290 residue = residue % 170003; residue *= residue;
291 residue = residue % 17011; residue *= residue;
292 residue = residue % 1709; residue *= residue;
293 residue = residue % 173; residue *= residue;
294 residue = residue % 17;
295 double applyresidue = residue;
296 applyresidue *= 0.00000001;
297 applyresidue *= 0.00000001;
298 inputSampleR = applyresidue;
299 //this denormalization routine produces a white noise at -300 dB which the noise
300 //shaping will interact with to produce a bipolar output, but the noise is actually
301 //all positive. That should stop any variables from going denormal, and the routine
302 //only kicks in if digital black is input. As a final touch, if you save to 24-bit
303 //the silence will return to being digital black again.
304 }
305 long double drySampleL = inputSampleL;
306 long double drySampleR = inputSampleR;
307 long double lowSampleL;
308 long double lowSampleR;
309 long double midSampleL;
310 long double midSampleR;
311 long double highSampleL;
312 long double highSampleR;
313
314
315 inputSampleL *= drive;
316 inputSampleR *= drive;
317
318 if (fpFlip)
319 {
320 iirSampleAL = (iirSampleAL * (1 - iirAmountL)) + (inputSampleL * iirAmountL);
321 iirSampleBL = (iirSampleBL * (1 - iirAmountL)) + (iirSampleAL * iirAmountL);
322 lowSampleL = iirSampleBL;
323
324 iirSampleAR = (iirSampleAR * (1 - iirAmountL)) + (inputSampleR * iirAmountL);
325 iirSampleBR = (iirSampleBR * (1 - iirAmountL)) + (iirSampleAR * iirAmountL);
326 lowSampleR = iirSampleBR;
327
328 iirSampleEL = (iirSampleEL * (1 - iirAmountH)) + (inputSampleL * iirAmountH);
329 iirSampleFL = (iirSampleFL * (1 - iirAmountH)) + (iirSampleEL * iirAmountH);
330 midSampleL = iirSampleFL - iirSampleBL;
331
332 iirSampleER = (iirSampleER * (1 - iirAmountH)) + (inputSampleR * iirAmountH);
333 iirSampleFR = (iirSampleFR * (1 - iirAmountH)) + (iirSampleER * iirAmountH);
334 midSampleR = iirSampleFR - iirSampleBR;
335
336 highSampleL = inputSampleL - iirSampleFL;
337 highSampleR = inputSampleR - iirSampleFR;
338 }
339 else
340 {
341 iirSampleCL = (iirSampleCL * (1 - iirAmountL)) + (inputSampleL * iirAmountL);
342 iirSampleDL = (iirSampleDL * (1 - iirAmountL)) + (iirSampleCL * iirAmountL);
343 lowSampleL = iirSampleDL;
344
345 iirSampleCR = (iirSampleCR * (1 - iirAmountL)) + (inputSampleR * iirAmountL);
346 iirSampleDR = (iirSampleDR * (1 - iirAmountL)) + (iirSampleCR * iirAmountL);
347 lowSampleR = iirSampleDR;
348
349 iirSampleGL = (iirSampleGL * (1 - iirAmountH)) + (inputSampleL * iirAmountH);
350 iirSampleHL = (iirSampleHL * (1 - iirAmountH)) + (iirSampleGL * iirAmountH);
351 midSampleL = iirSampleHL - iirSampleDL;
352
353 iirSampleGR = (iirSampleGR * (1 - iirAmountH)) + (inputSampleR * iirAmountH);
354 iirSampleHR = (iirSampleHR * (1 - iirAmountH)) + (iirSampleGR * iirAmountH);
355 midSampleR = iirSampleHR - iirSampleDR;
356
357 highSampleL = inputSampleL - iirSampleHL;
358 highSampleR = inputSampleR - iirSampleHR;
359 }
360 fpFlip = !fpFlip;
361
362 //generate the tone bands we're using
363 if (lowSampleL > 1.0) {lowSampleL = 1.0;}
364 if (lowSampleL < -1.0) {lowSampleL = -1.0;}
365 if (lowSampleR > 1.0) {lowSampleR = 1.0;}
366 if (lowSampleR < -1.0) {lowSampleR = -1.0;}
367 lowSampleL -= (lowSampleL * (fabs(lowSampleL) * 0.448) * (fabs(lowSampleL) * 0.448) );
368 lowSampleR -= (lowSampleR * (fabs(lowSampleR) * 0.448) * (fabs(lowSampleR) * 0.448) );
369 lowSampleL *= drive;
370 lowSampleR *= drive;
371
372 if (highSampleL > 1.0) {highSampleL = 1.0;}
373 if (highSampleL < -1.0) {highSampleL = -1.0;}
374 if (highSampleR > 1.0) {highSampleR = 1.0;}
375 if (highSampleR < -1.0) {highSampleR = -1.0;}
376 highSampleL -= (highSampleL * (fabs(highSampleL) * 0.599) * (fabs(highSampleL) * 0.599) );
377 highSampleR -= (highSampleR * (fabs(highSampleR) * 0.599) * (fabs(highSampleR) * 0.599) );
378 highSampleL *= drive;
379 highSampleR *= drive;
380
381 midSampleL = midSampleL * drive;
382 midSampleR = midSampleR * drive;
383
384 long double skew = (midSampleL - lastSampleL);
385 lastSampleL = midSampleL;
386 //skew will be direction/angle
387 long double bridgerectifier = fabs(skew);
388 if (bridgerectifier > 3.1415926) bridgerectifier = 3.1415926;
389 //for skew we want it to go to zero effect again, so we use full range of the sine
390 bridgerectifier = sin(bridgerectifier);
391 if (skew > 0) skew = bridgerectifier*3.1415926;
392 else skew = -bridgerectifier*3.1415926;
393 //skew is now sined and clamped and then re-amplified again
394 skew *= midSampleL;
395 //cools off sparkliness and crossover distortion
396 skew *= 1.557079633;
397 //crank up the gain on this so we can make it sing
398 bridgerectifier = fabs(midSampleL);
399 bridgerectifier += skew;
400 if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
401 bridgerectifier = sin(bridgerectifier);
402 bridgerectifier *= drive;
403 bridgerectifier += skew;
404 if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
405 bridgerectifier = sin(bridgerectifier);
406 if (midSampleL > 0)
407 {
408 midSampleL = bridgerectifier;
409 }
410 else
411 {
412 midSampleL = -bridgerectifier;
413 }
414 //blend according to positive and negative controls, left
415
416 skew = (midSampleR - lastSampleR);
417 lastSampleR = midSampleR;
418 //skew will be direction/angle
419 bridgerectifier = fabs(skew);
420 if (bridgerectifier > 3.1415926) bridgerectifier = 3.1415926;
421 //for skew we want it to go to zero effect again, so we use full range of the sine
422 bridgerectifier = sin(bridgerectifier);
423 if (skew > 0) skew = bridgerectifier*3.1415926;
424 else skew = -bridgerectifier*3.1415926;
425 //skew is now sined and clamped and then re-amplified again
426 skew *= midSampleR;
427 //cools off sparkliness and crossover distortion
428 skew *= 1.557079633;
429 //crank up the gain on this so we can make it sing
430 bridgerectifier = fabs(midSampleR);
431 bridgerectifier += skew;
432 if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
433 bridgerectifier = sin(bridgerectifier);
434 bridgerectifier *= drive;
435 bridgerectifier += skew;
436 if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
437 bridgerectifier = sin(bridgerectifier);
438 if (midSampleR > 0)
439 {
440 midSampleR = bridgerectifier;
441 }
442 else
443 {
444 midSampleR = -bridgerectifier;
445 }
446 //blend according to positive and negative controls, right
447
448 inputSampleL = ((lowSampleL + midSampleL + highSampleL)/drive)*out;
449 inputSampleR = ((lowSampleR + midSampleR + highSampleR)/drive)*out;
450
451 if (wet !=1.0) {
452 inputSampleL = (inputSampleL * wet) + (drySampleL * dry);
453 inputSampleR = (inputSampleR * wet) + (drySampleR * dry);
454 }
455
456 //stereo 64 bit dither, made small and tidy.
457 int expon; frexp((double)inputSampleL, &expon);
458 long double dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
459 dither /= 536870912.0; //needs this to scale to 64 bit zone
460 inputSampleL += (dither-fpNShapeL); fpNShapeL = dither;
461 frexp((double)inputSampleR, &expon);
462 dither = (rand()/(RAND_MAX*7.737125245533627e+25))*pow(2,expon+62);
463 dither /= 536870912.0; //needs this to scale to 64 bit zone
464 inputSampleR += (dither-fpNShapeR); fpNShapeR = dither;
465 //end 64 bit dither
466
467 *out1 = inputSampleL;
468 *out2 = inputSampleR;
469
470 in1++;
471 in2++;
472 out1++;
473 out2++;
474 }
475 }
476
477 } // end namespace DrumSlam
478
479