e6de8c3479548ddbbbfaa15c946c9c8e744c97a3
[goodguy/history.git] / cinelerra-5.1 / plugins / resamplert / resamplert.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2010 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 "language.h"
26 #include "resamplert.h"
27 #include "theme.h"
28 #include "transportque.h"
29
30 #include <string.h>
31
32
33
34
35
36
37
38 REGISTER_PLUGIN(ResampleRT);
39
40
41
42 ResampleRTConfig::ResampleRTConfig()
43 {
44         scale = 1;
45 }
46
47
48 int ResampleRTConfig::equivalent(ResampleRTConfig &src)
49 {
50         return fabs(scale - src.scale) < 0.0001;
51 }
52
53 void ResampleRTConfig::copy_from(ResampleRTConfig &src)
54 {
55         this->scale = src.scale;
56 }
57
58 void ResampleRTConfig::interpolate(ResampleRTConfig &prev, 
59         ResampleRTConfig &next, 
60         int64_t prev_frame, 
61         int64_t next_frame, 
62         int64_t current_frame)
63 {
64         this->scale = prev.scale;
65 }
66
67 void ResampleRTConfig::boundaries()
68 {
69         if(fabs(scale) < 0.0001) scale = 0.0001;
70 }
71
72
73
74
75 ResampleRTWindow::ResampleRTWindow(ResampleRT *plugin)
76  : PluginClientWindow(plugin, 
77         210, 
78         160, 
79         200, 
80         160, 
81         0)
82 {
83         this->plugin = plugin;
84 }
85
86 ResampleRTWindow::~ResampleRTWindow()
87 {
88 }
89
90 void ResampleRTWindow::create_objects()
91 {
92         int x = 10, y = 10;
93
94         BC_Title *title;
95         add_subwindow(title = new BC_Title(x, y, _("Scale by amount:")));
96         y += title->get_h() + plugin->get_theme()->widget_border;
97
98         scale = new ResampleRTScale(this,
99                 plugin, 
100                 x, 
101                 y);
102         scale->create_objects();
103         show_window();
104 }
105
106
107
108
109
110
111 ResampleRTScale::ResampleRTScale(ResampleRTWindow *window,
112         ResampleRT *plugin, 
113         int x, 
114         int y)
115  : BC_TumbleTextBox(window,
116         plugin->config.scale,
117         (float)0.0001,
118         (float)1000,
119         x, 
120         y, 
121         100)
122 {
123         this->plugin = plugin;
124         set_increment(0.001);
125 }
126
127 int ResampleRTScale::handle_event()
128 {
129         plugin->config.scale = atof(get_text());
130         plugin->send_configure_change();
131         return 1;
132 }
133
134
135
136
137
138
139 ResampleRTResample::ResampleRTResample(ResampleRT *plugin)
140  : Resample()
141 {
142         this->plugin = plugin;
143 }
144
145 // To get the keyframes to work, resampling is always done in the forward
146 // direction with the plugin converting to reverse.
147 int ResampleRTResample::read_samples(Samples *buffer, 
148         int64_t start, 
149         int64_t len)
150 {
151         int result = plugin->read_samples(buffer,
152                 0,
153                 plugin->get_samplerate(),
154                 plugin->source_start,
155                 len);
156
157 //printf("ResampleRTResample::read_samples %lld %lld %lld %d\n", start, plugin->source_start, len, result);
158         if(plugin->get_direction() == PLAY_FORWARD)
159                 plugin->source_start += len;
160         else
161                 plugin->source_start -= len;
162         
163         return result;
164 }
165
166
167
168
169
170
171 ResampleRT::ResampleRT(PluginServer *server)
172  : PluginAClient(server)
173 {
174         resample = 0;
175         need_reconfigure = 1;
176         prev_scale = 0;
177         dest_start = -1;
178 }
179
180
181 ResampleRT::~ResampleRT()
182 {
183         delete resample;
184 }
185
186 const char* ResampleRT::plugin_title() { return _("ResampleRT"); }
187 int ResampleRT::is_realtime() { return 1; }
188 int ResampleRT::is_synthesis() { return 1; }
189
190
191 NEW_WINDOW_MACRO(ResampleRT, ResampleRTWindow)
192
193 LOAD_CONFIGURATION_MACRO(ResampleRT, ResampleRTConfig)
194
195
196 int ResampleRT::process_buffer(int64_t size, 
197         Samples *buffer,
198         int64_t start_position,
199         int sample_rate)
200 {
201         if(!resample) resample = new ResampleRTResample(this);
202
203         need_reconfigure |= load_configuration();
204         
205         
206         if(start_position != dest_start) need_reconfigure = 1;
207         dest_start = start_position;
208
209 // Get start position of the input.
210 // Sample 0 is the keyframe position
211         if(need_reconfigure)
212         {
213                 int64_t prev_position = edl_to_local(
214                         get_prev_keyframe(
215                                 get_source_position())->position);
216
217                 if(prev_position == 0)
218                 {
219                         prev_position = get_source_start();
220                 }
221
222                 source_start = (int64_t)((start_position - prev_position) * 
223                         config.scale) + prev_position;
224
225                 resample->reset();
226                 need_reconfigure = 0;
227         }
228
229         resample->resample(buffer,
230                 size,
231                 (int)1000000,
232                 (int)(1000000 / config.scale),
233                 start_position,
234                 get_direction());       
235
236         if(get_direction() == PLAY_FORWARD)
237                 dest_start += size;
238         else
239                 dest_start -= size;
240
241         return 0;
242 }
243
244 void ResampleRT::render_stop()
245 {
246         need_reconfigure = 1;
247 }
248
249
250
251
252 void ResampleRT::save_data(KeyFrame *keyframe)
253 {
254         FileXML output;
255
256 // cause data to be stored directly in text
257         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
258         output.tag.set_title("RESAMPLERT");
259         output.tag.set_property("SCALE", config.scale);
260         output.append_tag();
261         output.tag.set_title("/RESAMPLERT");
262         output.append_tag();
263         output.append_newline();
264         output.terminate_string();
265 }
266
267 void ResampleRT::read_data(KeyFrame *keyframe)
268 {
269         FileXML input;
270
271         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
272
273         while(!input.read_tag())
274         {
275                 if(input.tag.title_is("RESAMPLERT"))
276                 {
277                         config.scale = input.tag.get_property("SCALE", config.scale);
278                 }
279         }
280 }
281
282 void ResampleRT::update_gui()
283 {
284         if(thread)
285         {
286                 if(load_configuration())
287                 {
288                         thread->window->lock_window("ResampleRT::update_gui");
289                         ((ResampleRTWindow*)thread->window)->scale->update((float)config.scale);
290                         thread->window->unlock_window();
291                 }
292         }
293 }
294
295
296
297
298