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;
111 //printf("FloatAutos::automation_is_constant 1 %d %d\n", start, end);
113 // No keyframes on track
116 constant = ((FloatAuto*)default_auto)->value;
120 // Only one keyframe on track.
123 constant = ((FloatAuto*)first)->value;
127 // Last keyframe is before region
128 if(last->position <= start)
130 constant = ((FloatAuto*)last)->value;
134 // First keyframe is after region
135 if(first->position > end)
137 constant = ((FloatAuto*)first)->value;
142 int64_t prev_position = -1;
143 for(Auto *current = first; current; current = NEXT)
145 int test_current_next = 0;
146 int test_previous_current = 0;
147 FloatAuto *float_current = (FloatAuto*)current;
149 // keyframes before and after region but not in region
150 if(prev_position >= 0 &&
151 prev_position < start &&
152 current->position >= end)
154 // Get value now in case change doesn't occur
155 constant = float_current->value;
156 test_previous_current = 1;
158 prev_position = current->position;
160 // Keyframe occurs in the region
161 if(!test_previous_current &&
162 current->position < end &&
163 current->position >= start)
166 // Get value now in case change doesn't occur
167 constant = float_current->value;
169 // Keyframe has neighbor
170 if(current->previous)
172 test_previous_current = 1;
177 test_current_next = 1;
181 if(test_current_next)
183 //printf("FloatAutos::automation_is_constant 1 %d\n", start);
184 FloatAuto *float_next = (FloatAuto*)current->next;
186 // Change occurs between keyframes
187 if(!EQUIV(float_current->value, float_next->value) ||
188 !EQUIV(float_current->control_out_value, 0) ||
189 !EQUIV(float_next->control_in_value, 0))
195 if(test_previous_current)
197 FloatAuto *float_previous = (FloatAuto*)current->previous;
199 // Change occurs between keyframes
200 if(!EQUIV(float_current->value, float_previous->value) ||
201 !EQUIV(float_current->control_in_value, 0) ||
202 !EQUIV(float_previous->control_out_value, 0))
204 // printf("FloatAutos::automation_is_constant %d %d %d %f %f %f %f\n",
206 // float_previous->position,
207 // float_current->position,
208 // float_previous->value,
209 // float_current->value,
210 // float_previous->control_out_value,
211 // float_current->control_in_value);
217 // Got nothing that changes in the region.
221 double FloatAutos::get_automation_constant(int64_t start, int64_t end)
223 Auto *current_auto, *before = 0, *after = 0;
225 // quickly get autos just outside range
226 get_neighbors(start, end, &before, &after);
228 // no auto before range so use first
230 current_auto = before;
232 current_auto = first;
234 // no autos at all so use default value
235 if(!current_auto) current_auto = default_auto;
237 return ((FloatAuto*)current_auto)->value;
241 float FloatAutos::get_value(int64_t position,
243 FloatAuto* &previous,
249 // Calculate bezier equation at position
250 float y0, y1, y2, y3;
253 previous = (FloatAuto*)get_prev_auto(position, direction, (Auto*)previous, 0);
254 next = (FloatAuto*)get_next_auto(position, direction, (Auto*)next, 0);
257 if(!next && !previous)
259 return ((FloatAuto*)default_auto)->value;
269 return previous->value;
274 return previous->value;
278 if(direction == PLAY_FORWARD &&
279 EQUIV(previous->value, next->value) &&
280 EQUIV(previous->control_out_value, 0) &&
281 EQUIV(next->control_in_value, 0))
283 return previous->value;
286 if(direction == PLAY_REVERSE &&
287 EQUIV(previous->value, next->value) &&
288 EQUIV(previous->control_in_value, 0) &&
289 EQUIV(next->control_out_value, 0))
291 return previous->value;
297 y0 = previous->value;
300 if(direction == PLAY_FORWARD)
302 y1 = previous->value + previous->control_out_value * 2;
303 y2 = next->value + next->control_in_value * 2;
304 t = (double)(position - previous->position) /
305 (next->position - previous->position);
307 if(next->position - previous->position == 0) return previous->value;
311 y1 = previous->value + previous->control_in_value * 2;
312 y2 = next->value + next->control_out_value * 2;
313 t = (double)(previous->position - position) /
314 (previous->position - next->position);
316 if(previous->position - next->position == 0) return previous->value;
320 float tpow3 = t * t * t;
322 float invtpow2 = invt * invt;
323 float invtpow3 = invt * invt * invt;
325 float result = ( invtpow3 * y0
326 + 3 * t * invtpow2 * y1
327 + 3 * tpow2 * invt * y2
329 //printf("FloatAutos::get_value %f %f %d %d %d %d\n", result, t, direction, position, previous->position, next->position);
335 // get_fade_automation(slope,
341 // return (float)intercept;
345 void FloatAutos::get_fade_automation(double &slope,
347 int64_t input_position,
352 FloatAuto *prev_keyframe =
353 (FloatAuto*)get_prev_auto(input_position, direction, current);
354 FloatAuto *next_keyframe =
355 (FloatAuto*)get_next_auto(input_position, direction, current);
356 int64_t new_slope_len;
358 if(direction == PLAY_FORWARD)
360 new_slope_len = next_keyframe->position - prev_keyframe->position;
362 //printf("FloatAutos::get_fade_automation %d %d %d\n",
363 // prev_keyframe->position, input_position, next_keyframe->position);
365 // Two distinct automation points within range
366 if(next_keyframe->position > prev_keyframe->position)
368 slope = ((double)next_keyframe->value - prev_keyframe->value) /
370 intercept = ((double)input_position - prev_keyframe->position) * slope + prev_keyframe->value;
372 if(next_keyframe->position < input_position + new_slope_len)
373 new_slope_len = next_keyframe->position - input_position;
374 slope_len = MIN(slope_len, new_slope_len);
377 // One automation point within range
380 intercept = prev_keyframe->value;
385 new_slope_len = prev_keyframe->position - next_keyframe->position;
386 // Two distinct automation points within range
387 if(next_keyframe->position < prev_keyframe->position)
389 slope = ((double)next_keyframe->value - prev_keyframe->value) / new_slope_len;
390 intercept = ((double)prev_keyframe->position - input_position) * slope + prev_keyframe->value;
392 if(prev_keyframe->position > input_position - new_slope_len)
393 new_slope_len = input_position - prev_keyframe->position;
394 slope_len = MIN(slope_len, new_slope_len);
397 // One automation point within range
400 intercept = next_keyframe->value;
405 float FloatAutos::value_to_percentage(float value)
407 return (value - min) / (max - min);
411 int FloatAutos::dump()
413 printf(" FloatAutos::dump %p\n", this);
414 printf(" Default: position %lld value=%f\n",
415 default_auto->position,
416 ((FloatAuto*)default_auto)->value);
417 for(Auto* current = first; current; current = NEXT)
419 printf(" position %lld value=%f invalue=%f outvalue=%f\n",
421 ((FloatAuto*)current)->value,
422 ((FloatAuto*)current)->control_in_value,
423 ((FloatAuto*)current)->control_out_value);