plugin fixes and upgrades
[goodguy/history.git] / cinelerra-5.0 / plugins / timestretchrt / timestretchrt.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
5  * 
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.
10  * 
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.
15  * 
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
19  * 
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "bchash.h"
24 #include "filexml.h"
25 #include "format.inc"
26 #include "language.h"
27 #include "theme.h"
28 #include "../timestretch/timestretchengine.h"
29 #include "timestretchrt.h"
30 #include "transportque.h"
31
32 #include <string.h>
33
34
35
36
37
38
39
40 REGISTER_PLUGIN(TimeStretchRT);
41
42
43
44 TimeStretchRTConfig::TimeStretchRTConfig()
45 {
46         scale = 1;
47         size = 40;
48 }
49
50
51 int TimeStretchRTConfig::equivalent(TimeStretchRTConfig &src)
52 {
53         return fabs(scale - src.scale) < 0.0001 && size == src.size;
54 }
55
56 void TimeStretchRTConfig::copy_from(TimeStretchRTConfig &src)
57 {
58         this->scale = src.scale;
59         this->size = src.size;
60 }
61
62 void TimeStretchRTConfig::interpolate(TimeStretchRTConfig &prev, 
63         TimeStretchRTConfig &next, 
64         int64_t prev_frame, 
65         int64_t next_frame, 
66         int64_t current_frame)
67 {
68         this->scale = prev.scale;
69         this->size = prev.size;
70         boundaries();
71 }
72
73 void TimeStretchRTConfig::boundaries()
74 {
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;
79 }
80
81
82
83
84 TimeStretchRTWindow::TimeStretchRTWindow(TimeStretchRT *plugin)
85  : PluginClientWindow(plugin, 
86         210, 
87         160, 
88         200, 
89         160, 
90         0)
91 {
92         this->plugin = plugin;
93 }
94
95 TimeStretchRTWindow::~TimeStretchRTWindow()
96 {
97 }
98
99 void TimeStretchRTWindow::create_objects()
100 {
101         int x = 10, y = 10;
102
103         BC_Title *title = 0;
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,
107                 plugin, 
108                 x, 
109                 y);
110         scale->create_objects();
111         
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,
116                 plugin, 
117                 x, 
118                 y);
119         size->create_objects();
120
121         show_window();
122 }
123
124
125
126
127
128
129 TimeStretchRTScale::TimeStretchRTScale(TimeStretchRTWindow *window,
130         TimeStretchRT *plugin, 
131         int x, 
132         int y)
133  : BC_TumbleTextBox(window,
134         (float)(1.0 / plugin->config.scale),
135         (float)0.0001,
136         (float)1000,
137         x, 
138         y, 
139         100)
140 {
141         this->plugin = plugin;
142         set_increment(0.01);
143 }
144
145 int TimeStretchRTScale::handle_event()
146 {
147         plugin->config.scale = 1.0 / atof(get_text());
148         plugin->send_configure_change();
149         return 1;
150 }
151
152
153
154
155 TimeStretchRTSize::TimeStretchRTSize(TimeStretchRTWindow *window,
156         TimeStretchRT *plugin, 
157         int x, 
158         int y)
159  : BC_TumbleTextBox(window,
160         plugin->config.size,
161         10,
162         1000,
163         x, 
164         y, 
165         100)
166 {
167         this->plugin = plugin;
168         set_increment(10);
169 }
170
171 int TimeStretchRTSize::handle_event()
172 {
173         plugin->config.size = atoi(get_text());
174         plugin->send_configure_change();
175         return 1;
176 }
177
178
179
180
181
182
183
184
185 TimeStretchRT::TimeStretchRT(PluginServer *server)
186  : PluginAClient(server)
187 {
188         need_reconfigure = 1;
189         dest_start = -1;
190         source_start = -1;
191         engine = 0;
192 }
193
194
195 TimeStretchRT::~TimeStretchRT()
196 {
197         delete engine;
198 }
199
200 const char* TimeStretchRT::plugin_title() { return _("Time Stretch RT"); }
201 int TimeStretchRT::is_realtime() { return 1; }
202 int TimeStretchRT::is_synthesis() { return 1; }
203
204
205 NEW_WINDOW_MACRO(TimeStretchRT, TimeStretchRTWindow)
206
207 LOAD_CONFIGURATION_MACRO(TimeStretchRT, TimeStretchRTConfig)
208
209
210 int TimeStretchRT::process_buffer(int64_t size, 
211         Samples *buffer,
212         int64_t start_position,
213         int sample_rate)
214 {
215         need_reconfigure = load_configuration();
216
217         if(!engine) engine = new TimeStretchEngine(config.scale, 
218                 sample_rate,
219                 config.size);
220
221         if(start_position != dest_start) need_reconfigure = 1;
222         dest_start = start_position;
223
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);
227         if(need_reconfigure)
228         {
229                 int64_t prev_position = edl_to_local(
230                         get_prev_keyframe(
231                                 get_source_position())->position);
232
233                 if(prev_position == 0)
234                 {
235                         prev_position = get_source_start();
236                 }
237
238                 source_start = (int64_t)((start_position - prev_position) / 
239                         config.scale) + prev_position;
240
241                 engine->reset();
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=%jd scale=%f source_start=%jd\n", 
246 //      __LINE__, start_position, prev_position, config.scale, source_start);
247         }
248
249 // process buffers until output length is reached
250         int error = 0;
251         while(!error && engine->get_output_size() < size)
252         {
253
254 // printf("TimeStretchRT::process_buffer %d buffer=%p size=%lld source_start=%lld\n", 
255 // __LINE__,
256 // buffer,
257 // size,
258 // source_start);
259                 read_samples(buffer,
260                         0,
261                         sample_rate,
262                         source_start,
263                         size);
264                 
265
266                 if(get_direction() == PLAY_FORWARD)
267                         source_start += size;
268                 else
269                         source_start -= size;
270                         
271 //printf("TimeStretchRT::process_buffer %d size=%d\n", __LINE__, size);
272                 engine->process(buffer, size);
273 //printf("TimeStretchRT::process_buffer %d\n", __LINE__);
274
275         }
276 //printf("TimeStretchRT::process_buffer %d\n", __LINE__);
277
278
279         engine->read_output(buffer, size);
280
281 //printf("TimeStretchRT::process_buffer %d\n", __LINE__);
282         if(get_direction() == PLAY_FORWARD)
283                 dest_start += size;
284         else
285                 dest_start -= size;
286
287         return 0;
288 }
289
290
291
292
293
294 void TimeStretchRT::save_data(KeyFrame *keyframe)
295 {
296         FileXML output;
297
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);
303         output.append_tag();
304         output.tag.set_title("/TIMESTRETCHRT");
305         output.append_tag();
306         output.append_newline();
307         output.terminate_string();
308 }
309
310 void TimeStretchRT::read_data(KeyFrame *keyframe)
311 {
312         FileXML input;
313
314         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
315
316         while(!input.read_tag())
317         {
318                 if(input.tag.title_is("TIMESTRETCHRT"))
319                 {
320                         config.scale = input.tag.get_property("SCALE", config.scale);
321                         config.size = input.tag.get_property("SIZE", config.size);
322                 }
323         }
324 }
325
326 void TimeStretchRT::update_gui()
327 {
328         if(thread)
329         {
330                 if(load_configuration())
331                 {
332                 
333                         thread->window->lock_window("TimeStretchRT::update_gui");
334                         ((TimeStretchRTWindow*)thread->window)->scale->update((float)(1.0 / config.scale));
335                         ((TimeStretchRTWindow*)thread->window)->size->update((int64_t)config.size);
336                         thread->window->unlock_window();
337                 }
338         }
339 }
340
341
342
343
344