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