4 #include "floatautos.h"
5 #include "transportque.inc"
7 FloatAutos::FloatAutos(EDL *edl,
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 ¢er_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)
37 canvas->draw_line(center_pixel - y1, x1, center_pixel - y2, x2);
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);
47 insert_before(current, new_auto = new FloatAuto(edl, this));
49 new_auto->position = position;
50 new_auto->value = value;
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)
72 value_int = (int)(value * 100);
73 value = (float)value_int / 100;
77 // not really floating point
78 value_int = (int)value;
82 if(value < min) value = min;
84 if(value > max) value = max;
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,
99 int total_autos = total();
101 if(direction == PLAY_FORWARD)
103 end = start + length;
112 // No keyframes on track
115 constant = ((FloatAuto*)default_auto)->value;
119 // Only one keyframe on track.
122 constant = ((FloatAuto*)first)->value;
126 // Last keyframe is before region
127 if(last->position <= start)
129 constant = ((FloatAuto*)last)->value;
133 // First keyframe is after region
134 if(first->position > end)
136 constant = ((FloatAuto*)first)->value;
141 int64_t prev_position = -1;
142 for(Auto *current = first; current; current = NEXT)
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)
153 // Get value now in case change doesn't occur
154 constant = float_current->value;
155 test_previous_current = 1;
157 prev_position = current->position;
159 // Keyframe occurs in the region
160 if(!test_previous_current &&
161 current->position < end &&
162 current->position >= start)
165 // Get value now in case change doesn't occur
166 constant = float_current->value;
168 // Keyframe has neighbor
169 if(current->previous)
171 test_previous_current = 1;
176 test_current_next = 1;
180 if(test_current_next)
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))
194 if(test_previous_current)
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))
203 // printf("FloatAutos::automation_is_constant %d %d %d %f %f %f %f\n",
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);
216 // Got nothing that changes in the region.
220 double FloatAutos::get_automation_constant(int64_t start, int64_t end)
222 Auto *current_auto, *before = 0, *after = 0;
224 // quickly get autos just outside range
225 get_neighbors(start, end, &before, &after);
227 // no auto before range so use first
229 current_auto = before;
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,
242 FloatAuto* &previous,
248 // Calculate bezier equation at position
249 float y0, y1, y2, y3;
252 previous = (FloatAuto*)get_prev_auto(position, direction, (Auto*&)previous, 0);
253 next = (FloatAuto*)get_next_auto(position, direction, (Auto*&)next, 0);
256 if(!next && !previous)
258 return ((FloatAuto*)default_auto)->value;
268 return previous->value;
273 return previous->value;
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))
282 return previous->value;
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))
290 return previous->value;
296 y0 = previous->value;
299 if(direction == PLAY_FORWARD)
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);
306 if(next->position - previous->position == 0) return previous->value;
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);
315 if(previous->position - next->position == 0) return previous->value;
319 float tpow3 = t * t * t;
321 float invtpow2 = invt * invt;
322 float invtpow3 = invt * invt * invt;
324 float result = ( invtpow3 * y0
325 + 3 * t * invtpow2 * y1
326 + 3 * tpow2 * invt * y2
328 //printf("FloatAutos::get_value %f %f %d %d %d %d\n", result, t, direction, position, previous->position, next->position);
334 // get_fade_automation(slope,
340 // return (float)intercept;
344 void FloatAutos::get_fade_automation(double &slope,
346 int64_t input_position,
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)
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)
367 slope = ((double)next_keyframe->value - prev_keyframe->value) /
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);
376 // One automation point within range
379 intercept = prev_keyframe->value;
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)
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);
396 // One automation point within range
399 intercept = next_keyframe->value;
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)
418 printf(" position %lld value=%f invalue=%f outvalue=%f\n",
420 ((FloatAuto*)current)->value,
421 ((FloatAuto*)current)->control_in_value,
422 ((FloatAuto*)current)->control_out_value);