new/reworked audio plugins ported from hv72 compressor/multi/reverb, glyph workaround...
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / compressormulti / comprmultigui.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2008-2019 Adam Williams <broadcast at earthling dot net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  * 
19  */
20
21 #include "asset.h"
22 #include "bchash.h"
23 #include "bcsignals.h"
24 #include "clip.h"
25 #include "comprmultigui.h"
26 #include "cursors.h"
27 #include "edl.h"
28 #include "edlsession.h"
29 #include "eqcanvas.h"
30 #include "file.h"
31 #include "language.h"
32 #include "theme.h"
33 #include "units.h"
34
35 #include <string.h>
36
37 ComprMultiWindow::ComprMultiWindow(ComprMultiEffect *plugin)
38  : PluginClientWindow(plugin, xS(650),yS(560), xS(650),yS(560), 0)
39 {
40         this->plugin = plugin;
41         char string[BCTEXTLEN];
42 // set the default directory
43         sprintf(string, "%s/compressormulti.rc", File::get_config_path());
44         defaults = new BC_Hash(string);
45         defaults->load();
46         plugin->config.current_band = defaults->get("CURRENT_BAND", plugin->config.current_band);
47         gain_frame = 0;
48         freq_frame = 0;
49 }
50
51 ComprMultiWindow::~ComprMultiWindow()
52 {
53         defaults->update("CURRENT_BAND", plugin->config.current_band);
54         defaults->save();
55         delete defaults;
56
57         delete eqcanvas;
58         delete reaction;
59         delete x_text;
60         delete y_text;
61         delete trigger;
62         delete decay;
63         delete gain_frame;
64         delete freq_frame;
65 }
66
67
68 void ComprMultiWindow::create_objects()
69 {
70         int margin = client->get_theme()->widget_border;
71         int x = margin, y = margin;
72         int control_margin = xS(150);
73         int canvas_y2 = get_h() * 2 / 3;
74         BC_Title *title;
75         BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
76         BandConfig *prev_band = 0;
77         if( plugin->config.current_band > 0 ) {
78                 prev_band = &plugin->config.bands[plugin->config.current_band - 1];
79         }
80
81         add_subwindow(title = new BC_Title(x, y, "In:"));
82         int y2 = y + title->get_h() + margin;
83         EDL *edl = plugin->get_edl();
84         add_subwindow(in = new BC_Meter(x, y2, METER_VERT,
85                 canvas_y2 - y2,
86                 edl->session->min_meter_db,
87                 edl->session->max_meter_db,
88                 edl->session->meter_format,
89                 1, // use_titles
90                 -1)); // span
91         x += in->get_w() + margin;
92
93         add_subwindow(title = new BC_Title(x, y, "Gain:"));
94         add_subwindow(gain_change = new BC_Meter(x, y2, METER_VERT,
95                 canvas_y2 - y2,
96                 MIN_GAIN_CHANGE,
97                 MAX_GAIN_CHANGE,
98                 METER_DB,
99                 1, // use_titles
100                 -1, // span
101                 0, // downmix
102                 1)); // is_gain_change
103         x += gain_change->get_w() + xS(35);
104
105         add_subwindow(title = new BC_Title(x, y, _("Current band:")));
106
107         int x1 = title->get_x() + title->get_w() + margin;
108         char string[BCTEXTLEN];
109         for( int i = 0; i < TOTAL_BANDS; i++ ) {
110                 sprintf(string, "%d", i + 1);
111                 add_subwindow(band[i] = new ComprMultiBand(this, plugin, 
112                         x1, y, i, string));
113                 x1 += band[i]->get_w() + margin;
114         }
115         y += band[0]->get_h() + 1;
116
117
118         add_subwindow(title = new BC_Title(x, y,
119                         _("Sound level (Press shift to snap to grid):")));
120         y += title->get_h() + 1;
121         add_subwindow(canvas = new ComprMultiCanvas(plugin, this,
122                 x, y, get_w() - x - control_margin - xS(10), canvas_y2 - y));
123         y += canvas->get_h() + yS(30);
124
125         add_subwindow(title = new BC_Title(margin, y, _("Bandwidth:")));
126         y += title->get_h();
127         eqcanvas = new EQCanvas(this, margin, y,
128                 canvas->get_w() + x - margin, get_h() - y - margin,
129                 plugin->config.min_db, 0.0);
130         eqcanvas->freq_divisions = 10;
131         eqcanvas->initialize();
132
133         x = get_w() - control_margin;
134         y = margin;
135         add_subwindow(title = new BC_Title(x, y, _("Attack secs:")));
136         y += title->get_h();
137         reaction = new ComprMultiReaction(plugin, this, x, y);
138         reaction->create_objects();
139         y += reaction->get_h() + margin;
140
141         add_subwindow(title = new BC_Title(x, y, _("Release secs:")));
142         y += title->get_h();
143         decay = new ComprMultiDecay(plugin, this, x, y);
144         decay->create_objects();
145         y += decay->get_h() + margin;
146
147         add_subwindow(solo = new ComprMultiSolo(plugin, x, y));
148         y += solo->get_h() + margin;
149         add_subwindow(bypass = new ComprMultiBypass(plugin, x, y));
150         y += bypass->get_h() + margin;
151         add_subwindow(title = new BC_Title(x, y, _("Output:")));
152         y += title->get_h();
153
154         y_text = new ComprMultiY(plugin, this, x, y);
155         y_text->create_objects();
156         y += y_text->get_h() + margin;
157
158         add_subwindow(title = new BC_Title(x, y, _("Input:")));
159         y += title->get_h();
160         x_text = new ComprMultiX(plugin, this, x, y);
161         x_text->create_objects();
162         y += x_text->get_h() + margin;
163
164         add_subwindow(clear = new ComprMultiClear(plugin, x, y));
165         y += clear->get_h() + margin;
166
167         add_subwindow(title = new BC_Title(x, y, _("Freq range:")));
168         y += title->get_h();
169
170 // the previous high frequency
171         int *ptr = 0;
172         if( prev_band ) {
173                 ptr = &prev_band->freq;
174         }
175
176         add_subwindow(freq1 = new ComprMultiQPot(this, 
177                 plugin, 
178                 get_w() - (margin + BC_Pot::calculate_w()) * 2, 
179                 y, 
180                 ptr));
181
182 // the current high frequency
183         ptr = &band_config->freq;
184         if( plugin->config.current_band == TOTAL_BANDS - 1 ) {
185                 ptr = 0;
186         }
187
188         add_subwindow(freq2 = new ComprMultiQPot(this, 
189                 plugin, 
190                 get_w() - margin - BC_Pot::calculate_w(), 
191                 y, 
192                 ptr));
193         y += freq1->get_h() + margin;
194
195         BC_Bar *bar;
196         add_subwindow(bar = new BC_Bar(x, y, get_w() - x - margin));
197         y += bar->get_h() + margin;
198
199         add_subwindow(title = new BC_Title(x, y, _("Trigger Type:")));
200         y += title->get_h();
201         add_subwindow(input = new ComprMultiInput(plugin, x, y));
202         input->create_objects();
203         y += input->get_h() + margin;
204         add_subwindow(title = new BC_Title(x, y, _("Trigger:")));
205         y += title->get_h();
206
207         trigger = new ComprMultiTrigger(plugin, this, x, y);
208         trigger->create_objects();
209         if( plugin->config.input != ComprMultiConfig::TRIGGER ) trigger->disable();
210         y += trigger->get_h() + margin;
211
212         add_subwindow(smooth = new ComprMultiSmooth(plugin, x, y));
213         y += smooth->get_h() + margin;
214
215         add_subwindow(title = new BC_Title(x, y, _("Steepness:")));
216         add_subwindow(q = new ComprMultiFPot(this, plugin, 
217                 get_w() - margin - BC_Pot::calculate_w(), y, 
218                 &plugin->config.q, 0, 1));
219         y += q->get_h() + margin;
220
221         add_subwindow(title = new BC_Title(x, y, _("Window size:")));
222         y += title->get_h();
223         add_subwindow(size = new ComprMultiSize(this,
224                 plugin,
225                 x,
226                 y));
227         size->create_objects();
228         size->update(plugin->config.window_size);
229         y += size->get_h() + margin;
230
231         canvas->create_objects();
232         update_eqcanvas();
233         show_window();
234 }
235
236 // called when the user selects a different band
237 void ComprMultiWindow::update()
238 {
239         BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
240
241         for( int i = 0; i < TOTAL_BANDS; i++ ) {
242                 if( plugin->config.current_band == i ) {
243                         band[i]->update(1);
244                 }
245                 else {
246                         band[i]->update(0);
247                 }
248         }
249
250         int *ptr = 0;
251         if( plugin->config.current_band > 0 ) {
252                 ptr = &plugin->config.bands[plugin->config.current_band - 1].freq;
253         }
254         else {
255                 ptr = 0;
256         }
257
258         freq1->output = ptr;
259         if( ptr ) {
260                 freq1->update(*ptr);
261                 freq1->enable();
262         }
263         else {
264                 freq1->update(0);
265                 freq1->disable();
266         }
267
268 // top band edits the penultimate band
269         if( plugin->config.current_band < TOTAL_BANDS - 1 ) {
270                 ptr = &band_config->freq;
271         }
272         else {
273                 ptr = 0;
274         }
275
276         freq2->output = ptr;
277         if( ptr ) {
278                 freq2->update(*ptr);
279                 freq2->enable();
280         }
281         else {
282                 freq2->update(0);
283                 freq2->disable();
284         }
285
286         q->update(plugin->config.q);
287         solo->update(band_config->solo);
288         bypass->update(band_config->bypass);
289         size->update(plugin->config.window_size);
290
291         if( atol(trigger->get_text()) != plugin->config.trigger ) {
292                 trigger->update((int64_t)plugin->config.trigger);
293         }
294
295         if( strcmp(input->get_text(), ComprMultiInput::value_to_text(plugin->config.input)) ) {
296                 input->set_text(ComprMultiInput::value_to_text(plugin->config.input));
297         }
298
299         if( plugin->config.input != ComprMultiConfig::TRIGGER && trigger->get_enabled() ) {
300                 trigger->disable();
301         }
302         else
303         if( plugin->config.input == ComprMultiConfig::TRIGGER && !trigger->get_enabled() ) {
304                 trigger->enable();
305         }
306
307         if( !EQUIV(atof(reaction->get_text()), band_config->attack_len) ) {
308                 reaction->update((float)band_config->attack_len);
309         }
310
311         if( !EQUIV(atof(decay->get_text()), band_config->release_len) ) {
312                 decay->update((float)band_config->release_len);
313         }
314
315         smooth->update(plugin->config.smoothing_only);
316         if( canvas->current_operation == ComprMultiCanvas::DRAG ) {
317                 x_text->update((float)band_config->levels.values[canvas->current_point].x);
318                 y_text->update((float)band_config->levels.values[canvas->current_point].y);
319         }
320
321         canvas->update();
322         update_eqcanvas();
323 }
324
325
326
327
328 void ComprMultiWindow::update_eqcanvas()
329 {
330         plugin->calculate_envelope();
331 // filter GUI frames by band & data type
332         int have_meter = 0;
333         CompressorClientFrame *frame = 0;
334 // gdb plugin->dump_frames();
335         double tracking_position = plugin->get_tracking_position();
336         int dir = plugin->get_tracking_direction() == PLAY_REVERSE ? -1 : 1;
337         while( (frame = (CompressorClientFrame*)plugin->next_gui_frame()) ) {
338                 if( dir*(frame->position - tracking_position) > 0 ) break;
339                 if( frame->band == plugin->config.current_band ) {
340 // only frames for desired band
341                         switch( frame->type ) {
342                         case FREQ_COMPRESSORFRAME: {
343                                 delete freq_frame;
344                                 freq_frame = (CompressorFreqFrame *)
345                                         plugin->get_gui_frame(0, 0);
346                                 continue; }
347                         case GAIN_COMPRESSORFRAME: {
348                                 delete gain_frame;
349                                 gain_frame = (CompressorGainFrame *)
350                                         plugin->get_gui_frame(0, 0);
351                                 have_meter = 1;
352                                 continue; }
353                         }
354                 }
355                 delete plugin->get_gui_frame(0, 0);
356         }
357         if( have_meter ) {
358                 gain_change->update(gain_frame->gain, 0);
359                 in->update(gain_frame->level, 0);
360         }
361
362 #ifndef DRAW_AFTER_BANDPASS
363         eqcanvas->update_spectrogram(freq_frame); 
364 #else
365         eqcanvas->update_spectrogram(freq_frame,
366                 plugin->config.current_band * plugin->config.window_size / 2,
367                 TOTAL_BANDS * plugin->config.window_size / 2,
368                 plugin->config.window_size);
369 #endif
370
371 // draw the active band on top of the others
372         for( int pass = 0; pass < 2; pass++ ) {
373                 for( int band = 0; band < TOTAL_BANDS; band++ ) {
374                         if( band == plugin->config.current_band && pass == 0 ||
375                                 band != plugin->config.current_band && pass == 1 ) {
376                                 continue;
377                         }
378
379                         eqcanvas->draw_envelope(plugin->band_states[band]->envelope,
380                                 plugin->PluginAClient::project_sample_rate,
381                                 plugin->config.window_size,
382                                 band == plugin->config.current_band,
383                                 0);
384                 }
385         }
386         eqcanvas->canvas->flash(1);
387 }
388
389 int ComprMultiWindow::resize_event(int w, int h)
390 {
391         return 1;
392 }
393
394
395 ComprMultiFPot::ComprMultiFPot(ComprMultiWindow *gui, ComprMultiEffect *plugin, 
396                 int x, int y, double *output, double min, double max)
397  : BC_FPot(x, y, *output, min, max)
398 {
399         this->gui = gui;
400         this->plugin = plugin;
401         this->output = output;
402         set_precision(0.01);
403 }
404
405 int ComprMultiFPot::handle_event()
406 {
407         *output = get_value();
408         plugin->send_configure_change();
409         gui->update_eqcanvas();
410         return 1;
411 }
412
413
414 ComprMultiQPot::ComprMultiQPot(ComprMultiWindow *gui, ComprMultiEffect *plugin, 
415                 int x, int y, int *output)
416  : BC_QPot(x, y, output ? *output : 0)
417 {
418         this->gui = gui;
419         this->plugin = plugin;
420         this->output = output;
421 }
422
423
424 int ComprMultiQPot::handle_event()
425 {
426         if( output ) {
427                 *output = get_value();
428                 plugin->send_configure_change();
429                 gui->update_eqcanvas();
430         }
431         return 1;
432 }
433
434
435 ComprMultiSize::ComprMultiSize(ComprMultiWindow *gui, 
436         ComprMultiEffect *plugin, int x, int y)
437  : BC_PopupMenu(x, y, xS(100), "4096", 1)
438 {
439         this->gui = gui;
440         this->plugin = plugin;
441 }
442
443 int ComprMultiSize::handle_event()
444 {
445         plugin->config.window_size = atoi(get_text());
446         plugin->send_configure_change();
447         gui->update_eqcanvas();
448         return 1;
449 }
450
451
452 void ComprMultiSize::create_objects()
453 {
454         add_item(new BC_MenuItem("2048"));
455         add_item(new BC_MenuItem("4096"));
456         add_item(new BC_MenuItem("8192"));
457         add_item(new BC_MenuItem("16384"));
458         add_item(new BC_MenuItem("32768"));
459         add_item(new BC_MenuItem("65536"));
460         add_item(new BC_MenuItem("131072"));
461         add_item(new BC_MenuItem("262144"));
462 }
463
464
465 void ComprMultiSize::update(int size)
466 {
467         char string[BCTEXTLEN];
468         sprintf(string, "%d", size);
469         set_text(string);
470 }
471
472
473 ComprMultiCanvas::ComprMultiCanvas(ComprMultiEffect *plugin, 
474                 ComprMultiWindow *window, int x, int y, int w, int h)
475  : CompressorCanvasBase(&plugin->config, plugin, window, x, y, w, h)
476 {
477 }
478
479 void ComprMultiCanvas::update_window()
480 {
481         ((ComprMultiWindow*)window)->update();
482 }
483
484
485 ComprMultiReaction::ComprMultiReaction(ComprMultiEffect *plugin, 
486         ComprMultiWindow *window, int x, int y) 
487  : BC_TumbleTextBox(window,
488         (float)plugin->config.bands[plugin->config.current_band].attack_len,
489         (float)MIN_ATTACK, (float)MAX_ATTACK, x, y, xS(100))
490 {
491         this->plugin = plugin;
492         set_increment(0.1);
493         set_precision(2);
494 }
495
496 int ComprMultiReaction::handle_event()
497 {
498         plugin->config.bands[plugin->config.current_band].attack_len = atof(get_text());
499         plugin->send_configure_change();
500         return 1;
501 }
502
503
504
505 ComprMultiDecay::ComprMultiDecay(ComprMultiEffect *plugin, 
506         ComprMultiWindow *window, int x, int y) 
507  : BC_TumbleTextBox(window,
508         (float)plugin->config.bands[plugin->config.current_band].release_len,
509         (float)MIN_DECAY, (float)MAX_DECAY, x, y, xS(100))
510 {
511         this->plugin = plugin;
512         set_increment(0.1);
513         set_precision(2);
514 }
515 int ComprMultiDecay::handle_event()
516 {
517         plugin->config.bands[plugin->config.current_band].release_len = atof(get_text());
518         plugin->send_configure_change();
519         return 1;
520 }
521
522
523 ComprMultiX::ComprMultiX(ComprMultiEffect *plugin, 
524         ComprMultiWindow *window, int x, int y) 
525  : BC_TumbleTextBox(window, (float)0.0,
526         plugin->config.min_db, plugin->config.max_db, x, y, xS(100))
527 {
528         this->plugin = plugin;
529         set_increment(0.1);
530         set_precision(2);
531 }
532 int ComprMultiX::handle_event()
533 {
534         BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
535
536         int current_point = ((ComprMultiWindow*)plugin->thread->window)->canvas->current_point;
537         if( current_point < band_config->levels.total ) {
538                 band_config->levels.values[current_point].x = atof(get_text());
539                 ((ComprMultiWindow*)plugin->thread->window)->canvas->update();
540                 plugin->send_configure_change();
541         }
542         return 1;
543 }
544
545
546 ComprMultiY::ComprMultiY(ComprMultiEffect *plugin, 
547         ComprMultiWindow *window, 
548         int x, 
549         int y) 
550  : BC_TumbleTextBox(window, (float)0.0,
551         plugin->config.min_db, plugin->config.max_db, x, y, xS(100))
552 {
553         this->plugin = plugin;
554         set_increment(0.1);
555         set_precision(2);
556 }
557 int ComprMultiY::handle_event()
558 {
559         BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
560
561         int current_point = ((ComprMultiWindow*)plugin->thread->window)->canvas->current_point;
562         if( current_point < band_config->levels.total ) {
563                 band_config->levels.values[current_point].y = atof(get_text());
564                 ((ComprMultiWindow*)plugin->thread->window)->canvas->update();
565                 plugin->send_configure_change();
566         }
567         return 1;
568 }
569
570
571 ComprMultiTrigger::ComprMultiTrigger(ComprMultiEffect *plugin, 
572         ComprMultiWindow *window,
573         int x, 
574         int y) 
575  : BC_TumbleTextBox(window, (int)plugin->config.trigger,
576         MIN_TRIGGER, MAX_TRIGGER, x, y, xS(100))
577 {
578         this->plugin = plugin;
579 }
580 int ComprMultiTrigger::handle_event()
581 {
582         plugin->config.trigger = atol(get_text());
583         plugin->send_configure_change();
584         return 1;
585 }
586
587
588 ComprMultiInput::ComprMultiInput(ComprMultiEffect *plugin, int x, int y) 
589  : BC_PopupMenu(x, y, xS(100), 
590         ComprMultiInput::value_to_text(plugin->config.input), 1)
591 {
592         this->plugin = plugin;
593 }
594 int ComprMultiInput::handle_event()
595 {
596         plugin->config.input = text_to_value(get_text());
597         ((ComprMultiWindow*)plugin->thread->window)->update();
598         plugin->send_configure_change();
599         return 1;
600 }
601
602 void ComprMultiInput::create_objects()
603 {
604         for( int i = 0; i < 3; i++ ) {
605                 add_item(new BC_MenuItem(value_to_text(i)));
606         }
607 }
608
609 const char* ComprMultiInput::value_to_text(int value)
610 {
611         switch( value ) {
612         case ComprMultiConfig::TRIGGER: return "Trigger";
613         case ComprMultiConfig::MAX: return "Maximum";
614         case ComprMultiConfig::SUM: return "Total";
615         }
616
617         return "Trigger";
618 }
619
620 int ComprMultiInput::text_to_value(char *text)
621 {
622         for( int i = 0; i < 3; i++ ) {
623                 if( !strcmp(value_to_text(i), text) ) return i;
624         }
625
626         return ComprMultiConfig::TRIGGER;
627 }
628
629
630 ComprMultiClear::ComprMultiClear(ComprMultiEffect *plugin, int x, int y) 
631  : BC_GenericButton(x, y, _("Clear"))
632 {
633         this->plugin = plugin;
634 }
635
636 int ComprMultiClear::handle_event()
637 {
638         BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
639
640         band_config->levels.remove_all();
641 //plugin->config.dump();
642         ((ComprMultiWindow*)plugin->thread->window)->update();
643         plugin->send_configure_change();
644         return 1;
645 }
646
647
648 ComprMultiSmooth::ComprMultiSmooth(ComprMultiEffect *plugin, int x, int y) 
649  : BC_CheckBox(x, y, plugin->config.smoothing_only, _("Smooth only"))
650 {
651         this->plugin = plugin;
652 }
653
654 int ComprMultiSmooth::handle_event()
655 {
656         plugin->config.smoothing_only = get_value();
657         plugin->send_configure_change();
658         return 1;
659 }
660
661
662 ComprMultiSolo::ComprMultiSolo(ComprMultiEffect *plugin, int x, int y) 
663  : BC_CheckBox(x, y, plugin->config.bands[plugin->config.current_band].solo, _("Solo band"))
664 {
665         this->plugin = plugin;
666 }
667
668 int ComprMultiSolo::handle_event()
669 {
670         plugin->config.bands[plugin->config.current_band].solo = get_value();
671         for( int i = 0; i < TOTAL_BANDS; i++ ) {
672                 if( i != plugin->config.current_band ) {
673                         plugin->config.bands[i].solo = 0;
674                 }
675         }
676         plugin->send_configure_change();
677         return 1;
678 }
679
680
681 ComprMultiBypass::ComprMultiBypass(ComprMultiEffect *plugin, int x, int y) 
682  : BC_CheckBox(x, y, plugin->config.bands[plugin->config.current_band].bypass, _("Bypass band"))
683 {
684         this->plugin = plugin;
685 }
686
687 int ComprMultiBypass::handle_event()
688 {
689         plugin->config.bands[plugin->config.current_band].bypass = get_value();
690         plugin->send_configure_change();
691         return 1;
692 }
693
694
695 ComprMultiBand::ComprMultiBand(ComprMultiWindow *window, 
696                 ComprMultiEffect *plugin, int x, int y, int number,
697                 char *text)
698  : BC_Radial(x, y, plugin->config.current_band == number, text)
699 {
700         this->window = window;
701         this->plugin = plugin;
702         this->number = number;
703 }
704
705 int ComprMultiBand::handle_event()
706 {
707         if( plugin->config.current_band != number ) {
708                 plugin->config.current_band = number;
709                 window->update();
710         }
711         return 1;
712 }
713
714 // dump envelope sum
715 //       printf("ComprMultiWindow::update_eqcanvas %d\n", __LINE__);
716 //       for( int i = 0; i < plugin->config.window_size / 2; i++ )
717 //       {
718 //               double sum = 0;
719 //               for( int band = 0; band < TOTAL_BANDS; band++ )
720 //               {
721 //                       sum += plugin->engines[band]->envelope[i];
722 //               }
723 //               
724 //               printf("%f ", sum);
725 //               for( int band = 0; band < TOTAL_BANDS; band++ )
726 //               {
727 //                       printf("%f ", plugin->engines[band]->envelope[i]);
728 //               }
729 //               printf("\n");
730 //       }
731
732