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