4 * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "bcdisplayinfo.h"
28 #include "../timestretch/timestretchengine.h"
29 #include "timestretchrt.h"
30 #include "transportque.h"
40 REGISTER_PLUGIN(TimeStretchRT);
44 TimeStretchRTConfig::TimeStretchRTConfig()
51 int TimeStretchRTConfig::equivalent(TimeStretchRTConfig &src)
53 return fabs(scale - src.scale) < 0.0001 && size == src.size;
56 void TimeStretchRTConfig::copy_from(TimeStretchRTConfig &src)
58 this->scale = src.scale;
59 this->size = src.size;
62 void TimeStretchRTConfig::interpolate(TimeStretchRTConfig &prev,
63 TimeStretchRTConfig &next,
66 int64_t current_frame)
68 this->scale = prev.scale;
69 this->size = prev.size;
73 void TimeStretchRTConfig::boundaries()
75 if(fabs(scale) < 0.01) scale = 0.01;
76 if(fabs(scale) > 100) scale = 100;
77 if(size < 10) size = 10;
78 if(size > 1000) size = 1000;
84 TimeStretchRTWindow::TimeStretchRTWindow(TimeStretchRT *plugin)
85 : PluginClientWindow(plugin,
92 this->plugin = plugin;
95 TimeStretchRTWindow::~TimeStretchRTWindow()
99 void TimeStretchRTWindow::create_objects()
104 add_subwindow(title = new BC_Title(x, y, _("Fraction of original speed:")));
105 y += title->get_h() + plugin->get_theme()->widget_border;
106 scale = new TimeStretchRTScale(this,
110 scale->create_objects();
112 y += scale->get_h() + plugin->get_theme()->widget_border;
113 add_subwindow(title = new BC_Title(x, y, _("Window size (ms):")));
114 y += title->get_h() + plugin->get_theme()->widget_border;
115 size = new TimeStretchRTSize(this,
119 size->create_objects();
129 TimeStretchRTScale::TimeStretchRTScale(TimeStretchRTWindow *window,
130 TimeStretchRT *plugin,
133 : BC_TumbleTextBox(window,
134 (float)(1.0 / plugin->config.scale),
141 this->plugin = plugin;
145 int TimeStretchRTScale::handle_event()
147 plugin->config.scale = 1.0 / atof(get_text());
148 plugin->send_configure_change();
155 TimeStretchRTSize::TimeStretchRTSize(TimeStretchRTWindow *window,
156 TimeStretchRT *plugin,
159 : BC_TumbleTextBox(window,
167 this->plugin = plugin;
171 int TimeStretchRTSize::handle_event()
173 plugin->config.size = atoi(get_text());
174 plugin->send_configure_change();
185 TimeStretchRT::TimeStretchRT(PluginServer *server)
186 : PluginAClient(server)
188 need_reconfigure = 1;
195 TimeStretchRT::~TimeStretchRT()
200 const char* TimeStretchRT::plugin_title() { return _("Time Stretch RT"); }
201 int TimeStretchRT::is_realtime() { return 1; }
202 int TimeStretchRT::is_synthesis() { return 1; }
205 NEW_WINDOW_MACRO(TimeStretchRT, TimeStretchRTWindow)
207 LOAD_CONFIGURATION_MACRO(TimeStretchRT, TimeStretchRTConfig)
210 int TimeStretchRT::process_buffer(int64_t size,
212 int64_t start_position,
215 need_reconfigure = load_configuration();
217 if(!engine) engine = new TimeStretchEngine(config.scale,
221 if(start_position != dest_start) need_reconfigure = 1;
222 dest_start = start_position;
224 // Get start position of the input.
225 // Sample 0 is the keyframe position
226 //printf("TimeStretchRT::process_buffer %d %f\n", __LINE__, config.scale);
229 int64_t prev_position = edl_to_local(
231 get_source_position())->position);
233 if(prev_position == 0)
235 prev_position = get_source_start();
238 source_start = (int64_t)((start_position - prev_position) /
239 config.scale) + prev_position;
242 engine->update(config.scale, sample_rate, config.size);
243 need_reconfigure = 0;
244 //printf("TimeStretchRT::process_buffer %d start_position=" _LD
245 // " prev_position=" _LD " scale=%f source_start=" _LD "\n",
246 // __LINE__, start_position, prev_position, config.scale, source_start);
249 // process buffers until output length is reached
251 while(!error && engine->get_output_size() < size)
254 // printf("TimeStretchRT::process_buffer %d buffer=%p size=%lld source_start=%lld\n",
266 if(get_direction() == PLAY_FORWARD)
267 source_start += size;
269 source_start -= size;
271 //printf("TimeStretchRT::process_buffer %d size=%d\n", __LINE__, size);
272 engine->process(buffer, size);
273 //printf("TimeStretchRT::process_buffer %d\n", __LINE__);
276 //printf("TimeStretchRT::process_buffer %d\n", __LINE__);
279 engine->read_output(buffer, size);
281 //printf("TimeStretchRT::process_buffer %d\n", __LINE__);
282 if(get_direction() == PLAY_FORWARD)
294 void TimeStretchRT::save_data(KeyFrame *keyframe)
298 // cause data to be stored directly in text
299 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
300 output.tag.set_title("TIMESTRETCHRT");
301 output.tag.set_property("SCALE", config.scale);
302 output.tag.set_property("SIZE", config.size);
304 output.terminate_string();
307 void TimeStretchRT::read_data(KeyFrame *keyframe)
311 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
313 while(!input.read_tag())
315 if(input.tag.title_is("TIMESTRETCHRT"))
317 config.scale = input.tag.get_property("SCALE", config.scale);
318 config.size = input.tag.get_property("SIZE", config.size);
323 void TimeStretchRT::update_gui()
327 if(load_configuration())
330 thread->window->lock_window("TimeStretchRT::update_gui");
331 ((TimeStretchRTWindow*)thread->window)->scale->update((float)(1.0 / config.scale));
332 ((TimeStretchRTWindow*)thread->window)->size->update((int64_t)config.size);
333 thread->window->unlock_window();