]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/picomodel/lwo/envelope.c
my own uncrustify run
[xonotic/netradiant.git] / libs / picomodel / lwo / envelope.c
index 3720a8eb2d16281a9e79d01c2392cee9bb741119..8c5bb8fa78b389bf030c6b8bcda22d9bf3a86ba2 100644 (file)
 /*
-======================================================================
-envelope.c
+   ======================================================================
+   envelope.c
 
-Envelope functions for an LWO2 reader.
+   Envelope functions for an LWO2 reader.
 
-Ernie Wright  16 Nov 00
-====================================================================== */
+   Ernie Wright  16 Nov 00
+   ====================================================================== */
 
 #include "../picointernal.h"
 #include "lwo2.h"
 
 /*
-======================================================================
-lwFreeEnvelope()
-
-Free the memory used by an lwEnvelope.
-====================================================================== */
-
-void lwFreeEnvelope( lwEnvelope *env )
-{
-   if ( env ) {
-      if ( env->name ) _pico_free( env->name );
-      lwListFree( env->key, _pico_free );
-      lwListFree( env->cfilter, (void *) lwFreePlugin );
-      _pico_free( env );
-   }
+   ======================================================================
+   lwFreeEnvelope()
+
+   Free the memory used by an lwEnvelope.
+   ====================================================================== */
+
+void lwFreeEnvelope( lwEnvelope *env ){
+       if ( env ) {
+               if ( env->name ) {
+                       _pico_free( env->name );
+               }
+               lwListFree( env->key, _pico_free );
+               lwListFree( env->cfilter, (void *) lwFreePlugin );
+               _pico_free( env );
+       }
 }
 
 
-static int compare_keys( lwKey *k1, lwKey *k2 )
-{
-   return k1->time > k2->time ? 1 : k1->time < k2->time ? -1 : 0;
+static int compare_keys( lwKey *k1, lwKey *k2 ){
+       return k1->time > k2->time ? 1 : k1->time < k2->time ? -1 : 0;
 }
 
 
 /*
-======================================================================
-lwGetEnvelope()
-
-Read an ENVL chunk from an LWO2 file.
-====================================================================== */
-
-lwEnvelope *lwGetEnvelope( picoMemStream_t *fp, int cksize )
-{
-   lwEnvelope *env;
-   lwKey *key = NULL;
-   lwPlugin *plug;
-   unsigned int id;
-   unsigned short sz;
-   float f[ 4 ];
-   int i, nparams, pos, rlen;
-
-
-   /* allocate the Envelope structure */
-
-   env = _pico_calloc( 1, sizeof( lwEnvelope ));
-   if ( !env ) goto Fail;
-
-   /* remember where we started */
-
-   set_flen( 0 );
-   pos = _pico_memstream_tell( fp );
-
-   /* index */
-
-   env->index = getVX( fp );
-
-   /* first subchunk header */
-
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   /* process subchunks as they're encountered */
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_TYPE:
-            env->type = getU2( fp );
-            break;
-
-         case ID_NAME:
-            env->name = getS0( fp );
-            break;
-
-         case ID_PRE:
-            env->behavior[ 0 ] = getU2( fp );
-            break;
-
-         case ID_POST:
-            env->behavior[ 1 ] = getU2( fp );
-            break;
-
-         case ID_KEY:
-            key = _pico_calloc( 1, sizeof( lwKey ));
-            if ( !key ) goto Fail;
-            key->time = getF4( fp );
-            key->value = getF4( fp );
-            lwListInsert( (void **) &env->key, key, (void *) compare_keys );
-            env->nkeys++;
-            break;
-
-         case ID_SPAN:
-            if ( !key ) goto Fail;
-            key->shape = getU4( fp );
-
-            nparams = ( sz - 4 ) / 4;
-            if ( nparams > 4 ) nparams = 4;
-            for ( i = 0; i < nparams; i++ )
-               f[ i ] = getF4( fp );
-
-            switch ( key->shape ) {
-               case ID_TCB:
-                  key->tension = f[ 0 ];
-                  key->continuity = f[ 1 ];
-                  key->bias = f[ 2 ];
-                  break;
-
-               case ID_BEZI:
-               case ID_HERM:
-               case ID_BEZ2:
-                  for ( i = 0; i < nparams; i++ )
-                     key->param[ i ] = f[ i ];
-                  break;
-            }
-            break;
-
-         case ID_CHAN:
-            plug = _pico_calloc( 1, sizeof( lwPlugin ));
-            if ( !plug ) goto Fail;
-
-            plug->name = getS0( fp );
-            plug->flags = getU2( fp );
-            plug->data = getbytes( fp, sz - get_flen() );
-
-            lwListAdd( (void *) &env->cfilter, plug );
-            env->ncfilters++;
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) goto Fail;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the ENVL chunk? */
-
-      rlen = _pico_memstream_tell( fp ) - pos;
-      if ( cksize < rlen ) goto Fail;
-      if ( cksize == rlen ) break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) goto Fail;
-   }
-
-   return env;
+   ======================================================================
+   lwGetEnvelope()
+
+   Read an ENVL chunk from an LWO2 file.
+   ====================================================================== */
+
+lwEnvelope *lwGetEnvelope( picoMemStream_t *fp, int cksize ){
+       lwEnvelope *env;
+       lwKey *key = NULL;
+       lwPlugin *plug;
+       unsigned int id;
+       unsigned short sz;
+       float f[ 4 ];
+       int i, nparams, pos, rlen;
+
+
+       /* allocate the Envelope structure */
+
+       env = _pico_calloc( 1, sizeof( lwEnvelope ) );
+       if ( !env ) {
+               goto Fail;
+       }
+
+       /* remember where we started */
+
+       set_flen( 0 );
+       pos = _pico_memstream_tell( fp );
+
+       /* index */
+
+       env->index = getVX( fp );
+
+       /* first subchunk header */
+
+       id = getU4( fp );
+       sz = getU2( fp );
+       if ( 0 > get_flen() ) {
+               goto Fail;
+       }
+
+       /* process subchunks as they're encountered */
+
+       while ( 1 ) {
+               sz += sz & 1;
+               set_flen( 0 );
+
+               switch ( id ) {
+               case ID_TYPE:
+                       env->type = getU2( fp );
+                       break;
+
+               case ID_NAME:
+                       env->name = getS0( fp );
+                       break;
+
+               case ID_PRE:
+                       env->behavior[ 0 ] = getU2( fp );
+                       break;
+
+               case ID_POST:
+                       env->behavior[ 1 ] = getU2( fp );
+                       break;
+
+               case ID_KEY:
+                       key = _pico_calloc( 1, sizeof( lwKey ) );
+                       if ( !key ) {
+                               goto Fail;
+                       }
+                       key->time = getF4( fp );
+                       key->value = getF4( fp );
+                       lwListInsert( (void **) &env->key, key, (void *) compare_keys );
+                       env->nkeys++;
+                       break;
+
+               case ID_SPAN:
+                       if ( !key ) {
+                               goto Fail;
+                       }
+                       key->shape = getU4( fp );
+
+                       nparams = ( sz - 4 ) / 4;
+                       if ( nparams > 4 ) {
+                               nparams = 4;
+                       }
+                       for ( i = 0; i < nparams; i++ )
+                               f[ i ] = getF4( fp );
+
+                       switch ( key->shape ) {
+                       case ID_TCB:
+                               key->tension = f[ 0 ];
+                               key->continuity = f[ 1 ];
+                               key->bias = f[ 2 ];
+                               break;
+
+                       case ID_BEZI:
+                       case ID_HERM:
+                       case ID_BEZ2:
+                               for ( i = 0; i < nparams; i++ )
+                                       key->param[ i ] = f[ i ];
+                               break;
+                       }
+                       break;
+
+               case ID_CHAN:
+                       plug = _pico_calloc( 1, sizeof( lwPlugin ) );
+                       if ( !plug ) {
+                               goto Fail;
+                       }
+
+                       plug->name = getS0( fp );
+                       plug->flags = getU2( fp );
+                       plug->data = getbytes( fp, sz - get_flen() );
+
+                       lwListAdd( (void *) &env->cfilter, plug );
+                       env->ncfilters++;
+                       break;
+
+               default:
+                       break;
+               }
+
+               /* error while reading current subchunk? */
+
+               rlen = get_flen();
+               if ( rlen < 0 || rlen > sz ) {
+                       goto Fail;
+               }
+
+               /* skip unread parts of the current subchunk */
+
+               if ( rlen < sz ) {
+                       _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+               }
+
+               /* end of the ENVL chunk? */
+
+               rlen = _pico_memstream_tell( fp ) - pos;
+               if ( cksize < rlen ) {
+                       goto Fail;
+               }
+               if ( cksize == rlen ) {
+                       break;
+               }
+
+               /* get the next subchunk header */
+
+               set_flen( 0 );
+               id = getU4( fp );
+               sz = getU2( fp );
+               if ( 6 != get_flen() ) {
+                       goto Fail;
+               }
+       }
+
+       return env;
 
 Fail:
-   lwFreeEnvelope( env );
-   return NULL;
+       lwFreeEnvelope( env );
+       return NULL;
 }
 
 
 /*
-======================================================================
-lwFindEnvelope()
-
-Returns an lwEnvelope pointer, given an envelope index.
-====================================================================== */
-
-lwEnvelope *lwFindEnvelope( lwEnvelope *list, int index )
-{
-   lwEnvelope *env;
-
-   env = list;
-   while ( env ) {
-      if ( env->index == index ) break;
-      env = env->next;
-   }
-   return env;
+   ======================================================================
+   lwFindEnvelope()
+
+   Returns an lwEnvelope pointer, given an envelope index.
+   ====================================================================== */
+
+lwEnvelope *lwFindEnvelope( lwEnvelope *list, int index ){
+       lwEnvelope *env;
+
+       env = list;
+       while ( env ) {
+               if ( env->index == index ) {
+                       break;
+               }
+               env = env->next;
+       }
+       return env;
 }
 
 
 /*
-======================================================================
-range()
+   ======================================================================
+   range()
 
-Given the value v of a periodic function, returns the equivalent value
-v2 in the principal interval [lo, hi].  If i isn't NULL, it receives
-the number of wavelengths between v and v2.
+   Given the value v of a periodic function, returns the equivalent value
+   v2 in the principal interval [lo, hi].  If i isn't NULL, it receives
+   the number of wavelengths between v and v2.
 
    v2 = v - i * (hi - lo)
 
-For example, range( 3 pi, 0, 2 pi, i ) returns pi, with i = 1.
-====================================================================== */
+   For example, range( 3 pi, 0, 2 pi, i ) returns pi, with i = 1.
+   ====================================================================== */
 
-static float range( float v, float lo, float hi, int *i )
-{
-   float v2, r = hi - lo;
+static float range( float v, float lo, float hi, int *i ){
+       float v2, r = hi - lo;
 
-   if ( r == 0.0 ) {
-      if ( i ) *i = 0;
-      return lo;
-   }
+       if ( r == 0.0 ) {
+               if ( i ) {
+                       *i = 0;
+               }
+               return lo;
+       }
 
-   v2 = lo + v - r * ( float ) floor(( double ) v / r );
-   if ( i ) *i = -( int )(( v2 - v ) / r + ( v2 > v ? 0.5 : -0.5 ));
+       v2 = lo + v - r * ( float ) floor( ( double ) v / r );
+       if ( i ) {
+               *i = -( int )( ( v2 - v ) / r + ( v2 > v ? 0.5 : -0.5 ) );
+       }
 
-   return v2;
+       return v2;
 }
 
 
 /*
-======================================================================
-hermite()
+   ======================================================================
+   hermite()
 
-Calculate the Hermite coefficients.
-====================================================================== */
+   Calculate the Hermite coefficients.
+   ====================================================================== */
 
-static void hermite( float t, float *h1, float *h2, float *h3, float *h4 )
-{
-   float t2, t3;
+static void hermite( float t, float *h1, float *h2, float *h3, float *h4 ){
+       float t2, t3;
 
-   t2 = t * t;
-   t3 = t * t2;
+       t2 = t * t;
+       t3 = t * t2;
 
-   *h2 = 3.0f * t2 - t3 - t3;
-   *h1 = 1.0f - *h2;
-   *h4 = t3 - t2;
-   *h3 = *h4 - t2 + t;
+       *h2 = 3.0f * t2 - t3 - t3;
+       *h1 = 1.0f - *h2;
+       *h4 = t3 - t2;
+       *h3 = *h4 - t2 + t;
 }
 
 
 /*
-======================================================================
-bezier()
+   ======================================================================
+   bezier()
 
-Interpolate the value of a 1D Bezier curve.
-====================================================================== */
+   Interpolate the value of a 1D Bezier curve.
+   ====================================================================== */
 
-static float bezier( float x0, float x1, float x2, float x3, float t )
-{
-   float a, b, c, t2, t3;
+static float bezier( float x0, float x1, float x2, float x3, float t ){
+       float a, b, c, t2, t3;
 
-   t2 = t * t;
-   t3 = t2 * t;
+       t2 = t * t;
+       t3 = t2 * t;
 
-   c = 3.0f * ( x1 - x0 );
-   b = 3.0f * ( x2 - x1 ) - c;
-   a = x3 - x0 - c - b;
+       c = 3.0f * ( x1 - x0 );
+       b = 3.0f * ( x2 - x1 ) - c;
+       a = x3 - x0 - c - b;
 
-   return a * t3 + b * t2 + c * t + x0;
+       return a * t3 + b * t2 + c * t + x0;
 }
 
 
 /*
-======================================================================
-bez2_time()
+   ======================================================================
+   bez2_time()
 
-Find the t for which bezier() returns the input time.  The handle
-endpoints of a BEZ2 curve represent the control points, and these have
-(time, value) coordinates, so time is used as both a coordinate and a
-parameter for this curve type.
-====================================================================== */
+   Find the t for which bezier() returns the input time.  The handle
+   endpoints of a BEZ2 curve represent the control points, and these have
+   (time, value) coordinates, so time is used as both a coordinate and a
+   parameter for this curve type.
+   ====================================================================== */
 
 static float bez2_time( float x0, float x1, float x2, float x3, float time,
-   float *t0, float *t1 )
-{
-   float v, t;
-
-   t = *t0 + ( *t1 - *t0 ) * 0.5f;
-   v = bezier( x0, x1, x2, x3, t );
-   if ( fabs( time - v ) > .0001f ) {
-      if ( v > time )
-         *t1 = t;
-      else
-         *t0 = t;
-      return bez2_time( x0, x1, x2, x3, time, t0, t1 );
-   }
-   else
-      return t;
+                                               float *t0, float *t1 ){
+       float v, t;
+
+       t = *t0 + ( *t1 - *t0 ) * 0.5f;
+       v = bezier( x0, x1, x2, x3, t );
+       if ( fabs( time - v ) > .0001f ) {
+               if ( v > time ) {
+                       *t1 = t;
+               }
+               else{
+                       *t0 = t;
+               }
+               return bez2_time( x0, x1, x2, x3, time, t0, t1 );
+       }
+       else{
+               return t;
+       }
 }
 
 
 /*
-======================================================================
-bez2()
+   ======================================================================
+   bez2()
 
-Interpolate the value of a BEZ2 curve.
-====================================================================== */
+   Interpolate the value of a BEZ2 curve.
+   ====================================================================== */
 
-static float bez2( lwKey *key0, lwKey *key1, float time )
-{
-   float x, y, t, t0 = 0.0f, t1 = 1.0f;
+static float bez2( lwKey *key0, lwKey *key1, float time ){
+       float x, y, t, t0 = 0.0f, t1 = 1.0f;
 
-   if ( key0->shape == ID_BEZ2 )
-      x = key0->time + key0->param[ 2 ];
-   else
-      x = key0->time + ( key1->time - key0->time ) / 3.0f;
+       if ( key0->shape == ID_BEZ2 ) {
+               x = key0->time + key0->param[ 2 ];
+       }
+       else{
+               x = key0->time + ( key1->time - key0->time ) / 3.0f;
+       }
 
-   t = bez2_time( key0->time, x, key1->time + key1->param[ 0 ], key1->time,
-      time, &t0, &t1 );
+       t = bez2_time( key0->time, x, key1->time + key1->param[ 0 ], key1->time,
+                                  time, &t0, &t1 );
 
-   if ( key0->shape == ID_BEZ2 )
-      y = key0->value + key0->param[ 3 ];
-   else
-      y = key0->value + key0->param[ 1 ] / 3.0f;
+       if ( key0->shape == ID_BEZ2 ) {
+               y = key0->value + key0->param[ 3 ];
+       }
+       else{
+               y = key0->value + key0->param[ 1 ] / 3.0f;
+       }
 
-   return bezier( key0->value, y, key1->param[ 1 ] + key1->value, key1->value, t );
+       return bezier( key0->value, y, key1->param[ 1 ] + key1->value, key1->value, t );
 }
 
 
 /*
-======================================================================
-outgoing()
-
-Return the outgoing tangent to the curve at key0.  The value returned
-for the BEZ2 case is used when extrapolating a linear pre behavior and
-when interpolating a non-BEZ2 span.
-====================================================================== */
-
-static float outgoing( lwKey *key0, lwKey *key1 )
-{
-   float a, b, d, t, out;
-
-   switch ( key0->shape )
-   {
-      case ID_TCB:
-         a = ( 1.0f - key0->tension )
-           * ( 1.0f + key0->continuity )
-           * ( 1.0f + key0->bias );
-         b = ( 1.0f - key0->tension )
-           * ( 1.0f - key0->continuity )
-           * ( 1.0f - key0->bias );
-         d = key1->value - key0->value;
-
-         if ( key0->prev ) {
-            t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
-            out = t * ( a * ( key0->value - key0->prev->value ) + b * d );
-         }
-         else
-            out = b * d;
-         break;
-
-      case ID_LINE:
-         d = key1->value - key0->value;
-         if ( key0->prev ) {
-            t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
-            out = t * ( key0->value - key0->prev->value + d );
-         }
-         else
-            out = d;
-         break;
-
-      case ID_BEZI:
-      case ID_HERM:
-         out = key0->param[ 1 ];
-         if ( key0->prev )
-            out *= ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
-         break;
-
-      case ID_BEZ2:
-         out = key0->param[ 3 ] * ( key1->time - key0->time );
-         if ( fabs( key0->param[ 2 ] ) > 1e-5f )
-            out /= key0->param[ 2 ];
-         else
-            out *= 1e5f;
-         break;
-
-      case ID_STEP:
-      default:
-         out = 0.0f;
-         break;
-   }
-
-   return out;
+   ======================================================================
+   outgoing()
+
+   Return the outgoing tangent to the curve at key0.  The value returned
+   for the BEZ2 case is used when extrapolating a linear pre behavior and
+   when interpolating a non-BEZ2 span.
+   ====================================================================== */
+
+static float outgoing( lwKey *key0, lwKey *key1 ){
+       float a, b, d, t, out;
+
+       switch ( key0->shape )
+       {
+       case ID_TCB:
+               a = ( 1.0f - key0->tension )
+                       * ( 1.0f + key0->continuity )
+                       * ( 1.0f + key0->bias );
+               b = ( 1.0f - key0->tension )
+                       * ( 1.0f - key0->continuity )
+                       * ( 1.0f - key0->bias );
+               d = key1->value - key0->value;
+
+               if ( key0->prev ) {
+                       t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
+                       out = t * ( a * ( key0->value - key0->prev->value ) + b * d );
+               }
+               else{
+                       out = b * d;
+               }
+               break;
+
+       case ID_LINE:
+               d = key1->value - key0->value;
+               if ( key0->prev ) {
+                       t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
+                       out = t * ( key0->value - key0->prev->value + d );
+               }
+               else{
+                       out = d;
+               }
+               break;
+
+       case ID_BEZI:
+       case ID_HERM:
+               out = key0->param[ 1 ];
+               if ( key0->prev ) {
+                       out *= ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
+               }
+               break;
+
+       case ID_BEZ2:
+               out = key0->param[ 3 ] * ( key1->time - key0->time );
+               if ( fabs( key0->param[ 2 ] ) > 1e-5f ) {
+                       out /= key0->param[ 2 ];
+               }
+               else{
+                       out *= 1e5f;
+               }
+               break;
+
+       case ID_STEP:
+       default:
+               out = 0.0f;
+               break;
+       }
+
+       return out;
 }
 
 
 /*
-======================================================================
-incoming()
-
-Return the incoming tangent to the curve at key1.  The value returned
-for the BEZ2 case is used when extrapolating a linear post behavior.
-====================================================================== */
-
-static float incoming( lwKey *key0, lwKey *key1 )
-{
-   float a, b, d, t, in;
-
-   switch ( key1->shape )
-   {
-      case ID_LINE:
-         d = key1->value - key0->value;
-         if ( key1->next ) {
-            t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
-            in = t * ( key1->next->value - key1->value + d );
-         }
-         else
-            in = d;
-         break;
-
-      case ID_TCB:
-         a = ( 1.0f - key1->tension )
-           * ( 1.0f - key1->continuity )
-           * ( 1.0f + key1->bias );
-         b = ( 1.0f - key1->tension )
-           * ( 1.0f + key1->continuity )
-           * ( 1.0f - key1->bias );
-         d = key1->value - key0->value;
-
-         if ( key1->next ) {
-            t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
-            in = t * ( b * ( key1->next->value - key1->value ) + a * d );
-         }
-         else
-            in = a * d;
-         break;
-
-      case ID_BEZI:
-      case ID_HERM:
-         in = key1->param[ 0 ];
-         if ( key1->next )
-            in *= ( key1->time - key0->time ) / ( key1->next->time - key0->time );
-         break;
-         return in;
-
-      case ID_BEZ2:
-         in = key1->param[ 1 ] * ( key1->time - key0->time );
-         if ( fabs( key1->param[ 0 ] ) > 1e-5f )
-            in /= key1->param[ 0 ];
-         else
-            in *= 1e5f;
-         break;
-
-      case ID_STEP:
-      default:
-         in = 0.0f;
-         break;
-   }
-
-   return in;
+   ======================================================================
+   incoming()
+
+   Return the incoming tangent to the curve at key1.  The value returned
+   for the BEZ2 case is used when extrapolating a linear post behavior.
+   ====================================================================== */
+
+static float incoming( lwKey *key0, lwKey *key1 ){
+       float a, b, d, t, in;
+
+       switch ( key1->shape )
+       {
+       case ID_LINE:
+               d = key1->value - key0->value;
+               if ( key1->next ) {
+                       t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
+                       in = t * ( key1->next->value - key1->value + d );
+               }
+               else{
+                       in = d;
+               }
+               break;
+
+       case ID_TCB:
+               a = ( 1.0f - key1->tension )
+                       * ( 1.0f - key1->continuity )
+                       * ( 1.0f + key1->bias );
+               b = ( 1.0f - key1->tension )
+                       * ( 1.0f + key1->continuity )
+                       * ( 1.0f - key1->bias );
+               d = key1->value - key0->value;
+
+               if ( key1->next ) {
+                       t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
+                       in = t * ( b * ( key1->next->value - key1->value ) + a * d );
+               }
+               else{
+                       in = a * d;
+               }
+               break;
+
+       case ID_BEZI:
+       case ID_HERM:
+               in = key1->param[ 0 ];
+               if ( key1->next ) {
+                       in *= ( key1->time - key0->time ) / ( key1->next->time - key0->time );
+               }
+               break;
+               return in;
+
+       case ID_BEZ2:
+               in = key1->param[ 1 ] * ( key1->time - key0->time );
+               if ( fabs( key1->param[ 0 ] ) > 1e-5f ) {
+                       in /= key1->param[ 0 ];
+               }
+               else{
+                       in *= 1e5f;
+               }
+               break;
+
+       case ID_STEP:
+       default:
+               in = 0.0f;
+               break;
+       }
+
+       return in;
 }
 
 
 /*
-======================================================================
-evalEnvelope()
-
-Given a list of keys and a time, returns the interpolated value of the
-envelope at that time.
-====================================================================== */
-
-float evalEnvelope( lwEnvelope *env, float time )
-{
-   lwKey *key0, *key1, *skey, *ekey;
-   float t, h1, h2, h3, h4, in, out, offset = 0.0f;
-   int noff;
-
-
-   /* if there's no key, the value is 0 */
-
-   if ( env->nkeys == 0 ) return 0.0f;
-
-   /* if there's only one key, the value is constant */
-
-   if ( env->nkeys == 1 )
-      return env->key->value;
+   ======================================================================
+   evalEnvelope()
 
-   /* find the first and last keys */
+   Given a list of keys and a time, returns the interpolated value of the
+   envelope at that time.
+   ====================================================================== */
 
-   skey = ekey = env->key;
-   while ( ekey->next ) ekey = ekey->next;
+float evalEnvelope( lwEnvelope *env, float time ){
+       lwKey *key0, *key1, *skey, *ekey;
+       float t, h1, h2, h3, h4, in, out, offset = 0.0f;
+       int noff;
+
+
+       /* if there's no key, the value is 0 */
 
-   /* use pre-behavior if time is before first key time */
+       if ( env->nkeys == 0 ) {
+               return 0.0f;
+       }
 
-   if ( time < skey->time ) {
-      switch ( env->behavior[ 0 ] )
-      {
-         case BEH_RESET:
-            return 0.0f;
+       /* if there's only one key, the value is constant */
 
-         case BEH_CONSTANT:
-            return skey->value;
+       if ( env->nkeys == 1 ) {
+               return env->key->value;
+       }
 
-         case BEH_REPEAT:
-            time = range( time, skey->time, ekey->time, NULL );
-            break;
+       /* find the first and last keys */
 
-         case BEH_OSCILLATE:
-            time = range( time, skey->time, ekey->time, &noff );
-            if ( noff % 2 )
-               time = ekey->time - skey->time - time;
-            break;
+       skey = ekey = env->key;
+       while ( ekey->next ) ekey = ekey->next;
 
-         case BEH_OFFSET:
-            time = range( time, skey->time, ekey->time, &noff );
-            offset = noff * ( ekey->value - skey->value );
-            break;
+       /* use pre-behavior if time is before first key time */
+
+       if ( time < skey->time ) {
+               switch ( env->behavior[ 0 ] )
+               {
+               case BEH_RESET:
+                       return 0.0f;
 
-         case BEH_LINEAR:
-            out = outgoing( skey, skey->next )
-                / ( skey->next->time - skey->time );
-            return out * ( time - skey->time ) + skey->value;
-      }
-   }
+               case BEH_CONSTANT:
+                       return skey->value;
 
-   /* use post-behavior if time is after last key time */
+               case BEH_REPEAT:
+                       time = range( time, skey->time, ekey->time, NULL );
+                       break;
 
-   else if ( time > ekey->time ) {
-      switch ( env->behavior[ 1 ] )
-      {
-         case BEH_RESET:
-            return 0.0f;
+               case BEH_OSCILLATE:
+                       time = range( time, skey->time, ekey->time, &noff );
+                       if ( noff % 2 ) {
+                               time = ekey->time - skey->time - time;
+                       }
+                       break;
 
-         case BEH_CONSTANT:
-            return ekey->value;
+               case BEH_OFFSET:
+                       time = range( time, skey->time, ekey->time, &noff );
+                       offset = noff * ( ekey->value - skey->value );
+                       break;
 
-         case BEH_REPEAT:
-            time = range( time, skey->time, ekey->time, NULL );
-            break;
+               case BEH_LINEAR:
+                       out = outgoing( skey, skey->next )
+                                 / ( skey->next->time - skey->time );
+                       return out * ( time - skey->time ) + skey->value;
+               }
+       }
 
-         case BEH_OSCILLATE:
-            time = range( time, skey->time, ekey->time, &noff );
-            if ( noff % 2 )
-               time = ekey->time - skey->time - time;
-            break;
+       /* use post-behavior if time is after last key time */
 
-         case BEH_OFFSET:
-            time = range( time, skey->time, ekey->time, &noff );
-            offset = noff * ( ekey->value - skey->value );
-            break;
+       else if ( time > ekey->time ) {
+               switch ( env->behavior[ 1 ] )
+               {
+               case BEH_RESET:
+                       return 0.0f;
 
-         case BEH_LINEAR:
-            in = incoming( ekey->prev, ekey )
-               / ( ekey->time - ekey->prev->time );
-            return in * ( time - ekey->time ) + ekey->value;
-      }
-   }
+               case BEH_CONSTANT:
+                       return ekey->value;
 
-   /* get the endpoints of the interval being evaluated */
+               case BEH_REPEAT:
+                       time = range( time, skey->time, ekey->time, NULL );
+                       break;
 
-   key0 = env->key;
-   while ( time > key0->next->time )
-      key0 = key0->next;
-   key1 = key0->next;
+               case BEH_OSCILLATE:
+                       time = range( time, skey->time, ekey->time, &noff );
+                       if ( noff % 2 ) {
+                               time = ekey->time - skey->time - time;
+                       }
+                       break;
 
-   /* check for singularities first */
+               case BEH_OFFSET:
+                       time = range( time, skey->time, ekey->time, &noff );
+                       offset = noff * ( ekey->value - skey->value );
+                       break;
 
-   if ( time == key0->time )
-      return key0->value + offset;
-   else if ( time == key1->time )
-      return key1->value + offset;
+               case BEH_LINEAR:
+                       in = incoming( ekey->prev, ekey )
+                                / ( ekey->time - ekey->prev->time );
+                       return in * ( time - ekey->time ) + ekey->value;
+               }
+       }
 
-   /* get interval length, time in [0, 1] */
+       /* get the endpoints of the interval being evaluated */
 
-   t = ( time - key0->time ) / ( key1->time - key0->time );
+       key0 = env->key;
+       while ( time > key0->next->time )
+               key0 = key0->next;
+       key1 = key0->next;
 
-   /* interpolate */
+       /* check for singularities first */
 
-   switch ( key1->shape )
-   {
-      case ID_TCB:
-      case ID_BEZI:
-      case ID_HERM:
-         out = outgoing( key0, key1 );
-         in = incoming( key0, key1 );
-         hermite( t, &h1, &h2, &h3, &h4 );
-         return h1 * key0->value + h2 * key1->value + h3 * out + h4 * in + offset;
-
-      case ID_BEZ2:
-         return bez2( key0, key1, time ) + offset;
-
-      case ID_LINE:
-         return key0->value + t * ( key1->value - key0->value ) + offset;
-
-      case ID_STEP:
-         return key0->value + offset;
-
-      default:
-         return offset;
-   }
+       if ( time == key0->time ) {
+               return key0->value + offset;
+       }
+       else if ( time == key1->time ) {
+               return key1->value + offset;
+       }
+
+       /* get interval length, time in [0, 1] */
+
+       t = ( time - key0->time ) / ( key1->time - key0->time );
+
+       /* interpolate */
+
+       switch ( key1->shape )
+       {
+       case ID_TCB:
+       case ID_BEZI:
+       case ID_HERM:
+               out = outgoing( key0, key1 );
+               in = incoming( key0, key1 );
+               hermite( t, &h1, &h2, &h3, &h4 );
+               return h1 * key0->value + h2 * key1->value + h3 * out + h4 * in + offset;
+
+       case ID_BEZ2:
+               return bez2( key0, key1, time ) + offset;
+
+       case ID_LINE:
+               return key0->value + t * ( key1->value - key0->value ) + offset;
+
+       case ID_STEP:
+               return key0->value + offset;
+
+       default:
+               return offset;
+       }
 }