00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filesystem.h"
00005 #include "filexml.h"
00006 #include "guicast.h"
00007 #include "language.h"
00008 #include "mutex.h"
00009 #include "fourier.h"
00010 #include "picon_png.h"
00011 #include "pluginaclient.h"
00012 #include "transportque.inc"
00013 #include "units.h"
00014 #include "vframe.h"
00015
00016 #include <errno.h>
00017 #include <math.h>
00018 #include <string.h>
00019
00020
00021
00022 #define WINDOW_SIZE 16384
00023
00024
00025
00026
00027
00028
00029 class DenoiseFFTEffect;
00030 class DenoiseFFTWindow;
00031
00032
00033
00034
00035 class DenoiseFFTConfig
00036 {
00037 public:
00038 DenoiseFFTConfig();
00039
00040 int samples;
00041 double level;
00042 };
00043
00044 class DenoiseFFTLevel : public BC_FPot
00045 {
00046 public:
00047 DenoiseFFTLevel(DenoiseFFTEffect *plugin, int x, int y);
00048 int handle_event();
00049 DenoiseFFTEffect *plugin;
00050 };
00051
00052 class DenoiseFFTSamples : public BC_PopupMenu
00053 {
00054 public:
00055 DenoiseFFTSamples(DenoiseFFTEffect *plugin, int x, int y, char *text);
00056 int handle_event();
00057 DenoiseFFTEffect *plugin;
00058 };
00059
00060 class DenoiseFFTWindow : public BC_Window
00061 {
00062 public:
00063 DenoiseFFTWindow(DenoiseFFTEffect *plugin, int x, int y);
00064 void create_objects();
00065 int close_event();
00066 DenoiseFFTLevel *level;
00067 DenoiseFFTSamples *samples;
00068 DenoiseFFTEffect *plugin;
00069 };
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 PLUGIN_THREAD_HEADER(DenoiseFFTEffect, DenoiseFFTThread, DenoiseFFTWindow)
00084
00085
00086 class DenoiseFFTRemove : public CrossfadeFFT
00087 {
00088 public:
00089 DenoiseFFTRemove(DenoiseFFTEffect *plugin);
00090 int signal_process();
00091 int read_samples(int64_t output_sample,
00092 int samples,
00093 double *buffer);
00094 DenoiseFFTEffect *plugin;
00095 };
00096
00097 class DenoiseFFTCollect : public CrossfadeFFT
00098 {
00099 public:
00100 DenoiseFFTCollect(DenoiseFFTEffect *plugin);
00101 int signal_process();
00102 int read_samples(int64_t output_sample,
00103 int samples,
00104 double *buffer);
00105 DenoiseFFTEffect *plugin;
00106 };
00107
00108 class DenoiseFFTEffect : public PluginAClient
00109 {
00110 public:
00111 DenoiseFFTEffect(PluginServer *server);
00112 ~DenoiseFFTEffect();
00113
00114 int is_realtime();
00115 void read_data(KeyFrame *keyframe);
00116 void save_data(KeyFrame *keyframe);
00117 int process_buffer(int64_t size,
00118 double *buffer,
00119 int64_t start_position,
00120 int sample_rate);
00121 void collect_noise();
00122
00123
00124
00125 int load_defaults();
00126 int save_defaults();
00127 void reset();
00128 void update_gui();
00129
00130 void process_window();
00131
00132
00133 PLUGIN_CLASS_MEMBERS(DenoiseFFTConfig, DenoiseFFTThread)
00134
00135
00136 int need_collection;
00137
00138 int64_t collection_sample;
00139 double *reference;
00140 DenoiseFFTRemove *remove_engine;
00141 DenoiseFFTCollect *collect_engine;
00142 };
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 REGISTER_PLUGIN(DenoiseFFTEffect)
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 DenoiseFFTConfig::DenoiseFFTConfig()
00164 {
00165 samples = WINDOW_SIZE;
00166 level = 0.0;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 DenoiseFFTLevel::DenoiseFFTLevel(DenoiseFFTEffect *plugin, int x, int y)
00181 : BC_FPot(x, y, (float)plugin->config.level, INFINITYGAIN, 6.0)
00182 {
00183 this->plugin = plugin;
00184 set_precision(0.1);
00185 }
00186
00187 int DenoiseFFTLevel::handle_event()
00188 {
00189 plugin->config.level = get_value();
00190 plugin->send_configure_change();
00191 return 1;
00192 }
00193
00194 DenoiseFFTSamples::DenoiseFFTSamples(DenoiseFFTEffect *plugin,
00195 int x,
00196 int y,
00197 char *text)
00198 : BC_PopupMenu(x, y, 100, text, 1)
00199 {
00200 this->plugin = plugin;
00201 }
00202
00203 int DenoiseFFTSamples::handle_event()
00204 {
00205 plugin->config.samples = atol(get_text());
00206 plugin->send_configure_change();
00207 return 1;
00208 }
00209
00210
00211
00212 DenoiseFFTWindow::DenoiseFFTWindow(DenoiseFFTEffect *plugin, int x, int y)
00213 : BC_Window(plugin->gui_string,
00214 x,
00215 y,
00216 300,
00217 130,
00218 300,
00219 130,
00220 0,
00221 0,
00222 1)
00223 {
00224 this->plugin = plugin;
00225 }
00226
00227 void DenoiseFFTWindow::create_objects()
00228 {
00229 int x = 10, y = 10;
00230
00231 add_subwindow(new BC_Title(x, y, _("Denoise power:")));
00232 add_subwindow(level = new DenoiseFFTLevel(plugin, x + 130, y));
00233 y += level->get_h() + 10;
00234 add_subwindow(new BC_Title(x, y, _("Number of samples for reference:")));
00235 y += 20;
00236 add_subwindow(new BC_Title(x, y, _("The keyframe is the start of the reference")));
00237 y += 20;
00238
00239 char string[BCTEXTLEN];
00240 sprintf(string, "%d\n", plugin->config.samples);
00241 add_subwindow(samples = new DenoiseFFTSamples(plugin, x + 100, y, string));
00242 for(int i = WINDOW_SIZE; i < 0x100000; )
00243 {
00244 sprintf(string, "%d", i);
00245 samples->add_item(new BC_MenuItem(string));
00246 i *= 2;
00247 }
00248 show_window();
00249 flush();
00250 }
00251
00252 WINDOW_CLOSE_EVENT(DenoiseFFTWindow)
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 PLUGIN_THREAD_OBJECT(DenoiseFFTEffect, DenoiseFFTThread, DenoiseFFTWindow)
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 DenoiseFFTEffect::DenoiseFFTEffect(PluginServer *server)
00275 : PluginAClient(server)
00276 {
00277 reset();
00278 PLUGIN_CONSTRUCTOR_MACRO
00279 }
00280
00281 DenoiseFFTEffect::~DenoiseFFTEffect()
00282 {
00283 PLUGIN_DESTRUCTOR_MACRO
00284 if(reference) delete [] reference;
00285 if(remove_engine) delete remove_engine;
00286 if(collect_engine) delete collect_engine;
00287 }
00288
00289 NEW_PICON_MACRO(DenoiseFFTEffect)
00290
00291 SHOW_GUI_MACRO(DenoiseFFTEffect, DenoiseFFTThread)
00292
00293 RAISE_WINDOW_MACRO(DenoiseFFTEffect)
00294
00295 SET_STRING_MACRO(DenoiseFFTEffect)
00296
00297
00298 void DenoiseFFTEffect::reset()
00299 {
00300 reference = 0;
00301 remove_engine = 0;
00302 collect_engine = 0;
00303 need_collection = 1;
00304 collection_sample = 0;
00305 }
00306
00307 int DenoiseFFTEffect::is_realtime() { return 1; }
00308 char* DenoiseFFTEffect::plugin_title() { return N_("DenoiseFFT"); }
00309
00310
00311
00312
00313
00314 void DenoiseFFTEffect::read_data(KeyFrame *keyframe)
00315 {
00316 FileXML input;
00317 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00318
00319 int result = 0;
00320 while(!result)
00321 {
00322 result = input.read_tag();
00323
00324 if(!result)
00325 {
00326 if(input.tag.title_is("DENOISEFFT"))
00327 {
00328 config.samples = input.tag.get_property("SAMPLES", config.samples);
00329 config.level = input.tag.get_property("LEVEL", config.level);
00330 }
00331 }
00332 }
00333 }
00334
00335 void DenoiseFFTEffect::save_data(KeyFrame *keyframe)
00336 {
00337 FileXML output;
00338 output.set_shared_string(keyframe->data, MESSAGESIZE);
00339
00340 output.tag.set_title("DENOISEFFT");
00341 output.tag.set_property("SAMPLES", config.samples);
00342 output.tag.set_property("LEVEL", config.level);
00343 output.append_tag();
00344 output.tag.set_title("/DENOISEFFT");
00345 output.append_tag();
00346 output.append_newline();
00347
00348 output.terminate_string();
00349 }
00350
00351 int DenoiseFFTEffect::load_defaults()
00352 {
00353 defaults = new BC_Hash(BCASTDIR "denoisefft.rc");
00354 defaults->load();
00355
00356 config.level = defaults->get("LEVEL", config.level);
00357 config.samples = defaults->get("SAMPLES", config.samples);
00358 return 0;
00359 }
00360
00361 int DenoiseFFTEffect::save_defaults()
00362 {
00363 char string[BCTEXTLEN];
00364
00365 defaults->update("LEVEL", config.level);
00366 defaults->update("SAMPLES", config.samples);
00367 defaults->save();
00368
00369 return 0;
00370 }
00371
00372 void DenoiseFFTEffect::update_gui()
00373 {
00374 if(thread)
00375 {
00376 load_configuration();
00377 thread->window->lock_window();
00378 thread->window->level->update(config.level);
00379 char string[BCTEXTLEN];
00380 sprintf(string, "%d", config.samples);
00381 thread->window->samples->set_text(string);
00382 thread->window->unlock_window();
00383 }
00384 }
00385
00386 int DenoiseFFTEffect::load_configuration()
00387 {
00388 KeyFrame *prev_keyframe = get_prev_keyframe(get_source_position());
00389 int64_t prev_position = edl_to_local(prev_keyframe->position);
00390 read_data(prev_keyframe);
00391 if(prev_position == 0) prev_position = get_source_start();
00392
00393 if(prev_position != collection_sample)
00394 {
00395 collection_sample = prev_position;
00396 need_collection = 1;
00397 }
00398 return 0;
00399 }
00400
00401 int DenoiseFFTEffect::process_buffer(int64_t size,
00402 double *buffer,
00403 int64_t start_position,
00404 int sample_rate)
00405 {
00406 load_configuration();
00407
00408
00409 if(need_collection)
00410 {
00411 need_collection = 0;
00412 collect_noise();
00413 }
00414
00415
00416 if(!remove_engine)
00417 {
00418 remove_engine = new DenoiseFFTRemove(this);
00419 remove_engine->initialize(WINDOW_SIZE);
00420 }
00421 remove_engine->process_buffer(start_position,
00422 size,
00423 buffer,
00424 get_direction());
00425
00426 return 0;
00427 }
00428
00429
00430 void DenoiseFFTEffect::collect_noise()
00431 {
00432 if(!reference) reference = new double[WINDOW_SIZE / 2];
00433 if(!collect_engine)
00434 {
00435 collect_engine = new DenoiseFFTCollect(this);
00436 collect_engine->initialize(WINDOW_SIZE);
00437 }
00438 bzero(reference, sizeof(double) * WINDOW_SIZE / 2);
00439
00440 int64_t collection_start = collection_sample;
00441 int step = 1;
00442 int total_windows = 0;
00443
00444 if(get_direction() == PLAY_REVERSE)
00445 {
00446 collection_start += config.samples;
00447 step = -1;
00448 }
00449
00450 for(int i = 0; i < config.samples; i += WINDOW_SIZE)
00451 {
00452 collect_engine->process_buffer(collection_start,
00453 WINDOW_SIZE,
00454 0,
00455 get_direction());
00456
00457 collection_start += step * WINDOW_SIZE;
00458 total_windows++;
00459 }
00460
00461 for(int i = 0; i < WINDOW_SIZE / 2; i++)
00462 {
00463 reference[i] /= total_windows;
00464 }
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474 DenoiseFFTRemove::DenoiseFFTRemove(DenoiseFFTEffect *plugin)
00475 {
00476 this->plugin = plugin;
00477 }
00478
00479 int DenoiseFFTRemove::signal_process()
00480 {
00481 double level = DB::fromdb(plugin->config.level);
00482 for(int i = 0; i < window_size / 2; i++)
00483 {
00484 double result = sqrt(freq_real[i] * freq_real[i] + freq_imag[i] * freq_imag[i]);
00485 double angle = atan2(freq_imag[i], freq_real[i]);
00486 result -= plugin->reference[i] * level;
00487 if(result < 0) result = 0;
00488 freq_real[i] = result * cos(angle);
00489 freq_imag[i] = result * sin(angle);
00490 }
00491 symmetry(window_size, freq_real, freq_imag);
00492 return 0;
00493 }
00494
00495 int DenoiseFFTRemove::read_samples(int64_t output_sample,
00496 int samples,
00497 double *buffer)
00498 {
00499 return plugin->read_samples(buffer,
00500 0,
00501 plugin->get_samplerate(),
00502 output_sample,
00503 samples);
00504 }
00505
00506
00507
00508
00509
00510 DenoiseFFTCollect::DenoiseFFTCollect(DenoiseFFTEffect *plugin)
00511 {
00512 this->plugin = plugin;
00513 }
00514
00515 int DenoiseFFTCollect::signal_process()
00516 {
00517 for(int i = 0; i < window_size / 2; i++)
00518 {
00519 double result = sqrt(freq_real[i] * freq_real[i] + freq_imag[i] * freq_imag[i]);
00520 plugin->reference[i] += result;
00521 }
00522 return 0;
00523 }
00524
00525 int DenoiseFFTCollect::read_samples(int64_t output_sample,
00526 int samples,
00527 double *buffer)
00528 {
00529 return plugin->read_samples(buffer,
00530 0,
00531 plugin->get_samplerate(),
00532 output_sample,
00533 samples);
00534 }
00535