Third set of 50 GPL attribution for CV-Contributors added +
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / eqcanvas.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2008 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 "clip.h"
22 #include "eqcanvas.h"
23 #include "mwindow.h"
24 #include "pluginaclient.h"
25 #include "theme.h"
26
27 #define graph_bg_color 0x559977
28 #define graph_border1_color 0xeeaa44
29 #define graph_border2_color 0xeeaaff
30 #define graph_grid_color 0xeeffcc
31 #define graph_active_color 0x99cc77
32 #define graph_inactive_color 0x666688
33
34 EQCanvas::EQCanvas(BC_WindowBase *parent,
35                 int x, int y, int w, int h,
36                 float min_db, float max_db)
37 {
38         this->parent = parent;
39         this->x = x;  this->y = y;
40         this->w = w;  this->h = h;
41         this->min_db = min_db;
42         this->max_db = max_db;
43         canvas = 0;
44
45         minor_divisions = 5;
46         freq_divisions = 5;
47 }
48
49 EQCanvas::~EQCanvas()
50 {
51         delete canvas;
52 }
53
54 void EQCanvas::initialize()
55 {
56         int big_xtick = xS(10), big_ytick = yS(10);
57         int small_xtick = xS(5), small_ytick = yS(5);
58         int tiny_xtick = xS(2);
59         int db_width = parent->get_text_width(SMALLFONT, "-00", -1) + big_xtick;
60         int freq_height = parent->get_text_ascent(SMALLFONT);
61
62         canvas_x = x + db_width;
63         canvas_y = y;
64         canvas_w = w - db_width;
65         canvas_h = h - freq_height - big_ytick;
66         parent->add_subwindow(canvas = new BC_SubWindow(
67                 canvas_x, canvas_y, canvas_w, canvas_h, BLACK));
68
69 // Draw canvas titles
70 // DB
71         parent->set_font(SMALLFONT);
72         int ascent = parent->get_text_ascent(SMALLFONT);
73 // DB per minor division
74         db_per_division = 1;
75         pixels_per_division = (float)canvas_h / (max_db - min_db) * db_per_division;
76 // increase the DB per minor division until they fit
77 //printf("EQCanvas::initialize %d pixels_per_division=%f\n", __LINE__, pixels_per_division);
78         while( pixels_per_division < 5 ) {
79                 db_per_division *= 2;
80                 pixels_per_division = (float)canvas_h / (max_db - min_db) * db_per_division;
81         }
82         total_divisions = (int)((max_db - min_db) / db_per_division);
83
84         char string[BCTEXTLEN];
85         for( int i = 0; i <= total_divisions; i++ ) {
86                 int y1 = canvas_y + (int)(i * pixels_per_division);
87                 int y2 = y1 + ascent;
88                 int x2 = canvas_x - big_xtick;
89                 int x3 = canvas_x - tiny_xtick;
90                 int x4 = x3 - small_xtick;
91
92                 if( !(i % minor_divisions) ||
93                         i == total_divisions ) {
94                         if( i == total_divisions ) {
95                                 sprintf(string, "oo");
96                         }
97                         else {
98                                 sprintf(string, "%d", (int)(max_db - i * db_per_division));
99                         }
100
101                         parent->set_color(BLACK);
102                         int text_w = parent->get_text_width(SMALLFONT, string, -1);
103                         int x1 = canvas_x - big_xtick - text_w;
104                         parent->set_color(parent->get_resources()->default_text_color);
105                         parent->draw_text(x1, y2, string);
106                         parent->draw_line(x2, y1, x3, y1);
107                 }
108                 else {
109                         parent->draw_line(x4, y1, x3, y1);
110                 }
111         }
112
113 // freq
114         for( int i = 0; i <= freq_divisions; i++ ) {
115                 int freq = Freq::tofreq(i * TOTALFREQS / freq_divisions);
116                 sprintf(string, "%d", freq);
117                 int x1 = canvas_x + i * canvas_w / freq_divisions;
118                 int x2 = x1 - parent->get_text_width(SMALLFONT, string);
119                 int y1 = canvas_y + canvas_h;
120                 int y2 = y1 + big_ytick;
121                 int y3 = y1 + small_ytick;
122                 int y4 = y2 + parent->get_text_ascent(SMALLFONT);
123
124 //              parent->set_color(BLACK);
125 //              parent->draw_text(x2 + 1, y4 + 1, string);
126 //              parent->draw_line(x1 + 1, y1 + 1, x1 + 1, y2 + 1);
127 //              parent->set_color(RED);
128                 parent->set_color(parent->get_resources()->default_text_color);
129                 parent->draw_text(x2, y4, string);
130                 parent->draw_line(x1, y1, x1, y2);
131
132                 if( i < freq_divisions ) {
133                         for( int j = 0; j < minor_divisions; j++ ) {
134                                 int x3 = (int)(x1 +
135                                         (canvas_w / freq_divisions) -
136                                         exp(-(double)j * 0.7) *
137                                         (canvas_w / freq_divisions));
138 //                              parent->set_color(BLACK);
139 //                              parent->draw_line(x3 + 1, y1 + 1, x3 + 1, y3 + 1);
140 //                              parent->set_color(RED);
141                                 parent->set_color(parent->get_resources()->default_text_color);
142                                 parent->draw_line(x3, y1, x3, y3);
143                         }
144                 }
145         }
146
147         draw_grid();
148 }
149
150
151 void EQCanvas::draw_grid()
152 {
153         canvas->set_line_dashes(1);
154         canvas->set_color(graph_grid_color);
155         for( int i = minor_divisions; i < total_divisions; i += minor_divisions ) {
156                 int y = (int)(i * pixels_per_division);
157                 canvas->draw_line(0, y, canvas_w, y);
158         }
159 //      for( int i = 1; i < major_divisions; i++ ) {
160 //              int y = canvas_h - i * canvas_h / major_divisions;
161 //              canvas->draw_line(0, y, canvas_w, y);
162 //      }
163         for( int i = 1; i < freq_divisions; i++ ) {
164                 int x = i * canvas_w / freq_divisions;
165                 canvas->draw_line(x, 0, x, canvas_h);
166         }
167         canvas->set_line_dashes(0);
168 }
169
170 void EQCanvas::update_spectrogram(CompressorFreqFrame *frame,
171                 int offset, int size, int window_size)
172 {
173 //if( frame ) printf("EQCanvas::update_spectrogram %d frame->freq_max=%f frame->data=%p\n",
174 // __LINE__, frame->freq_max, frame->data);
175         canvas->set_color(graph_bg_color);
176         canvas->draw_box(0, 0, canvas->get_w(), canvas->get_h());
177         draw_grid();
178
179 // Draw it
180         if( frame && !EQUIV(frame->freq_max, 0.0) && frame->data ) {
181                 int y1 = 0, y2 = 0;
182                 if( offset < 0 ) {
183                         offset = 0;
184                         size = frame->data_size;
185                         window_size = frame->data_size * 2;
186                 }
187
188                 canvas->set_color(graph_inactive_color);
189                 if( !EQUIV(frame->freq_max, 0) ) {
190                         for( int i = 0; i < canvas->get_w(); i++ ) {
191                                 int freq = Freq::tofreq(i * TOTALFREQS / canvas->get_w());
192
193                                 if( freq < frame->nyquist ) {
194                                         int index = offset +
195                                                 (int64_t)freq * (int64_t)window_size / 2 /
196                                                 frame->nyquist;
197
198                                         if( index < frame->data_size ) {
199                                                 double magnitude = frame->data[index] /
200                                                         frame->freq_max * frame->time_max;
201
202                                                 y2 = (int)(canvas->get_h() -
203                                                         (DB::todb(magnitude) - INFINITYGAIN) *
204                                                         canvas->get_h() /
205                                                         -INFINITYGAIN);
206                                                 CLAMP(y2, 0, canvas->get_h() - 1);
207                                                 if( i > 0 ) {
208                                                         canvas->draw_line(i - 1, y1, i, y2);
209                                                 }
210                                                 y1 = y2;
211                                         }
212                                 }
213                                 else {
214 //                                       printf("EQCanvas::update_spectrogram %d i=%d freq=%d nyquist=%d\n",
215 //                                               __LINE__, i, freq, frame->nyquist);
216                                 }
217                         }
218                 }
219         }
220
221 }
222
223
224 void EQCanvas::draw_envelope(double *envelope,
225                 int samplerate, int window_size, int is_top, int flash_it)
226 {
227         int niquist = samplerate / 2;
228
229         if( is_top ) {
230                 canvas->set_color(graph_active_color);
231                 canvas->set_line_width(2);
232         }
233         else {
234                 canvas->set_color(graph_inactive_color);
235                 canvas->set_line_width(1);
236         }
237
238         int y1;
239         for( int i = 0; i < canvas->get_w(); i++ ) {
240                 int freq = Freq::tofreq(i * TOTALFREQS / canvas->get_w());
241                 int index = (int64_t)freq * (int64_t)window_size / 2 / niquist;
242                 if( freq < niquist && index < window_size / 2 ) {
243                         double mag = envelope[index];
244                         int y2 = (int)(DB::todb(mag) * canvas->get_h() / INFINITYGAIN);
245
246                         if( y2 >= canvas->get_h() ) {
247                                 y2 = canvas->get_h() - 1;
248                         }
249
250                         if( i > 0 ) {
251                                 canvas->draw_line(i - 1, y1, i, y2);
252                         }
253                         y1 = y2;
254                 }
255                 else
256                 if( i > 0 ) {
257                         int y2 = canvas->get_h() - 1;
258                         canvas->draw_line(i - 1, y1, i, y2);
259                         y1 = y2;
260                 }
261         }
262
263         canvas->set_line_width(1);
264         if( flash_it ) {
265                 canvas->flash(1);
266         }
267 }
268