#include "clip.h" #include "eqcanvas.h" #include "mwindow.h" #include "pluginaclient.h" #include "theme.h" #define graph_bg_color 0x559977 #define graph_border1_color 0xeeaa44 #define graph_border2_color 0xeeaaff #define graph_grid_color 0xeeffcc #define graph_active_color 0x99cc77 #define graph_inactive_color 0x666688 EQCanvas::EQCanvas(BC_WindowBase *parent, int x, int y, int w, int h, float min_db, float max_db) { this->parent = parent; this->x = x; this->y = y; this->w = w; this->h = h; this->min_db = min_db; this->max_db = max_db; canvas = 0; minor_divisions = 5; freq_divisions = 5; } EQCanvas::~EQCanvas() { delete canvas; } void EQCanvas::initialize() { int big_xtick = xS(10), big_ytick = yS(10); int small_xtick = xS(5), small_ytick = yS(5); int tiny_xtick = xS(2); int db_width = parent->get_text_width(SMALLFONT, "-00", -1) + big_xtick; int freq_height = parent->get_text_ascent(SMALLFONT); canvas_x = x + db_width; canvas_y = y; canvas_w = w - db_width; canvas_h = h - freq_height - big_ytick; parent->add_subwindow(canvas = new BC_SubWindow( canvas_x, canvas_y, canvas_w, canvas_h, BLACK)); // Draw canvas titles // DB parent->set_font(SMALLFONT); int ascent = parent->get_text_ascent(SMALLFONT); // DB per minor division db_per_division = 1; pixels_per_division = (float)canvas_h / (max_db - min_db) * db_per_division; // increase the DB per minor division until they fit //printf("EQCanvas::initialize %d pixels_per_division=%f\n", __LINE__, pixels_per_division); while( pixels_per_division < 5 ) { db_per_division *= 2; pixels_per_division = (float)canvas_h / (max_db - min_db) * db_per_division; } total_divisions = (int)((max_db - min_db) / db_per_division); char string[BCTEXTLEN]; for( int i = 0; i <= total_divisions; i++ ) { int y1 = canvas_y + (int)(i * pixels_per_division); int y2 = y1 + ascent; int x2 = canvas_x - big_xtick; int x3 = canvas_x - tiny_xtick; int x4 = x3 - small_xtick; if( !(i % minor_divisions) || i == total_divisions ) { if( i == total_divisions ) { sprintf(string, "oo"); } else { sprintf(string, "%d", (int)(max_db - i * db_per_division)); } parent->set_color(BLACK); int text_w = parent->get_text_width(SMALLFONT, string, -1); int x1 = canvas_x - big_xtick - text_w; parent->set_color(parent->get_resources()->default_text_color); parent->draw_text(x1, y2, string); parent->draw_line(x2, y1, x3, y1); } else { parent->draw_line(x4, y1, x3, y1); } } // freq for( int i = 0; i <= freq_divisions; i++ ) { int freq = Freq::tofreq(i * TOTALFREQS / freq_divisions); sprintf(string, "%d", freq); int x1 = canvas_x + i * canvas_w / freq_divisions; int x2 = x1 - parent->get_text_width(SMALLFONT, string); int y1 = canvas_y + canvas_h; int y2 = y1 + big_ytick; int y3 = y1 + small_ytick; int y4 = y2 + parent->get_text_ascent(SMALLFONT); // parent->set_color(BLACK); // parent->draw_text(x2 + 1, y4 + 1, string); // parent->draw_line(x1 + 1, y1 + 1, x1 + 1, y2 + 1); // parent->set_color(RED); parent->set_color(parent->get_resources()->default_text_color); parent->draw_text(x2, y4, string); parent->draw_line(x1, y1, x1, y2); if( i < freq_divisions ) { for( int j = 0; j < minor_divisions; j++ ) { int x3 = (int)(x1 + (canvas_w / freq_divisions) - exp(-(double)j * 0.7) * (canvas_w / freq_divisions)); // parent->set_color(BLACK); // parent->draw_line(x3 + 1, y1 + 1, x3 + 1, y3 + 1); // parent->set_color(RED); parent->set_color(parent->get_resources()->default_text_color); parent->draw_line(x3, y1, x3, y3); } } } draw_grid(); } void EQCanvas::draw_grid() { canvas->set_line_dashes(1); canvas->set_color(graph_grid_color); for( int i = minor_divisions; i < total_divisions; i += minor_divisions ) { int y = (int)(i * pixels_per_division); canvas->draw_line(0, y, canvas_w, y); } // for( int i = 1; i < major_divisions; i++ ) { // int y = canvas_h - i * canvas_h / major_divisions; // canvas->draw_line(0, y, canvas_w, y); // } for( int i = 1; i < freq_divisions; i++ ) { int x = i * canvas_w / freq_divisions; canvas->draw_line(x, 0, x, canvas_h); } canvas->set_line_dashes(0); } void EQCanvas::update_spectrogram(CompressorFreqFrame *frame, int offset, int size, int window_size) { //if( frame ) printf("EQCanvas::update_spectrogram %d frame->freq_max=%f frame->data=%p\n", // __LINE__, frame->freq_max, frame->data); canvas->set_color(graph_bg_color); canvas->draw_box(0, 0, canvas->get_w(), canvas->get_h()); draw_grid(); // Draw it if( frame && !EQUIV(frame->freq_max, 0.0) && frame->data ) { int y1 = 0, y2 = 0; if( offset < 0 ) { offset = 0; size = frame->data_size; window_size = frame->data_size * 2; } canvas->set_color(graph_inactive_color); if( !EQUIV(frame->freq_max, 0) ) { for( int i = 0; i < canvas->get_w(); i++ ) { int freq = Freq::tofreq(i * TOTALFREQS / canvas->get_w()); if( freq < frame->nyquist ) { int index = offset + (int64_t)freq * (int64_t)window_size / 2 / frame->nyquist; if( index < frame->data_size ) { double magnitude = frame->data[index] / frame->freq_max * frame->time_max; y2 = (int)(canvas->get_h() - (DB::todb(magnitude) - INFINITYGAIN) * canvas->get_h() / -INFINITYGAIN); CLAMP(y2, 0, canvas->get_h() - 1); if( i > 0 ) { canvas->draw_line(i - 1, y1, i, y2); } y1 = y2; } } else { // printf("EQCanvas::update_spectrogram %d i=%d freq=%d nyquist=%d\n", // __LINE__, i, freq, frame->nyquist); } } } } } void EQCanvas::draw_envelope(double *envelope, int samplerate, int window_size, int is_top, int flash_it) { int niquist = samplerate / 2; if( is_top ) { canvas->set_color(graph_active_color); canvas->set_line_width(2); } else { canvas->set_color(graph_inactive_color); canvas->set_line_width(1); } int y1; for( int i = 0; i < canvas->get_w(); i++ ) { int freq = Freq::tofreq(i * TOTALFREQS / canvas->get_w()); int index = (int64_t)freq * (int64_t)window_size / 2 / niquist; if( freq < niquist && index < window_size / 2 ) { double mag = envelope[index]; int y2 = (int)(DB::todb(mag) * canvas->get_h() / INFINITYGAIN); if( y2 >= canvas->get_h() ) { y2 = canvas->get_h() - 1; } if( i > 0 ) { canvas->draw_line(i - 1, y1, i, y2); } y1 = y2; } else if( i > 0 ) { int y2 = canvas->get_h() - 1; canvas->draw_line(i - 1, y1, i, y2); y1 = y2; } } canvas->set_line_width(1); if( flash_it ) { canvas->flash(1); } }