1 #include "bcdisplayinfo.h"
7 #include "spectrogram.h"
16 REGISTER_PLUGIN(Spectrogram)
18 #define WINDOW_SIZE 4096
19 #define HALF_WINDOW 2048
22 SpectrogramConfig::SpectrogramConfig()
33 SpectrogramLevel::SpectrogramLevel(Spectrogram *plugin, int x, int y)
34 : BC_FPot(x, y, plugin->config.level, INFINITYGAIN, 0)
36 this->plugin = plugin;
39 int SpectrogramLevel::handle_event()
41 plugin->config.level = get_value();
42 plugin->send_configure_change();
56 SpectrogramWindow::SpectrogramWindow(Spectrogram *plugin, int x, int y)
57 : BC_Window(plugin->gui_string,
68 this->plugin = plugin;
71 SpectrogramWindow::~SpectrogramWindow()
75 void SpectrogramWindow::create_objects()
79 char string[BCTEXTLEN];
81 add_subwindow(canvas = new BC_SubWindow(x,
88 for(int i = 0; i <= divisions; i++)
90 y = (int)((float)(canvas->get_h() - 10) / divisions * i) + 10;
92 Freq::tofreq((int)((float)TOTALFREQS / divisions * (divisions - i))));
93 add_subwindow(new BC_Title(x, y, string));
97 y = canvas->get_y() + canvas->get_h() + 5;
99 add_subwindow(new BC_Title(x, y + 10, _("Level:")));
100 add_subwindow(level = new SpectrogramLevel(plugin, x + 50, y));
106 WINDOW_CLOSE_EVENT(SpectrogramWindow)
109 void SpectrogramWindow::update_gui()
111 level->update(plugin->config.level);
123 PLUGIN_THREAD_OBJECT(Spectrogram, SpectrogramThread, SpectrogramWindow)
133 SpectrogramFFT::SpectrogramFFT(Spectrogram *plugin)
136 this->plugin = plugin;
139 SpectrogramFFT::~SpectrogramFFT()
144 int SpectrogramFFT::signal_process()
146 double level = DB::fromdb(plugin->config.level);
147 for(int i = 0; i < HALF_WINDOW; i++)
149 plugin->data[i] += level *
150 sqrt(freq_real[i] * freq_real[i] +
151 freq_imag[i] * freq_imag[i]);
154 plugin->total_windows++;
158 int SpectrogramFFT::read_samples(int64_t output_sample,
162 return plugin->read_samples(buffer,
164 plugin->get_samplerate(),
177 Spectrogram::Spectrogram(PluginServer *server)
178 : PluginAClient(server)
181 PLUGIN_CONSTRUCTOR_MACRO
184 Spectrogram::~Spectrogram()
186 PLUGIN_DESTRUCTOR_MACRO
189 if(data) delete [] data;
193 void Spectrogram::reset()
202 char* Spectrogram::plugin_title() { return N_("Spectrogram"); }
203 int Spectrogram::is_realtime() { return 1; }
205 int Spectrogram::process_buffer(int64_t size,
207 int64_t start_position,
210 load_configuration();
213 fft = new SpectrogramFFT(this);
214 fft->initialize(WINDOW_SIZE);
218 data = new float[HALF_WINDOW];
221 bzero(data, sizeof(float) * HALF_WINDOW);
223 fft->process_buffer(start_position,
227 for(int i = 0; i < HALF_WINDOW; i++)
228 data[i] /= total_windows;
229 send_render_gui(data, HALF_WINDOW);
234 SET_STRING_MACRO(Spectrogram)
236 NEW_PICON_MACRO(Spectrogram)
238 SHOW_GUI_MACRO(Spectrogram, SpectrogramThread)
240 RAISE_WINDOW_MACRO(Spectrogram)
242 void Spectrogram::update_gui()
246 load_configuration();
247 thread->window->lock_window("Spectrogram::update_gui");
248 thread->window->update_gui();
249 thread->window->unlock_window();
253 void Spectrogram::render_gui(void *data, int size)
257 thread->window->lock_window("Spectrogram::render_gui");
258 float *frame = (float*)data;
259 int niquist = get_project_samplerate();
260 BC_SubWindow *canvas = thread->window->canvas;
261 int h = canvas->get_h();
262 int input1 = HALF_WINDOW - 1;
263 double *temp = new double[h];
265 // Scale frame to canvas height
266 for(int i = 0; i < h; i++)
268 int input2 = (int)((h - 1 - i) * TOTALFREQS / h);
269 input2 = Freq::tofreq(input2) *
272 input2 = MIN(HALF_WINDOW - 1, input2);
276 for(int j = input1 - 1; j >= input2; j--)
279 sum /= input1 - input2;
297 int x = canvas->get_w() - 1;
298 double scale = (double)0xffffff;
299 for(int i = 0; i < h; i++)
302 color = (int)(scale * temp[i]);
304 if(color < 0) color = 0;
305 if(color > 0xffffff) color = 0xffffff;
306 canvas->set_color(color);
307 canvas->draw_pixel(x, i);
314 thread->window->unlock_window();
318 void Spectrogram::load_configuration()
320 KeyFrame *prev_keyframe;
321 prev_keyframe = get_prev_keyframe(get_source_position());
323 read_data(prev_keyframe);
326 void Spectrogram::read_data(KeyFrame *keyframe)
329 input.set_shared_string(keyframe->data, strlen(keyframe->data));
334 result = input.read_tag();
338 if(input.tag.title_is("SPECTROGRAM"))
340 config.level = input.tag.get_property("LEVEL", config.level);
346 void Spectrogram::save_data(KeyFrame *keyframe)
349 output.set_shared_string(keyframe->data, MESSAGESIZE);
351 output.tag.set_title("SPECTROGRAM");
352 output.tag.set_property("LEVEL", (double)config.level);
354 output.append_newline();
355 output.terminate_string();
358 int Spectrogram::load_defaults()
360 char directory[BCTEXTLEN];
362 sprintf(directory, "%sspectrogram.rc", BCASTDIR);
363 defaults = new BC_Hash(directory);
365 config.level = defaults->get("LEVEL", config.level);
369 int Spectrogram::save_defaults()
371 defaults->update("LEVEL", config.level);