4 * Copyright (C) 2010-2016 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"
26 #include "resamplert.h"
28 #include "transportque.h"
38 REGISTER_PLUGIN(ResampleRT);
42 ResampleRTConfig::ResampleRTConfig()
49 int ResampleRTConfig::equivalent(ResampleRTConfig &src)
51 return fabs(num - src.num) < 0.0001 &&
52 fabs(denom - src.denom) < 0.0001;
55 void ResampleRTConfig::copy_from(ResampleRTConfig &src)
58 this->denom = src.denom;
61 void ResampleRTConfig::interpolate(ResampleRTConfig &prev,
62 ResampleRTConfig &next,
65 int64_t current_frame)
68 this->denom = prev.denom;
71 void ResampleRTConfig::boundaries()
73 if(num < 0.0001) num = 0.0001;
74 if(denom < 0.0001) denom = 0.0001;
80 ResampleRTWindow::ResampleRTWindow(ResampleRT *plugin)
81 : PluginClientWindow(plugin,
88 this->plugin = plugin;
91 ResampleRTWindow::~ResampleRTWindow()
95 void ResampleRTWindow::create_objects()
97 int x = plugin->get_theme()->window_border;
98 int y = plugin->get_theme()->window_border;
101 add_subwindow(title = new BC_Title(x, y, _("Input samples:")));
102 y += title->get_h() + plugin->get_theme()->widget_border;
103 num = new ResampleRTNum(this, plugin, x, y);
104 num->create_objects();
106 y += num->get_h() + plugin->get_theme()->widget_border;
107 add_subwindow(title = new BC_Title(x, y, _("Output samples:")));
108 y += title->get_h() + plugin->get_theme()->widget_border;
109 denom = new ResampleRTDenom(this, plugin, x, y);
110 denom->create_objects();
120 ResampleRTNum::ResampleRTNum(ResampleRTWindow *window,
124 : BC_TumbleTextBox(window,
132 this->plugin = plugin;
133 set_increment(0.001);
136 int ResampleRTNum::handle_event()
138 plugin->config.num = atof(get_text());
139 plugin->config.boundaries();
140 plugin->send_configure_change();
147 ResampleRTDenom::ResampleRTDenom(ResampleRTWindow *window,
151 : BC_TumbleTextBox(window,
152 plugin->config.denom,
159 this->plugin = plugin;
160 set_increment(0.001);
163 int ResampleRTDenom::handle_event()
165 plugin->config.denom = atof(get_text());
166 plugin->config.boundaries();
167 plugin->send_configure_change();
176 ResampleRTResample::ResampleRTResample(ResampleRT *plugin)
179 this->plugin = plugin;
182 // To get the keyframes to work, resampling is always done in the forward
183 // direction with the plugin converting to reverse.
184 int ResampleRTResample::read_samples(Samples *buffer,
185 int64_t start, int64_t len, int direction)
187 int result = plugin->read_samples(buffer,
189 plugin->get_samplerate(),
190 plugin->source_start,
193 //printf("ResampleRTResample::read_samples %lld %lld %lld %d\n", start, plugin->source_start, len, result);
194 if(plugin->get_direction() == PLAY_FORWARD)
195 plugin->source_start += len;
197 plugin->source_start -= len;
207 ResampleRT::ResampleRT(PluginServer *server)
208 : PluginAClient(server)
211 need_reconfigure = 1;
217 ResampleRT::~ResampleRT()
222 const char* ResampleRT::plugin_title() { return N_("ResampleRT"); }
223 int ResampleRT::is_realtime() { return 1; }
224 int ResampleRT::is_synthesis() { return 1; }
227 NEW_WINDOW_MACRO(ResampleRT, ResampleRTWindow)
229 LOAD_CONFIGURATION_MACRO(ResampleRT, ResampleRTConfig)
232 int ResampleRT::process_buffer(int64_t size,
234 int64_t start_position,
237 if(!resample) resample = new ResampleRTResample(this);
239 need_reconfigure |= load_configuration();
242 if(start_position != dest_start) need_reconfigure = 1;
243 dest_start = start_position;
245 // Get start position of the input.
246 // Sample 0 is the keyframe position
249 int64_t prev_position = edl_to_local(
251 get_source_position())->position);
253 if(prev_position == 0)
255 prev_position = get_source_start();
258 source_start = (int64_t)((start_position - prev_position) *
259 config.num / config.denom) + prev_position;
262 need_reconfigure = 0;
265 resample->resample(buffer,
267 (int)(65536 * config.num),
268 (int)(65536 * config.denom),
272 if(get_direction() == PLAY_FORWARD)
280 void ResampleRT::render_stop()
282 need_reconfigure = 1;
288 void ResampleRT::save_data(KeyFrame *keyframe)
292 // cause data to be stored directly in text
293 output.set_shared_output(keyframe->xbuf);
294 output.tag.set_title("RESAMPLERT");
295 output.tag.set_property("SCALE", config.num);
296 output.tag.set_property("DENOM", config.denom);
298 output.tag.set_title("/RESAMPLERT");
300 output.append_newline();
301 output.terminate_string();
304 void ResampleRT::read_data(KeyFrame *keyframe)
308 input.set_shared_input(keyframe->xbuf);
310 while(!input.read_tag())
312 if(input.tag.title_is("RESAMPLERT"))
314 config.num = input.tag.get_property("SCALE", config.num);
315 config.denom = input.tag.get_property("DENOM", config.denom);
320 void ResampleRT::update_gui()
324 if(load_configuration())
326 thread->window->lock_window("ResampleRT::update_gui");
327 ((ResampleRTWindow*)thread->window)->num->update((float)config.num);
328 ((ResampleRTWindow*)thread->window)->denom->update((float)config.denom);
329 thread->window->unlock_window();