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,
188 int result = plugin->read_samples(buffer,
190 plugin->get_samplerate(),
191 plugin->source_start,
194 //printf("ResampleRTResample::read_samples %lld %lld %lld %d\n", start, plugin->source_start, len, result);
195 if(plugin->get_direction() == PLAY_FORWARD)
196 plugin->source_start += len;
198 plugin->source_start -= len;
208 ResampleRT::ResampleRT(PluginServer *server)
209 : PluginAClient(server)
212 need_reconfigure = 1;
218 ResampleRT::~ResampleRT()
223 const char* ResampleRT::plugin_title() { return N_("ResampleRT"); }
224 int ResampleRT::is_realtime() { return 1; }
225 int ResampleRT::is_synthesis() { return 1; }
228 NEW_WINDOW_MACRO(ResampleRT, ResampleRTWindow)
230 LOAD_CONFIGURATION_MACRO(ResampleRT, ResampleRTConfig)
233 int ResampleRT::process_buffer(int64_t size,
235 int64_t start_position,
238 if(!resample) resample = new ResampleRTResample(this);
240 need_reconfigure |= load_configuration();
243 if(start_position != dest_start) need_reconfigure = 1;
244 dest_start = start_position;
246 // Get start position of the input.
247 // Sample 0 is the keyframe position
250 int64_t prev_position = edl_to_local(
252 get_source_position())->position);
254 if(prev_position == 0)
256 prev_position = get_source_start();
259 source_start = (int64_t)((start_position - prev_position) *
260 config.num / config.denom) + prev_position;
263 need_reconfigure = 0;
266 resample->resample(buffer,
268 (int)(65536 * config.num),
269 (int)(65536 * config.denom),
273 if(get_direction() == PLAY_FORWARD)
281 void ResampleRT::render_stop()
283 need_reconfigure = 1;
289 void ResampleRT::save_data(KeyFrame *keyframe)
293 // cause data to be stored directly in text
294 output.set_shared_output(keyframe->xbuf);
295 output.tag.set_title("RESAMPLERT");
296 output.tag.set_property("SCALE", config.num);
297 output.tag.set_property("DENOM", config.denom);
299 output.tag.set_title("/RESAMPLERT");
301 output.append_newline();
302 output.terminate_string();
305 void ResampleRT::read_data(KeyFrame *keyframe)
309 input.set_shared_input(keyframe->xbuf);
311 while(!input.read_tag())
313 if(input.tag.title_is("RESAMPLERT"))
315 config.num = input.tag.get_property("SCALE", config.num);
316 config.denom = input.tag.get_property("DENOM", config.denom);
321 void ResampleRT::update_gui()
325 if(load_configuration())
327 thread->window->lock_window("ResampleRT::update_gui");
328 ((ResampleRTWindow*)thread->window)->num->update((float)config.num);
329 ((ResampleRTWindow*)thread->window)->denom->update((float)config.denom);
330 thread->window->unlock_window();