1 #include "automation.inc"
4 #include "edlsession.h"
7 #include "floatautos.h"
9 #include "localsession.h"
10 #include "transportque.inc"
12 FloatAutos::FloatAutos(EDL *edl,
17 this->default_ = default_;
18 type = AUTOMATION_TYPE_FLOAT;
21 FloatAutos::~FloatAutos()
25 void FloatAutos::straighten(int64_t start, int64_t end)
27 FloatAuto *current = (FloatAuto*)first;
30 FloatAuto *previous_auto = (FloatAuto*)PREVIOUS;
31 FloatAuto *next_auto = (FloatAuto*)NEXT;
33 // Is current auto in range?
34 if(current->position >= start && current->position < end)
36 float current_value = current->value;
38 // Determine whether to set the control in point.
39 if(previous_auto && previous_auto->position >= start)
41 float previous_value = previous_auto->value;
42 current->control_in_value = (previous_value - current_value) / 6.0;
43 if(!current->control_in_position)
44 current->control_in_position = -track->to_units(1.0, 0);
47 // Determine whether to set the control out point
48 if(next_auto && next_auto->position < end)
50 float next_value = next_auto->value;
51 current->control_out_value = (next_value - current_value) / 6.0;
52 if(!current->control_out_position)
53 current->control_out_position = track->to_units(1.0, 0);
56 current = (FloatAuto*)NEXT;
60 int FloatAutos::draw_joining_line(BC_SubWindow *canvas, int vertical, int center_pixel, int x1, int y1, int x2, int y2)
63 canvas->draw_line(center_pixel - y1, x1, center_pixel - y2, x2);
65 canvas->draw_line(x1, center_pixel + y1, x2, center_pixel + y2);
68 Auto* FloatAutos::add_auto(int64_t position, float value)
70 FloatAuto* current = (FloatAuto*)autoof(position);
73 insert_before(current, result = (FloatAuto*)new_auto());
75 result->position = position;
76 result->value = value;
81 Auto* FloatAutos::new_auto()
83 FloatAuto *result = new FloatAuto(edl, this);
84 result->value = default_;
88 int FloatAutos::get_testy(float slope, int cursor_x, int ax, int ay)
90 return (int)(slope * (cursor_x - ax)) + ay;
93 int FloatAutos::automation_is_constant(int64_t start,
98 int total_autos = total();
100 if(direction == PLAY_FORWARD)
102 end = start + length;
111 // No keyframes on track
114 constant = ((FloatAuto*)default_auto)->value;
118 // Only one keyframe on track.
121 constant = ((FloatAuto*)first)->value;
125 // Last keyframe is before region
126 if(last->position <= start)
128 constant = ((FloatAuto*)last)->value;
132 // First keyframe is after region
133 if(first->position > end)
135 constant = ((FloatAuto*)first)->value;
140 int64_t prev_position = -1;
141 for(Auto *current = first; current; current = NEXT)
143 int test_current_next = 0;
144 int test_previous_current = 0;
145 FloatAuto *float_current = (FloatAuto*)current;
147 // keyframes before and after region but not in region
148 if(prev_position >= 0 &&
149 prev_position < start &&
150 current->position >= end)
152 // Get value now in case change doesn't occur
153 constant = float_current->value;
154 test_previous_current = 1;
156 prev_position = current->position;
158 // Keyframe occurs in the region
159 if(!test_previous_current &&
160 current->position < end &&
161 current->position >= start)
164 // Get value now in case change doesn't occur
165 constant = float_current->value;
167 // Keyframe has neighbor
168 if(current->previous)
170 test_previous_current = 1;
175 test_current_next = 1;
179 if(test_current_next)
181 //printf("FloatAutos::automation_is_constant 1 %d\n", start);
182 FloatAuto *float_next = (FloatAuto*)current->next;
184 // Change occurs between keyframes
185 if(!EQUIV(float_current->value, float_next->value) ||
186 !EQUIV(float_current->control_out_value, 0) ||
187 !EQUIV(float_next->control_in_value, 0))
193 if(test_previous_current)
195 FloatAuto *float_previous = (FloatAuto*)current->previous;
197 // Change occurs between keyframes
198 if(!EQUIV(float_current->value, float_previous->value) ||
199 !EQUIV(float_current->control_in_value, 0) ||
200 !EQUIV(float_previous->control_out_value, 0))
202 // printf("FloatAutos::automation_is_constant %d %d %d %f %f %f %f\n",
204 // float_previous->position,
205 // float_current->position,
206 // float_previous->value,
207 // float_current->value,
208 // float_previous->control_out_value,
209 // float_current->control_in_value);
215 // Got nothing that changes in the region.
219 double FloatAutos::get_automation_constant(int64_t start, int64_t end)
221 Auto *current_auto, *before = 0, *after = 0;
223 // quickly get autos just outside range
224 get_neighbors(start, end, &before, &after);
226 // no auto before range so use first
228 current_auto = before;
230 current_auto = first;
232 // no autos at all so use default value
233 if(!current_auto) current_auto = default_auto;
235 return ((FloatAuto*)current_auto)->value;
239 float FloatAutos::get_value(int64_t position,
241 FloatAuto* &previous,
247 // Calculate bezier equation at position
248 float y0, y1, y2, y3;
251 previous = (FloatAuto*)get_prev_auto(position, direction, (Auto* &)previous, 0);
252 next = (FloatAuto*)get_next_auto(position, direction, (Auto* &)next, 0);
255 if(!next && !previous)
257 return ((FloatAuto*)default_auto)->value;
267 return previous->value;
272 return previous->value;
276 if(direction == PLAY_FORWARD &&
277 EQUIV(previous->value, next->value) &&
278 EQUIV(previous->control_out_value, 0) &&
279 EQUIV(next->control_in_value, 0))
281 return previous->value;
284 if(direction == PLAY_REVERSE &&
285 EQUIV(previous->value, next->value) &&
286 EQUIV(previous->control_in_value, 0) &&
287 EQUIV(next->control_out_value, 0))
289 return previous->value;
295 y0 = previous->value;
298 if(direction == PLAY_FORWARD)
300 y1 = previous->value + previous->control_out_value * 2;
301 y2 = next->value + next->control_in_value * 2;
302 t = (double)(position - previous->position) /
303 (next->position - previous->position);
305 if(next->position - previous->position == 0) return previous->value;
309 y1 = previous->value + previous->control_in_value * 2;
310 y2 = next->value + next->control_out_value * 2;
311 t = (double)(previous->position - position) /
312 (previous->position - next->position);
314 if(previous->position - next->position == 0) return previous->value;
318 float tpow3 = t * t * t;
320 float invtpow2 = invt * invt;
321 float invtpow3 = invt * invt * invt;
323 float result = ( invtpow3 * y0
324 + 3 * t * invtpow2 * y1
325 + 3 * tpow2 * invt * y2
327 //printf("FloatAutos::get_value %f %f %d %d %d %d\n", result, t, direction, position, previous->position, next->position);
333 // get_fade_automation(slope,
339 // return (float)intercept;
343 void FloatAutos::get_fade_automation(double &slope,
345 int64_t input_position,
350 FloatAuto *prev_keyframe =
351 (FloatAuto*)get_prev_auto(input_position, direction, current);
352 FloatAuto *next_keyframe =
353 (FloatAuto*)get_next_auto(input_position, direction, current);
354 int64_t new_slope_len;
356 if(direction == PLAY_FORWARD)
358 new_slope_len = next_keyframe->position - prev_keyframe->position;
360 //printf("FloatAutos::get_fade_automation %d %d %d\n",
361 // prev_keyframe->position, input_position, next_keyframe->position);
363 // Two distinct automation points within range
364 if(next_keyframe->position > prev_keyframe->position)
366 slope = ((double)next_keyframe->value - prev_keyframe->value) /
368 intercept = ((double)input_position - prev_keyframe->position) * slope + prev_keyframe->value;
370 if(next_keyframe->position < input_position + new_slope_len)
371 new_slope_len = next_keyframe->position - input_position;
372 slope_len = MIN(slope_len, new_slope_len);
375 // One automation point within range
378 intercept = prev_keyframe->value;
383 new_slope_len = prev_keyframe->position - next_keyframe->position;
384 // Two distinct automation points within range
385 if(next_keyframe->position < prev_keyframe->position)
387 slope = ((double)next_keyframe->value - prev_keyframe->value) / new_slope_len;
388 intercept = ((double)prev_keyframe->position - input_position) * slope + prev_keyframe->value;
390 if(prev_keyframe->position > input_position - new_slope_len)
391 new_slope_len = input_position - prev_keyframe->position;
392 slope_len = MIN(slope_len, new_slope_len);
395 // One automation point within range
398 intercept = next_keyframe->value;
403 void FloatAutos::get_extents(float *min,
405 int *coords_undefined,
411 printf("FloatAutos::get_extents edl == NULL\n");
417 printf("FloatAutos::get_extents track == NULL\n");
424 FloatAuto *current = (FloatAuto*)default_auto;
425 if(*coords_undefined)
427 *min = *max = current->value;
428 *coords_undefined = 0;
431 *min = MIN(current->value, *min);
432 *max = MAX(current->value, *max);
436 for(FloatAuto *current = (FloatAuto*)first; current; current = (FloatAuto*)NEXT)
438 if(current->position >= unit_start && current->position < unit_end)
440 if(*coords_undefined)
442 *min = *max = current->value;
443 *coords_undefined = 0;
446 *min = MIN(current->value, *min);
447 *min = MIN(current->value + current->control_in_value, *min);
448 *min = MIN(current->value + current->control_out_value, *min);
450 *max = MAX(current->value, *max);
451 *max = MAX(current->value + current->control_in_value, *max);
452 *max = MAX(current->value + current->control_out_value, *max);
456 // Test joining regions
459 int64_t unit_step = edl->local_session->zoom_sample;
460 if(track->data_type == TRACK_VIDEO)
461 unit_step = (int64_t)(unit_step *
462 edl->session->frame_rate /
463 edl->session->sample_rate);
464 unit_step = MAX(unit_step, 1);
465 for(int64_t position = unit_start;
467 position += unit_step)
469 float value = get_value(position,
473 if(*coords_undefined)
476 *coords_undefined = 0;
480 *min = MIN(value, *min);
481 *max = MAX(value, *max);
486 void FloatAutos::dump()
488 printf(" FloatAutos::dump %p\n", this);
489 printf(" Default: position %lld value=%f\n",
490 default_auto->position,
491 ((FloatAuto*)default_auto)->value);
492 for(Auto* current = first; current; current = NEXT)
494 printf(" position %lld value=%f invalue=%f outvalue=%f inposition=%lld outposition=%lld\n",
496 ((FloatAuto*)current)->value,
497 ((FloatAuto*)current)->control_in_value,
498 ((FloatAuto*)current)->control_out_value,
499 ((FloatAuto*)current)->control_in_position,
500 ((FloatAuto*)current)->control_out_position);