r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / spectrogram / spectrogram.C
blob4a78cf1073505a69886439ee0d20bc3b04bb4fe7
1 #include "bcdisplayinfo.h"
2 #include "defaults.h"
3 #include "filexml.h"
4 #include "picon_png.h"
5 #include "spectrogram.h"
6 #include "units.h"
7 #include "vframe.h"
10 #include <string.h>
12 #include <libintl.h>
13 #define _(String) gettext(String)
14 #define gettext_noop(String) String
15 #define N_(String) gettext_noop (String)
19 REGISTER_PLUGIN(Spectrogram)
25 SpectrogramConfig::SpectrogramConfig()
27         level = 0.0;
36 SpectrogramLevel::SpectrogramLevel(Spectrogram *plugin, int x, int y)
37  : BC_FPot(x, y, plugin->config.level, INFINITYGAIN, 0)
39         this->plugin = plugin;
42 int SpectrogramLevel::handle_event()
44         plugin->config.level = get_value();
45         plugin->send_configure_change();
46         return 1;
59 SpectrogramWindow::SpectrogramWindow(Spectrogram *plugin, int x, int y)
60  : BC_Window(plugin->gui_string, 
61         x, 
62         y, 
63         640, 
64         480, 
65         640, 
66         480,
67         0, 
68         0,
69         1)
71         this->plugin = plugin;
74 SpectrogramWindow::~SpectrogramWindow()
78 void SpectrogramWindow::create_objects()
80         int x = 60, y = 10;
81         int divisions = 5;
82         char string[BCTEXTLEN];
84         add_subwindow(canvas = new BC_SubWindow(x, 
85                 y, 
86                 get_w() - x - 10, 
87                 get_h() - 50 - y,
88                 BLACK));
89         x = 10;
91         for(int i = 0; i <= divisions; i++)
92         {
93                 y = (int)((float)(canvas->get_h() - 10) / divisions * i) + 10;
94                 sprintf(string, "%d", 
95                         Freq::tofreq((int)((float)TOTALFREQS / divisions * (divisions - i))));
96                 add_subwindow(new BC_Title(x, y, string));
97         }
99         x = canvas->get_x();
100         y = canvas->get_y() + canvas->get_h() + 5;
102         add_subwindow(new BC_Title(x, y + 10, _("Level:")));
103         add_subwindow(level = new SpectrogramLevel(plugin, x + 50, y));
105         show_window();
106         flush();
109 WINDOW_CLOSE_EVENT(SpectrogramWindow)
112 void SpectrogramWindow::update_gui()
114         level->update(plugin->config.level);
126 PLUGIN_THREAD_OBJECT(Spectrogram, SpectrogramThread, SpectrogramWindow)
136 SpectrogramFFT::SpectrogramFFT(Spectrogram *plugin)
137  : CrossfadeFFT()
139         this->plugin = plugin;
142 SpectrogramFFT::~SpectrogramFFT()
147 int SpectrogramFFT::signal_process()
150 //printf("SpectrogramFFT::signal_process %d\n", window_size);
151         BC_SubWindow *window = plugin->thread->window->canvas;
153         int h = window->get_h();
154         double *temp = new double[h];
155         int niquist = plugin->PluginAClient::project_sample_rate / 2;
156         int input1 = window_size / 2;
157         double level = DB::fromdb(plugin->config.level);
159         for(int i = 0; i < h; i++)
160         {
161                 int input2 = (int)((float)(h - 1 - i) / h * TOTALFREQS);
162                 input2 = (int)((float)Freq::tofreq(input2) / 
163                         niquist * 
164                         window_size / 
165                         2);
166                 if(input2 > window_size / 2 - 1) input2 = window_size / 2 - 1;
168                 double sum = 0;
169                 if(input1 > input2)
170                 {
171                         for(int j = input1 - 1; j >= input2; j--)
172                                 sum += sqrt(freq_real[j] * freq_real[j] + 
173                                         freq_imag[j] * freq_imag[j]);
175                         sum /= (double)(input1 - input2);
176                 }
177                 else
178                         sum = sqrt(freq_real[input2] * freq_real[input2] + 
179                                         freq_imag[input2] * freq_imag[input2]);
182                 temp[i] = sum * level;
183                 input1 = input2;
184         }
186         window->copy_area(1, 
187                 0, 
188                 0, 
189                 0, 
190                 window->get_w() - 1,
191                 window->get_h());
192         int x = window->get_w() - 1;
194         double scale = (double)0xffffff;
195         for(int i = 0; i < h; i++)
196         {
197                 int64_t color;
198                 color = (int)(scale * temp[i]);
200                 if(color < 0) color = 0;
201                 if(color > 0xffffff) color = 0xffffff;
202                 window->set_color(color);
203                 window->draw_pixel(x, i);
204         }
206         window->flash();
207         window->flush();
208         delete [] temp;
210         return 0;
222 Spectrogram::Spectrogram(PluginServer *server)
223  : PluginAClient(server)
225         reset();
226         PLUGIN_CONSTRUCTOR_MACRO
229 Spectrogram::~Spectrogram()
231         PLUGIN_DESTRUCTOR_MACRO
233         if(fft) delete fft;
237 void Spectrogram::reset()
239         thread = 0;
240         fft = 0;
241         done = 0;
245 char* Spectrogram::plugin_title()
247         return _("Spectrogram");
250 int Spectrogram::is_realtime()
252         return 1;
255 int Spectrogram::process_realtime(int64_t size, double *input_ptr, double *output_ptr)
257 //printf("Spectrogram::process_realtime 1\n");
258         send_render_gui(input_ptr, size);
259         memcpy(output_ptr, input_ptr, sizeof(double) * size);
261         return 0;
264 SET_STRING_MACRO(Spectrogram)
266 NEW_PICON_MACRO(Spectrogram)
268 SHOW_GUI_MACRO(Spectrogram, SpectrogramThread)
270 RAISE_WINDOW_MACRO(Spectrogram)
272 void Spectrogram::update_gui()
274         if(thread)
275         {
276                 load_configuration();
277                 thread->window->lock_window();
278                 thread->window->update_gui();
279                 thread->window->unlock_window();
280         }
283 void Spectrogram::render_gui(void *data, int size)
285 //printf("Spectrogram::render_gui 1\n");
286         if(thread)
287         {
288                 thread->window->lock_window();
289                 load_configuration();
291                 if(!fft) 
292                 {
293                         fft = new SpectrogramFFT(this);
294                         fft->initialize(WINDOW_SIZE);
295                 }
296                 double *temp = new double[size];
297                 fft->process_fifo(size, (double*)data, temp);
299                 delete [] temp;
300                 thread->window->unlock_window();
301         }
304 void Spectrogram::load_configuration()
306         KeyFrame *prev_keyframe;
307         prev_keyframe = get_prev_keyframe(get_source_position());
309         read_data(prev_keyframe);
312 void Spectrogram::read_data(KeyFrame *keyframe)
314         FileXML input;
315         input.set_shared_string(keyframe->data, strlen(keyframe->data));
317         int result = 0;
318         while(!result)
319         {
320                 result = input.read_tag();
322                 if(!result)
323                 {
324                         if(input.tag.title_is("SPECTROGRAM"))
325                         {
326                                 config.level = input.tag.get_property("LEVEL", config.level);
327                         }
328                 }
329         }
332 void Spectrogram::save_data(KeyFrame *keyframe)
334         FileXML output;
335         output.set_shared_string(keyframe->data, MESSAGESIZE);
337         output.tag.set_title("SPECTROGRAM");
338         output.tag.set_property("LEVEL", (double)config.level);
339         output.append_tag();
340         output.append_newline();
341         output.terminate_string();
344 int Spectrogram::load_defaults()
346         char directory[BCTEXTLEN];
348         sprintf(directory, "%sspectrogram.rc", BCASTDIR);
349         defaults = new Defaults(directory);
350         defaults->load();
351         config.level = defaults->get("LEVEL", config.level);
352         return 0;
355 int Spectrogram::save_defaults()
357         defaults->update("LEVEL", config.level);
358         defaults->save();
359         return 0;