00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filexml.h"
00005 #include "guicast.h"
00006 #include "language.h"
00007 #include "pluginaclient.h"
00008 #include "transportque.h"
00009
00010 #include <string.h>
00011
00012 class LoopAudio;
00013
00014 class LoopAudioConfig
00015 {
00016 public:
00017 LoopAudioConfig();
00018 int64_t samples;
00019 };
00020
00021
00022 class LoopAudioSamples : public BC_TextBox
00023 {
00024 public:
00025 LoopAudioSamples(LoopAudio *plugin,
00026 int x,
00027 int y);
00028 int handle_event();
00029 LoopAudio *plugin;
00030 };
00031
00032 class LoopAudioWindow : public BC_Window
00033 {
00034 public:
00035 LoopAudioWindow(LoopAudio *plugin, int x, int y);
00036 ~LoopAudioWindow();
00037 void create_objects();
00038 int close_event();
00039 LoopAudio *plugin;
00040 LoopAudioSamples *samples;
00041 };
00042
00043 PLUGIN_THREAD_HEADER(LoopAudio, LoopAudioThread, LoopAudioWindow)
00044
00045 class LoopAudio : public PluginAClient
00046 {
00047 public:
00048 LoopAudio(PluginServer *server);
00049 ~LoopAudio();
00050
00051 PLUGIN_CLASS_MEMBERS(LoopAudioConfig, LoopAudioThread)
00052
00053 int load_defaults();
00054 int save_defaults();
00055 void save_data(KeyFrame *keyframe);
00056 void read_data(KeyFrame *keyframe);
00057 void update_gui();
00058 int is_realtime();
00059 int is_synthesis();
00060 int process_buffer(int64_t size,
00061 double *buffer,
00062 int64_t start_position,
00063 int sample_rate);
00064 };
00065
00066
00067
00068
00069
00070
00071
00072 REGISTER_PLUGIN(LoopAudio);
00073
00074
00075
00076 LoopAudioConfig::LoopAudioConfig()
00077 {
00078 samples = 48000;
00079 }
00080
00081
00082
00083
00084
00085 LoopAudioWindow::LoopAudioWindow(LoopAudio *plugin, int x, int y)
00086 : BC_Window(plugin->gui_string,
00087 x,
00088 y,
00089 210,
00090 160,
00091 200,
00092 160,
00093 0,
00094 0,
00095 1)
00096 {
00097 this->plugin = plugin;
00098 }
00099
00100 LoopAudioWindow::~LoopAudioWindow()
00101 {
00102 }
00103
00104 void LoopAudioWindow::create_objects()
00105 {
00106 int x = 10, y = 10;
00107
00108 add_subwindow(new BC_Title(x, y, _("Samples to loop:")));
00109 y += 20;
00110 add_subwindow(samples = new LoopAudioSamples(plugin,
00111 x,
00112 y));
00113 show_window();
00114 flush();
00115 }
00116
00117 WINDOW_CLOSE_EVENT(LoopAudioWindow)
00118
00119
00120 PLUGIN_THREAD_OBJECT(LoopAudio, LoopAudioThread, LoopAudioWindow)
00121
00122
00123
00124
00125
00126
00127 LoopAudioSamples::LoopAudioSamples(LoopAudio *plugin,
00128 int x,
00129 int y)
00130 : BC_TextBox(x,
00131 y,
00132 100,
00133 1,
00134 plugin->config.samples)
00135 {
00136 this->plugin = plugin;
00137 set_precision(2);
00138 }
00139
00140 int LoopAudioSamples::handle_event()
00141 {
00142 plugin->config.samples = atol(get_text());
00143 plugin->config.samples = MAX(1, plugin->config.samples);
00144 plugin->send_configure_change();
00145 return 1;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 LoopAudio::LoopAudio(PluginServer *server)
00157 : PluginAClient(server)
00158 {
00159 PLUGIN_CONSTRUCTOR_MACRO
00160 }
00161
00162
00163 LoopAudio::~LoopAudio()
00164 {
00165 PLUGIN_DESTRUCTOR_MACRO
00166 }
00167
00168 char* LoopAudio::plugin_title() { return N_("Loop audio"); }
00169 int LoopAudio::is_realtime() { return 1; }
00170 int LoopAudio::is_synthesis() { return 1; }
00171
00172
00173 #include "picon_png.h"
00174 NEW_PICON_MACRO(LoopAudio)
00175
00176 SHOW_GUI_MACRO(LoopAudio, LoopAudioThread)
00177
00178 RAISE_WINDOW_MACRO(LoopAudio)
00179
00180 SET_STRING_MACRO(LoopAudio);
00181
00182
00183 int LoopAudio::process_buffer(int64_t size,
00184 double *buffer,
00185 int64_t start_position,
00186 int sample_rate)
00187 {
00188 int64_t current_position = start_position;
00189 int step = (get_direction() == PLAY_FORWARD) ? 1 : -1;
00190 int fragment_size;
00191 int64_t current_loop_end;
00192
00193
00194
00195 current_position = start_position;
00196
00197 for(int i = 0; i < size; i += fragment_size)
00198 {
00199
00200 fragment_size = MIN(size - i, size);
00201
00202 int64_t current_loop_position;
00203
00204
00205 if(get_direction() == PLAY_FORWARD)
00206 {
00207 KeyFrame *next_keyframe = get_next_keyframe(current_position);
00208 int64_t next_position = edl_to_local(next_keyframe->position);
00209 if(next_position > current_position)
00210 fragment_size = MIN(fragment_size, next_position - current_position);
00211
00212
00213 KeyFrame *prev_keyframe = get_prev_keyframe(current_position);
00214 int64_t prev_position = edl_to_local(prev_keyframe->position);
00215 if(prev_position == 0)
00216 prev_position = get_source_start();
00217 read_data(prev_keyframe);
00218
00219
00220 current_loop_position = prev_position +
00221 ((current_position - prev_position) %
00222 config.samples);
00223 while(current_loop_position < prev_position) current_loop_position += config.samples;
00224 while(current_loop_position >= prev_position + config.samples) current_loop_position -= config.samples;
00225
00226
00227 current_loop_end = current_position -
00228 current_loop_position +
00229 prev_position +
00230 config.samples;
00231 fragment_size = MIN(current_loop_end - current_position,
00232 fragment_size);
00233 }
00234 else
00235 {
00236 KeyFrame *next_keyframe = get_prev_keyframe(current_position);
00237 int64_t next_position = edl_to_local(next_keyframe->position);
00238 if(next_position < current_position)
00239 fragment_size = MIN(fragment_size, current_position - next_position);
00240
00241 KeyFrame *prev_keyframe = get_next_keyframe(current_position);
00242 int64_t prev_position = edl_to_local(prev_keyframe->position);
00243 if(prev_position == 0)
00244 prev_position = get_source_start() + get_total_len();
00245 read_data(prev_keyframe);
00246
00247 current_loop_position = prev_position -
00248 ((prev_position - current_position) %
00249 config.samples);
00250 while(current_loop_position <= prev_position - config.samples) current_loop_position += config.samples;
00251 while(current_loop_position > prev_position) current_loop_position -= config.samples;
00252
00253
00254 current_loop_end = current_position +
00255 prev_position -
00256 current_loop_position -
00257 config.samples;
00258 fragment_size = MIN(current_position - current_loop_end,
00259 fragment_size);
00260 }
00261
00262
00263
00264
00265 read_samples(buffer + i,
00266 0,
00267 sample_rate,
00268 current_loop_position,
00269 fragment_size);
00270
00271
00272 current_position += step * fragment_size;
00273 }
00274
00275
00276 return 0;
00277 }
00278
00279
00280
00281
00282 int LoopAudio::load_configuration()
00283 {
00284 KeyFrame *prev_keyframe;
00285 int64_t old_samples = config.samples;
00286 prev_keyframe = get_prev_keyframe(get_source_position());
00287 read_data(prev_keyframe);
00288 return old_samples != config.samples;
00289 }
00290
00291 int LoopAudio::load_defaults()
00292 {
00293 char directory[BCTEXTLEN];
00294
00295 sprintf(directory, "%sloopaudio.rc", BCASTDIR);
00296
00297
00298 defaults = new BC_Hash(directory);
00299 defaults->load();
00300
00301 config.samples = defaults->get("SAMPLES", config.samples);
00302 return 0;
00303 }
00304
00305 int LoopAudio::save_defaults()
00306 {
00307 defaults->update("SAMPLES", config.samples);
00308 defaults->save();
00309 return 0;
00310 }
00311
00312 void LoopAudio::save_data(KeyFrame *keyframe)
00313 {
00314 FileXML output;
00315
00316
00317 output.set_shared_string(keyframe->data, MESSAGESIZE);
00318 output.tag.set_title("LOOPAUDIO");
00319 output.tag.set_property("SAMPLES", config.samples);
00320 output.append_tag();
00321 output.tag.set_title("/LOOPAUDIO");
00322 output.append_tag();
00323 output.terminate_string();
00324 }
00325
00326 void LoopAudio::read_data(KeyFrame *keyframe)
00327 {
00328 FileXML input;
00329
00330 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00331
00332 int result = 0;
00333
00334 while(!input.read_tag())
00335 {
00336 if(input.tag.title_is("LOOPAUDIO"))
00337 {
00338 config.samples = input.tag.get_property("SAMPLES", config.samples);
00339 }
00340 }
00341 }
00342
00343 void LoopAudio::update_gui()
00344 {
00345 if(thread)
00346 {
00347 load_configuration();
00348 thread->window->lock_window();
00349 thread->window->samples->update(config.samples);
00350 thread->window->unlock_window();
00351 }
00352 }
00353
00354
00355
00356
00357