4 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcdisplayinfo.h"
23 #include "bcsignals.h"
41 #define MAJOR_DIVISIONS 7
42 #define MINOR_DIVISIONS 5
43 #define LINE_W4 xS(12)
44 #define LINE_W3 xS(10)
55 REGISTER_PLUGIN(GraphicEQ)
63 GraphicPoint::GraphicPoint()
76 GraphicConfig::GraphicConfig()
79 // wetness = INFINITYGAIN;
82 GraphicConfig::~GraphicConfig()
84 points.remove_all_objects();
88 int GraphicConfig::equivalent(GraphicConfig &that)
90 if(that.points.size() != points.size() ||
91 window_size != that.window_size) return 0;
93 for(int i = 0; i < points.size(); i++)
95 if(that.points.get(i)->freq != points.get(i)->freq ||
96 !EQUIV(that.points.get(i)->value, points.get(i)->value))
104 void GraphicConfig::copy_from(GraphicConfig &that)
106 points.remove_all_objects();
107 for(int i = 0; i < that.points.size(); i++)
110 points.append(point = new GraphicPoint);
111 point->freq = that.points.get(i)->freq;
112 point->value = that.points.get(i)->value;
115 window_size = that.window_size;
118 void GraphicConfig::interpolate(GraphicConfig &prev,
122 int64_t current_frame)
124 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
125 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
127 // Get current set of points from previous configuration
131 // Interpolate between current set of points and next set
132 for(int i = 0; i < MIN(next.points.size(), points.size()); i++)
134 points.get(i)->freq = (int)(prev.points.get(i)->freq *
136 next.points.get(i)->freq *
138 points.get(i)->value = prev.points.get(i)->value *
140 next.points.get(i)->value *
146 void GraphicConfig::delete_point(int number)
148 points.remove_object_number(number);
157 GraphicCanvas::GraphicCanvas(GraphicEQ *plugin,
169 this->plugin = plugin;
171 state = GraphicCanvas::NONE;
174 GraphicCanvas::~GraphicCanvas()
176 temp_points.remove_all_objects();
179 int GraphicCanvas::button_press_event()
182 if(state == GraphicCanvas::DRAG_POINT)
188 int GraphicCanvas::cursor_motion_event()
192 if(state == GraphicCanvas::DRAG_POINT)
200 int GraphicCanvas::button_release_event()
202 if(state == GraphicCanvas::DRAG_POINT && plugin->active_point >= 0)
204 // Delete point if out of order
205 int point_number = plugin->active_point;
206 GraphicPoint *active_point = temp_points.get(point_number);
209 for(int i = 0; i < temp_points.size(); i++)
211 GraphicPoint *point = temp_points.get(i);
212 if((point->freq <= active_point->freq && i > point_number) ||
213 (point->freq >= active_point->freq && i < point_number))
215 temp_points.remove_object_number(point_number);
216 plugin->active_point = -1;
223 plugin->send_configure_change();
226 state = GraphicCanvas::NONE;
230 #define BOX_SIZE xS(10)
232 int GraphicCanvas::freq_to_y(int freq,
233 ArrayList<GraphicPoint*> *points,
236 int center_y = get_h() / 2;
237 double magnitude = plugin->freq_to_magnitude(freq, points, envelope);
238 double magnitude_db = DB::todb(magnitude);
239 if(magnitude_db < -MAXMAGNITUDE) magnitude_db = -MAXMAGNITUDE;
240 int y = (int)(center_y - magnitude_db * center_y / MAXMAGNITUDE);
241 //printf("GraphicCanvas::freq_to_y magnitude=%f magnitude_db=%f y=%d\n",
242 //magnitude, magnitude_db, y);
247 void GraphicCanvas::new_temps()
249 // Copy configuration from plugin for editing
250 temp_points.remove_all_objects();
251 for(int i = 0; i < plugin->config.points.size(); i++)
253 GraphicPoint *point = new GraphicPoint;
254 *point = *plugin->config.points.get(i);
255 temp_points.append(point);
258 plugin->calculate_envelope(&temp_points, temp_envelope);
261 void GraphicCanvas::save_temps()
263 plugin->config.points.remove_all_objects();
264 for(int i = 0; i < temp_points.size(); i++)
267 plugin->config.points.append(point = new GraphicPoint);
268 *point = *temp_points.get(i);
273 void GraphicCanvas::insert_point(GraphicPoint *point)
277 temp_points.append(point);
281 for(int i = 0; i < temp_points.size() - 1; i++)
283 if(temp_points.get(i)->freq > temp_points.get(i + 1)->freq)
285 GraphicPoint *point = temp_points.get(i);
286 temp_points.set(i, temp_points.get(i + 1));
287 temp_points.set(i + 1, point);
295 void GraphicCanvas::process(int buttonpress, int motion, int draw)
298 int center_y = get_h() / 2;
299 int out_of_order = 0;
300 ArrayList<GraphicPoint*> *points;
302 //const int debug = 0;
305 if(state == GraphicCanvas::NONE)
307 points = &plugin->config.points;
308 envelope = plugin->envelope;
312 points = &temp_points;
313 envelope = temp_envelope;
316 plugin->calculate_envelope(points, envelope);
322 clear_box(0, 0, get_w(), get_h());
323 int niquist = plugin->PluginAClient::project_sample_rate / 2;
325 // delete frames up to current tracking position
326 double tracking_position = plugin->get_tracking_position();
327 GraphicGUIFrame *frame = (GraphicGUIFrame *)
328 plugin->get_gui_frame(tracking_position, 1);
333 for(int i = 0; i < get_w(); i++)
335 int freq = Freq::tofreq(i * TOTALFREQS / get_w());
336 int index = (int64_t)freq * (int64_t)frame->window_size / 2 / niquist;
337 if(index < frame->window_size / 2)
339 double magnitude = frame->data[index] /
343 (DB::todb(magnitude) - INFINITYGAIN) *
346 CLAMP(y2, 0, get_h() - 1);
349 draw_line(i - 1, y1, i, y2);
350 //printf(" %.0f", frame->data[index]);
360 // Determine if active point is out of order
361 if(plugin->active_point_exists())
363 GraphicPoint *active_point = points->get(plugin->active_point);
364 for(int i = 0; i < points->size(); i++)
366 if(i == plugin->active_point)
368 if( (i < points->size() - 1 &&
369 active_point->freq >= points->get(i + 1)->freq) ||
371 active_point->freq <= points->get(i - 1)->freq) )
383 if(state == GraphicCanvas::DRAG_POINT)
385 int point_x = get_cursor_x() + x_diff;
386 int point_y = get_cursor_y() + y_diff;
387 CLAMP(point_x, 0, get_w());
388 CLAMP(point_y, 0, get_h());
390 int frequency = Freq::tofreq(point_x * TOTALFREQS / get_w());
391 double magnitude_db = (double)(center_y - point_y) * MAXMAGNITUDE / center_y;
392 int minfreq = Freq::tofreq(0);
393 int maxfreq = Freq::tofreq(TOTALFREQS - 1);
395 CLAMP(frequency, minfreq, maxfreq);
396 CLAMP(magnitude_db, -MAXMAGNITUDE, MAXMAGNITUDE);
397 if(plugin->active_point >= 0)
399 GraphicPoint *active_point = points->get(plugin->active_point);
400 active_point->freq = frequency;
401 active_point->value = magnitude_db;
404 // Redraw with new value
407 plugin->send_configure_change();
408 gui->update_textboxes();
418 for(int i = 1; i < MAJOR_DIVISIONS; i++)
420 int y = i * get_h() / (MAJOR_DIVISIONS - 1);
421 draw_line(0, y, get_w(), y);
427 if(draw) set_color(WHITE);
429 // Control points, cursor change and control point selection
430 int new_cursor = CROSS_CURSOR;
431 for(int i = 0; i < points->size(); i++)
433 GraphicPoint *point = points->get(i);
434 int x = Freq::fromfreq(point->freq) * get_w() / TOTALFREQS;
435 int y = freq_to_y(point->freq, points, envelope);
440 // Draw point under cursor if out of order
441 if(i == plugin->active_point && out_of_order)
442 y1 = get_cursor_y() + y_diff;
444 if(i == plugin->active_point)
445 draw_box(x - BOX_SIZE / 2, y1 - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
447 draw_rectangle(x - BOX_SIZE / 2, y1 - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
451 state == GraphicCanvas::NONE &&
455 if(get_cursor_x() >= x - BOX_SIZE / 2 &&
456 get_cursor_y() >= y - BOX_SIZE / 2 &&
457 get_cursor_x() < x + BOX_SIZE / 2 &&
458 get_cursor_y() < y + BOX_SIZE / 2)
460 new_cursor = UPRIGHT_ARROW_CURSOR;
465 state == GraphicCanvas::NONE &&
470 if(get_cursor_x() >= x - BOX_SIZE / 2 &&
471 get_cursor_y() >= y - BOX_SIZE / 2 &&
472 get_cursor_x() < x + BOX_SIZE / 2 &&
473 get_cursor_y() < y + BOX_SIZE / 2)
475 plugin->active_point = i;
476 state = GraphicCanvas::DRAG_POINT;
478 points = &temp_points;
479 envelope = temp_envelope;
481 x_diff = x - get_cursor_x();
482 y_diff = y - get_cursor_y();
486 plugin->send_configure_change();
487 gui->update_textboxes();
492 if(motion && new_cursor != get_cursor())
494 set_cursor(new_cursor, 0, 1);
500 for(int i = 0; i < get_w(); i++)
502 int y = freq_to_y(Freq::tofreq(i * TOTALFREQS / get_w()),
508 if(i > 0) draw_line(i - 1, y1, i, y);
516 if(buttonpress && !got_button)
518 if(is_event_win() && cursor_inside())
520 GraphicPoint *new_point = new GraphicPoint;
521 new_point->freq = Freq::tofreq(get_cursor_x() *
524 new_point->value = (double)(center_y - get_cursor_y()) *
527 state = GraphicCanvas::DRAG_POINT;
529 points = &temp_points;
530 envelope = temp_envelope;
532 insert_point(new_point);
533 plugin->active_point = points->number_of(new_point);
537 // Redraw with new point
540 plugin->send_configure_change();
541 gui->update_textboxes();
560 FreqTextBox::FreqTextBox(GraphicEQ *plugin,
565 : BC_TextBox(x, y, w, 1, "")
567 this->plugin = plugin;
571 int FreqTextBox::handle_event()
573 if(plugin->active_point_exists())
575 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
576 if(atoi(get_text()) != active_point->freq)
578 active_point->freq = atoi(get_text());
579 gui->update_canvas();
580 plugin->send_configure_change();
588 void FreqTextBox::update(int freq)
590 if(plugin->active_point_exists())
592 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
593 if(atoi(get_text()) != active_point->freq)
595 char string[BCTEXTLEN];
596 sprintf(string, "%d", active_point->freq);
597 BC_TextBox::update(string);
605 ValueTextBox::ValueTextBox(GraphicEQ *plugin,
610 : BC_TextBox(x, y, w, 1, "")
612 this->plugin = plugin;
616 int ValueTextBox::handle_event()
618 if(plugin->active_point_exists())
620 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
621 if(!EQUIV(atof(get_text()), active_point->value))
623 active_point->value = atof(get_text());
624 gui->update_canvas();
625 plugin->send_configure_change();
633 void ValueTextBox::update(float value)
635 if(plugin->active_point_exists())
637 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
638 if(!EQUIV(atof(get_text()), active_point->value))
640 char string[BCTEXTLEN];
641 sprintf(string, "%.04f", active_point->value);
642 BC_TextBox::update(string);
647 GraphicReset::GraphicReset(GraphicEQ *plugin,
651 : BC_GenericButton(x, y, _("Reset"))
653 this->plugin = plugin;
657 int GraphicReset::handle_event()
659 plugin->config.points.remove_all_objects();
660 plugin->active_point = -1;
661 gui->update_canvas();
662 gui->update_textboxes();
663 plugin->send_configure_change();
671 GraphicSize::GraphicSize(GraphicGUI *window, GraphicEQ *plugin, int x, int y)
672 : BC_PopupMenu(x, y, xS(120), "4096", 1)
674 this->plugin = plugin;
675 this->window = window;
679 int GraphicSize::handle_event()
681 plugin->config.window_size = atoi(get_text());
682 plugin->send_configure_change();
684 window->update_canvas();
688 void GraphicSize::create_objects()
690 add_item(new BC_MenuItem("2048"));
691 add_item(new BC_MenuItem("4096"));
692 add_item(new BC_MenuItem("8192"));
693 add_item(new BC_MenuItem("16384"));
694 add_item(new BC_MenuItem("32768"));
695 add_item(new BC_MenuItem("65536"));
696 add_item(new BC_MenuItem("131072"));
697 add_item(new BC_MenuItem("262144"));
700 void GraphicSize::update(int size)
702 char string[BCTEXTLEN];
703 sprintf(string, "%d", size);
712 // GraphicWetness::GraphicWetness(GraphicGUI *window, GraphicEQ *plugin, int x, int y)
713 // : BC_FPot(x, y, plugin->config.wetness, INFINITYGAIN, 0)
715 // this->plugin = plugin;
716 // this->window = window;
719 // int GraphicWetness::handle_event()
721 // plugin->config.wetness = get_value();
722 // plugin->send_configure_change();
723 // window->update_canvas();
735 GraphicGUI::GraphicGUI(GraphicEQ *plugin)
736 : PluginClientWindow(plugin,
743 this->plugin = plugin;
746 GraphicGUI::~GraphicGUI()
751 void GraphicGUI::create_objects()
753 int margin = plugin->get_theme()->widget_border;
754 int x = get_text_width(SMALLFONT, "-00") + LINE_W4 + margin;
756 int freq_h = get_text_height(SMALLFONT) + LINE_W4;
758 add_subwindow(canvas = new GraphicCanvas(plugin,
762 get_w() - x - margin,
764 // BC_Pot::calculate_h() -
765 BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1) -
769 y += canvas->get_h() + freq_h + margin;
773 add_subwindow(freq_title = new BC_Title(x, y, _("Frequency:")));
774 x += freq_title->get_w() + margin;
775 add_subwindow(freq_text = new FreqTextBox(plugin, this, x, y, xS(100)));
776 x += freq_text->get_w() + margin;
778 add_subwindow(level_title = new BC_Title(x, y, _("Level:")));
779 x += level_title->get_w() + margin;
780 add_subwindow(value_text = new ValueTextBox(plugin, this, x, y, xS(100)));
781 x += value_text->get_w() + margin;
783 add_subwindow(reset = new GraphicReset(plugin, this, x, y));
784 x += reset->get_w() + margin;
788 // y += value_text->get_h() + margin;
790 add_subwindow(size_title = new BC_Title(x, y, _("Window size:")));
791 x += size_title->get_w() + margin;
792 add_subwindow(size = new GraphicSize(this, plugin, x, y));
793 size->create_objects();
794 size->update(plugin->config.window_size);
795 x += size->get_w() + margin;
797 // add_subwindow(title = new BC_Title(x, y, "Wetness:"));
798 // x += title->get_w() + margin;
799 // add_subwindow(wetness = new GraphicWetness(this, plugin,
809 int GraphicGUI::resize_event(int w, int h)
811 int difference = h - get_h();
812 int canvas_xdiff = get_w() - canvas->get_w();
813 int canvas_ydiff = get_h() - canvas->get_h();
815 canvas->reposition_window(canvas->get_x(),
819 freq_text->reposition_window(freq_text->get_x(),
820 freq_text->get_y() + difference);
821 value_text->reposition_window(value_text->get_x(),
822 value_text->get_y() + difference);
823 freq_title->reposition_window(freq_title->get_x(),
824 freq_title->get_y() + difference);
825 level_title->reposition_window(level_title->get_x(),
826 level_title->get_y() + difference);
827 size_title->reposition_window(size_title->get_x(),
828 size_title->get_y() + difference);
829 reset->reposition_window(reset->get_x(),
830 reset->get_y() + difference);
831 size->reposition_window(size->get_x(),
832 size->get_y() + difference);
840 plugin->send_configure_change();
849 int GraphicGUI::keypress_event()
851 if(get_keypress() == BACKSPACE ||
852 get_keypress() == DELETE)
854 if(plugin->active_point_exists())
856 int point_number = -1;
857 for(int i = 0; i < plugin->config.points.size(); i++)
859 if(i == plugin->active_point)
866 if(point_number >= 0)
868 plugin->config.delete_point(point_number);
869 canvas->process(0, 0, 1);
870 plugin->send_configure_change();
879 void GraphicGUI::draw_ticks()
881 //int x = canvas->get_x() - 5 - get_text_width(SMALLFONT, "-00");
882 int y = canvas->get_y() - 1;
883 int x1 = canvas->get_x() - LINE_W3;
884 int x2 = canvas->get_x() - LINE_W2;
885 int x3 = canvas->get_x() - LINE_W1;
886 char string[BCTEXTLEN];
890 int major_division = canvas->get_h() / (MAJOR_DIVISIONS - 1);
891 for(int i = 0; i < MAJOR_DIVISIONS; i++)
893 int current_db = (MAJOR_DIVISIONS - 1 - i) * (MAX_DB - MIN_DB) / (MAJOR_DIVISIONS - 1) + MIN_DB;
894 if(current_db == MIN_DB)
895 sprintf(string, "oo");
897 if(current_db <= 0.0)
898 sprintf(string, "%d", current_db);
900 sprintf(string, "+%d", current_db);
903 int y1 = y + 1 + i * canvas->get_h() / (MAJOR_DIVISIONS - 1);
904 int x4 = canvas->get_x() - LINE_W4 - get_text_width(SMALLFONT, string);
905 draw_text(x4 + 1, y1 + get_text_ascent(SMALLFONT) / 2 + 1, string);
906 draw_line(x1 + 1, y1 + 1, x3 + 1, y1 + 1);
908 draw_text(x4, y1 + get_text_ascent(SMALLFONT) / 2, string);
909 draw_line(x1, y1, x3, y1);
912 if(i < MAJOR_DIVISIONS - 1)
914 for(int j = 0; j < MINOR_DIVISIONS; j++)
916 int y2 = y1 + j * major_division / MINOR_DIVISIONS;
918 draw_line(x2 + 1, y2 + 1, x3 + 1, y2 + 1);
920 draw_line(x2, y2, x3, y2);
927 for(int i = 0; i <= MAJOR_DIVISIONS; i++)
929 int freq = Freq::tofreq(i * TOTALFREQS / MAJOR_DIVISIONS);
930 char string[BCTEXTLEN];
931 x1 = canvas->get_x() + i * canvas->get_w() / MAJOR_DIVISIONS;
932 int y1 = canvas->get_y() + canvas->get_h() + LINE_W1 - 1;
933 sprintf(string, "%d", freq);
934 int x2 = x1 - get_text_width(SMALLFONT, string);
935 int y2 = canvas->get_y() + canvas->get_h() + LINE_W2 - 1;
936 int y3 = canvas->get_y() + canvas->get_h() + LINE_W3 - 1;
937 int y4 = canvas->get_y() + canvas->get_h() + get_text_height(SMALLFONT) + LINE_W4 - 1;
940 draw_text(x2 + 1, y4 + 1, string);
941 draw_line(x1 + 1, y3 + 1, x1 + 1, y1 + 1);
944 draw_text(x2, y4, string);
945 draw_line(x1, y3, x1, y1);
947 if(i < MAJOR_DIVISIONS)
949 for(int j = 0; j < MINOR_DIVISIONS; j++)
952 (canvas->get_w() / MAJOR_DIVISIONS) -
953 exp(-(double)j * 0.7) *
954 (canvas->get_w() / MAJOR_DIVISIONS));
956 draw_line(x3 + 1, y2 + 1, x3 + 1, y1 + 1);
958 draw_line(x3, y2, x3, y1);
964 void GraphicGUI::update_canvas()
966 canvas->process(0, 0, 1);
969 void GraphicGUI::update_textboxes()
971 if(plugin->active_point_exists())
973 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
974 freq_text->update(active_point->freq);
975 value_text->update(active_point->value);
980 GraphicEQ::GraphicEQ(PluginServer *server)
981 : PluginAClient(server)
985 need_reconfigure = 1;
991 GraphicEQ::~GraphicEQ()
999 int GraphicEQ::is_realtime() { return 1; }
1001 const char* GraphicEQ::plugin_title() { return N_("EQ Graphic"); }
1003 NEW_WINDOW_MACRO(GraphicEQ, GraphicGUI)
1005 LOAD_CONFIGURATION_MACRO(GraphicEQ, GraphicConfig)
1007 int GraphicEQ::active_point_exists()
1009 if(active_point >= 0 && active_point < config.points.size()) return 1;
1014 void GraphicEQ::read_data(KeyFrame *keyframe)
1019 input.set_shared_input(keyframe->xbuf);
1020 config.points.remove_all_objects();
1022 while( !(result = input.read_tag()) ) {
1023 if(input.tag.title_is("GRAPHICEQ")) {
1024 config.window_size = input.tag.get_property("WINDOW_SIZE", config.window_size);
1026 w = input.tag.get_property("W", w);
1027 h = input.tag.get_property("H", h);
1030 else if(input.tag.title_is("POINT")) {
1031 GraphicPoint *point;
1032 config.points.append(point = new GraphicPoint);
1033 point->freq = input.tag.get_property("X", 0);
1034 point->value = input.tag.get_property("Y", 0.0);
1037 // if(!active_point_exists()) active_point = -1;
1043 void GraphicEQ::save_data(KeyFrame *keyframe)
1046 output.set_shared_output(keyframe->xbuf);
1048 output.tag.set_title("GRAPHICEQ");
1049 output.tag.set_property("WINDOW_SIZE", config.window_size);
1050 output.tag.set_property("W", w);
1051 output.tag.set_property("H", h);
1052 output.append_tag();
1053 output.tag.set_title("/GRAPHICEQ");
1054 output.append_tag();
1055 output.append_newline();
1057 for(int i = 0; i < config.points.total; i++) {
1058 output.tag.set_title("POINT");
1059 output.tag.set_property("X", config.points.values[i]->freq);
1060 output.tag.set_property("Y", config.points.values[i]->value);
1061 output.append_tag();
1062 output.tag.set_title("/POINT");
1063 output.append_tag();
1064 output.append_newline();
1067 output.terminate_string();
1071 void GraphicEQ::update_gui()
1073 if( !thread ) return;
1074 GraphicGUI *window = (GraphicGUI *)thread->window;
1075 window->lock_window("GraphicEQ::update_gui");
1076 //lock here for points, needed by window cursor_motion callback
1077 // deleted in load_configuration by read_data
1078 if( load_configuration() &&
1079 window->canvas->state != GraphicCanvas::DRAG_POINT ) {
1080 window->update_canvas();
1081 window->update_textboxes();
1083 else if( pending_gui_frame() ) {
1084 window->update_canvas();
1086 window->unlock_window();
1089 void GraphicEQ::reconfigure()
1091 if(fft && fft->window_size != config.window_size) {
1097 fft = new GraphicFFT(this);
1098 fft->initialize(config.window_size);
1101 calculate_envelope(&config.points, envelope);
1103 for(int i = 0; i < config.window_size / 2; i++) {
1104 if(envelope[i] < 0) envelope[i] = 0;
1107 need_reconfigure = 0;
1110 int GraphicEQ::process_buffer(int64_t size,
1112 int64_t start_position,
1115 need_reconfigure |= load_configuration();
1116 if(need_reconfigure) reconfigure();
1118 fft->process_buffer(start_position, size, buffer, get_direction());
1125 double GraphicEQ::freq_to_magnitude(double frequency,
1126 ArrayList<GraphicPoint*> *points,
1129 // Calculate using control points
1130 for(int i = 0; i < points->size(); i++)
1132 GraphicPoint *point = points->get(i);
1133 if(point->freq == (int)frequency)
1135 return DB::fromdb(point->value);
1140 int nyquist = PluginAClient::project_sample_rate / 2;
1141 int slot = (int)(frequency * config.window_size / 2 / nyquist);
1142 if(slot >= config.window_size / 2) slot = config.window_size / 2 - 1;
1143 //printf("GraphicEQ::freq_to_db %d %f\n", slot, envelope[slot]);
1144 return envelope[slot];
1148 void GraphicEQ::calculate_envelope(ArrayList<GraphicPoint*> *points,
1151 int niquist = PluginAClient::project_sample_rate / 2;
1153 // Make temporary list of just points in order
1154 ArrayList<GraphicPoint*> temp_points;
1155 for(int i = 0; i < points->size(); i++)
1157 temp_points.append(points->get(i));
1160 for(int i = 0; i < temp_points.size(); i++)
1162 GraphicPoint *point = temp_points.get(i);
1163 if(i == active_point)
1165 GraphicPoint *prev_point = 0;
1166 GraphicPoint *next_point = 0;
1167 if(i >= 1) prev_point = temp_points.get(i - 1);
1168 if(i < temp_points.size() - 1) next_point = temp_points.get(i + 1);
1169 if( (prev_point && prev_point->freq >= point->freq) ||
1170 (next_point && next_point->freq <= point->freq) )
1171 temp_points.remove_number(i);
1178 if(temp_points.size())
1180 GraphicPoint *first_point = temp_points.get(0);
1181 GraphicPoint *last_point = temp_points.get(temp_points.size() - 1);
1182 for(int i = 0; i < config.window_size / 2; i++)
1184 int freq = i * niquist / (config.window_size / 2);
1185 if(freq <= first_point->freq)
1186 envelope[i] = first_point->value;
1188 if(freq >= last_point->freq)
1189 envelope[i] = last_point->value;
1192 GraphicPoint *point1 = first_point;
1193 GraphicPoint *point2 = last_point;
1194 for(int j = 0; j < temp_points.size(); j++)
1196 if(temp_points.get(j)->freq <= freq)
1197 point1 = temp_points.get(j);
1200 point2 = temp_points.get(j);
1205 if(point2->freq != point1->freq)
1207 int freqslot1 = Freq::fromfreq(point1->freq);
1208 int freqslot2 = Freq::fromfreq(point2->freq);
1209 int freqslot = Freq::fromfreq(freq);
1211 envelope[i] = (double)(freqslot - freqslot1) *
1212 (point2->value - point1->value) /
1213 (freqslot2 - freqslot1) +
1217 envelope[i] = point1->value;
1221 if(envelope[i] < MIN_DB + 0.01)
1224 envelope[i] = DB::fromdb(envelope[i]);
1229 for(int i = 0; i < config.window_size / 2; i++)
1237 GraphicGUIFrame::GraphicGUIFrame(int window_size, int sample_rate)
1238 : PluginClientFrame()
1240 this->window_size = window_size;
1241 data_size = window_size / 2;
1242 data = new double[data_size];
1247 GraphicGUIFrame::~GraphicGUIFrame()
1253 GraphicFFT::GraphicFFT(GraphicEQ *plugin)
1256 this->plugin = plugin;
1259 GraphicFFT::~GraphicFFT()
1264 int GraphicFFT::signal_process()
1266 // Create new frame for updating GUI
1267 frame = new GraphicGUIFrame(window_size,
1268 plugin->PluginAClient::project_sample_rate);
1269 plugin->add_gui_frame(frame);
1271 double freq_max = 0;
1272 for(int i = 0; i < window_size / 2; i++)
1274 double result = plugin->envelope[i] * sqrt(freq_real[i] * freq_real[i] + freq_imag[i] * freq_imag[i]);
1275 double angle = atan2(freq_imag[i], freq_real[i]);
1276 freq_real[i] = result * cos(angle);
1277 freq_imag[i] = result * sin(angle);
1278 frame->data[i] = result;
1279 if(result > freq_max) freq_max = result;
1281 frame->freq_max = freq_max;
1283 symmetry(window_size, freq_real, freq_imag);
1288 int GraphicFFT::post_process()
1290 double time_max = 0;
1291 for(int i = 0; i < window_size; i++)
1293 if(output_real[i] > time_max) time_max = output_real[i];
1295 frame->time_max = time_max;
1301 int GraphicFFT::read_samples(int64_t output_sample,
1305 return plugin->read_samples(buffer,
1307 plugin->get_samplerate(),