initial commit
[goodguy/history.git] / cinelerra-5.0 / 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, 180, 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         350, 
114         120, 
115         350, 
116         120,
117         0)
118 {
119         this->plugin = plugin;
120 }
121
122 void SoundLevelWindow::create_objects()
123 {
124 //printf("SoundLevelWindow::create_objects 1\n");
125         int x = 10, y = 10;
126
127
128         add_subwindow(new BC_Title(x, y, _("Duration (seconds):")));
129         add_subwindow(duration = new SoundLevelDuration(plugin, x + 150, y));
130         y += 35;
131         add_subwindow(new BC_Title(x, y, _("Max soundlevel (dB):")));
132         add_subwindow(soundlevel_max = new BC_Title(x + 150, y, "0.0"));
133         y += 35;
134         add_subwindow(new BC_Title(x, y, _("RMS soundlevel (dB):")));
135         add_subwindow(soundlevel_rms = new BC_Title(x + 150, y, "0.0"));
136
137         show_window();
138         flush();
139 //printf("SoundLevelWindow::create_objects 2\n");
140 }
141
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 SoundLevelEffect::SoundLevelEffect(PluginServer *server)
171  : PluginAClient(server)
172 {
173         
174         reset();
175 }
176
177 SoundLevelEffect::~SoundLevelEffect()
178 {
179         
180 }
181
182
183 LOAD_CONFIGURATION_MACRO(SoundLevelEffect, SoundLevelConfig)
184
185 NEW_WINDOW_MACRO(SoundLevelEffect, SoundLevelWindow)
186
187
188
189 void SoundLevelEffect::reset()
190 {
191         rms_accum = 0;
192         max_accum = 0;
193         accum_size = 0;
194 }
195
196 const char* SoundLevelEffect::plugin_title() { return N_("SoundLevel"); }
197 int SoundLevelEffect::is_realtime() { return 1; }
198
199
200 void SoundLevelEffect::read_data(KeyFrame *keyframe)
201 {
202         FileXML input;
203         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
204
205         int result = 0;
206         while(!result)
207         {
208                 result = input.read_tag();
209
210                 if(!result)
211                 {
212                         if(input.tag.title_is("SOUNDLEVEL"))
213                         {
214                                 config.duration = input.tag.get_property("DURATION", config.duration);
215                         }
216                 }
217         }
218 }
219
220 void SoundLevelEffect::save_data(KeyFrame *keyframe)
221 {
222         FileXML output;
223         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
224
225         output.tag.set_title("SOUNDLEVEL");
226         output.tag.set_property("DURATION", config.duration);
227         output.append_tag();
228         output.append_newline();
229
230         output.terminate_string();
231 }
232
233
234 void SoundLevelEffect::update_gui()
235 {
236 //printf("SoundLevelEffect::update_gui 1\n");
237         if(thread)
238         {
239                 load_configuration();
240                 thread->window->lock_window();
241                 ((SoundLevelWindow*)thread->window)->duration->update(config.duration);
242                 thread->window->unlock_window();
243         }
244 //printf("SoundLevelEffect::update_gui 2\n");
245 }
246
247 int SoundLevelEffect::process_realtime(int64_t size, Samples *input_ptr, Samples *output_ptr)
248 {
249         load_configuration();
250
251         accum_size += size;
252         double *input_samples = input_ptr->get_data();
253         for(int i = 0; i < size; i++)
254         {
255                 double value = fabs(input_samples[i]);
256                 if(value > max_accum) max_accum = value;
257                 rms_accum += value * value;
258         }
259
260         if(accum_size > config.duration * PluginAClient::project_sample_rate)
261         {
262 //printf("SoundLevelEffect::process_realtime 1 %f %d\n", rms_accum, accum_size);
263                 rms_accum = sqrt(rms_accum / accum_size);
264                 double arg[2];
265                 arg[0] = max_accum;
266                 arg[1] = rms_accum;
267                 send_render_gui(arg, 2);
268                 rms_accum = 0;
269                 max_accum = 0;
270                 accum_size = 0;
271         }
272         return 0;
273 }
274
275 void SoundLevelEffect::render_gui(void *data, int size)
276 {
277         if(thread)
278         {
279                 thread->window->lock_window();
280                 char string[BCTEXTLEN];
281                 double *arg = (double*)data;
282                 sprintf(string, "%.2f", DB::todb(arg[0]));
283                 ((SoundLevelWindow*)thread->window)->soundlevel_max->update(string);
284                 sprintf(string, "%.2f", DB::todb(arg[1]));
285                 ((SoundLevelWindow*)thread->window)->soundlevel_rms->update(string);
286                 thread->window->flush();
287                 thread->window->unlock_window();
288         }
289 }