r602: Fix baver's code... don't insert timecode when show_tc is not set
[cinelerra_cv/mob.git] / cinelerra / floatautos.C
blob8ae467d1929e4200809ac4f2dd0b5937d572454c
1 #include "clip.h"
2 #include "filexml.h"
3 #include "floatauto.h"
4 #include "floatautos.h"
5 #include "transportque.inc"
7 FloatAutos::FloatAutos(EDL *edl,
8                                 Track *track, 
9                                 int color, 
10                                 float min, 
11                                 float max, 
12                                 float default_,
13                                 int virtual_h,
14                                 int use_floats)
15  : Autos(edl, track)
17         this->max = max; 
18         this->min = min;
19         this->default_ = default_;
20         this->virtual_h = virtual_h;
21         this->use_floats = use_floats;
24 FloatAutos::~FloatAutos()
28 int FloatAutos::get_track_pixels(int zoom_track, int pixel, int &center_pixel, float &yscale)
30         center_pixel = pixel + zoom_track / 2;
31         yscale = -(float)zoom_track / (max - min);
34 int FloatAutos::draw_joining_line(BC_SubWindow *canvas, int vertical, int center_pixel, int x1, int y1, int x2, int y2)
36         if(vertical)
37         canvas->draw_line(center_pixel - y1, x1, center_pixel - y2, x2);
38         else
39         canvas->draw_line(x1, center_pixel + y1, x2, center_pixel + y2);
42 Auto* FloatAutos::add_auto(int64_t position, float value)
44         FloatAuto* current = (FloatAuto*)autoof(position);
45         FloatAuto* new_auto;
46         
47         insert_before(current, new_auto = new FloatAuto(edl, this));
49         new_auto->position = position;
50         new_auto->value = value;
51         
52         return new_auto;
55 Auto* FloatAutos::append_auto()
57         return append(new FloatAuto(edl, this));
60 Auto* FloatAutos::new_auto()
62         return new FloatAuto(edl, this);
65 float FloatAutos::fix_value(float value)
67         int value_int;
68         
69         if(use_floats)
70         {
71 // Fix precision
72                 value_int = (int)(value * 100);
73                 value = (float)value_int / 100;
74         }
75         else
76         {
77 // not really floating point
78                 value_int = (int)value;
79                 value = value_int;
80         }
82         if(value < min) value = min;
83         else
84         if(value > max) value = max;
85         
86         return value;   
89 int FloatAutos::get_testy(float slope, int cursor_x, int ax, int ay)
91         return (int)(slope * (cursor_x - ax)) + ay;
94 int FloatAutos::automation_is_constant(int64_t start, 
95         int64_t length, 
96         int direction,
97         double &constant)
99         int total_autos = total();
100         int64_t end;
101         if(direction == PLAY_FORWARD)
102         {
103                 end = start + length;
104         }
105         else
106         {
107                 end = start + 1;
108                 start -= length;
109         }
112 // No keyframes on track
113         if(total_autos == 0)
114         {
115                 constant = ((FloatAuto*)default_auto)->value;
116                 return 1;
117         }
118         else
119 // Only one keyframe on track.
120         if(total_autos == 1)
121         {
122                 constant = ((FloatAuto*)first)->value;
123                 return 1;
124         }
125         else
126 // Last keyframe is before region
127         if(last->position <= start)
128         {
129                 constant = ((FloatAuto*)last)->value;
130                 return 1;
131         }
132         else
133 // First keyframe is after region
134         if(first->position > end)
135         {
136                 constant = ((FloatAuto*)first)->value;
137                 return 1;
138         }
140 // Scan sequentially
141         int64_t prev_position = -1;
142         for(Auto *current = first; current; current = NEXT)
143         {
144                 int test_current_next = 0;
145                 int test_previous_current = 0;
146                 FloatAuto *float_current = (FloatAuto*)current;
148 // keyframes before and after region but not in region
149                 if(prev_position >= 0 &&
150                         prev_position < start && 
151                         current->position >= end)
152                 {
153 // Get value now in case change doesn't occur
154                         constant = float_current->value;
155                         test_previous_current = 1;
156                 }
157                 prev_position = current->position;
159 // Keyframe occurs in the region
160                 if(!test_previous_current &&
161                         current->position < end && 
162                         current->position >= start)
163                 {
165 // Get value now in case change doesn't occur
166                         constant = float_current->value;
168 // Keyframe has neighbor
169                         if(current->previous)
170                         {
171                                 test_previous_current = 1;
172                         }
174                         if(current->next)
175                         {
176                                 test_current_next = 1;
177                         }
178                 }
180                 if(test_current_next)
181                 {
182 //printf("FloatAutos::automation_is_constant 1 %d\n", start);
183                         FloatAuto *float_next = (FloatAuto*)current->next;
185 // Change occurs between keyframes
186                         if(!EQUIV(float_current->value, float_next->value) ||
187                                 !EQUIV(float_current->control_out_value, 0) ||
188                                 !EQUIV(float_next->control_in_value, 0))
189                         {
190                                 return 0;
191                         }
192                 }
194                 if(test_previous_current)
195                 {
196                         FloatAuto *float_previous = (FloatAuto*)current->previous;
198 // Change occurs between keyframes
199                         if(!EQUIV(float_current->value, float_previous->value) ||
200                                 !EQUIV(float_current->control_in_value, 0) ||
201                                 !EQUIV(float_previous->control_out_value, 0))
202                         {
203 // printf("FloatAutos::automation_is_constant %d %d %d %f %f %f %f\n", 
204 // start, 
205 // float_previous->position, 
206 // float_current->position, 
207 // float_previous->value, 
208 // float_current->value, 
209 // float_previous->control_out_value, 
210 // float_current->control_in_value);
211                                 return 0;
212                         }
213                 }
214         }
216 // Got nothing that changes in the region.
217         return 1;
220 double FloatAutos::get_automation_constant(int64_t start, int64_t end)
222         Auto *current_auto, *before = 0, *after = 0;
223         
224 // quickly get autos just outside range 
225         get_neighbors(start, end, &before, &after);
227 // no auto before range so use first
228         if(before)
229                 current_auto = before;
230         else
231                 current_auto = first;
233 // no autos at all so use default value
234         if(!current_auto) current_auto = default_auto;
236         return ((FloatAuto*)current_auto)->value;
240 float FloatAutos::get_value(int64_t position, 
241         int direction, 
242         FloatAuto* &previous, 
243         FloatAuto* &next)
245         double slope;
246         double intercept;
247         int64_t slope_len;
248 // Calculate bezier equation at position
249         float y0, y1, y2, y3;
250         float t;
252         previous = (FloatAuto*)get_prev_auto(position, direction, (Auto*&)previous, 0);
253         next = (FloatAuto*)get_next_auto(position, direction, (Auto*&)next, 0);
255 // Constant
256         if(!next && !previous)
257         {
258                 return ((FloatAuto*)default_auto)->value;
259         }
260         else
261         if(!previous)
262         {
263                 return next->value;
264         }
265         else
266         if(!next)
267         {
268                 return previous->value;
269         }
270         else
271         if(next == previous)
272         {
273                 return previous->value;
274         }
275         else
276         {
277                 if(direction == PLAY_FORWARD &&
278                         EQUIV(previous->value, next->value) &&
279                         EQUIV(previous->control_out_value, 0) &&
280                         EQUIV(next->control_in_value, 0))
281                 {
282                         return previous->value;
283                 }
284                 else
285                 if(direction == PLAY_REVERSE &&
286                         EQUIV(previous->value, next->value) &&
287                         EQUIV(previous->control_in_value, 0) &&
288                         EQUIV(next->control_out_value, 0))
289                 {
290                         return previous->value;
291                 }
292         }
295 // Interpolate
296         y0 = previous->value;
297         y3 = next->value;
299         if(direction == PLAY_FORWARD)
300         {
301                 y1 = previous->value + previous->control_out_value * 2;
302                 y2 = next->value + next->control_in_value * 2;
303                 t = (double)(position - previous->position) / 
304                         (next->position - previous->position);
305 // division by 0
306                 if(next->position - previous->position == 0) return previous->value;
307         }
308         else
309         {
310                 y1 = previous->value + previous->control_in_value * 2;
311                 y2 = next->value + next->control_out_value * 2;
312                 t = (double)(previous->position - position) / 
313                         (previous->position - next->position);
314 // division by 0
315                 if(previous->position - next->position == 0) return previous->value;
316         }
318         float tpow2 = t * t;
319         float tpow3 = t * t * t;
320         float invt = 1 - t;
321         float invtpow2 = invt * invt;
322         float invtpow3 = invt * invt * invt;
323         
324         float result = (  invtpow3 * y0
325                 + 3 * t     * invtpow2 * y1
326                 + 3 * tpow2 * invt     * y2 
327                 +     tpow3            * y3);
328 //printf("FloatAutos::get_value %f %f %d %d %d %d\n", result, t, direction, position, previous->position, next->position);
330         return result;
334 //      get_fade_automation(slope,
335 //              intercept,
336 //              position,
337 //              slope_len,
338 //              PLAY_FORWARD);
339 // 
340 //      return (float)intercept;
344 void FloatAutos::get_fade_automation(double &slope,
345         double &intercept,
346         int64_t input_position,
347         int64_t &slope_len,
348         int direction)
350         Auto *current = 0;
351         FloatAuto *prev_keyframe = 
352                 (FloatAuto*)get_prev_auto(input_position, direction, current);
353         FloatAuto *next_keyframe = 
354                 (FloatAuto*)get_next_auto(input_position, direction, current);
355         int64_t new_slope_len;
357         if(direction == PLAY_FORWARD)
358         {
359                 new_slope_len = next_keyframe->position - prev_keyframe->position;
361 //printf("FloatAutos::get_fade_automation %d %d %d\n", 
362 //      prev_keyframe->position, input_position, next_keyframe->position);
364 // Two distinct automation points within range
365                 if(next_keyframe->position > prev_keyframe->position)
366                 {
367                         slope = ((double)next_keyframe->value - prev_keyframe->value) / 
368                                 new_slope_len;
369                         intercept = ((double)input_position - prev_keyframe->position) * slope + prev_keyframe->value;
371                         if(next_keyframe->position < input_position + new_slope_len)
372                                 new_slope_len = next_keyframe->position - input_position;
373                         slope_len = MIN(slope_len, new_slope_len);
374                 }
375                 else
376 // One automation point within range
377                 {
378                         slope = 0;
379                         intercept = prev_keyframe->value;
380                 }
381         }
382         else
383         {
384                 new_slope_len = prev_keyframe->position - next_keyframe->position;
385 // Two distinct automation points within range
386                 if(next_keyframe->position < prev_keyframe->position)
387                 {
388                         slope = ((double)next_keyframe->value - prev_keyframe->value) / new_slope_len;
389                         intercept = ((double)prev_keyframe->position - input_position) * slope + prev_keyframe->value;
391                         if(prev_keyframe->position > input_position - new_slope_len)
392                                 new_slope_len = input_position - prev_keyframe->position;
393                         slope_len = MIN(slope_len, new_slope_len);
394                 }
395                 else
396 // One automation point within range
397                 {
398                         slope = 0;
399                         intercept = next_keyframe->value;
400                 }
401         }
404 float FloatAutos::value_to_percentage(float value)
406         return (value - min) / (max - min);
410 int FloatAutos::dump()
412         printf("        FloatAutos::dump %p\n", this);
413         printf("        Default: position %lld value=%f\n", 
414                 default_auto->position, 
415                 ((FloatAuto*)default_auto)->value);
416         for(Auto* current = first; current; current = NEXT)
417         {
418                 printf("        position %lld value=%f invalue=%f outvalue=%f\n", 
419                         current->position, 
420                         ((FloatAuto*)current)->value,
421                         ((FloatAuto*)current)->control_in_value,
422                         ((FloatAuto*)current)->control_out_value);
423         }
424         return 0;