}
}
+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);
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;
+}
+