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