1 #include "bcdisplayinfo.h"
7 #include "pluginaclient.h"
8 #include "transportque.h"
22 class LoopAudioSamples : public BC_TextBox
25 LoopAudioSamples(LoopAudio *plugin,
32 class LoopAudioWindow : public BC_Window
35 LoopAudioWindow(LoopAudio *plugin, int x, int y);
37 void create_objects();
40 LoopAudioSamples *samples;
43 PLUGIN_THREAD_HEADER(LoopAudio, LoopAudioThread, LoopAudioWindow)
45 class LoopAudio : public PluginAClient
48 LoopAudio(PluginServer *server);
51 PLUGIN_CLASS_MEMBERS(LoopAudioConfig, LoopAudioThread)
55 void save_data(KeyFrame *keyframe);
56 void read_data(KeyFrame *keyframe);
60 int process_buffer(int64_t size,
62 int64_t start_position,
72 REGISTER_PLUGIN(LoopAudio);
76 LoopAudioConfig::LoopAudioConfig()
85 LoopAudioWindow::LoopAudioWindow(LoopAudio *plugin, int x, int y)
86 : BC_Window(plugin->gui_string,
97 this->plugin = plugin;
100 LoopAudioWindow::~LoopAudioWindow()
104 void LoopAudioWindow::create_objects()
108 add_subwindow(new BC_Title(x, y, _("Samples to loop:")));
110 add_subwindow(samples = new LoopAudioSamples(plugin,
117 WINDOW_CLOSE_EVENT(LoopAudioWindow)
120 PLUGIN_THREAD_OBJECT(LoopAudio, LoopAudioThread, LoopAudioWindow)
127 LoopAudioSamples::LoopAudioSamples(LoopAudio *plugin,
134 plugin->config.samples)
136 this->plugin = plugin;
140 int LoopAudioSamples::handle_event()
142 plugin->config.samples = atol(get_text());
143 plugin->config.samples = MAX(1, plugin->config.samples);
144 plugin->send_configure_change();
156 LoopAudio::LoopAudio(PluginServer *server)
157 : PluginAClient(server)
159 PLUGIN_CONSTRUCTOR_MACRO
163 LoopAudio::~LoopAudio()
165 PLUGIN_DESTRUCTOR_MACRO
168 char* LoopAudio::plugin_title() { return N_("Loop audio"); }
169 int LoopAudio::is_realtime() { return 1; }
170 int LoopAudio::is_synthesis() { return 1; }
173 #include "picon_png.h"
174 NEW_PICON_MACRO(LoopAudio)
176 SHOW_GUI_MACRO(LoopAudio, LoopAudioThread)
178 RAISE_WINDOW_MACRO(LoopAudio)
180 SET_STRING_MACRO(LoopAudio);
183 int LoopAudio::process_buffer(int64_t size,
185 int64_t start_position,
188 int64_t current_position = start_position;
189 int step = (get_direction() == PLAY_FORWARD) ? 1 : -1;
191 int64_t current_loop_end;
193 //printf("LoopAudio::process_buffer 1 %lld %d\n", start_position, size);
195 current_position = start_position;
197 for(int i = 0; i < size; i += fragment_size)
199 // Truncate to end of buffer
200 fragment_size = MIN(size - i, size);
202 int64_t current_loop_position;
204 // Truncate to next keyframe
205 if(get_direction() == PLAY_FORWARD)
207 KeyFrame *next_keyframe = get_next_keyframe(current_position);
208 int64_t next_position = edl_to_local(next_keyframe->position);
209 if(next_position > current_position)
210 fragment_size = MIN(fragment_size, next_position - current_position);
212 // Get start of current loop
213 KeyFrame *prev_keyframe = get_prev_keyframe(current_position);
214 int64_t prev_position = edl_to_local(prev_keyframe->position);
215 if(prev_position == 0)
216 prev_position = get_source_start();
217 read_data(prev_keyframe);
219 // Get start of fragment in current loop
220 current_loop_position = prev_position +
221 ((current_position - prev_position) %
223 while(current_loop_position < prev_position) current_loop_position += config.samples;
224 while(current_loop_position >= prev_position + config.samples) current_loop_position -= config.samples;
226 // Truncate fragment to end of loop
227 current_loop_end = current_position -
228 current_loop_position +
231 fragment_size = MIN(current_loop_end - current_position,
236 KeyFrame *next_keyframe = get_prev_keyframe(current_position);
237 int64_t next_position = edl_to_local(next_keyframe->position);
238 if(next_position < current_position)
239 fragment_size = MIN(fragment_size, current_position - next_position);
241 KeyFrame *prev_keyframe = get_next_keyframe(current_position);
242 int64_t prev_position = edl_to_local(prev_keyframe->position);
243 if(prev_position == 0)
244 prev_position = get_source_start() + get_total_len();
245 read_data(prev_keyframe);
247 current_loop_position = prev_position -
248 ((prev_position - current_position) %
250 while(current_loop_position <= prev_position - config.samples) current_loop_position += config.samples;
251 while(current_loop_position > prev_position) current_loop_position -= config.samples;
253 // Truncate fragment to end of loop
254 current_loop_end = current_position +
256 current_loop_position -
258 fragment_size = MIN(current_position - current_loop_end,
263 // printf("LoopAudio::process_buffer 100 %lld %lld %lld %d\n",
264 // current_position, current_loop_position, current_loop_end, fragment_size);
265 read_samples(buffer + i,
268 current_loop_position,
272 current_position += step * fragment_size;
282 int LoopAudio::load_configuration()
284 KeyFrame *prev_keyframe;
285 int64_t old_samples = config.samples;
286 prev_keyframe = get_prev_keyframe(get_source_position());
287 read_data(prev_keyframe);
288 return old_samples != config.samples;
291 int LoopAudio::load_defaults()
293 char directory[BCTEXTLEN];
294 // set the default directory
295 sprintf(directory, "%sloopaudio.rc", BCASTDIR);
298 defaults = new BC_Hash(directory);
301 config.samples = defaults->get("SAMPLES", config.samples);
305 int LoopAudio::save_defaults()
307 defaults->update("SAMPLES", config.samples);
312 void LoopAudio::save_data(KeyFrame *keyframe)
316 // cause data to be stored directly in text
317 output.set_shared_string(keyframe->data, MESSAGESIZE);
318 output.tag.set_title("LOOPAUDIO");
319 output.tag.set_property("SAMPLES", config.samples);
321 output.terminate_string();
324 void LoopAudio::read_data(KeyFrame *keyframe)
328 input.set_shared_string(keyframe->data, strlen(keyframe->data));
332 while(!input.read_tag())
334 if(input.tag.title_is("LOOPAUDIO"))
336 config.samples = input.tag.get_property("SAMPLES", config.samples);
341 void LoopAudio::update_gui()
345 load_configuration();
346 thread->window->lock_window();
347 thread->window->samples->update(config.samples);
348 thread->window->unlock_window();