1 /*
2 rakarrack - a guitar effects software
3
4 Opticaltrem.C - Optical tremolo effect
5
6 Copyright (C) 2008-2010 Ryan Billing
7 Author: Josep Andreu
8
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of version 2 of the GNU General Public License
12 as published by the Free Software Foundation.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License (version 2) for more details.
18
19 You should have received a copy of the GNU General Public License
20 (version2) along with this program; if not, write to the Free Software
21 Foundation,
22 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
24 */
25
26 #include <math.h>
27 #include "Opticaltrem.h"
28
Opticaltrem(float * efxoutl_,float * efxoutr_,double sample_rate)29 Opticaltrem::Opticaltrem (float * efxoutl_, float * efxoutr_, double sample_rate)
30 {
31 efxoutl = efxoutl_;
32 efxoutr = efxoutr_;
33 cSAMPLE_RATE = 1.0f/sample_rate;
34
35 R1 = 2700.0f; //tremolo circuit series resistance
36 Ra = 1000000.0f; //Cds cell dark resistance.
37 Ra = logf(Ra); //this is done for clarity
38 Rb = 300.0f; //Cds cell full illumination
39 Rp = 100000.0f; //Resistor in parallel with Cds cell
40 b = exp(Ra/logf(Rb)) - CNST_E;
41 dTC = 0.03f;
42 dRCl = dTC;
43 dRCr = dTC; //Right & left channel dynamic time contsants
44 minTC = logf(0.005f/dTC);
45 alphal = 1.0f - cSAMPLE_RATE/(dRCl + cSAMPLE_RATE);
46 alphar = alphal;
47 lstep = 0.0f;
48 rstep = 0.0f;
49 Pdepth = 127;
50 Ppanning = 64;
51 lpanning = 1.0f;
52 rpanning = 1.0f;
53 fdepth = 1.0f;
54 Pinvert = 0;
55 oldgl = 0.0f;
56 oldgr = 0.0f;
57 gl = 0.0f;
58 gr = 0.0f;
59
60 lfo = new EffectLFO(sample_rate);
61 PERIOD = 256;//best guess until better info comes
62
63 }
64
~Opticaltrem()65 Opticaltrem::~Opticaltrem ()
66 {
67 delete lfo;
68 }
69
70
71 void
cleanup()72 Opticaltrem::cleanup ()
73 {
74
75
76 };
77
78 void
out(float * smpsl,float * smpsr,uint32_t period)79 Opticaltrem::out (float *smpsl, float *smpsr, uint32_t period)
80 {
81
82 unsigned int i;
83 float lfol, lfor, xl, xr, fxl, fxr;
84 float rdiff, ldiff;
85 lfo->effectlfoout (&lfol, &lfor);
86
87 if(Pinvert) {
88 lfol = lfol*fdepth;
89 lfor = lfor*fdepth;
90 } else {
91 lfor = 1.0f - lfor*fdepth;
92 lfol = 1.0f - lfol*fdepth;
93 }
94
95 if (lfol > 1.0f)
96 lfol = 1.0f;
97 else if (lfol < 0.0f)
98 lfol = 0.0f;
99 if (lfor > 1.0f)
100 lfor = 1.0f;
101 else if (lfor < 0.0f)
102 lfor = 0.0f;
103
104 lfor = powf(lfor, 1.9f);
105 lfol = powf(lfol, 1.9f); //emulate lamp turn on/off characteristic
106
107 //lfo interpolation
108 rdiff = (lfor - oldgr)/(float)period;
109 ldiff = (lfol - oldgl)/(float)period;
110 gr = lfor;
111 gl = lfol;
112 oldgr = lfor;
113 oldgl = lfol;
114
115 for (i = 0; i < period; i++) {
116 //Left Cds
117 stepl = gl*(1.0f - alphal) + alphal*oldstepl;
118 oldstepl = stepl;
119 dRCl = dTC*f_exp(stepl*minTC);
120 alphal = 1.0f - cSAMPLE_RATE/(dRCl + cSAMPLE_RATE);
121 xl = CNST_E + stepl*b;
122 fxl = f_exp(Ra/logf(xl));
123 if(Pinvert) {
124 fxl = fxl*Rp/(fxl + Rp); //Parallel resistance
125 fxl = fxl/(fxl + R1);
126 }
127 else fxl = R1/(fxl + R1);
128
129 //Right Cds
130 stepr = gr*(1.0f - alphar) + alphar*oldstepr;
131 oldstepr = stepr;
132 dRCr = dTC*f_exp(stepr*minTC);
133 alphar = 1.0f - cSAMPLE_RATE/(dRCr + cSAMPLE_RATE);
134 xr = CNST_E + stepr*b;
135 fxr = f_exp(Ra/logf(xr));
136 if(Pinvert) {
137 fxr = fxr*Rp/(fxr + Rp); //Parallel resistance
138 fxr = fxr/(fxr + R1);
139 }
140 else fxr = R1/(fxr + R1);
141
142 //Modulate input signal
143 efxoutl[i] = lpanning*fxl*smpsl[i];
144 efxoutr[i] = rpanning*fxr*smpsr[i];
145
146 gl += ldiff;
147 gr += rdiff; //linear interpolation of LFO
148
149 };
150
151
152 };
153
154 void
setpanning(int value)155 Opticaltrem::setpanning (int value)
156 {
157 Ppanning = value;
158 rpanning = ((float)Ppanning) / 64.0f;
159 lpanning = 2.0f - rpanning;
160 lpanning = 10.0f * powf(lpanning, 4);
161 rpanning = 10.0f * powf(rpanning, 4);
162 lpanning = 1.0f - 1.0f/(lpanning + 1.0f);
163 rpanning = 1.0f - 1.0f/(rpanning + 1.0f);
164
165 if(Pinvert) {
166 rpanning *= 2.0f;
167 lpanning *= 2.0f;
168 } else {
169 rpanning *= 1.3f;
170 lpanning *= 1.3f;
171 }
172
173 };
174
175 void
setpreset(int npreset)176 Opticaltrem::setpreset (int npreset)
177 {
178 const int PRESET_SIZE = 7;
179 const int NUM_PRESETS = 6;
180 int pdata[PRESET_SIZE];
181 int presets[NUM_PRESETS][PRESET_SIZE] = {
182 //Fast
183 {127, 260, 10, 0, 64, 64, 0},
184 //trem2
185 {45, 140, 10, 0, 64, 64, 0},
186 //hard pan
187 {127, 120, 10, 5, 0, 64, 0},
188 //soft pan
189 {45, 240, 10, 1, 16, 64, 0},
190 //ramp down
191 {65, 200, 0, 3, 32, 64, 0},
192 //hard ramp
193 {127, 480, 0, 3, 32, 64, 0}
194
195 };
196
197 if(npreset>NUM_PRESETS-1) {
198 Fpre->ReadPreset(44,npreset-NUM_PRESETS+1, pdata);
199 for (int n = 0; n < PRESET_SIZE; n++)
200 changepar (n, pdata[n]);
201 } else {
202 for (int n = 0; n < PRESET_SIZE; n++)
203 changepar (n, presets[npreset][n]);
204 }
205
206 };
207
208 void
changepar(int npar,int value)209 Opticaltrem::changepar (int npar, int value)
210 {
211
212 switch (npar) {
213
214 case 0:
215 Pdepth = value;
216 fdepth = 0.5f + ((float) Pdepth)/254.0f;
217 break;
218 case 1:
219 lfo->Pfreq = value;
220 lfo->updateparams (PERIOD);
221 break;
222 case 2:
223 lfo->Prandomness = value;
224 lfo->updateparams (PERIOD);
225 break;
226 case 3:
227 lfo->PLFOtype = value;
228 lfo->updateparams (PERIOD);
229 break;
230 case 4:
231 lfo->Pstereo = value;
232 lfo->updateparams (PERIOD);
233 break;
234 case 5: // pan
235 Ppanning = value;
236 setpanning(value);
237 break;
238 case 6: //Invert
239 Pinvert = value;
240 if(Pinvert) {
241 R1 = 68000.0f; //tremolo circuit series resistance
242 Ra = 500000.0f; //Cds cell dark resistance.
243 } else {
244 R1 = 2700.0f; //tremolo circuit series resistance
245 Ra = 1000000.0f; //Cds cell dark resistance.
246 }
247 setpanning(Ppanning);
248
249 Ra = logf(Ra); //this is done for clarity
250 Rb = 300.0f; //Cds cell full illumination
251 b = exp(Ra/logf(Rb)) - CNST_E;
252 break;
253 }
254
255 };
256
257 int
getpar(int npar)258 Opticaltrem::getpar (int npar)
259 {
260
261 switch (npar)
262
263 {
264 case 0:
265 return (Pdepth);
266 break;
267 case 1:
268 return (lfo->Pfreq);
269 break;
270 case 2:
271 return (lfo->Prandomness);
272 break;
273 case 3:
274 return (lfo->PLFOtype);
275 break;
276 case 4:
277 return (lfo->Pstereo);
278 break;
279 case 5:
280 return (Ppanning); //pan
281 break;
282 case 6:
283 return (Pinvert); //pan
284 break;
285
286 }
287
288 return (0);
289
290 };
291
292
293