00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filesystem.h"
00005 #include "filexml.h"
00006 #include "leveleffect.h"
00007 #include "picon_png.h"
00008 #include "units.h"
00009 #include "vframe.h"
00010
00011 #include <errno.h>
00012 #include <math.h>
00013 #include <string.h>
00014 #include <unistd.h>
00015
00016 #include <libintl.h>
00017 #define _(String) gettext(String)
00018 #define gettext_noop(String) String
00019 #define N_(String) gettext_noop (String)
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 REGISTER_PLUGIN(SoundLevelEffect)
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 SoundLevelConfig::SoundLevelConfig()
00040 {
00041 duration = 1.0;
00042 }
00043
00044 void SoundLevelConfig::copy_from(SoundLevelConfig &that)
00045 {
00046 duration = that.duration;
00047 }
00048
00049 int SoundLevelConfig::equivalent(SoundLevelConfig &that)
00050 {
00051 return EQUIV(duration, that.duration);
00052 }
00053
00054 void SoundLevelConfig::interpolate(SoundLevelConfig &prev,
00055 SoundLevelConfig &next,
00056 int64_t prev_frame,
00057 int64_t next_frame,
00058 int64_t current_frame)
00059 {
00060 duration = prev.duration;
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 SoundLevelDuration::SoundLevelDuration(SoundLevelEffect *plugin, int x, int y)
00078 : BC_FSlider(x, y, 0, 180, 180, 0.0, 10.0, plugin->config.duration)
00079 {
00080 this->plugin = plugin;
00081 set_precision(0.1);
00082 }
00083
00084 int SoundLevelDuration::handle_event()
00085 {
00086 plugin->config.duration = get_value();
00087 plugin->send_configure_change();
00088 return 1;
00089 }
00090
00091
00092
00093 SoundLevelWindow::SoundLevelWindow(SoundLevelEffect *plugin, int x, int y)
00094 : BC_Window(plugin->gui_string,
00095 x,
00096 y,
00097 350,
00098 120,
00099 350,
00100 120,
00101 0,
00102 0,
00103 1)
00104 {
00105 this->plugin = plugin;
00106 }
00107
00108 void SoundLevelWindow::create_objects()
00109 {
00110
00111 int x = 10, y = 10;
00112
00113
00114 add_subwindow(new BC_Title(x, y, _("Duration (seconds):")));
00115 add_subwindow(duration = new SoundLevelDuration(plugin, x + 150, y));
00116 y += 35;
00117 add_subwindow(new BC_Title(x, y, _("Max soundlevel (dB):")));
00118 add_subwindow(soundlevel_max = new BC_Title(x + 150, y, "0.0"));
00119 y += 35;
00120 add_subwindow(new BC_Title(x, y, _("RMS soundlevel (dB):")));
00121 add_subwindow(soundlevel_rms = new BC_Title(x + 150, y, "0.0"));
00122
00123 show_window();
00124 flush();
00125
00126 }
00127
00128 WINDOW_CLOSE_EVENT(SoundLevelWindow)
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 PLUGIN_THREAD_OBJECT(SoundLevelEffect, SoundLevelThread, SoundLevelWindow)
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 SoundLevelEffect::SoundLevelEffect(PluginServer *server)
00157 : PluginAClient(server)
00158 {
00159 PLUGIN_CONSTRUCTOR_MACRO
00160 reset();
00161 }
00162
00163 SoundLevelEffect::~SoundLevelEffect()
00164 {
00165 PLUGIN_DESTRUCTOR_MACRO
00166 }
00167
00168 NEW_PICON_MACRO(SoundLevelEffect)
00169
00170 LOAD_CONFIGURATION_MACRO(SoundLevelEffect, SoundLevelConfig)
00171
00172 SHOW_GUI_MACRO(SoundLevelEffect, SoundLevelThread)
00173
00174 RAISE_WINDOW_MACRO(SoundLevelEffect)
00175
00176 SET_STRING_MACRO(SoundLevelEffect)
00177
00178
00179 void SoundLevelEffect::reset()
00180 {
00181 rms_accum = 0;
00182 max_accum = 0;
00183 accum_size = 0;
00184 }
00185
00186 char* SoundLevelEffect::plugin_title() { return N_("SoundLevel"); }
00187 int SoundLevelEffect::is_realtime() { return 1; }
00188
00189
00190 void SoundLevelEffect::read_data(KeyFrame *keyframe)
00191 {
00192 FileXML input;
00193 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00194
00195 int result = 0;
00196 while(!result)
00197 {
00198 result = input.read_tag();
00199
00200 if(!result)
00201 {
00202 if(input.tag.title_is("SOUNDLEVEL"))
00203 {
00204 config.duration = input.tag.get_property("DURATION", config.duration);
00205 }
00206 }
00207 }
00208 }
00209
00210 void SoundLevelEffect::save_data(KeyFrame *keyframe)
00211 {
00212 FileXML output;
00213 output.set_shared_string(keyframe->data, MESSAGESIZE);
00214
00215 output.tag.set_title("SOUNDLEVEL");
00216 output.tag.set_property("DURATION", config.duration);
00217 output.append_tag();
00218 output.tag.set_title("/SOUNDLEVEL");
00219 output.append_tag();
00220 output.append_newline();
00221
00222 output.terminate_string();
00223 }
00224
00225 int SoundLevelEffect::load_defaults()
00226 {
00227 defaults = new BC_Hash(BCASTDIR "soundlevel.rc");
00228 defaults->load();
00229
00230 config.duration = defaults->get("DURATION", config.duration);
00231 return 0;
00232 }
00233
00234 int SoundLevelEffect::save_defaults()
00235 {
00236 defaults->update("DURATION", config.duration);
00237 defaults->save();
00238
00239 return 0;
00240 }
00241
00242 void SoundLevelEffect::update_gui()
00243 {
00244
00245 if(thread)
00246 {
00247 load_configuration();
00248 thread->window->lock_window();
00249 thread->window->duration->update(config.duration);
00250 thread->window->unlock_window();
00251 }
00252
00253 }
00254
00255 int SoundLevelEffect::process_realtime(int64_t size, double *input_ptr, double *output_ptr)
00256 {
00257 load_configuration();
00258
00259 accum_size += size;
00260 for(int i = 0; i < size; i++)
00261 {
00262 double value = fabs(input_ptr[i]);
00263 if(value > max_accum) max_accum = value;
00264 rms_accum += value * value;
00265 }
00266
00267 if(accum_size > config.duration * PluginAClient::project_sample_rate)
00268 {
00269
00270 rms_accum = sqrt(rms_accum / accum_size);
00271 double arg[2];
00272 arg[0] = max_accum;
00273 arg[1] = rms_accum;
00274 send_render_gui(arg, 2);
00275 rms_accum = 0;
00276 max_accum = 0;
00277 accum_size = 0;
00278 }
00279 return 0;
00280 }
00281
00282 void SoundLevelEffect::render_gui(void *data, int size)
00283 {
00284 if(thread)
00285 {
00286 thread->window->lock_window();
00287 char string[BCTEXTLEN];
00288 double *arg = (double*)data;
00289 sprintf(string, "%.2f", DB::todb(arg[0]));
00290 thread->window->soundlevel_max->update(string);
00291 sprintf(string, "%.2f", DB::todb(arg[1]));
00292 thread->window->soundlevel_rms->update(string);
00293 thread->window->flush();
00294 thread->window->unlock_window();
00295 }
00296 }