add BC_SCALE env var for hi def monitors, cleanup theme data
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / level / leveleffect.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "bchash.h"
25 #include "filesystem.h"
26 #include "filexml.h"
27 #include "language.h"
28 #include "leveleffect.h"
29 #include "samples.h"
30 #include "units.h"
31 #include "vframe.h"
32
33 #include <errno.h>
34 #include <math.h>
35 #include <string.h>
36 #include <unistd.h>
37
38
39
40
41
42
43
44
45
46
47 REGISTER_PLUGIN(SoundLevelEffect)
48
49
50
51
52
53
54
55
56
57 SoundLevelConfig::SoundLevelConfig()
58 {
59         duration = 1.0;
60 }
61
62 void SoundLevelConfig::copy_from(SoundLevelConfig &that)
63 {
64         duration = that.duration;
65 }
66
67 int SoundLevelConfig::equivalent(SoundLevelConfig &that)
68 {
69         return EQUIV(duration, that.duration);
70 }
71
72 void SoundLevelConfig::interpolate(SoundLevelConfig &prev,
73         SoundLevelConfig &next,
74         int64_t prev_frame,
75         int64_t next_frame,
76         int64_t current_frame)
77 {
78         duration = prev.duration;
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 SoundLevelDuration::SoundLevelDuration(SoundLevelEffect *plugin, int x, int y)
96  : BC_FSlider(x, y, 0, xS(180), yS(180), 0.0, 10.0, plugin->config.duration)
97 {
98         this->plugin = plugin;
99         set_precision(0.1);
100 }
101
102 int SoundLevelDuration::handle_event()
103 {
104         plugin->config.duration = get_value();
105         plugin->send_configure_change();
106         return 1;
107 }
108
109
110
111 SoundLevelWindow::SoundLevelWindow(SoundLevelEffect *plugin)
112  : PluginClientWindow(plugin,
113         xS(350),
114         yS(120),
115         xS(350),
116         yS(120),
117         0)
118 {
119         this->plugin = plugin;
120 }
121
122 void SoundLevelWindow::create_objects()
123 {
124         int xs10 = xS(10), xs150 = xS(150);
125         int ys10 = yS(10), ys35 = yS(35);
126 //printf("SoundLevelWindow::create_objects 1\n");
127         int x = xs10, y = ys10;
128
129
130         add_subwindow(new BC_Title(x, y, _("Duration (seconds):")));
131         add_subwindow(duration = new SoundLevelDuration(plugin, x + xs150, y));
132         y += ys35;
133         add_subwindow(new BC_Title(x, y, _("Max soundlevel (dB):")));
134         add_subwindow(soundlevel_max = new BC_Title(x + xs150, y, "0.0"));
135         y += ys35;
136         add_subwindow(new BC_Title(x, y, _("RMS soundlevel (dB):")));
137         add_subwindow(soundlevel_rms = new BC_Title(x + xs150, y, "0.0"));
138
139         show_window();
140         flush();
141 //printf("SoundLevelWindow::create_objects 2\n");
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 SoundLevelEffect::SoundLevelEffect(PluginServer *server)
173  : PluginAClient(server)
174 {
175
176         reset();
177 }
178
179 SoundLevelEffect::~SoundLevelEffect()
180 {
181
182 }
183
184
185 LOAD_CONFIGURATION_MACRO(SoundLevelEffect, SoundLevelConfig)
186
187 NEW_WINDOW_MACRO(SoundLevelEffect, SoundLevelWindow)
188
189
190
191 void SoundLevelEffect::reset()
192 {
193         rms_accum = 0;
194         max_accum = 0;
195         accum_size = 0;
196 }
197
198 const char* SoundLevelEffect::plugin_title() { return N_("SoundLevel"); }
199 int SoundLevelEffect::is_realtime() { return 1; }
200
201
202 void SoundLevelEffect::read_data(KeyFrame *keyframe)
203 {
204         FileXML input;
205         input.set_shared_input(keyframe->xbuf);
206
207         int result = 0;
208         while(!result)
209         {
210                 result = input.read_tag();
211
212                 if(!result)
213                 {
214                         if(input.tag.title_is("SOUNDLEVEL"))
215                         {
216                                 config.duration = input.tag.get_property("DURATION", config.duration);
217                         }
218                 }
219         }
220 }
221
222 void SoundLevelEffect::save_data(KeyFrame *keyframe)
223 {
224         FileXML output;
225         output.set_shared_output(keyframe->xbuf);
226
227         output.tag.set_title("SOUNDLEVEL");
228         output.tag.set_property("DURATION", config.duration);
229         output.append_tag();
230         output.tag.set_title("/SOUNDLEVEL");
231         output.append_tag();
232         output.append_newline();
233         output.terminate_string();
234 }
235
236
237 void SoundLevelEffect::update_gui()
238 {
239 //printf("SoundLevelEffect::update_gui 1\n");
240         if(thread)
241         {
242                 load_configuration();
243                 thread->window->lock_window();
244                 ((SoundLevelWindow*)thread->window)->duration->update(config.duration);
245                 thread->window->unlock_window();
246         }
247 //printf("SoundLevelEffect::update_gui 2\n");
248 }
249
250 int SoundLevelEffect::process_realtime(int64_t size, Samples *input_ptr, Samples *output_ptr)
251 {
252         load_configuration();
253
254         accum_size += size;
255         double *input_samples = input_ptr->get_data();
256         for(int i = 0; i < size; i++)
257         {
258                 double value = fabs(input_samples[i]);
259                 if(value > max_accum) max_accum = value;
260                 rms_accum += value * value;
261         }
262
263         if(accum_size > config.duration * PluginAClient::project_sample_rate)
264         {
265 //printf("SoundLevelEffect::process_realtime 1 %f %d\n", rms_accum, accum_size);
266                 rms_accum = sqrt(rms_accum / accum_size);
267                 double arg[2];
268                 arg[0] = max_accum;
269                 arg[1] = rms_accum;
270                 send_render_gui(arg, 2);
271                 rms_accum = 0;
272                 max_accum = 0;
273                 accum_size = 0;
274         }
275         return 0;
276 }
277
278 void SoundLevelEffect::render_gui(void *data, int size)
279 {
280         if(thread)
281         {
282                 thread->window->lock_window();
283                 char string[BCTEXTLEN];
284                 double *arg = (double*)data;
285                 sprintf(string, "%.2f", DB::todb(arg[0]));
286                 ((SoundLevelWindow*)thread->window)->soundlevel_max->update(string);
287                 sprintf(string, "%.2f", DB::todb(arg[1]));
288                 ((SoundLevelWindow*)thread->window)->soundlevel_rms->update(string);
289                 thread->window->flush();
290                 thread->window->unlock_window();
291         }
292 }