X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Ffloatautos.C;h=95dcace9ce6d97288a6357a7e93512ec7a825eb6;hp=80e9c8bfb54e10dee21e6c59d4aeab8b2c89ac9b;hb=df72ca6732207dc25472a23169ff79ef6d4cca1c;hpb=21c2e6b36d6a96c2f662a89459d607b5a387f4eb diff --git a/cinelerra-5.1/cinelerra/floatautos.C b/cinelerra-5.1/cinelerra/floatautos.C index 80e9c8bf..95dcace9 100644 --- a/cinelerra-5.1/cinelerra/floatautos.C +++ b/cinelerra-5.1/cinelerra/floatautos.C @@ -409,6 +409,22 @@ void FloatAutos::get_extents(float *min, } } +void FloatAutos::set_proxy(int orig_scale, int new_scale) +{ + float orig_value; + orig_value = ((FloatAuto*)default_auto)->value * orig_scale; + ((FloatAuto*)default_auto)->value = orig_value / new_scale; + + for( FloatAuto *current= (FloatAuto*)first; current; current=(FloatAuto*)NEXT ) { + orig_value = current->value * orig_scale; + current->value = orig_value / new_scale; + orig_value = current->control_in_value * orig_scale; + current->control_in_value = orig_value / new_scale; + orig_value = current->control_out_value * orig_scale; + current->control_out_value = orig_value / new_scale; + } +} + void FloatAutos::dump() { printf(" FloatAutos::dump %p\n", this); @@ -424,3 +440,66 @@ void FloatAutos::dump() FloatAuto::curve_name(((FloatAuto*)current)->curve_mode)); } } + +double FloatAutos::automation_integral(int64_t start, int64_t length, int direction) +{ + if( direction == PLAY_REVERSE ) + start -= length; + if( start < 0 ) { + length += start; + start = 0; + } + double value = 0; + int64_t pos = start, len = length, end = pos + len; + while( pos < end ) { + int64_t prev_pos = 0, next_pos = end; + Auto *zprev = 0, *znext = 0; + FloatAuto *prev = (FloatAuto*)get_prev_auto(pos, direction, zprev, 0); + if( prev ) prev_pos = prev->position; + FloatAuto *next = (FloatAuto*)get_next_auto(pos, direction, znext, 0); + if( next ) next_pos = next->position; + if( !prev && !next ) prev = next = (FloatAuto*)default_auto; + else if( !prev ) prev = next; + else if( !next ) next = prev; + + double dt = next_pos - prev_pos; + double t0 = (pos - prev_pos) / dt; + if( (pos = next_pos) > end ) pos = end; + double t1 = (pos - prev_pos) / dt; + + double y0 = prev->get_value(), y1 = y0 + prev->get_control_out_value(); + double y3 = next->get_value(), y2 = y3 + next->get_control_in_value(); + if( y0 != y1 || y1 != y2 || y2 != y3 ) { +// bezier definite integral t0..t1 + double f4 = -y0/4 + 3*y1/4 - 3*y2/4 + y3/4; + double f3 = y0 - 2*y1 + y2; + double f2 = -3*y0/2 + 3*y1/2; + double f1 = y0, t = t0; + double t2 = t*t, t3 = t2*t, t4 = t3*t; + t0 = t4*f4 + t3*f3 + t2*f2 + t*f1; + t = t1; t2 = t*t; t3 = t2*t; t4 = t3*t; + t1 = t4*f4 + t3*f3 + t2*f2 + t*f1; + } + else { + t0 *= y0; t1 *= y0; + } + value += dt * (t1 - t0); + } + + return value + 1e-6; +} + +int64_t FloatAutos::speed_position(double pos) +{ + double length = track->get_length(); + int64_t l = -1, r = track->to_units(length, 1); + if( r < 1 ) r = 1; + for( int i=32; --i >= 0 && automation_integral(0,r,PLAY_FORWARD) <= pos; r*=2 ); + for( int i=64; --i >= 0 && (r-l)>1; ) { + int64_t m = (l + r) / 2; + double t = automation_integral(0,m,PLAY_FORWARD) - pos; + *(t >= 0 ? &r : &l) = m; + } + return r; +} +