Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

floatautos.C

Go to the documentation of this file.
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 // No keyframes on track
00077         if(total_autos == 0)
00078         {
00079                 constant = ((FloatAuto*)default_auto)->value;
00080                 return 1;
00081         }
00082         else
00083 // Only one keyframe on track.
00084         if(total_autos == 1)
00085         {
00086                 constant = ((FloatAuto*)first)->value;
00087                 return 1;
00088         }
00089         else
00090 // Last keyframe is before region
00091         if(last->position <= start)
00092         {
00093                 constant = ((FloatAuto*)last)->value;
00094                 return 1;
00095         }
00096         else
00097 // First keyframe is after region
00098         if(first->position > end)
00099         {
00100                 constant = ((FloatAuto*)first)->value;
00101                 return 1;
00102         }
00103 
00104 // Scan sequentially
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 // keyframes before and after region but not in region
00113                 if(prev_position >= 0 &&
00114                         prev_position < start && 
00115                         current->position >= end)
00116                 {
00117 // Get value now in case change doesn't occur
00118                         constant = float_current->value;
00119                         test_previous_current = 1;
00120                 }
00121                 prev_position = current->position;
00122 
00123 // Keyframe occurs in the region
00124                 if(!test_previous_current &&
00125                         current->position < end && 
00126                         current->position >= start)
00127                 {
00128 
00129 // Get value now in case change doesn't occur
00130                         constant = float_current->value;
00131 
00132 // Keyframe has neighbor
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 //printf("FloatAutos::automation_is_constant 1 %d\n", start);
00147                         FloatAuto *float_next = (FloatAuto*)current->next;
00148 
00149 // Change occurs between keyframes
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 // Change occurs between keyframes
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 // printf("FloatAutos::automation_is_constant %d %d %d %f %f %f %f\n", 
00168 // start, 
00169 // float_previous->position, 
00170 // float_current->position, 
00171 // float_previous->value, 
00172 // float_current->value, 
00173 // float_previous->control_out_value, 
00174 // float_current->control_in_value);
00175                                 return 0;
00176                         }
00177                 }
00178         }
00179 
00180 // Got nothing that changes in the region.
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 // quickly get autos just outside range 
00189         get_neighbors(start, end, &before, &after);
00190 
00191 // no auto before range so use first
00192         if(before)
00193                 current_auto = before;
00194         else
00195                 current_auto = first;
00196 
00197 // no autos at all so use default value
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 // Calculate bezier equation at position
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 // Constant
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 // Interpolate
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 // division by 0
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 // division by 0
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 //printf("FloatAutos::get_value %f %f %d %d %d %d\n", result, t, direction, position, previous->position, next->position);
00293 
00294         return result;
00295 
00296 
00297 
00298 //      get_fade_automation(slope,
00299 //              intercept,
00300 //              position,
00301 //              slope_len,
00302 //              PLAY_FORWARD);
00303 // 
00304 //      return (float)intercept;
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 //printf("FloatAutos::get_fade_automation %d %d %d\n", 
00326 //      prev_keyframe->position, input_position, next_keyframe->position);
00327 
00328 // Two distinct automation points within range
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 // One automation point within range
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 // Two distinct automation points within range
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 // One automation point within range
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 // Use default auto
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 // Test all handles
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 // Test joining regions
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 }

Generated on Sun Jan 8 13:38:55 2006 for Cinelerra-svn by  doxygen 1.4.4