1 /*
2
3 (c) Fraser Stuart 2009
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21
22 #include <stdlib.h>
23 #include <math.h>
24 #include <string.h>
25 #include "display-Compressor.h"
26
27
28
29 static void inv_display_comp_class_init(InvDisplayCompClass *klass);
30 static void inv_display_comp_init(InvDisplayComp *displayComp);
31 static void inv_display_comp_size_request(GtkWidget *widget, GtkRequisition *requisition);
32 static void inv_display_comp_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
33 static void inv_display_comp_realize(GtkWidget *widget);
34 static gboolean inv_display_comp_expose(GtkWidget *widget,GdkEventExpose *event);
35 static void inv_display_comp_paint(GtkWidget *widget, gint mode);
36 static void inv_display_comp_destroy(GtkObject *object);
37 float inv_display_comp_rms_waveform(float pos, float width, float height);
38
39
40 GtkType
inv_display_comp_get_type(void)41 inv_display_comp_get_type(void)
42 {
43 static GtkType inv_display_comp_type = 0;
44 char *name;
45 int i;
46
47
48 if (!inv_display_comp_type)
49 {
50 static const GTypeInfo type_info = {
51 sizeof(InvDisplayCompClass),
52 NULL, /* base_init */
53 NULL, /* base_finalize */
54 (GClassInitFunc)inv_display_comp_class_init,
55 NULL, /* class_finalize */
56 NULL, /* class_data */
57 sizeof(InvDisplayComp),
58 0, /* n_preallocs */
59 (GInstanceInitFunc)inv_display_comp_init
60 };
61 for (i = 0; ; i++) {
62 name = g_strdup_printf("InvDisplayComp-%p-%d",inv_display_comp_class_init, i);
63 if (g_type_from_name(name)) {
64 free(name);
65 continue;
66 }
67 inv_display_comp_type = g_type_register_static(GTK_TYPE_WIDGET,name,&type_info,(GTypeFlags)0);
68 free(name);
69 break;
70 }
71 }
72 return inv_display_comp_type;
73 }
74
75 void
inv_display_comp_set_bypass(InvDisplayComp * displayComp,gint num)76 inv_display_comp_set_bypass(InvDisplayComp *displayComp, gint num)
77 {
78 displayComp->bypass = num;
79 }
80
81 void
inv_display_comp_set_rms(InvDisplayComp * displayComp,float num)82 inv_display_comp_set_rms(InvDisplayComp *displayComp, float num)
83 {
84 if(num<0)
85 displayComp->rms = 0;
86 else if (num <= 1)
87 displayComp->rms = num;
88 else displayComp->rms = 1;
89 if(displayComp->rms != displayComp->Lastrms) {
90 if(GTK_WIDGET_REALIZED(displayComp))
91 inv_display_comp_paint(GTK_WIDGET(displayComp),INV_DISPLAYCOMP_DRAW_DATA);
92 }
93 }
94
95 void
inv_display_comp_set_attack(InvDisplayComp * displayComp,float num)96 inv_display_comp_set_attack(InvDisplayComp *displayComp, float num)
97 {
98 if(num<0.00001)
99 displayComp->attack = 0.00001;
100 else if (num <= 0.750)
101 displayComp->attack = num;
102 else displayComp->attack = 0.750;
103 if(displayComp->attack != displayComp->Lastattack) {
104 if(GTK_WIDGET_REALIZED(displayComp))
105 inv_display_comp_paint(GTK_WIDGET(displayComp),INV_DISPLAYCOMP_DRAW_DATA);
106 }
107 }
108
109 void
inv_display_comp_set_release(InvDisplayComp * displayComp,float num)110 inv_display_comp_set_release(InvDisplayComp *displayComp, float num)
111 {
112 if(num<0.001)
113 displayComp->release = 0.001;
114 else if (num <= 5.0)
115 displayComp->release = num;
116 else displayComp->release = 5.0;
117 if(displayComp->release != displayComp->Lastrelease) {
118 if(GTK_WIDGET_REALIZED(displayComp))
119 inv_display_comp_paint(GTK_WIDGET(displayComp),INV_DISPLAYCOMP_DRAW_DATA);
120 }
121 }
122
123 void
inv_display_comp_set_threshold(InvDisplayComp * displayComp,float num)124 inv_display_comp_set_threshold(InvDisplayComp *displayComp, float num)
125 {
126 if(num<-36.0)
127 displayComp->threshold = -36.0;
128 else if (num <= 0.0)
129 displayComp->threshold = num;
130 else displayComp->threshold = 0.0;
131 if(displayComp->threshold != displayComp->Lastthreshold) {
132 if(GTK_WIDGET_REALIZED(displayComp))
133 inv_display_comp_paint(GTK_WIDGET(displayComp),INV_DISPLAYCOMP_DRAW_DATA);
134 }
135 }
136
137 void
inv_display_comp_set_ratio(InvDisplayComp * displayComp,float num)138 inv_display_comp_set_ratio(InvDisplayComp *displayComp, float num)
139 {
140 if(num<1.0)
141 displayComp->ratio = 1.0;
142 else if (num <= 20.0)
143 displayComp->ratio = num;
144 else displayComp->ratio = 20.0;
145 if(displayComp->ratio != displayComp->Lastratio) {
146 if(GTK_WIDGET_REALIZED(displayComp))
147 inv_display_comp_paint(GTK_WIDGET(displayComp),INV_DISPLAYCOMP_DRAW_DATA);
148 }
149 }
150
151 void
inv_display_comp_set_gain(InvDisplayComp * displayComp,float num)152 inv_display_comp_set_gain(InvDisplayComp *displayComp, float num)
153 {
154 if(num<-6.0)
155 displayComp->gain = -6.0;
156 else if (num <= 36.0)
157 displayComp->gain = num;
158 else displayComp->gain = 36.0;
159 if(displayComp->gain != displayComp->Lastgain) {
160 if(GTK_WIDGET_REALIZED(displayComp))
161 inv_display_comp_paint(GTK_WIDGET(displayComp),INV_DISPLAYCOMP_DRAW_DATA);
162 }
163 }
164
165
inv_display_comp_new()166 GtkWidget * inv_display_comp_new()
167 {
168 return GTK_WIDGET(gtk_type_new(inv_display_comp_get_type()));
169 }
170
171
172 static void
inv_display_comp_class_init(InvDisplayCompClass * klass)173 inv_display_comp_class_init(InvDisplayCompClass *klass)
174 {
175 GtkWidgetClass *widget_class;
176 GtkObjectClass *object_class;
177
178
179 widget_class = (GtkWidgetClass *) klass;
180 object_class = (GtkObjectClass *) klass;
181
182 widget_class->realize = inv_display_comp_realize;
183 widget_class->size_request = inv_display_comp_size_request;
184 widget_class->size_allocate = inv_display_comp_size_allocate;
185 widget_class->expose_event = inv_display_comp_expose;
186
187 object_class->destroy = inv_display_comp_destroy;
188 }
189
190
191 static void
inv_display_comp_init(InvDisplayComp * displayComp)192 inv_display_comp_init(InvDisplayComp *displayComp)
193 {
194 gint i;
195 displayComp->bypass=INV_PLUGIN_ACTIVE;
196 displayComp->rms=0.5;
197 displayComp->attack=0.00001;
198 displayComp->release=0.001;
199 displayComp->threshold=0.0;
200 displayComp->ratio=1.0;
201 displayComp->gain=0.0;
202
203 displayComp->Lastrms=displayComp->rms;
204 displayComp->Lastattack=displayComp->attack;
205 displayComp->Lastrelease=displayComp->release;
206 displayComp->Lastthreshold=displayComp->threshold;
207 displayComp->Lastratio=displayComp->ratio;
208 displayComp->Lastgain=displayComp->gain;
209
210 displayComp->SIGmax=0.0;
211 for (i=0;i<292;i++) {
212 displayComp->SIG[i]=inv_display_comp_rms_waveform((float) i, 292, 104);
213 displayComp->SIGmax= fabs(displayComp->SIG[i]) > displayComp->SIGmax ? displayComp->SIG[i] : displayComp->SIGmax;
214 }
215
216 displayComp->header_font_size=0;
217 displayComp->label_font_size=0;
218 displayComp->info_font_size=0;
219
220 gtk_widget_set_tooltip_markup(GTK_WIDGET(displayComp),"<span size=\"8000\"><b>Detector and Envelope:</b> This shows how the RMS, Attack and Release interact to produce an envelope.\n<b>Compressor:</b> This shows how the Threshold, Ratio and Gain affect the audio at different levels.</span>");
221 }
222
223
224 static void
inv_display_comp_size_request(GtkWidget * widget,GtkRequisition * requisition)225 inv_display_comp_size_request(GtkWidget *widget,
226 GtkRequisition *requisition)
227 {
228 g_return_if_fail(widget != NULL);
229 g_return_if_fail(INV_IS_DISPLAY_COMP(widget));
230 g_return_if_fail(requisition != NULL);
231
232 requisition->width = 600;
233 requisition->height = 234;
234 }
235
236
237 static void
inv_display_comp_size_allocate(GtkWidget * widget,GtkAllocation * allocation)238 inv_display_comp_size_allocate(GtkWidget *widget,
239 GtkAllocation *allocation)
240 {
241 g_return_if_fail(widget != NULL);
242 g_return_if_fail(INV_IS_DISPLAY_COMP(widget));
243 g_return_if_fail(allocation != NULL);
244
245 widget->allocation = *allocation;
246
247 if (GTK_WIDGET_REALIZED(widget)) {
248 gdk_window_move_resize(
249 widget->window,
250 allocation->x, allocation->y,
251 allocation->width, allocation->height
252 );
253 }
254 }
255
256
257 static void
inv_display_comp_realize(GtkWidget * widget)258 inv_display_comp_realize(GtkWidget *widget)
259 {
260 GdkWindowAttr attributes;
261 guint attributes_mask;
262
263 g_return_if_fail(widget != NULL);
264 g_return_if_fail(INV_IS_DISPLAY_COMP(widget));
265
266 GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
267
268 attributes.window_type = GDK_WINDOW_CHILD;
269 attributes.x = widget->allocation.x;
270 attributes.y = widget->allocation.y;
271 attributes.width = 600;
272 attributes.height = 234;
273
274 attributes.wclass = GDK_INPUT_OUTPUT;
275 attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;
276
277 attributes_mask = GDK_WA_X | GDK_WA_Y;
278
279 widget->window = gdk_window_new(
280 gtk_widget_get_parent_window (widget),
281 & attributes, attributes_mask
282 );
283
284 gdk_window_set_user_data(widget->window, widget);
285
286 widget->style = gtk_style_attach(widget->style, widget->window);
287 gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
288 }
289
290
291 static gboolean
inv_display_comp_expose(GtkWidget * widget,GdkEventExpose * event)292 inv_display_comp_expose(GtkWidget *widget, GdkEventExpose *event)
293 {
294 g_return_val_if_fail(widget != NULL, FALSE);
295 g_return_val_if_fail(INV_IS_DISPLAY_COMP(widget), FALSE);
296 g_return_val_if_fail(event != NULL, FALSE);
297
298 inv_display_comp_paint(widget,INV_DISPLAYCOMP_DRAW_ALL);
299
300 return FALSE;
301 }
302
303
304 static void
inv_display_comp_paint(GtkWidget * widget,gint mode)305 inv_display_comp_paint(GtkWidget *widget, gint mode)
306 {
307 gint bypass;
308 float rms;
309 float attack;
310 float release;
311 float threshold;
312 float ratio;
313 float gain;
314
315 gint i;
316 float rmsC,rmsV,attackC,releaseC,env;
317 float y,threshsig;
318 cairo_t *cr;
319 GtkStyle *style;
320 char label[50];
321
322 style = gtk_widget_get_style(widget);
323 bypass=INV_DISPLAY_COMP(widget)->bypass;
324 rms=INV_DISPLAY_COMP(widget)->rms;
325 attack=INV_DISPLAY_COMP(widget)->attack;
326 release=INV_DISPLAY_COMP(widget)->release;
327 threshold=INV_DISPLAY_COMP(widget)->threshold;
328 ratio=INV_DISPLAY_COMP(widget)->ratio;
329 gain=INV_DISPLAY_COMP(widget)->gain;
330
331 cr = gdk_cairo_create(widget->window);
332
333 if(INV_DISPLAY_COMP(widget)->header_font_size==0) {
334 INV_DISPLAY_COMP(widget)->header_font_size=inv_choose_font_size(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL,99.0,8.1,"0");
335 }
336
337 if(INV_DISPLAY_COMP(widget)->label_font_size==0) {
338 INV_DISPLAY_COMP(widget)->label_font_size=inv_choose_font_size(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL,99.0,7.1,"0");
339 }
340
341 if(INV_DISPLAY_COMP(widget)->info_font_size==0) {
342 INV_DISPLAY_COMP(widget)->info_font_size=inv_choose_font_size(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL,99.0,6.1,"0");
343 }
344
345 if(mode==INV_DISPLAYCOMP_DRAW_ALL) {
346
347 cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
348 cairo_set_antialias (cr,CAIRO_ANTIALIAS_NONE);
349 cairo_set_line_width(cr,1);
350
351 for(i=0;i<2;i++) {
352 gdk_cairo_set_source_color(cr,&style->dark[GTK_STATE_NORMAL]);
353 cairo_move_to(cr, (i*300), 233);
354 cairo_line_to(cr, (i*300), 0);
355 cairo_line_to(cr, (i*300)+299, 0);
356 cairo_stroke(cr);
357
358 gdk_cairo_set_source_color(cr,&style->light[GTK_STATE_NORMAL]);
359 cairo_move_to(cr, (i*300), 233);
360 cairo_line_to(cr, (i*300)+299, 233);
361 cairo_line_to(cr, (i*300)+299, 0);
362 cairo_stroke(cr);
363
364 cairo_set_antialias (cr,CAIRO_ANTIALIAS_DEFAULT);
365 cairo_new_path(cr);
366
367 if(bypass==INV_PLUGIN_BYPASS) {
368 cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
369 } else {
370 cairo_set_source_rgb(cr, 0.05, 0.05, 0.2);
371 }
372 cairo_rectangle(cr, (i*300)+1, 1, 298, 232 );
373 cairo_fill(cr);
374 }
375
376 /* detector labels */
377 cairo_select_font_face(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL);
378 if(bypass==INV_PLUGIN_BYPASS) {
379 cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
380 } else {
381 cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
382 }
383
384 cairo_set_font_size(cr,INV_DISPLAY_COMP(widget)->header_font_size);
385 sprintf(label,"Detector And Envelope");
386 cairo_move_to(cr,75,13);
387 cairo_show_text(cr,label);
388
389 cairo_set_font_size(cr,INV_DISPLAY_COMP(widget)->label_font_size);
390 sprintf(label,"Audio");
391 cairo_move_to(cr,35,230);
392 cairo_show_text(cr,label);
393
394 sprintf(label,"Detected Signal");
395 cairo_move_to(cr,105,230);
396 cairo_show_text(cr,label);
397
398 sprintf(label,"Envelope");
399 cairo_move_to(cr,225,230);
400 cairo_show_text(cr,label);
401
402 if(bypass==INV_PLUGIN_BYPASS) {
403 cairo_set_source_rgba(cr, 0.7, 0.7, 0.7, 0.4);
404 } else {
405 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
406 }
407
408
409 cairo_set_line_width(cr,1.0);
410 cairo_move_to(cr, 25, 230);
411 cairo_line_to(cr, 31, 222);
412 cairo_stroke(cr);
413
414 if(bypass==INV_PLUGIN_BYPASS) {
415 cairo_set_source_rgba(cr, 0.4, 0.4, 0.4, 0.25);
416 } else {
417 cairo_set_source_rgba(cr, 1.0, 0.1, 0.0, 0.25);
418 }
419 cairo_rectangle(cr, 95, 222, 6, 6 );
420 cairo_fill(cr);
421
422 if(bypass==INV_PLUGIN_BYPASS) {
423 cairo_set_source_rgb(cr, 0.4, 0.4, 0.4);
424 } else {
425 cairo_set_source_rgb(cr, 0.0, 0.1, 1.0);
426 }
427 cairo_rectangle(cr, 215, 222, 6, 6 );
428 cairo_fill(cr);
429
430 /* compressor labels */
431 cairo_select_font_face(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL);
432 if(bypass==INV_PLUGIN_BYPASS) {
433 cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
434 } else {
435 cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
436 }
437
438 cairo_set_font_size(cr,INV_DISPLAY_COMP(widget)->header_font_size);
439 sprintf(label,"Compressor");
440 cairo_move_to(cr,415,13);
441 cairo_show_text(cr,label);
442
443 if(bypass==INV_PLUGIN_BYPASS) {
444 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
445 } else {
446 cairo_set_source_rgb(cr, 1, 1, 1);
447 }
448 cairo_rectangle(cr, 566, 17, 1, 191);
449 cairo_fill(cr);
450
451 cairo_rectangle(cr, 306, 207, 260, 1);
452 cairo_fill(cr);
453
454 cairo_select_font_face(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL);
455 cairo_set_font_size(cr,INV_DISPLAY_COMP(widget)->info_font_size);
456 if(bypass==INV_PLUGIN_BYPASS) {
457 cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
458 } else {
459 cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
460 }
461 for(i=0;i<8;i+=2)
462 {
463 sprintf(label,"%3idB",-(i*6));
464 cairo_move_to(cr,569,42+(i*21));
465 cairo_show_text(cr,label);
466
467 sprintf(label,"%idB",-(i*6));
468 switch(i) {
469 case 0:
470 cairo_move_to(cr,530-(i*30),219);
471 break;
472 case 2:
473 case 4:
474 case 6:
475 cairo_move_to(cr,525-(i*30),219);
476 break;
477 }
478 cairo_show_text(cr,label);
479 }
480
481 if(bypass==INV_PLUGIN_BYPASS) {
482 cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
483 } else {
484 cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
485 }
486 cairo_set_font_size(cr,INV_DISPLAY_COMP(widget)->label_font_size);
487 sprintf(label,"Original");
488 cairo_move_to(cr,385,230);
489 cairo_show_text(cr,label);
490
491 sprintf(label,"Compressed");
492 cairo_move_to(cr,465,230);
493 cairo_show_text(cr,label);
494
495 if(bypass==INV_PLUGIN_BYPASS) {
496 cairo_set_source_rgba(cr, 0.7, 0.7, 0.7, 0.4);
497 } else {
498 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
499 }
500 cairo_set_line_width(cr,1.0);
501 cairo_move_to(cr, 375, 230);
502 cairo_line_to(cr, 381, 222);
503 cairo_stroke(cr);
504
505 if(bypass==INV_PLUGIN_BYPASS) {
506 cairo_set_source_rgb(cr, 0.4, 0.4, 0.4);
507 } else {
508 cairo_set_source_rgb(cr, 0.0, 0.1, 1);
509 }
510 cairo_set_line_width(cr,2.0);
511 cairo_move_to(cr, 455, 230);
512 cairo_line_to(cr, 461, 222);
513 cairo_stroke(cr);
514
515
516
517 }
518
519 /* rms display */
520 if(mode == INV_DISPLAYCOMP_DRAW_ALL
521 || rms != INV_DISPLAY_COMP(widget)->Lastrms
522 || attack != INV_DISPLAY_COMP(widget)->Lastattack
523 || release != INV_DISPLAY_COMP(widget)->Lastrelease ) {
524
525
526 if(mode == INV_DISPLAYCOMP_DRAW_ALL
527 || rms != INV_DISPLAY_COMP(widget)->Lastrms ) {
528 //compute new rms if needed
529 rmsC= (pow(rms,3) * 400)+1;
530 rmsV=0;
531 attackC= 1 - pow(10, -301.0301 / (attack*1000000.0));
532 releaseC= 1 - pow(10, -301.0301 / (release*1000000.0));
533 env=0;
534 for (i=0;i<292;i++) {
535 y=INV_DISPLAY_COMP(widget)->SIG[i];
536 rmsV = sqrt(( (rmsC-1)*rmsV*rmsV + y*y ) / rmsC);
537 INV_DISPLAY_COMP(widget)->RMS[i]=rmsV;
538 env += (INV_DISPLAY_COMP(widget)->RMS[i] > env) ?
539 attackC * (INV_DISPLAY_COMP(widget)->RMS[i] - env) :
540 releaseC * (INV_DISPLAY_COMP(widget)->RMS[i] - env) ;
541 INV_DISPLAY_COMP(widget)->ENV[i]=env;
542 }
543
544 } else if(attack != INV_DISPLAY_COMP(widget)->Lastattack
545 || release != INV_DISPLAY_COMP(widget)->Lastrelease ) {
546 //compute new evelope if needed
547 attackC= 1 - pow(10, -301.0301 / (attack*1000000.0));
548 releaseC= 1 - pow(10, -301.0301 / (release*1000000.0));
549 env=0;
550 for (i=0;i<292;i++) {
551 env += (INV_DISPLAY_COMP(widget)->RMS[i] > env) ?
552 attackC * (INV_DISPLAY_COMP(widget)->RMS[i] - env) :
553 releaseC * (INV_DISPLAY_COMP(widget)->RMS[i] - env) ;
554 INV_DISPLAY_COMP(widget)->ENV[i]=env;
555 }
556 }
557
558 if(bypass==INV_PLUGIN_BYPASS) {
559 cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
560 } else {
561 cairo_set_source_rgb(cr, 0.05, 0.05, 0.2);
562 }
563
564 cairo_rectangle(cr, 3, 15, 294, 206 );
565 cairo_fill(cr);
566
567
568 //draw envelope
569 if(bypass==INV_PLUGIN_BYPASS) {
570 cairo_set_source_rgb(cr, 0.4, 0.4, 0.4);
571 } else {
572 cairo_set_source_rgb(cr, 0.0, 0.1, 1);
573 }
574 cairo_set_line_width(cr,1.0);
575 cairo_move_to(cr, 4, 117);
576
577 for (i=0;i<292;i++) {
578 cairo_line_to(cr, 4+i, 117-INV_DISPLAY_COMP(widget)->ENV[i]);
579 }
580 cairo_line_to(cr, 295, 117);
581 cairo_line_to(cr, 4, 117);
582 cairo_fill(cr);
583
584 // draw axis
585 if(bypass==INV_PLUGIN_BYPASS) {
586 cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
587 } else {
588 cairo_set_source_rgb(cr, 0.35, 0.35, 0.35);
589 }
590 cairo_rectangle(cr, 4, 117, 292, 1 );
591 cairo_fill(cr);
592
593
594 //draw rms
595 if(bypass==INV_PLUGIN_BYPASS) {
596 cairo_set_source_rgba(cr, 0.4, 0.4, 0.4, 0.25);
597 } else {
598 cairo_set_source_rgba(cr, 1.0, 0.1, 0.0, 0.25);
599 }
600 cairo_set_line_width(cr,1.0);
601 cairo_move_to(cr, 4, 117);
602 for (i=0;i<292;i++) {
603 cairo_line_to(cr, 4+i, 117-INV_DISPLAY_COMP(widget)->RMS[i]);
604 }
605 cairo_line_to(cr, 295, 117);
606 cairo_line_to(cr, 4, 117);
607 cairo_fill(cr);
608
609
610 //draw original signal
611 if(bypass==INV_PLUGIN_BYPASS) {
612 cairo_set_source_rgba(cr, 0.7, 0.7, 0.7, 0.25);
613 } else {
614 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.25);
615 }
616 cairo_set_line_width(cr,1.0);
617 cairo_move_to(cr, 4, 117);
618 for (i=0;i<292;i++) {
619 cairo_line_to(cr, 4+i, 117-INV_DISPLAY_COMP(widget)->SIG[i]);
620 }
621 cairo_stroke(cr);
622 }
623
624
625 /* compressor display */
626 if(mode == INV_DISPLAYCOMP_DRAW_ALL
627 || threshold != INV_DISPLAY_COMP(widget)->Lastthreshold
628 || ratio != INV_DISPLAY_COMP(widget)->Lastratio
629 || gain != INV_DISPLAY_COMP(widget)->Lastgain ) {
630
631 if(bypass==INV_PLUGIN_BYPASS) {
632 cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
633 } else {
634 cairo_set_source_rgb(cr, 0.05, 0.05, 0.2);
635 }
636 cairo_rectangle(cr, 306, 17, 260, 190 );
637 cairo_fill(cr);
638
639 for(i=1;i<8;i+=2) {
640 if(bypass==INV_PLUGIN_BYPASS) {
641 cairo_set_source_rgb(cr, 0.15, 0.15, 0.15);
642 } else {
643 cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
644 }
645 cairo_rectangle(cr, 296+(i*30), 17, 1, 190);
646 cairo_fill(cr);
647 cairo_rectangle(cr, 306, 38+(i*21), 260, 1);
648 cairo_fill(cr);
649 }
650
651 for(i=0;i<5;i+=2) {
652 if(bypass==INV_PLUGIN_BYPASS) {
653 cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
654 } else {
655 cairo_set_source_rgb(cr, 0.35, 0.35, 0.35);
656 }
657 cairo_rectangle(cr, 356+(i*30), 17, 1, 190);
658 cairo_fill(cr);
659 cairo_rectangle(cr, 306, 80+(i*21), 260, 1);
660 cairo_fill(cr);
661 }
662
663
664 if(bypass==INV_PLUGIN_BYPASS) {
665 cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
666 } else {
667 cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
668 }
669 cairo_rectangle(cr, 536, 17, 1, 190);
670 cairo_fill(cr);
671 cairo_rectangle(cr, 306, 38, 260, 1);
672 cairo_fill(cr);
673
674 cairo_rectangle(cr, 306, 17, 260, 190 );
675 cairo_clip(cr);
676
677 /* compressed signal */
678
679 // gain change at +6 db <- GRAPH MUST END HERE
680 threshsig=pow(10,threshold/20);
681 y = 20*log10(threshsig+((2-threshsig)/ratio));
682
683 if(bypass==INV_PLUGIN_BYPASS) {
684 cairo_set_source_rgb(cr, 0.4, 0.4, 0.4);
685 } else {
686 cairo_set_source_rgb(cr, 0.0, 0.1, 1);
687 }
688 cairo_set_line_width(cr,2);
689
690 cairo_move_to(cr, 306 , 200-(21*gain/6));
691 cairo_line_to(cr, 536+(30*threshold/6), 38-(21*gain/6)-(21*threshold/6));
692 cairo_line_to(cr, 566 , 38-(21*gain/6)-(21*y/6));
693 cairo_stroke(cr);
694
695 /* original signal */
696 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.25);
697 cairo_set_line_width(cr,1.0);
698 cairo_move_to(cr, 306, 200);
699 cairo_line_to(cr, 566, 17);
700 cairo_stroke(cr);
701
702
703
704 }
705 cairo_destroy(cr);
706
707 INV_DISPLAY_COMP(widget)->Lastrms=rms;
708 INV_DISPLAY_COMP(widget)->Lastattack=attack;
709 INV_DISPLAY_COMP(widget)->Lastrelease=release;
710 INV_DISPLAY_COMP(widget)->Lastthreshold=threshold;
711 INV_DISPLAY_COMP(widget)->Lastratio=ratio;
712 INV_DISPLAY_COMP(widget)->Lastgain=gain;
713
714 }
715
716
717 static void
inv_display_comp_destroy(GtkObject * object)718 inv_display_comp_destroy(GtkObject *object)
719 {
720 InvDisplayComp *displayComp;
721 InvDisplayCompClass *klass;
722
723 g_return_if_fail(object != NULL);
724 g_return_if_fail(INV_IS_DISPLAY_COMP(object));
725
726 displayComp = INV_DISPLAY_COMP(object);
727
728 klass = gtk_type_class(gtk_widget_get_type());
729
730 if (GTK_OBJECT_CLASS(klass)->destroy) {
731 (* GTK_OBJECT_CLASS(klass)->destroy) (object);
732 }
733 }
734
735 float
inv_display_comp_rms_waveform(float pos,float width,float height)736 inv_display_comp_rms_waveform(float pos, float width, float height)
737 {
738 float theta,theta2;
739 float heightr,heightr2;
740 float value;
741
742 value=0;
743
744 if(pos < width/3) {
745 theta=2*INV_PI*(13.5*pow(3*pos/width,0.5));
746 heightr=1-(pow(3*pos/width,0.1));
747 value+=3*height*heightr*sin(theta);
748 }
749
750 if(pos > width/3) {
751 theta=2*INV_PI*(8* 3* (pos-width/3) / (2*width) );
752 theta2=2*INV_PI*(32* 3* (pos-width/3) / (2*width) );
753 heightr=1-(pow(3*(pos-width/3)/(2*width),12));
754 heightr2=1-(pow(3*(pos-width/3)/(2*width),0.5));
755 value+=0.6*height*heightr*sin(theta) + 0.2*height*heightr2*sin(theta2);
756 }
757 return value;
758 }
759
760