1 #include "DistortionEffect.h"
2 #include <vt_dsp/halfratefilter.h>
3 #include "QuadFilterUnit.h"
4
5 // feedback can get tricky with packed SSE
6
7 const int dist_OS_bits = 2;
8 const int distortion_OS = 1 << dist_OS_bits;
9
DistortionEffect(SurgeStorage * storage,FxStorage * fxdata,pdata * pd)10 DistortionEffect::DistortionEffect(SurgeStorage *storage, FxStorage *fxdata, pdata *pd)
11 : Effect(storage, fxdata, pd), band1(storage), band2(storage), lp1(storage), lp2(storage),
12 hr_a(3, false), hr_b(3, true)
13 {
14 lp1.setBlockSize(BLOCK_SIZE * distortion_OS);
15 lp2.setBlockSize(BLOCK_SIZE * distortion_OS);
16 drive.set_blocksize(BLOCK_SIZE);
17 outgain.set_blocksize(BLOCK_SIZE);
18 }
19
~DistortionEffect()20 DistortionEffect::~DistortionEffect() {}
21
init()22 void DistortionEffect::init()
23 {
24 setvars(true);
25 band1.suspend();
26 band2.suspend();
27 lp1.suspend();
28 lp2.suspend();
29 bi = 0.f;
30 L = 0.f;
31 R = 0.f;
32 }
33
setvars(bool init)34 void DistortionEffect::setvars(bool init)
35 {
36
37 if (init)
38 {
39 float pregain = fxdata->p[dist_preeq_gain].get_extended(fxdata->p[dist_preeq_gain].val.f);
40 float postgain =
41 fxdata->p[dist_posteq_gain].get_extended(fxdata->p[dist_posteq_gain].val.f);
42 band1.coeff_peakEQ(band1.calc_omega(fxdata->p[dist_preeq_freq].val.f / 12.f),
43 fxdata->p[dist_preeq_bw].val.f, pregain);
44 band2.coeff_peakEQ(band2.calc_omega(fxdata->p[dist_posteq_freq].val.f / 12.f),
45 fxdata->p[dist_posteq_bw].val.f, postgain);
46 drive.set_target(0.f);
47 outgain.set_target(0.f);
48 }
49 else
50 {
51 float pregain = fxdata->p[dist_preeq_gain].get_extended(*f[dist_preeq_gain]);
52 float postgain = fxdata->p[dist_posteq_gain].get_extended(*f[dist_posteq_gain]);
53 band1.coeff_peakEQ(band1.calc_omega(*f[dist_preeq_freq] / 12.f), *f[dist_preeq_bw],
54 pregain);
55 band2.coeff_peakEQ(band2.calc_omega(*f[dist_posteq_freq] / 12.f), *f[dist_posteq_bw],
56 postgain);
57 lp1.coeff_LP2B(lp1.calc_omega((*f[dist_preeq_highcut] / 12.0) - 2.f), 0.707);
58 lp2.coeff_LP2B(lp2.calc_omega((*f[dist_posteq_highcut] / 12.0) - 2.f), 0.707);
59 lp1.coeff_instantize();
60 lp2.coeff_instantize();
61 }
62 }
63
process(float * dataL,float * dataR)64 void DistortionEffect::process(float *dataL, float *dataR)
65 {
66 // TODO fix denormals!
67 if (bi == 0)
68 setvars(false);
69 bi = (bi + 1) & slowrate_m1;
70
71 band1.process_block(dataL, dataR);
72 auto dS = drive.get_target();
73 auto dE = db_to_linear(fxdata->p[dist_drive].get_extended(*f[dist_drive]));
74 drive.set_target_smoothed(dE);
75 outgain.set_target_smoothed(db_to_linear(*f[dist_gain]));
76 float fb = *f[dist_feedback];
77 int ws = *pdata_ival[dist_model];
78 if (ws < 0 || ws >= n_ws_types)
79 ws = 0;
80
81 float bL alignas(16)[BLOCK_SIZE << dist_OS_bits];
82 float bR alignas(16)[BLOCK_SIZE << dist_OS_bits];
83 assert(dist_OS_bits == 2);
84
85 drive.multiply_2_blocks(dataL, dataR, BLOCK_SIZE_QUAD);
86
87 bool useSSEShaper = (ws + wst_soft == wst_digital || ws + wst_soft == wst_sine);
88
89 auto wsop = GetQFPtrWaveshaper(wst_soft + ws);
90
91 float dD = 0.f;
92 float dNow = dS;
93 if (useSSEShaper)
94 {
95 dD = (dE - dS) / (BLOCK_SIZE * dist_OS_bits);
96 }
97
98 for (int k = 0; k < BLOCK_SIZE; k++)
99 {
100 float a = (k & 16) ? 0.00000001 : -0.00000001; // denormal thingy
101 float Lin = dataL[k];
102 float Rin = dataR[k];
103 for (int s = 0; s < distortion_OS; s++)
104 {
105 L = Lin + fb * L;
106 R = Rin + fb * R;
107
108 if (!fxdata->p[dist_preeq_highcut].deactivated)
109 {
110 lp1.process_sample_nolag(L, R);
111 }
112
113 if (useSSEShaper)
114 {
115 float sb[4];
116 auto dInv = 1.f / dNow;
117
118 sb[0] = L * dInv;
119 sb[1] = R * dInv;
120 auto lr128 = _mm_load_ps(sb);
121 auto wsres = wsop(lr128, _mm_set1_ps(dNow));
122 _mm_store_ps(sb, wsres);
123 L = sb[0];
124 R = sb[1];
125
126 dNow += dD;
127 }
128 else
129 {
130 L = lookup_waveshape(wst_soft + ws, L);
131 R = lookup_waveshape(wst_soft + ws, R);
132 }
133
134 L += a;
135 R += a; // denormal
136
137 if (!fxdata->p[dist_posteq_highcut].deactivated)
138 {
139 lp2.process_sample_nolag(L, R);
140 }
141
142 bL[s + (k << dist_OS_bits)] = L;
143 bR[s + (k << dist_OS_bits)] = R;
144 }
145 }
146
147 hr_a.process_block_D2(bL, bR, 128);
148 hr_b.process_block_D2(bL, bR, 64);
149
150 outgain.multiply_2_blocks_to(bL, bR, dataL, dataR, BLOCK_SIZE_QUAD);
151
152 band2.process_block(dataL, dataR);
153 }
154
suspend()155 void DistortionEffect::suspend() { init(); }
156
group_label(int id)157 const char *DistortionEffect::group_label(int id)
158 {
159 switch (id)
160 {
161 case 0:
162 return "Pre-EQ";
163 case 1:
164 return "Distortion";
165 case 2:
166 return "Post-EQ";
167 case 3:
168 return "Output";
169 }
170 return 0;
171 }
group_label_ypos(int id)172 int DistortionEffect::group_label_ypos(int id)
173 {
174 switch (id)
175 {
176 case 0:
177 return 1;
178 case 1:
179 return 11;
180 case 2:
181 return 19;
182 case 3:
183 return 29;
184 }
185 return 0;
186 }
187
init_ctrltypes()188 void DistortionEffect::init_ctrltypes()
189 {
190 Effect::init_ctrltypes();
191
192 fxdata->p[dist_preeq_gain].set_name("Gain");
193 fxdata->p[dist_preeq_gain].set_type(ct_decibel_extendable);
194 fxdata->p[dist_preeq_freq].set_name("Frequency");
195 fxdata->p[dist_preeq_freq].set_type(ct_freq_audible);
196 fxdata->p[dist_preeq_bw].set_name("Bandwidth");
197 fxdata->p[dist_preeq_bw].set_type(ct_bandwidth);
198 fxdata->p[dist_preeq_highcut].set_name("High Cut");
199 fxdata->p[dist_preeq_highcut].set_type(ct_freq_audible_deactivatable);
200
201 fxdata->p[dist_drive].set_name("Drive");
202 fxdata->p[dist_drive].set_type(ct_decibel_narrow_extendable);
203 fxdata->p[dist_feedback].set_name("Feedback");
204 fxdata->p[dist_feedback].set_type(ct_percent_bipolar);
205 fxdata->p[dist_model].set_name("Model");
206 fxdata->p[dist_model].set_type(ct_distortion_waveshape);
207
208 fxdata->p[dist_posteq_gain].set_name("Gain");
209 fxdata->p[dist_posteq_gain].set_type(ct_decibel_extendable);
210 fxdata->p[dist_posteq_freq].set_name("Frequency");
211 fxdata->p[dist_posteq_freq].set_type(ct_freq_audible);
212 fxdata->p[dist_posteq_bw].set_name("Bandwidth");
213 fxdata->p[dist_posteq_bw].set_type(ct_bandwidth);
214 fxdata->p[dist_posteq_highcut].set_name("High Cut");
215 fxdata->p[dist_posteq_highcut].set_type(ct_freq_audible_deactivatable);
216
217 fxdata->p[dist_gain].set_name("Gain");
218 fxdata->p[dist_gain].set_type(ct_decibel_narrow);
219
220 fxdata->p[dist_preeq_gain].posy_offset = 1;
221 fxdata->p[dist_preeq_freq].posy_offset = 1;
222 fxdata->p[dist_preeq_bw].posy_offset = 1;
223 fxdata->p[dist_preeq_highcut].posy_offset = 1;
224
225 fxdata->p[dist_drive].posy_offset = 5;
226 fxdata->p[dist_feedback].posy_offset = 5;
227 fxdata->p[dist_model].posy_offset = -11;
228
229 fxdata->p[dist_posteq_gain].posy_offset = 7;
230 fxdata->p[dist_posteq_freq].posy_offset = 7;
231 fxdata->p[dist_posteq_bw].posy_offset = 7;
232 fxdata->p[dist_posteq_highcut].posy_offset = 7;
233
234 fxdata->p[dist_gain].posy_offset = 9;
235 }
init_default_values()236 void DistortionEffect::init_default_values()
237 {
238 fxdata->p[dist_preeq_gain].val.f = 0.f;
239 fxdata->p[dist_preeq_freq].val.f = 0.f;
240 fxdata->p[dist_preeq_bw].val.f = 2.f;
241 fxdata->p[dist_preeq_highcut].deactivated = false;
242
243 fxdata->p[dist_model].val.f = 0.f;
244
245 fxdata->p[dist_posteq_gain].val.f = 0.f;
246 fxdata->p[dist_posteq_freq].val.f = 0.f;
247 fxdata->p[dist_posteq_bw].val.f = 2.f;
248 fxdata->p[dist_posteq_highcut].deactivated = false;
249
250 fxdata->p[dist_gain].val.f = 0.f;
251 }
252
handleStreamingMismatches(int streamingRevision,int currentSynthStreamingRevision)253 void DistortionEffect::handleStreamingMismatches(int streamingRevision,
254 int currentSynthStreamingRevision)
255 {
256 if (streamingRevision <= 11)
257 {
258 fxdata->p[dist_model].val.i = 0;
259 fxdata->p[dist_preeq_gain].extend_range = false;
260 fxdata->p[dist_posteq_gain].extend_range = false;
261 }
262
263 if (streamingRevision <= 15)
264 {
265 fxdata->p[dist_preeq_highcut].deactivated = false;
266 fxdata->p[dist_posteq_highcut].deactivated = false;
267 }
268 }
269