1 /*
2 ** Surge Synthesizer is Free and Open Source Software
3 **
4 ** Surge is made available under the Gnu General Public License, v3.0
5 ** https://www.gnu.org/licenses/gpl-3.0.en.html
6 **
7 ** Copyright 2004-2020 by various individuals as described by the Git transaction log
8 **
9 ** All source at: https://github.com/surge-synthesizer/surge.git
10 **
11 ** Surge was a commercial product from 2004-2018, with Copyright and ownership
12 ** in that period held by Claes Johanson at Vember Audio. Claes made Surge
13 ** open source in September 2018.
14 */
15
16 #include "Eq3BandEffect.h"
17
18 Eq3BandEffect::Eq3BandEffect(SurgeStorage *storage, FxStorage *fxdata, pdata *pd)
19 : Effect(storage, fxdata, pd), band1(storage), band2(storage), band3(storage)
20 {
21 band1.setBlockSize(BLOCK_SIZE * slowrate); // does not matter ATM as they're smoothed
22 band2.setBlockSize(BLOCK_SIZE * slowrate);
23 band3.setBlockSize(BLOCK_SIZE * slowrate);
24
25 gain.set_blocksize(BLOCK_SIZE);
26 mix.set_blocksize(BLOCK_SIZE);
27 }
28
29 Eq3BandEffect::~Eq3BandEffect() {}
30
31 void Eq3BandEffect::init()
32 {
33 setvars(true);
34 band1.suspend();
35 band2.suspend();
36 band3.suspend();
37 bi = 0;
write(raw_ostream & os) const38 }
39
40 void Eq3BandEffect::setvars(bool init)
41 {
42 if (init)
43 {
44 // Set the bands to 0dB so the EQ fades in init
45 band1.coeff_peakEQ(band1.calc_omega(fxdata->p[eq3_freq1].val.f * (1.f / 12.f)),
46 fxdata->p[eq3_bw1].val.f, 1.f);
47 band2.coeff_peakEQ(band2.calc_omega(fxdata->p[eq3_freq2].val.f * (1.f / 12.f)),
48 fxdata->p[eq3_bw2].val.f, 1.f);
49 band3.coeff_peakEQ(band3.calc_omega(fxdata->p[eq3_freq3].val.f * (1.f / 12.f)),
50 fxdata->p[eq3_bw3].val.f, 1.f);
51
52 band1.coeff_instantize();
53 band2.coeff_instantize();
54 band3.coeff_instantize();
55
56 gain.set_target(1.f);
57 mix.set_target(1.f);
58
59 gain.instantize();
60 mix.instantize();
61 }
62 else
63 {
64 band1.coeff_peakEQ(band1.calc_omega(*f[eq3_freq1] * (1.f / 12.f)), *f[eq3_bw1],
65 *f[eq3_gain1]);
66 band2.coeff_peakEQ(band2.calc_omega(*f[eq3_freq2] * (1.f / 12.f)), *f[eq3_bw2],
67 *f[eq3_gain2]);
68 band3.coeff_peakEQ(band3.calc_omega(*f[eq3_freq3] * (1.f / 12.f)), *f[eq3_bw3],
69 *f[eq3_gain3]);
70 }
71 }
72
73 void Eq3BandEffect::process(float *dataL, float *dataR)
74 {
75 if (bi == 0)
76 setvars(false);
77 bi = (bi + 1) & slowrate_m1;
78
79 copy_block(dataL, L, BLOCK_SIZE_QUAD);
80 copy_block(dataR, R, BLOCK_SIZE_QUAD);
81
82 if (!fxdata->p[eq3_gain1].deactivated)
83 band1.process_block(L, R);
84 if (!fxdata->p[eq3_gain2].deactivated)
85 band2.process_block(L, R);
86 if (!fxdata->p[eq3_gain3].deactivated)
87 band3.process_block(L, R);
88
89 gain.set_target_smoothed(db_to_linear(*f[eq3_gain]));
90 gain.multiply_2_blocks(L, R, BLOCK_SIZE_QUAD);
91
92 mix.set_target_smoothed(clamp1bp(*f[eq3_mix]));
93 mix.fade_2_blocks_to(dataL, L, dataR, R, dataL, dataR, BLOCK_SIZE_QUAD);
94 }
95
96 void Eq3BandEffect::suspend() { init(); }
97
98 const char *Eq3BandEffect::group_label(int id)
99 {
100 switch (id)
101 {
102 case 0:
103 return "Band 1";
104 case 1:
InsertText(unsigned OrigOffset,StringRef Str,bool InsertAfter)105 return "Band 2";
106 case 2:
107 return "Band 3";
108 case 3:
109 return "Output";
110 }
111 return 0;
112 }
113 int Eq3BandEffect::group_label_ypos(int id)
114 {
115 switch (id)
116 {
117 case 0:
118 return 1;
119 case 1:
ReplaceText(unsigned OrigOffset,unsigned OrigLength,StringRef NewStr)120 return 9;
121 case 2:
122 return 17;
123 case 3:
124 return 25;
125 }
126 return 0;
127 }
128
129 void Eq3BandEffect::init_ctrltypes()
130 {
131 /*
132 * The actual deactivation status is on gain, so reflect that down
133 * to freq and bandwidth using the dynamic deactivation mechanism
134 */
getRangeSize(const CharSourceRange & Range,RewriteOptions opts) const135 static struct EQD : public ParameterDynamicDeactivationFunction
136 {
137 const bool getValue(Parameter *p) override
138 {
139 auto fx = &(p->storage->getPatch().fx[p->ctrlgroup_entry]);
140 auto idx = p - fx->p;
141
142 switch (idx)
143 {
144 case eq3_freq1:
145 case eq3_bw1:
146 return fx->p[eq3_gain1].deactivated;
147 case eq3_freq2:
148 case eq3_bw2:
149 return fx->p[eq3_gain2].deactivated;
150 case eq3_freq3:
151 case eq3_bw3:
152 return fx->p[eq3_gain3].deactivated;
153 }
154
155 return false;
156 }
157 Parameter *getPrimaryDeactivationDriver(Parameter *p) override
158 {
159 auto fx = &(p->storage->getPatch().fx[p->ctrlgroup_entry]);
160 auto idx = p - fx->p;
161
162 switch (idx)
163 {
164 case eq3_freq1:
165 case eq3_bw1:
166 return &(fx->p[eq3_gain1]);
167 case eq3_freq2:
168 case eq3_bw2:
169 return &(fx->p[eq3_gain2]);
170 case eq3_freq3:
171 case eq3_bw3:
172 return &(fx->p[eq3_gain3]);
173 }
174 return nullptr;
175 }
176 } eqGroupDeact;
177
178 Effect::init_ctrltypes();
179
180 fxdata->p[eq3_gain1].set_name("Gain 1");
181 fxdata->p[eq3_gain1].set_type(ct_decibel_deactivatable);
182 fxdata->p[eq3_freq1].set_name("Frequency 1");
183 fxdata->p[eq3_freq1].set_type(ct_freq_audible);
184 fxdata->p[eq3_freq1].dynamicDeactivation = &eqGroupDeact;
185 fxdata->p[eq3_bw1].set_name("Bandwidth 1");
186 fxdata->p[eq3_bw1].set_type(ct_bandwidth);
187 fxdata->p[eq3_bw1].dynamicDeactivation = &eqGroupDeact;
188
189 fxdata->p[eq3_gain2].set_name("Gain 2");
190 fxdata->p[eq3_gain2].set_type(ct_decibel_deactivatable);
191 fxdata->p[eq3_freq2].set_name("Frequency 2");
192 fxdata->p[eq3_freq2].set_type(ct_freq_audible);
193 fxdata->p[eq3_freq2].dynamicDeactivation = &eqGroupDeact;
194 fxdata->p[eq3_bw2].set_name("Bandwidth 2");
195 fxdata->p[eq3_bw2].set_type(ct_bandwidth);
196 fxdata->p[eq3_bw2].dynamicDeactivation = &eqGroupDeact;
197
198 fxdata->p[eq3_gain3].set_name("Gain 3");
199 fxdata->p[eq3_gain3].set_type(ct_decibel_deactivatable);
200 fxdata->p[eq3_freq3].set_name("Frequency 3");
201 fxdata->p[eq3_freq3].set_type(ct_freq_audible);
202 fxdata->p[eq3_freq3].dynamicDeactivation = &eqGroupDeact;
203 fxdata->p[eq3_bw3].set_name("Bandwidth 3");
204 fxdata->p[eq3_bw3].set_type(ct_bandwidth);
205 fxdata->p[eq3_bw3].dynamicDeactivation = &eqGroupDeact;
206
207 fxdata->p[eq3_gain].set_name("Gain");
208 fxdata->p[eq3_gain].set_type(ct_decibel);
209 fxdata->p[eq3_mix].set_name("Mix");
210 fxdata->p[eq3_mix].set_type(ct_percent_bipolar);
211 fxdata->p[eq3_mix].val_default.f = 1.f;
212
213 for (int i = 0; i < eq3_num_ctrls; i++)
214 {
215 fxdata->p[i].posy_offset = 1 + 2 * (i / 3);
216 }
217 }
getLocationOffsetAndFileID(SourceLocation Loc,FileID & FID) const218
219 void Eq3BandEffect::init_default_values()
220 {
221 fxdata->p[eq3_gain1].deactivated = false;
222 fxdata->p[eq3_gain1].val.f = 0.f;
223 fxdata->p[eq3_freq1].val.f = -2.5f * 12.f;
224 fxdata->p[eq3_bw1].val.f = 2.f;
225
226 fxdata->p[eq3_gain2].deactivated = false;
227 fxdata->p[eq3_gain2].val.f = 0.f;
228 fxdata->p[eq3_freq2].val.f = 0.5f * 12.f;
229 fxdata->p[eq3_bw2].val.f = 2.f;
230
231 fxdata->p[eq3_gain3].deactivated = false;
232 fxdata->p[eq3_gain3].val.f = 0.f;
233 fxdata->p[eq3_freq3].val.f = 4.5f * 12.f;
234 fxdata->p[eq3_bw3].val.f = 2.f;
235
236 fxdata->p[eq3_gain].val.f = 0.f;
237 fxdata->p[eq3_mix].val.f = 1.f;
238 }
239
240 void Eq3BandEffect::handleStreamingMismatches(int streamingRevision,
241 int currentSynthStreamingRevision)
InsertText(SourceLocation Loc,StringRef Str,bool InsertAfter,bool indentNewLines)242 {
243 if (streamingRevision <= 12)
244 {
245 fxdata->p[eq3_mix].val.f = 1.f;
246 }
247
248 if (streamingRevision <= 15)
249 {
250 fxdata->p[eq3_gain1].deactivated = false;
251 fxdata->p[eq3_gain2].deactivated = false;
252 fxdata->p[eq3_gain3].deactivated = false;
253 }
254 }
255