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());
325 int niquist = plugin->PluginAClient::project_sample_rate / 2;
326 int total_frames = plugin->get_gui_update_frames();
327 GraphicGUIFrame *frame = (GraphicGUIFrame*)plugin->get_gui_frame();
331 delete plugin->last_frame;
332 plugin->last_frame = frame;
336 frame = plugin->last_frame;
339 // Draw most recent frame
347 for(int i = 0; i < get_w(); i++)
349 int freq = Freq::tofreq(i * TOTALFREQS / get_w());
350 int index = (int64_t)freq * (int64_t)frame->window_size / 2 / niquist;
351 if(index < frame->window_size / 2)
353 double magnitude = frame->data[index] /
357 (DB::todb(magnitude) - INFINITYGAIN) *
360 CLAMP(y2, 0, get_h() - 1);
363 draw_line(i - 1, y1, i, y2);
364 //printf(" %.0f", frame->data[index]);
379 // Delete remaining frames
380 while(total_frames > 0)
382 PluginClientFrame *frame = plugin->get_gui_frame();
384 if(frame) delete frame;
390 // Determine if active point is out of order
391 if(plugin->active_point_exists())
393 GraphicPoint *active_point = points->get(plugin->active_point);
394 for(int i = 0; i < points->size(); i++)
396 if(i == plugin->active_point)
398 if( (i < points->size() - 1 &&
399 active_point->freq >= points->get(i + 1)->freq) ||
401 active_point->freq <= points->get(i - 1)->freq) )
413 if(state == GraphicCanvas::DRAG_POINT)
415 int point_x = get_cursor_x() + x_diff;
416 int point_y = get_cursor_y() + y_diff;
417 CLAMP(point_x, 0, get_w());
418 CLAMP(point_y, 0, get_h());
420 int frequency = Freq::tofreq(point_x * TOTALFREQS / get_w());
421 double magnitude_db = (double)(center_y - point_y) * MAXMAGNITUDE / center_y;
422 int minfreq = Freq::tofreq(0);
423 int maxfreq = Freq::tofreq(TOTALFREQS - 1);
425 CLAMP(frequency, minfreq, maxfreq);
426 CLAMP(magnitude_db, -MAXMAGNITUDE, MAXMAGNITUDE);
427 if(plugin->active_point >= 0)
429 GraphicPoint *active_point = points->get(plugin->active_point);
430 active_point->freq = frequency;
431 active_point->value = magnitude_db;
434 // Redraw with new value
437 plugin->send_configure_change();
438 gui->update_textboxes();
448 for(int i = 1; i < MAJOR_DIVISIONS; i++)
450 int y = i * get_h() / (MAJOR_DIVISIONS - 1);
451 draw_line(0, y, get_w(), y);
457 if(draw) set_color(WHITE);
459 // Control points, cursor change and control point selection
460 int new_cursor = CROSS_CURSOR;
461 for(int i = 0; i < points->size(); i++)
463 GraphicPoint *point = points->get(i);
464 int x = Freq::fromfreq(point->freq) * get_w() / TOTALFREQS;
465 int y = freq_to_y(point->freq, points, envelope);
470 // Draw point under cursor if out of order
471 if(i == plugin->active_point && out_of_order)
472 y1 = get_cursor_y() + y_diff;
474 if(i == plugin->active_point)
475 draw_box(x - BOX_SIZE / 2, y1 - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
477 draw_rectangle(x - BOX_SIZE / 2, y1 - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
481 state == GraphicCanvas::NONE &&
485 if(get_cursor_x() >= x - BOX_SIZE / 2 &&
486 get_cursor_y() >= y - BOX_SIZE / 2 &&
487 get_cursor_x() < x + BOX_SIZE / 2 &&
488 get_cursor_y() < y + BOX_SIZE / 2)
490 new_cursor = UPRIGHT_ARROW_CURSOR;
495 state == GraphicCanvas::NONE &&
500 if(get_cursor_x() >= x - BOX_SIZE / 2 &&
501 get_cursor_y() >= y - BOX_SIZE / 2 &&
502 get_cursor_x() < x + BOX_SIZE / 2 &&
503 get_cursor_y() < y + BOX_SIZE / 2)
505 plugin->active_point = i;
506 state = GraphicCanvas::DRAG_POINT;
508 points = &temp_points;
509 envelope = temp_envelope;
511 x_diff = x - get_cursor_x();
512 y_diff = y - get_cursor_y();
516 plugin->send_configure_change();
517 gui->update_textboxes();
522 if(motion && new_cursor != get_cursor())
524 set_cursor(new_cursor, 0, 1);
530 for(int i = 0; i < get_w(); i++)
532 int y = freq_to_y(Freq::tofreq(i * TOTALFREQS / get_w()),
538 if(i > 0) draw_line(i - 1, y1, i, y);
546 if(buttonpress && !got_button)
548 if(is_event_win() && cursor_inside())
550 GraphicPoint *new_point = new GraphicPoint;
551 new_point->freq = Freq::tofreq(get_cursor_x() *
554 new_point->value = (double)(center_y - get_cursor_y()) *
557 state = GraphicCanvas::DRAG_POINT;
559 points = &temp_points;
560 envelope = temp_envelope;
562 insert_point(new_point);
563 plugin->active_point = points->number_of(new_point);
567 // Redraw with new point
570 plugin->send_configure_change();
571 gui->update_textboxes();
590 FreqTextBox::FreqTextBox(GraphicEQ *plugin,
595 : BC_TextBox(x, y, w, 1, "")
597 this->plugin = plugin;
601 int FreqTextBox::handle_event()
603 if(plugin->active_point_exists())
605 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
606 if(atoi(get_text()) != active_point->freq)
608 active_point->freq = atoi(get_text());
609 gui->update_canvas();
610 plugin->send_configure_change();
618 void FreqTextBox::update(int freq)
620 if(plugin->active_point_exists())
622 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
623 if(atoi(get_text()) != active_point->freq)
625 char string[BCTEXTLEN];
626 sprintf(string, "%d", active_point->freq);
627 BC_TextBox::update(string);
635 ValueTextBox::ValueTextBox(GraphicEQ *plugin,
640 : BC_TextBox(x, y, w, 1, "")
642 this->plugin = plugin;
646 int ValueTextBox::handle_event()
648 if(plugin->active_point_exists())
650 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
651 if(!EQUIV(atof(get_text()), active_point->value))
653 active_point->value = atof(get_text());
654 gui->update_canvas();
655 plugin->send_configure_change();
663 void ValueTextBox::update(float value)
665 if(plugin->active_point_exists())
667 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
668 if(!EQUIV(atof(get_text()), active_point->value))
670 char string[BCTEXTLEN];
671 sprintf(string, "%.04f", active_point->value);
672 BC_TextBox::update(string);
677 GraphicReset::GraphicReset(GraphicEQ *plugin,
681 : BC_GenericButton(x, y, _("Reset"))
683 this->plugin = plugin;
687 int GraphicReset::handle_event()
689 plugin->config.points.remove_all_objects();
690 plugin->active_point = -1;
691 gui->update_canvas();
692 gui->update_textboxes();
693 plugin->send_configure_change();
701 GraphicSize::GraphicSize(GraphicGUI *window, GraphicEQ *plugin, int x, int y)
702 : BC_PopupMenu(x, y, xS(100), "4096", 1)
704 this->plugin = plugin;
705 this->window = window;
709 int GraphicSize::handle_event()
711 plugin->config.window_size = atoi(get_text());
712 plugin->send_configure_change();
714 window->update_canvas();
718 void GraphicSize::create_objects()
720 add_item(new BC_MenuItem("2048"));
721 add_item(new BC_MenuItem("4096"));
722 add_item(new BC_MenuItem("8192"));
723 add_item(new BC_MenuItem("16384"));
724 add_item(new BC_MenuItem("32768"));
725 add_item(new BC_MenuItem("65536"));
726 add_item(new BC_MenuItem("131072"));
727 add_item(new BC_MenuItem("262144"));
730 void GraphicSize::update(int size)
732 char string[BCTEXTLEN];
733 sprintf(string, "%d", size);
742 // GraphicWetness::GraphicWetness(GraphicGUI *window, GraphicEQ *plugin, int x, int y)
743 // : BC_FPot(x, y, plugin->config.wetness, INFINITYGAIN, 0)
745 // this->plugin = plugin;
746 // this->window = window;
749 // int GraphicWetness::handle_event()
751 // plugin->config.wetness = get_value();
752 // plugin->send_configure_change();
753 // window->update_canvas();
765 GraphicGUI::GraphicGUI(GraphicEQ *plugin)
766 : PluginClientWindow(plugin,
773 this->plugin = plugin;
776 GraphicGUI::~GraphicGUI()
781 void GraphicGUI::create_objects()
783 int margin = plugin->get_theme()->widget_border;
784 int x = get_text_width(SMALLFONT, "-00") + LINE_W4 + margin;
786 int freq_h = get_text_height(SMALLFONT) + LINE_W4;
788 add_subwindow(canvas = new GraphicCanvas(plugin,
792 get_w() - x - margin,
794 // BC_Pot::calculate_h() -
795 BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1) -
799 y += canvas->get_h() + freq_h + margin;
803 add_subwindow(freq_title = new BC_Title(x, y, _("Frequency:")));
804 x += freq_title->get_w() + margin;
805 add_subwindow(freq_text = new FreqTextBox(plugin, this, x, y, xS(100)));
806 x += freq_text->get_w() + margin;
808 add_subwindow(level_title = new BC_Title(x, y, _("Level:")));
809 x += level_title->get_w() + margin;
810 add_subwindow(value_text = new ValueTextBox(plugin, this, x, y, xS(100)));
811 x += value_text->get_w() + margin;
813 add_subwindow(reset = new GraphicReset(plugin, this, x, y));
814 x += reset->get_w() + margin;
818 // y += value_text->get_h() + margin;
820 add_subwindow(size_title = new BC_Title(x, y, _("Window size:")));
821 x += size_title->get_w() + margin;
822 add_subwindow(size = new GraphicSize(this, plugin, x, y));
823 size->create_objects();
824 size->update(plugin->config.window_size);
825 x += size->get_w() + margin;
827 // add_subwindow(title = new BC_Title(x, y, "Wetness:"));
828 // x += title->get_w() + margin;
829 // add_subwindow(wetness = new GraphicWetness(this, plugin,
839 int GraphicGUI::resize_event(int w, int h)
841 int difference = h - get_h();
842 int canvas_xdiff = get_w() - canvas->get_w();
843 int canvas_ydiff = get_h() - canvas->get_h();
845 canvas->reposition_window(canvas->get_x(),
849 freq_text->reposition_window(freq_text->get_x(),
850 freq_text->get_y() + difference);
851 value_text->reposition_window(value_text->get_x(),
852 value_text->get_y() + difference);
853 freq_title->reposition_window(freq_title->get_x(),
854 freq_title->get_y() + difference);
855 level_title->reposition_window(level_title->get_x(),
856 level_title->get_y() + difference);
857 size_title->reposition_window(size_title->get_x(),
858 size_title->get_y() + difference);
859 reset->reposition_window(reset->get_x(),
860 reset->get_y() + difference);
861 size->reposition_window(size->get_x(),
862 size->get_y() + difference);
870 plugin->send_configure_change();
879 int GraphicGUI::keypress_event()
881 if(get_keypress() == BACKSPACE ||
882 get_keypress() == DELETE)
884 if(plugin->active_point_exists())
886 int point_number = -1;
887 for(int i = 0; i < plugin->config.points.size(); i++)
889 if(i == plugin->active_point)
896 if(point_number >= 0)
898 plugin->config.delete_point(point_number);
899 canvas->process(0, 0, 1);
900 plugin->send_configure_change();
909 void GraphicGUI::draw_ticks()
911 //int x = canvas->get_x() - 5 - get_text_width(SMALLFONT, "-00");
912 int y = canvas->get_y() - 1;
913 int x1 = canvas->get_x() - LINE_W3;
914 int x2 = canvas->get_x() - LINE_W2;
915 int x3 = canvas->get_x() - LINE_W1;
916 char string[BCTEXTLEN];
920 int major_division = canvas->get_h() / (MAJOR_DIVISIONS - 1);
921 for(int i = 0; i < MAJOR_DIVISIONS; i++)
923 int current_db = (MAJOR_DIVISIONS - 1 - i) * (MAX_DB - MIN_DB) / (MAJOR_DIVISIONS - 1) + MIN_DB;
924 if(current_db == MIN_DB)
925 sprintf(string, "oo");
927 if(current_db <= 0.0)
928 sprintf(string, "%d", current_db);
930 sprintf(string, "+%d", current_db);
933 int y1 = y + 1 + i * canvas->get_h() / (MAJOR_DIVISIONS - 1);
934 int x4 = canvas->get_x() - LINE_W4 - get_text_width(SMALLFONT, string);
935 draw_text(x4 + 1, y1 + get_text_ascent(SMALLFONT) / 2 + 1, string);
936 draw_line(x1 + 1, y1 + 1, x3 + 1, y1 + 1);
938 draw_text(x4, y1 + get_text_ascent(SMALLFONT) / 2, string);
939 draw_line(x1, y1, x3, y1);
942 if(i < MAJOR_DIVISIONS - 1)
944 for(int j = 0; j < MINOR_DIVISIONS; j++)
946 int y2 = y1 + j * major_division / MINOR_DIVISIONS;
948 draw_line(x2 + 1, y2 + 1, x3 + 1, y2 + 1);
950 draw_line(x2, y2, x3, y2);
957 for(int i = 0; i <= MAJOR_DIVISIONS; i++)
959 int freq = Freq::tofreq(i * TOTALFREQS / MAJOR_DIVISIONS);
960 char string[BCTEXTLEN];
961 x1 = canvas->get_x() + i * canvas->get_w() / MAJOR_DIVISIONS;
962 int y1 = canvas->get_y() + canvas->get_h() + LINE_W1 - 1;
963 sprintf(string, "%d", freq);
964 int x2 = x1 - get_text_width(SMALLFONT, string);
965 int y2 = canvas->get_y() + canvas->get_h() + LINE_W2 - 1;
966 int y3 = canvas->get_y() + canvas->get_h() + LINE_W3 - 1;
967 int y4 = canvas->get_y() + canvas->get_h() + get_text_height(SMALLFONT) + LINE_W4 - 1;
970 draw_text(x2 + 1, y4 + 1, string);
971 draw_line(x1 + 1, y3 + 1, x1 + 1, y1 + 1);
974 draw_text(x2, y4, string);
975 draw_line(x1, y3, x1, y1);
977 if(i < MAJOR_DIVISIONS)
979 for(int j = 0; j < MINOR_DIVISIONS; j++)
982 (canvas->get_w() / MAJOR_DIVISIONS) -
983 exp(-(double)j * 0.7) *
984 (canvas->get_w() / MAJOR_DIVISIONS));
986 draw_line(x3 + 1, y2 + 1, x3 + 1, y1 + 1);
988 draw_line(x3, y2, x3, y1);
994 void GraphicGUI::update_canvas()
996 canvas->process(0, 0, 1);
999 void GraphicGUI::update_textboxes()
1001 if(plugin->active_point_exists())
1003 GraphicPoint *active_point = plugin->config.points.get(plugin->active_point);
1004 freq_text->update(active_point->freq);
1005 value_text->update(active_point->value);
1027 GraphicEQ::GraphicEQ(PluginServer *server)
1028 : PluginAClient(server)
1032 need_reconfigure = 1;
1038 GraphicEQ::~GraphicEQ()
1046 int GraphicEQ::is_realtime() { return 1; }
1048 const char* GraphicEQ::plugin_title() { return N_("EQ Graphic"); }
1050 NEW_WINDOW_MACRO(GraphicEQ, GraphicGUI)
1052 LOAD_CONFIGURATION_MACRO(GraphicEQ, GraphicConfig)
1054 int GraphicEQ::active_point_exists()
1056 if(active_point >= 0 && active_point < config.points.size()) return 1;
1061 void GraphicEQ::read_data(KeyFrame *keyframe)
1066 input.set_shared_input(keyframe->xbuf);
1067 config.points.remove_all_objects();
1071 result = input.read_tag();
1075 if(input.tag.title_is("GRAPHICEQ"))
1077 config.window_size = input.tag.get_property("WINDOW_SIZE", config.window_size);
1080 w = input.tag.get_property("W", w);
1081 h = input.tag.get_property("H", h);
1085 if(input.tag.title_is("POINT"))
1087 GraphicPoint *point;
1088 config.points.append(point = new GraphicPoint);
1089 point->freq = input.tag.get_property("X", 0);
1090 point->value = input.tag.get_property("Y", 0.0);
1095 // if(!active_point_exists()) active_point = -1;
1101 void GraphicEQ::save_data(KeyFrame *keyframe)
1104 output.set_shared_output(keyframe->xbuf);
1106 output.tag.set_title("GRAPHICEQ");
1107 output.tag.set_property("WINDOW_SIZE", config.window_size);
1108 output.tag.set_property("W", w);
1109 output.tag.set_property("H", h);
1110 output.append_tag();
1111 output.tag.set_title("/GRAPHICEQ");
1112 output.append_tag();
1113 output.append_newline();
1115 for(int i = 0; i < config.points.total; i++)
1117 output.tag.set_title("POINT");
1118 output.tag.set_property("X", config.points.values[i]->freq);
1119 output.tag.set_property("Y", config.points.values[i]->value);
1120 output.append_tag();
1121 output.tag.set_title("/POINT");
1122 output.append_tag();
1123 output.append_newline();
1126 output.terminate_string();
1130 void GraphicEQ::update_gui()
1132 if( !thread ) return;
1133 GraphicGUI *window = (GraphicGUI *)thread->window;
1134 //lock here for points, needed by window cursor_motion callback
1135 // deleted in load_configuration by read_data
1136 window->lock_window("GraphicEQ::update_gui");
1137 if( load_configuration() &&
1138 window->canvas->state != GraphicCanvas::DRAG_POINT ) {
1139 window->update_canvas();
1140 window->update_textboxes();
1143 int total_frames = get_gui_update_frames();
1144 //printf("ParametricEQ::update_gui %d %d\n", __LINE__, total_frames);
1146 window->update_canvas();
1148 window->unlock_window();
1151 void GraphicEQ::reconfigure()
1153 if(fft && fft->window_size != config.window_size)
1161 fft = new GraphicFFT(this);
1162 fft->initialize(config.window_size);
1165 calculate_envelope(&config.points, envelope);
1167 for(int i = 0; i < config.window_size / 2; i++)
1169 if(envelope[i] < 0) envelope[i] = 0;
1172 need_reconfigure = 0;
1175 int GraphicEQ::process_buffer(int64_t size,
1177 int64_t start_position,
1180 need_reconfigure |= load_configuration();
1181 if(need_reconfigure) reconfigure();
1183 fft->process_buffer(start_position, size, buffer, get_direction());
1190 double GraphicEQ::freq_to_magnitude(double frequency,
1191 ArrayList<GraphicPoint*> *points,
1194 // Calculate using control points
1195 for(int i = 0; i < points->size(); i++)
1197 GraphicPoint *point = points->get(i);
1198 if(point->freq == (int)frequency)
1200 return DB::fromdb(point->value);
1205 int nyquist = PluginAClient::project_sample_rate / 2;
1206 int slot = (int)(frequency * config.window_size / 2 / nyquist);
1207 if(slot >= config.window_size / 2) slot = config.window_size / 2 - 1;
1208 //printf("GraphicEQ::freq_to_db %d %f\n", slot, envelope[slot]);
1209 return envelope[slot];
1213 void GraphicEQ::calculate_envelope(ArrayList<GraphicPoint*> *points,
1216 int niquist = PluginAClient::project_sample_rate / 2;
1218 // Make temporary list of just points in order
1219 ArrayList<GraphicPoint*> temp_points;
1220 for(int i = 0; i < points->size(); i++)
1222 temp_points.append(points->get(i));
1225 for(int i = 0; i < temp_points.size(); i++)
1227 GraphicPoint *point = temp_points.get(i);
1228 if(i == active_point)
1230 GraphicPoint *prev_point = 0;
1231 GraphicPoint *next_point = 0;
1232 if(i >= 1) prev_point = temp_points.get(i - 1);
1233 if(i < temp_points.size() - 1) next_point = temp_points.get(i + 1);
1234 if( (prev_point && prev_point->freq >= point->freq) ||
1235 (next_point && next_point->freq <= point->freq) )
1236 temp_points.remove_number(i);
1243 if(temp_points.size())
1245 GraphicPoint *first_point = temp_points.get(0);
1246 GraphicPoint *last_point = temp_points.get(temp_points.size() - 1);
1247 for(int i = 0; i < config.window_size / 2; i++)
1249 int freq = i * niquist / (config.window_size / 2);
1250 if(freq <= first_point->freq)
1251 envelope[i] = first_point->value;
1253 if(freq >= last_point->freq)
1254 envelope[i] = last_point->value;
1257 GraphicPoint *point1 = first_point;
1258 GraphicPoint *point2 = last_point;
1259 for(int j = 0; j < temp_points.size(); j++)
1261 if(temp_points.get(j)->freq <= freq)
1262 point1 = temp_points.get(j);
1265 point2 = temp_points.get(j);
1270 if(point2->freq != point1->freq)
1272 int freqslot1 = Freq::fromfreq(point1->freq);
1273 int freqslot2 = Freq::fromfreq(point2->freq);
1274 int freqslot = Freq::fromfreq(freq);
1276 envelope[i] = (double)(freqslot - freqslot1) *
1277 (point2->value - point1->value) /
1278 (freqslot2 - freqslot1) +
1282 envelope[i] = point1->value;
1286 if(envelope[i] < MIN_DB + 0.01)
1289 envelope[i] = DB::fromdb(envelope[i]);
1294 for(int i = 0; i < config.window_size / 2; i++)
1304 GraphicGUIFrame::GraphicGUIFrame(int window_size, int sample_rate)
1305 : PluginClientFrame(window_size / 2, window_size / 2, sample_rate)
1307 data = new double[window_size / 2];
1310 this->window_size = window_size;
1313 GraphicGUIFrame::~GraphicGUIFrame()
1323 GraphicFFT::GraphicFFT(GraphicEQ *plugin)
1326 this->plugin = plugin;
1329 GraphicFFT::~GraphicFFT()
1334 int GraphicFFT::signal_process()
1336 // Create new frame for updating GUI
1337 frame = new GraphicGUIFrame(window_size,
1338 plugin->PluginAClient::project_sample_rate);
1339 plugin->add_gui_frame(frame);
1341 double freq_max = 0;
1342 for(int i = 0; i < window_size / 2; i++)
1344 double result = plugin->envelope[i] * sqrt(freq_real[i] * freq_real[i] + freq_imag[i] * freq_imag[i]);
1345 double angle = atan2(freq_imag[i], freq_real[i]);
1346 freq_real[i] = result * cos(angle);
1347 freq_imag[i] = result * sin(angle);
1348 frame->data[i] = result;
1349 if(result > freq_max) freq_max = result;
1351 frame->freq_max = freq_max;
1353 symmetry(window_size, freq_real, freq_imag);
1358 int GraphicFFT::post_process()
1360 double time_max = 0;
1361 for(int i = 0; i < window_size; i++)
1363 if(output_real[i] > time_max) time_max = output_real[i];
1365 frame->time_max = time_max;
1371 int GraphicFFT::read_samples(int64_t output_sample,
1375 return plugin->read_samples(buffer,
1377 plugin->get_samplerate(),