00001 #include "automation.inc"
00002 #include "clip.h"
00003 #include "edl.h"
00004 #include "edlsession.h"
00005 #include "filexml.h"
00006 #include "floatauto.h"
00007 #include "floatautos.h"
00008 #include "track.h"
00009 #include "localsession.h"
00010 #include "transportque.inc"
00011
00012 FloatAutos::FloatAutos(EDL *edl,
00013 Track *track,
00014 float default_)
00015 : Autos(edl, track)
00016 {
00017 this->default_ = default_;
00018 type = AUTOMATION_TYPE_FLOAT;
00019 }
00020
00021 FloatAutos::~FloatAutos()
00022 {
00023 }
00024
00025 int FloatAutos::draw_joining_line(BC_SubWindow *canvas, int vertical, int center_pixel, int x1, int y1, int x2, int y2)
00026 {
00027 if(vertical)
00028 canvas->draw_line(center_pixel - y1, x1, center_pixel - y2, x2);
00029 else
00030 canvas->draw_line(x1, center_pixel + y1, x2, center_pixel + y2);
00031 }
00032
00033 Auto* FloatAutos::add_auto(int64_t position, float value)
00034 {
00035 FloatAuto* current = (FloatAuto*)autoof(position);
00036 FloatAuto* result;
00037
00038 insert_before(current, result = (FloatAuto*)new_auto());
00039
00040 result->position = position;
00041 result->value = value;
00042
00043 return result;
00044 }
00045
00046 Auto* FloatAutos::new_auto()
00047 {
00048 FloatAuto *result = new FloatAuto(edl, this);
00049 result->value = default_;
00050 return result;
00051 }
00052
00053 int FloatAutos::get_testy(float slope, int cursor_x, int ax, int ay)
00054 {
00055 return (int)(slope * (cursor_x - ax)) + ay;
00056 }
00057
00058 int FloatAutos::automation_is_constant(int64_t start,
00059 int64_t length,
00060 int direction,
00061 double &constant)
00062 {
00063 int total_autos = total();
00064 int64_t end;
00065 if(direction == PLAY_FORWARD)
00066 {
00067 end = start + length;
00068 }
00069 else
00070 {
00071 end = start + 1;
00072 start -= length;
00073 }
00074
00075
00076
00077 if(total_autos == 0)
00078 {
00079 constant = ((FloatAuto*)default_auto)->value;
00080 return 1;
00081 }
00082 else
00083
00084 if(total_autos == 1)
00085 {
00086 constant = ((FloatAuto*)first)->value;
00087 return 1;
00088 }
00089 else
00090
00091 if(last->position <= start)
00092 {
00093 constant = ((FloatAuto*)last)->value;
00094 return 1;
00095 }
00096 else
00097
00098 if(first->position > end)
00099 {
00100 constant = ((FloatAuto*)first)->value;
00101 return 1;
00102 }
00103
00104
00105 int64_t prev_position = -1;
00106 for(Auto *current = first; current; current = NEXT)
00107 {
00108 int test_current_next = 0;
00109 int test_previous_current = 0;
00110 FloatAuto *float_current = (FloatAuto*)current;
00111
00112
00113 if(prev_position >= 0 &&
00114 prev_position < start &&
00115 current->position >= end)
00116 {
00117
00118 constant = float_current->value;
00119 test_previous_current = 1;
00120 }
00121 prev_position = current->position;
00122
00123
00124 if(!test_previous_current &&
00125 current->position < end &&
00126 current->position >= start)
00127 {
00128
00129
00130 constant = float_current->value;
00131
00132
00133 if(current->previous)
00134 {
00135 test_previous_current = 1;
00136 }
00137
00138 if(current->next)
00139 {
00140 test_current_next = 1;
00141 }
00142 }
00143
00144 if(test_current_next)
00145 {
00146
00147 FloatAuto *float_next = (FloatAuto*)current->next;
00148
00149
00150 if(!EQUIV(float_current->value, float_next->value) ||
00151 !EQUIV(float_current->control_out_value, 0) ||
00152 !EQUIV(float_next->control_in_value, 0))
00153 {
00154 return 0;
00155 }
00156 }
00157
00158 if(test_previous_current)
00159 {
00160 FloatAuto *float_previous = (FloatAuto*)current->previous;
00161
00162
00163 if(!EQUIV(float_current->value, float_previous->value) ||
00164 !EQUIV(float_current->control_in_value, 0) ||
00165 !EQUIV(float_previous->control_out_value, 0))
00166 {
00167
00168
00169
00170
00171
00172
00173
00174
00175 return 0;
00176 }
00177 }
00178 }
00179
00180
00181 return 1;
00182 }
00183
00184 double FloatAutos::get_automation_constant(int64_t start, int64_t end)
00185 {
00186 Auto *current_auto, *before = 0, *after = 0;
00187
00188
00189 get_neighbors(start, end, &before, &after);
00190
00191
00192 if(before)
00193 current_auto = before;
00194 else
00195 current_auto = first;
00196
00197
00198 if(!current_auto) current_auto = default_auto;
00199
00200 return ((FloatAuto*)current_auto)->value;
00201 }
00202
00203
00204 float FloatAutos::get_value(int64_t position,
00205 int direction,
00206 FloatAuto* &previous,
00207 FloatAuto* &next)
00208 {
00209 double slope;
00210 double intercept;
00211 int64_t slope_len;
00212
00213 float y0, y1, y2, y3;
00214 float t;
00215
00216 previous = (FloatAuto*)get_prev_auto(position, direction, (Auto* &)previous, 0);
00217 next = (FloatAuto*)get_next_auto(position, direction, (Auto* &)next, 0);
00218
00219
00220 if(!next && !previous)
00221 {
00222 return ((FloatAuto*)default_auto)->value;
00223 }
00224 else
00225 if(!previous)
00226 {
00227 return next->value;
00228 }
00229 else
00230 if(!next)
00231 {
00232 return previous->value;
00233 }
00234 else
00235 if(next == previous)
00236 {
00237 return previous->value;
00238 }
00239 else
00240 {
00241 if(direction == PLAY_FORWARD &&
00242 EQUIV(previous->value, next->value) &&
00243 EQUIV(previous->control_out_value, 0) &&
00244 EQUIV(next->control_in_value, 0))
00245 {
00246 return previous->value;
00247 }
00248 else
00249 if(direction == PLAY_REVERSE &&
00250 EQUIV(previous->value, next->value) &&
00251 EQUIV(previous->control_in_value, 0) &&
00252 EQUIV(next->control_out_value, 0))
00253 {
00254 return previous->value;
00255 }
00256 }
00257
00258
00259
00260 y0 = previous->value;
00261 y3 = next->value;
00262
00263 if(direction == PLAY_FORWARD)
00264 {
00265 y1 = previous->value + previous->control_out_value * 2;
00266 y2 = next->value + next->control_in_value * 2;
00267 t = (double)(position - previous->position) /
00268 (next->position - previous->position);
00269
00270 if(next->position - previous->position == 0) return previous->value;
00271 }
00272 else
00273 {
00274 y1 = previous->value + previous->control_in_value * 2;
00275 y2 = next->value + next->control_out_value * 2;
00276 t = (double)(previous->position - position) /
00277 (previous->position - next->position);
00278
00279 if(previous->position - next->position == 0) return previous->value;
00280 }
00281
00282 float tpow2 = t * t;
00283 float tpow3 = t * t * t;
00284 float invt = 1 - t;
00285 float invtpow2 = invt * invt;
00286 float invtpow3 = invt * invt * invt;
00287
00288 float result = ( invtpow3 * y0
00289 + 3 * t * invtpow2 * y1
00290 + 3 * tpow2 * invt * y2
00291 + tpow3 * y3);
00292
00293
00294 return result;
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 }
00306
00307
00308 void FloatAutos::get_fade_automation(double &slope,
00309 double &intercept,
00310 int64_t input_position,
00311 int64_t &slope_len,
00312 int direction)
00313 {
00314 Auto *current = 0;
00315 FloatAuto *prev_keyframe =
00316 (FloatAuto*)get_prev_auto(input_position, direction, current);
00317 FloatAuto *next_keyframe =
00318 (FloatAuto*)get_next_auto(input_position, direction, current);
00319 int64_t new_slope_len;
00320
00321 if(direction == PLAY_FORWARD)
00322 {
00323 new_slope_len = next_keyframe->position - prev_keyframe->position;
00324
00325
00326
00327
00328
00329 if(next_keyframe->position > prev_keyframe->position)
00330 {
00331 slope = ((double)next_keyframe->value - prev_keyframe->value) /
00332 new_slope_len;
00333 intercept = ((double)input_position - prev_keyframe->position) * slope + prev_keyframe->value;
00334
00335 if(next_keyframe->position < input_position + new_slope_len)
00336 new_slope_len = next_keyframe->position - input_position;
00337 slope_len = MIN(slope_len, new_slope_len);
00338 }
00339 else
00340
00341 {
00342 slope = 0;
00343 intercept = prev_keyframe->value;
00344 }
00345 }
00346 else
00347 {
00348 new_slope_len = prev_keyframe->position - next_keyframe->position;
00349
00350 if(next_keyframe->position < prev_keyframe->position)
00351 {
00352 slope = ((double)next_keyframe->value - prev_keyframe->value) / new_slope_len;
00353 intercept = ((double)prev_keyframe->position - input_position) * slope + prev_keyframe->value;
00354
00355 if(prev_keyframe->position > input_position - new_slope_len)
00356 new_slope_len = input_position - prev_keyframe->position;
00357 slope_len = MIN(slope_len, new_slope_len);
00358 }
00359 else
00360
00361 {
00362 slope = 0;
00363 intercept = next_keyframe->value;
00364 }
00365 }
00366 }
00367
00368 void FloatAutos::get_extents(float *min,
00369 float *max,
00370 int *coords_undefined,
00371 int64_t unit_start,
00372 int64_t unit_end)
00373 {
00374 if(!edl)
00375 {
00376 printf("FloatAutos::get_extents edl == NULL\n");
00377 return;
00378 }
00379
00380 if(!track)
00381 {
00382 printf("FloatAutos::get_extents track == NULL\n");
00383 return;
00384 }
00385
00386
00387 if(!first)
00388 {
00389 FloatAuto *current = (FloatAuto*)default_auto;
00390 if(*coords_undefined)
00391 {
00392 *min = *max = current->value;
00393 *coords_undefined = 0;
00394 }
00395
00396 *min = MIN(current->value, *min);
00397 *max = MAX(current->value, *max);
00398 }
00399
00400
00401 for(FloatAuto *current = (FloatAuto*)first; current; current = (FloatAuto*)NEXT)
00402 {
00403 if(current->position >= unit_start && current->position < unit_end)
00404 {
00405 if(*coords_undefined)
00406 {
00407 *min = *max = current->value;
00408 *coords_undefined = 0;
00409 }
00410
00411 *min = MIN(current->value, *min);
00412 *min = MIN(current->value + current->control_in_value, *min);
00413 *min = MIN(current->value + current->control_out_value, *min);
00414
00415 *max = MAX(current->value, *max);
00416 *max = MAX(current->value + current->control_in_value, *max);
00417 *max = MAX(current->value + current->control_out_value, *max);
00418 }
00419 }
00420
00421
00422 FloatAuto *prev = 0;
00423 FloatAuto *next = 0;
00424 int64_t unit_step = edl->local_session->zoom_sample;
00425 if(track->data_type == TRACK_VIDEO)
00426 unit_step = (int64_t)(unit_step *
00427 edl->session->frame_rate /
00428 edl->session->sample_rate);
00429 unit_step = MAX(unit_step, 1);
00430 for(int64_t position = unit_start;
00431 position < unit_end;
00432 position += unit_step)
00433 {
00434 float value = get_value(position,
00435 PLAY_FORWARD,
00436 prev,
00437 next);
00438 if(*coords_undefined)
00439 {
00440 *min = *max = value;
00441 *coords_undefined = 0;
00442 }
00443 else
00444 {
00445 *min = MIN(value, *min);
00446 *max = MAX(value, *max);
00447 }
00448 }
00449 }
00450
00451 void FloatAutos::dump()
00452 {
00453 printf(" FloatAutos::dump %p\n", this);
00454 printf(" Default: position %lld value=%f\n",
00455 default_auto->position,
00456 ((FloatAuto*)default_auto)->value);
00457 for(Auto* current = first; current; current = NEXT)
00458 {
00459 printf(" position %lld value=%f invalue=%f outvalue=%f\n",
00460 current->position,
00461 ((FloatAuto*)current)->value,
00462 ((FloatAuto*)current)->control_in_value,
00463 ((FloatAuto*)current)->control_out_value);
00464 }
00465 }