1 /*
2 * mdaBeatBoxProcessor.cpp
3 * mda-vst3
4 *
5 * Created by Arne Scheffler on 6/14/08.
6 *
7 * mda VST Plug-ins
8 *
9 * Copyright (c) 2008 Paul Kellett
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14 *
15 */
16
17 #include "mdaBeatBoxProcessor.h"
18 #include "mdaBeatBoxController.h"
19
20 #include <cmath>
21 #include <cstdlib>
22
23 namespace Steinberg {
24 namespace Vst {
25 namespace mda {
26
27 #ifdef SMTG_MDA_VST2_COMPATIBILITY
28 //-----------------------------------------------------------------------------
29 FUID BeatBoxProcessor::uid (0x5653546D, 0x6461476D, 0x64612062, 0x65617462);
30 #else
31 //-----------------------------------------------------------------------------
32 FUID BeatBoxProcessor::uid (0x9E6A6E95, 0x9B734440, 0x97D787BE, 0xBBDDD831);
33 #endif
34
35 //-----------------------------------------------------------------------------
BeatBoxProcessor()36 BeatBoxProcessor::BeatBoxProcessor ()
37 {
38 hbuf = kbuf = sbuf = sbuf2 = nullptr;
39 hthr = hfil = sthr = kthr = kfil1 = kfil2 = mix = 0;
40 klev = hlev = slev = 0;
41 ww = wwx = sb1 = sb2 = sf1 = sf2 = sf3 = 0;
42 kww = kwwx = ksb1 = ksb2 = ksf1 = ksf2 = 0;
43 dyne = dyna = dynr = dynm = 0;
44
45 allocParameters(12);
46 setControllerClass (BeatBoxController::uid);
47 }
48
49 //-----------------------------------------------------------------------------
initialize(FUnknown * context)50 tresult PLUGIN_API BeatBoxProcessor::initialize (FUnknown* context)
51 {
52 tresult res = BaseProcessor::initialize (context);
53 if (res == kResultTrue)
54 {
55 addAudioInput (USTRING("Stereo In"), SpeakerArr::kStereo);
56 addAudioOutput (USTRING("Stereo Out"), SpeakerArr::kStereo);
57
58 params[0] = 0.30; //hat thresh
59 params[1] = 0.45; //hat rate
60 params[2] = 0.50; //hat mix
61 params[3] = 0.46; //kick thresh
62 params[4] = 0.15; //kick key
63 params[5] = 0.50; //kick mix
64 params[6] = 0.50; //snare thresh
65 params[7] = 0.70; //snare key
66 params[8] = 0.50; //snare mix
67 params[9] = 0.00; //dynamics
68 params[10] = 0.00; //record
69 params[11] = 0.00; //thru mix
70
71 recalculate ();
72 }
73 return res;
74 }
75
76 //-----------------------------------------------------------------------------
setActive(TBool state)77 tresult PLUGIN_API BeatBoxProcessor::setActive (TBool state)
78 {
79 if (state)
80 {
81 sdel = (int32)(0.12 * getSampleRate ());
82 kdel = (int32)(0.10 * getSampleRate ());
83 sf3 = 0.991f; //r
84 sfx = 0; ksfx = 0;
85 rec = 0;
86
87 hbuflen = 20000;
88 kbuflen = 20000;
89 sbuflen = 60000;
90 if (getSampleRate ()>49000) { hbuflen*=2; kbuflen*=2; sbuflen*=2; }
91
92 hbuf = new float[hbuflen];
93 sbuf = new float[sbuflen];
94 sbuf2 = new float[sbuflen];
95 kbuf = new float[kbuflen];
96 hbufpos = sbufpos = kbufpos = 0;
97
98 memset (sbuf, 0, sbuflen * sizeof (float));
99 memset (sbuf2, 0, sbuflen * sizeof (float));
100
101 int32 t;
102 float e=0.00012f, de, o, o1=0.f, o2=0.f, p=0.2f, dp;
103
104 memset (hbuf, 0, hbuflen * sizeof (float)); //generate hi-hat
105 de = (float)pow (10.0,-36.0/getSampleRate ());
106 for(t=0;t<5000;t++)
107 {
108 o = (float)((rand() % 2000) - 1000);
109 *(hbuf + t) = e * ( 2.f * o1 - o2 - o);
110 e *= de; o2=o1; o1=o;
111 }
112
113 memset (kbuf, 0, kbuflen * sizeof (float)); //generate kick
114 de = (float)pow (10.0,-3.8/getSampleRate ());
115 e=0.5f; dp = 1588.f / getSampleRate ();
116 for(t=0;t<14000;t++)
117 {
118 *(kbuf + t) = e * (float)sin(p);
119 e *= de; p = (float)fmod(p + dp * e ,6.2831853f);
120 }
121
122 memset (sbuf, 0, sbuflen * sizeof (float)); //generate snare
123 de = (float)pow (10.0,-15.0/getSampleRate ());
124 e=0.38f; dp = 1103.f / getSampleRate ();
125 for(t=0;t<7000;t++)
126 {
127 o = (0.3f * o) + (float)((rand() % 2000) - 1000);
128 *(sbuf + t) = (float)(e * (sin(p) + 0.0004 * o));
129 *(sbuf2 + t) = *(sbuf + t);
130 e *= de; p = (float)fmod(p + 0.025,6.2831853);
131 }
132 }
133 else
134 {
135 if (hbuf) delete [] hbuf;
136 if (kbuf) delete [] kbuf;
137 if (sbuf) delete [] sbuf;
138 if (sbuf2) delete [] sbuf2;
139 hbuf = kbuf = sbuf = sbuf2 = nullptr;
140 }
141 return BaseProcessor::setActive (state);
142 }
143
144 //-----------------------------------------------------------------------------
doProcessing(ProcessData & data)145 void BeatBoxProcessor::doProcessing (ProcessData& data)
146 {
147 int32 sampleFrames = data.numSamples;
148
149 float* in1 = data.inputs[0].channelBuffers32[0];
150 float* in2 = data.inputs[0].channelBuffers32[1];
151 float* out1 = data.outputs[0].channelBuffers32[0];
152 float* out2 = data.outputs[0].channelBuffers32[1];
153
154 float a, b, e, o, hf=hfil, ht=hthr, mx3=0.f, mx1=mix;
155 int32 hp=hbufpos, hl=hbuflen-2, hd=hdel;
156 float kt=kthr;
157 int32 kp=kbufpos, kl=kbuflen-2, kd=kdel;
158 float st=sthr, s, f1=sb1, f2=sb2, b1=sf1, b2=sf2, b3=sf3;
159 float k, kf1=ksb1, kf2=ksb2, kb1=ksf1, kb2=ksf2;
160 float hlv=hlev, klv=klev, slv=slev;
161 int32 sp=sbufpos, sl=sbuflen-2, sd=sdel;
162 float ya=dyna, yr = dynr, ye=dyne, ym=dynm, mx4;
163
164 if (sfx>0) { mx3=0.08f; slv=0.f; klv=0.f; hlv=0.f; mx1=0.f; sfx-=sampleFrames;} //key listen (snare)
165 if (ksfx>0) { mx3=0.03f; slv=0.f; klv=0.f; hlv=0.f; mx1=0.f; ksfx-=sampleFrames;
166 b1=ksf1; b2=ksf2; } //key listen (kick)
167
168 --in1;
169 --in2;
170 --out1;
171 --out2;
172
173 if (rec==0)
174 {
175 while (--sampleFrames >= 0)
176 {
177 a = *++in1;
178 b = *++in2;
179 e = a + b;
180
181 ye = (e<ye)? ye * yr : e - ya * (e - ye); //dynamics envelope
182
183 hf = e - hf; //high filter
184 if ((hp>hd) && (hf>ht)) hp=0; else { hp++; if (hp>hl)hp=hl; }
185 o = hlv * *(hbuf + hp); //hat
186
187 k = e + (kf1 * kb1) - (kf2 * kb2); //low filter
188 kf2 = b3 * ((kf1 * kb2) + (kf2 * kb1));
189 kf1 = b3 * k;
190 if ((kp>kd) && (k>kt)) kp=0; else { kp++; if (kp>kl)kp=kl; }
191 o += klv * *(kbuf + kp); //kick
192
193 s = hf + (0.3f * e) + (f1 * b1) - (f2 * b2); //mid filter
194 f2 = b3 * ((f1 * b2) + (f2 * b1));
195 f1 = b3 * s;
196
197 if ((sp>sd) && (s>st)) sp=0; else { sp++; if (sp>sl)sp=sl; }
198
199 mx4 = 1.f + ym * (ye + ye - 1.f); //dynamics
200
201 *++out1 = mx1*a + mx3*s + mx4*(o + slv * *(sbuf + sp));
202 *++out2 = mx1*a + mx3*s + mx4*(o + slv * *(sbuf2 + sp));
203
204 hf=e;
205 }
206 }
207 else //record
208 {
209 while (--sampleFrames >= 0)
210 {
211 a = *++in1;
212 b = *++in2;
213 e = 0.5f * (a + b);
214
215 if ((recpos==0) && (fabs (e) < 0.004)) e=0.f;
216 else
217 {
218 switch (rec)
219 {
220 case 1: break; //echo
221 case 2: if (recpos<hl) *(hbuf + recpos++) = e; else e=0.f; break;
222 case 3: if (recpos<kl) *(kbuf + recpos++) = e; else e=0.f; break;
223 case 4: if (recpos<sl)
224 { *(sbuf+recpos)=a; *(sbuf2+recpos)=b; recpos++; }
225 else e=0.f; break;
226 }
227 }
228 *++out1 = e;
229 *++out2 = e;
230 }
231 }
232 hfil=hf; hbufpos=hp;
233 sbufpos=sp; sb1 = f1; sb2 = f2;
234 kbufpos=kp; ksb1 = kf1; ksb2 = kf2;
235 dyne=ye;
236
237 }
238
239 //-----------------------------------------------------------------------------
recalculate()240 void BeatBoxProcessor::recalculate ()
241 {
242 //calcs here
243 hthr = (float)pow (10.f, (float)(2.f * params[0] - 2.f));
244 hdel = (int32)((0.04 + 0.20 * params[1]) * getSampleRate ());
245 sthr = (float)(40.0 * pow (10.f, (float)(2.f * params[6] - 2.f)));
246 kthr = (float)(220.0 * pow (10.f, (float)(2.f * params[3] - 2.f)));
247
248 hlev = (float)(0.0001f + params[2] * params[2] * 4.f);
249 klev = (float)(0.0001f + params[5] * params[5] * 4.f);
250 slev = (float)(0.0001f + params[8] * params[8] * 4.f);
251
252 wwx=ww;
253 ww = (float)pow (10.0,-3.0 + 2.2 * params[7]);
254 sf1 = (float)cos(3.1415927 * ww); //p
255 sf2 = (float)sin(3.1415927 * ww); //q
256 //sfx = 0; ksfx = 0;
257
258 kwwx=kww;
259 kww = (float)pow (10.0,-3.0 + 2.2 * params[4]);
260 ksf1 = (float)cos(3.1415927 * kww); //p
261 ksf2 = (float)sin(3.1415927 * kww); //q
262
263 if (wwx != ww) sfx = (int32)(2 * getSampleRate ());
264 if (kwwx != kww) ksfx = (int32)(2 * getSampleRate ());
265
266 rec = (int32)(4.9 * params[10]);
267 if ((rec!=recx) && (recpos>0)) //finish sample
268 {
269 switch (rec)
270 {
271 case 2: while (recpos<hbuflen) *(hbuf + recpos++) = 0.f; break;
272 case 3: while (recpos<kbuflen) *(kbuf + recpos++) = 0.f; break;
273 case 4: while (recpos<sbuflen)
274 {
275 *(sbuf + recpos) = 0.f;
276 *(sbuf2 + recpos) = 0.f; recpos++;
277 } break;
278 }
279 }
280 recpos=0; recx=rec;
281 mix = params[11];
282 dynm = params[9];
283 }
284
285 }}} // namespaces
286