1 /*
2 * sine_mixer.cc
3 * DIN Is Noise is copyright (c) 2006-2021 Jagannathan Sampath
4 * DIN Is Noise is released under GNU Public License 2.0
5 * For more information, please visit https://dinisnoise.org/
6 */
7
8 #include "dingl.h"
9 #include "input.h"
10 #include "viewwin.h"
11 #include "sine_mixer.h"
12 #include "ui_list.h"
13 #include "viewwin.h"
14 #include "vector2d.h"
15 #include "circler.h"
16 #include "log.h"
17 #include "console.h"
18 #include "container.h"
19 #include <math.h>
20 using namespace std;
21
22 extern const float PI;
23 extern const float TWO_PI;
24 extern curve_library sin_lib;
25 extern int line_height;
26 extern const char SPC;
27
sine_mixer()28 sine_mixer::sine_mixer () : cp_sin ("sine_mixer_sin.crv"), sin_ed ("sine_mixer_sin.ed"), harms ("harmonics"), phase ("phases") {
29 plugin::name = "Sine_Mixer";
30 shapeform = 0;
31 type = 0;
32 sin_ed.add (&cp_sin.crv, this);
33 sin_ed.attach_library (&sin_lib);
34 harms.paintl = this;
35 harms.chgl = this;
36 harms.shftl = this;
37 harms.szr.movlis = &szm;
38 phase.paintl = this;
39 phase.chgl = this;
40 phase.shftl = this;
41 phase.szr.movlis = &szm;
42 szm.data = this;
43
44 static const float fac = 0.6;
45 phase.set_color (1.0f - fac * harms.clr.r, 1.0f - fac * harms.clr.g, 1.0f - fac * harms.clr.b);
46 paintphase = 0;
47 }
48
load_params()49 void sine_mixer::load_params () {
50 ifstream f (make_fname().c_str(), ios::in);
51 string ignore;
52 f >> ignore >> num_points >> ignore >> make_shapeform >> ignore >> type >> ignore >> auto_apply;
53 NUM_SINE_SAMPLES = num_points + 1;
54 }
55
save_params()56 void sine_mixer::save_params () {
57 ofstream f (make_fname().c_str(), ios::out);
58 string ignore;
59 f << "num_points " << int (sp_points.f_value) << " make_shapeform " << cb_make_shapeform.state << " type " << type \
60 << " auto_apply " << cb_auto_apply.state << endl;
61 }
62
~sine_mixer()63 sine_mixer::~sine_mixer () {
64 save_params ();
65 widget_save ("d_sine_mixer", ctrls);
66 dlog << "--- destroyed sine mixer ---" << endl;
67 }
68
num_harmonics(int h)69 void sine_mixer::num_harmonics (int h) {
70 nharmonics = h;
71 if (nharmonics < 1) nharmonics = 1;
72 prep_harmonics ();
73 }
74
prep_harmonics()75 void sine_mixer::prep_harmonics () {
76 harmonics.resize (nharmonics);
77 float df = TWO_PI / (NUM_SINE_SAMPLES - 1);
78 funktion& f_sin = *pf_sin;
79 for (int i = 0, j = 1; i < nharmonics; ++i, ++j) {
80 vector< point<float> >& harmonic = harmonics[i];
81 harmonic.resize (NUM_SINE_SAMPLES);
82 float dx = j * df;
83 float x = phase.values[i] * TWO_PI;
84 for (int p = 0; p < NUM_SINE_SAMPLES; ++p) {
85 point<float>& hp = harmonic[p];
86 hp.x = cos(x);
87 hp.y = f_sin (x, TWO_PI);
88 x += dx;
89 if (x > TWO_PI) x -= TWO_PI;
90 }
91 }
92 norm.resize (NUM_SINE_SAMPLES);
93 mix ();
94 }
95
mix()96 void sine_mixer::mix () {
97 for (int p = 0; p < NUM_SINE_SAMPLES; ++p) { point<float>& pi = norm[p]; pi.x = pi.y = 0;}
98 ss.str(""); ss << plugin::name;
99 for (int i = 0; i < nharmonics; ++i) {
100 float lev = harms.values[i];
101 if (lev > 0) {
102 vector< point<float> >& harmonic = harmonics[i];
103 for (int p = 0; p < NUM_SINE_SAMPLES; ++p) {
104 point<float>& np = norm[p];
105 point<float>& hp = harmonic[p];
106 np.x += (lev * hp.x);
107 np.y += (lev * hp.y);
108 }
109 ss << '_' << (i+1);
110 }
111 }
112 normalise ();
113 }
114
normalise()115 void sine_mixer::normalise () {
116 int n = NUM_SINE_SAMPLES;
117 if (n) {
118 point<float>& np0 = norm[0];
119 float maxy = fabs (np0.y), maxx = fabs (np0.x);
120 for (int i = 0; i < n; ++i) {
121 point<float>& pi = norm[i];
122 float vx = fabs (pi.x), vy = fabs (pi.y);
123 if (vx > maxx) maxx = vx;
124 if (vy > maxy) maxy = vy;
125 }
126 if (maxx != 0) for (int p = 0; p < n; ++p) norm[p].x /= maxx;
127 if (maxy != 0) for (int p = 0; p < n; ++p) norm[p].y /= maxy;
128 }
129 }
130
render()131 void sine_mixer::render () {
132
133 undo = !cb_auto_apply.state;
134 shapeform = cb_make_shapeform.state;
135
136 int ns = norm.size ();
137 points.resize (ns);
138 if (shapeform) {
139 for (int i = 0; i < ns; ++i) {
140 point<float>& ni = norm[i];
141 point<float>& pi = points[i];
142 pi.x = ni.x;
143 pi.y = ni.y;
144 }
145 } else {
146 float x = 0;
147 float dx = 1.0f / (NUM_SINE_SAMPLES - 1);
148 for (int i = 0; i < ns; ++i) {
149 point<float>& ni = norm[i];
150 point<float>& pi = points[i];
151 pi.x = x;
152 pi.y = ni.y;
153 x += dx;
154 }
155 }
156
157 gen_pts ();
158
159 }
160
setup()161 void sine_mixer::setup () {
162
163 plugin::setup ();
164
165 widget* _ctrls [] = {
166 &sp_points,
167 &cb_make_shapeform,
168 &ol_sin,
169 &b_edit,
170 &cbpaint,
171 &olpaint,
172 };
173
174 num_ctrls = 8;
175
176 ctrls.resize (num_ctrls);
177 for (int i = 0, j = 2; j < num_ctrls; ++i, ++j) ctrls[j] = _ctrls[i];
178
179 load_params ();
180
181 sp_points.set ("Points", 1, 1, MILLION, this, 0);
182 sp_points.set_value (num_points);
183
184 cb_make_shapeform.set_text ("Make shapeform");
185 cb_make_shapeform.set_state (make_shapeform);
186 cb_make_shapeform.set_listener (this);
187 cbpaint.set_text ("Paint");
188
189 levs[0] = &harms;
190 levs[1] = &phase;
191 LISTEN (cbpaint, this)
192 pail.data = this;
193 LISTEN (olpaint, &pail)
194
195 if (auto_apply) {
196 cb_auto_apply.set_state (1, 0);
197 plugin::mix = undo = 0;
198 }
199
200 ol_sin.set_listener (this);
201
202 widget_load ("d_sine_mixer", ctrls);
203
204 ctrls.push_back (&harms);
205 olpaint.set_text (" Harmonics");
206
207 num_ctrls = 9;
208
209 //for (int i = 0; i < num_ctrls; ++i) ctrls[i]->set_moveable(1);
210
211 b_edit.set_text ("Edit");
212
213 set_type ();
214 num_harmonics (harms.n);
215 render ();
216
217 }
218
set_type()219 void sine_mixer::set_type () {
220 if (type) {
221 pf_sin = &cp_sin;
222 ol_sin.option.set_text (" Custom sin");
223 b_edit.set_color (clr.r, clr.g, clr.b);
224 b_edit.set_listener (this);
225 } else {
226 pf_sin = &st_sin;
227 ol_sin.option.set_text (" Standard sin");
228 b_edit.set_color (0.25f, 0.25f, 0.25f);
229 b_edit.set_listener (0);
230 }
231 int spacer = 10; b_edit.set_pos (ol_sin.option.extents.right + spacer, ol_sin.option.extents.bottom);
232 }
233
changed(field & f)234 void sine_mixer::changed (field& f) {
235 if (&f == &sp_points.f_value) {
236 set_samples (f);
237 do_render ();
238 }
239 }
240
changed(levels & l)241 void sine_mixer::changed (levels& l) {
242 if (&l == &phase) prep_harmonics ();
243 mix ();
244 do_render ();
245 }
246
changed(checkbutton & cb)247 void sine_mixer::changed (checkbutton& cb) {
248 if (&cb == &cb_make_shapeform) {
249 render ();
250 apply_not_auto_apply ();
251 } else if (&cb == &cbpaint) {
252 levs[paintphase]->paint = cbpaint.state;
253 } else plugin::changed (cb);
254 }
255
set_samples(int s)256 void sine_mixer::set_samples (int s) {
257 NUM_SINE_SAMPLES = s + 1;
258 if (NUM_SINE_SAMPLES < MIN_SINE_SAMPLES) NUM_SINE_SAMPLES = MIN_SINE_SAMPLES;
259 prep_harmonics ();
260 }
261
apply_not_auto_apply()262 void sine_mixer::apply_not_auto_apply () {
263 if (cb_auto_apply.state) {
264 plugin::mix = undo = 1;
265 uis.crved->apply_plugin (this);
266 plugin::mix = undo = 0;
267 } else uis.crved->apply_plugin (this);
268 }
269
picked(label & lbl,int dir)270 void sine_mixer::picked (label& lbl, int dir) {
271 type = !type;
272 set_type ();
273 prep_harmonics ();
274 render ();
275 }
276
shift_apply()277 void sine_mixer::shift_apply () {
278 mix ();
279 render ();
280 apply_not_auto_apply ();
281 }
282
clicked(button & b)283 void sine_mixer::clicked (button& b) {
284 if (&b == &b_edit) uis.set_current (&sin_ed);
285 else plugin::clicked (b);
286 }
287
edited(curve_editor * e,int i)288 void sine_mixer::edited (curve_editor* e, int i) {
289 cp_sin.sol.update ();
290 curve_listener::edited (e, i);
291 prep_harmonics ();
292 render ();
293 }
294
295
moused(int dx,double scl)296 void sine_mixer::moused (int dx, double scl) {
297 if (dx > 0) harms.rshift (); else harms.lshift ();
298 shift_apply ();
299 }
300
paint(levels & l)301 void sine_mixer::paint (levels& l) {
302 cbpaint.set_state (levs[paintphase]->paint, 0);
303 }
304
shifted(levels & l)305 void sine_mixer::shifted (levels& l) {
306 if (&l == &phase) prep_harmonics ();
307 shift_apply ();
308 }
309
toggpaint(label & l)310 void sine_mixer::toggpaint (label& l) {
311 static const char* pp [] = {" Harmonics", " Phase"};
312 paintphase = !paintphase;
313 ctrls.pop_back ();
314 if (paintphase) {
315 uis.plugin__browser.l_title.swapchild (&harms, &phase);
316 ctrls.push_back (&phase);
317 phase.setpos2 (harms);
318 }
319 else {
320 uis.plugin__browser.l_title.swapchild (&phase, &harms);
321 ctrls.push_back (&harms);
322 harms.setpos2 (phase);
323 }
324
325 l.set_text (pp[paintphase]);
326
327 levels* lp = levs[paintphase];
328 olpaint.option.set_color (lp->clr.r, lp->clr.g, lp->clr.b);
329 cbpaint.set_state (lp->paint,0);
330
331 }
332
handle_input()333 int sine_mixer::handle_input () {
334 int r = plugin::handle_input ();
335 if (!_folded) {
336 if (keypressed (SDLK_g)) {
337 pressed.g = 1;
338 toggpaint (olpaint.option);
339 r |= 1;
340 }
341 }
342 return r;
343 }
344
PICKED_OPTION(sine_mixer,paintlis)345 PICKED_OPTION (sine_mixer, paintlis) {
346 sine_mixer& sm = (* (sine_mixer*) data);
347 sm.toggpaint (l);
348 }
349
MOVED(sine_mixer,szrmov)350 MOVED (sine_mixer, szrmov) {
351 sine_mixer& sm = (* (sine_mixer*) data);
352 levels* pla = sm.levs[sm.paintphase];
353 pla->moved ();
354 levels* plb = sm.levs[!sm.paintphase];
355 plb->extents = pla->extents;
356 plb->szr.setpos2 (pla->szr);
357 plb->moved ();
358 }
359