2 ======================================================================
5 Envelope functions for an LWO2 reader.
8 ====================================================================== */
10 #include "../picointernal.h"
14 ======================================================================
17 Free the memory used by an lwEnvelope.
18 ====================================================================== */
20 void lwFreeEnvelope( lwEnvelope *env ){
23 _pico_free( env->name );
25 lwListFree( env->key, _pico_free );
26 lwListFree(env->cfilter, (void (*)(void *)) lwFreePlugin);
32 static int compare_keys( lwKey *k1, lwKey *k2 ){
33 return k1->time > k2->time ? 1 : k1->time < k2->time ? -1 : 0;
38 ======================================================================
41 Read an ENVL chunk from an LWO2 file.
42 ====================================================================== */
44 lwEnvelope *lwGetEnvelope( picoMemStream_t *fp, int cksize ){
51 int i, nparams, pos, rlen;
54 /* allocate the Envelope structure */
56 env = _pico_calloc( 1, sizeof( lwEnvelope ) );
61 /* remember where we started */
64 pos = _pico_memstream_tell( fp );
68 env->index = getVX( fp );
70 /* first subchunk header */
74 if ( 0 > get_flen() ) {
78 /* process subchunks as they're encountered */
86 env->type = getU2( fp );
90 env->name = getS0( fp );
94 env->behavior[ 0 ] = getU2( fp );
98 env->behavior[ 1 ] = getU2( fp );
102 key = _pico_calloc( 1, sizeof( lwKey ) );
106 key->time = getF4( fp );
107 key->value = getF4( fp );
108 lwListInsert((void **) &env->key, key, (int (*)(void *, void *)) compare_keys);
116 key->shape = getU4( fp );
118 nparams = ( sz - 4 ) / 4;
122 for ( i = 0; i < nparams; i++ )
123 f[ i ] = getF4( fp );
125 switch ( key->shape ) {
127 key->tension = f[ 0 ];
128 key->continuity = f[ 1 ];
135 for ( i = 0; i < nparams; i++ )
136 key->param[ i ] = f[ i ];
142 plug = _pico_calloc( 1, sizeof( lwPlugin ) );
147 plug->name = getS0( fp );
148 plug->flags = getU2( fp );
149 plug->data = getbytes( fp, sz - get_flen() );
151 lwListAdd( (void *) &env->cfilter, plug );
159 /* error while reading current subchunk? */
162 if ( rlen < 0 || rlen > sz ) {
166 /* skip unread parts of the current subchunk */
169 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
172 /* end of the ENVL chunk? */
174 rlen = _pico_memstream_tell( fp ) - pos;
175 if ( cksize < rlen ) {
178 if ( cksize == rlen ) {
182 /* get the next subchunk header */
187 if ( 6 != get_flen() ) {
195 lwFreeEnvelope( env );
201 ======================================================================
204 Returns an lwEnvelope pointer, given an envelope index.
205 ====================================================================== */
207 lwEnvelope *lwFindEnvelope( lwEnvelope *list, int index ){
212 if ( env->index == index ) {
222 ======================================================================
225 Given the value v of a periodic function, returns the equivalent value
226 v2 in the principal interval [lo, hi]. If i isn't NULL, it receives
227 the number of wavelengths between v and v2.
229 v2 = v - i * (hi - lo)
231 For example, range( 3 pi, 0, 2 pi, i ) returns pi, with i = 1.
232 ====================================================================== */
234 static float range( float v, float lo, float hi, int *i ){
235 float v2, r = hi - lo;
244 v2 = lo + v - r * ( float ) floor( ( double ) v / r );
246 *i = -( int )( ( v2 - v ) / r + ( v2 > v ? 0.5 : -0.5 ) );
254 ======================================================================
257 Calculate the Hermite coefficients.
258 ====================================================================== */
260 static void hermite( float t, float *h1, float *h2, float *h3, float *h4 ){
266 *h2 = 3.0f * t2 - t3 - t3;
274 ======================================================================
277 Interpolate the value of a 1D Bezier curve.
278 ====================================================================== */
280 static float bezier( float x0, float x1, float x2, float x3, float t ){
281 float a, b, c, t2, t3;
286 c = 3.0f * ( x1 - x0 );
287 b = 3.0f * ( x2 - x1 ) - c;
290 return a * t3 + b * t2 + c * t + x0;
295 ======================================================================
298 Find the t for which bezier() returns the input time. The handle
299 endpoints of a BEZ2 curve represent the control points, and these have
300 (time, value) coordinates, so time is used as both a coordinate and a
301 parameter for this curve type.
302 ====================================================================== */
304 static float bez2_time( float x0, float x1, float x2, float x3, float time,
305 float *t0, float *t1 ){
308 t = *t0 + ( *t1 - *t0 ) * 0.5f;
309 v = bezier( x0, x1, x2, x3, t );
310 if ( fabs( time - v ) > .0001f ) {
317 return bez2_time( x0, x1, x2, x3, time, t0, t1 );
326 ======================================================================
329 Interpolate the value of a BEZ2 curve.
330 ====================================================================== */
332 static float bez2( lwKey *key0, lwKey *key1, float time ){
333 float x, y, t, t0 = 0.0f, t1 = 1.0f;
335 if ( key0->shape == ID_BEZ2 ) {
336 x = key0->time + key0->param[ 2 ];
339 x = key0->time + ( key1->time - key0->time ) / 3.0f;
342 t = bez2_time( key0->time, x, key1->time + key1->param[ 0 ], key1->time,
345 if ( key0->shape == ID_BEZ2 ) {
346 y = key0->value + key0->param[ 3 ];
349 y = key0->value + key0->param[ 1 ] / 3.0f;
352 return bezier( key0->value, y, key1->param[ 1 ] + key1->value, key1->value, t );
357 ======================================================================
360 Return the outgoing tangent to the curve at key0. The value returned
361 for the BEZ2 case is used when extrapolating a linear pre behavior and
362 when interpolating a non-BEZ2 span.
363 ====================================================================== */
365 static float outgoing( lwKey *key0, lwKey *key1 ){
366 float a, b, d, t, out;
368 switch ( key0->shape )
371 a = ( 1.0f - key0->tension )
372 * ( 1.0f + key0->continuity )
373 * ( 1.0f + key0->bias );
374 b = ( 1.0f - key0->tension )
375 * ( 1.0f - key0->continuity )
376 * ( 1.0f - key0->bias );
377 d = key1->value - key0->value;
380 t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
381 out = t * ( a * ( key0->value - key0->prev->value ) + b * d );
389 d = key1->value - key0->value;
391 t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
392 out = t * ( key0->value - key0->prev->value + d );
401 out = key0->param[ 1 ];
403 out *= ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
408 out = key0->param[ 3 ] * ( key1->time - key0->time );
409 if ( fabs( key0->param[ 2 ] ) > 1e-5f ) {
410 out /= key0->param[ 2 ];
428 ======================================================================
431 Return the incoming tangent to the curve at key1. The value returned
432 for the BEZ2 case is used when extrapolating a linear post behavior.
433 ====================================================================== */
435 static float incoming( lwKey *key0, lwKey *key1 ){
436 float a, b, d, t, in;
438 switch ( key1->shape )
441 d = key1->value - key0->value;
443 t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
444 in = t * ( key1->next->value - key1->value + d );
452 a = ( 1.0f - key1->tension )
453 * ( 1.0f - key1->continuity )
454 * ( 1.0f + key1->bias );
455 b = ( 1.0f - key1->tension )
456 * ( 1.0f + key1->continuity )
457 * ( 1.0f - key1->bias );
458 d = key1->value - key0->value;
461 t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
462 in = t * ( b * ( key1->next->value - key1->value ) + a * d );
471 in = key1->param[ 0 ];
473 in *= ( key1->time - key0->time ) / ( key1->next->time - key0->time );
479 in = key1->param[ 1 ] * ( key1->time - key0->time );
480 if ( fabs( key1->param[ 0 ] ) > 1e-5f ) {
481 in /= key1->param[ 0 ];
499 ======================================================================
502 Given a list of keys and a time, returns the interpolated value of the
503 envelope at that time.
504 ====================================================================== */
506 float evalEnvelope( lwEnvelope *env, float time ){
507 lwKey *key0, *key1, *skey, *ekey;
508 float t, h1, h2, h3, h4, in, out, offset = 0.0f;
512 /* if there's no key, the value is 0 */
514 if ( env->nkeys == 0 ) {
518 /* if there's only one key, the value is constant */
520 if ( env->nkeys == 1 ) {
521 return env->key->value;
524 /* find the first and last keys */
526 skey = ekey = env->key;
527 while ( ekey->next ) ekey = ekey->next;
529 /* use pre-behavior if time is before first key time */
531 if ( time < skey->time ) {
532 switch ( env->behavior[ 0 ] )
541 time = range( time, skey->time, ekey->time, NULL );
545 time = range( time, skey->time, ekey->time, &noff );
547 time = ekey->time - skey->time - time;
552 time = range( time, skey->time, ekey->time, &noff );
553 offset = noff * ( ekey->value - skey->value );
557 out = outgoing( skey, skey->next )
558 / ( skey->next->time - skey->time );
559 return out * ( time - skey->time ) + skey->value;
563 /* use post-behavior if time is after last key time */
565 else if ( time > ekey->time ) {
566 switch ( env->behavior[ 1 ] )
575 time = range( time, skey->time, ekey->time, NULL );
579 time = range( time, skey->time, ekey->time, &noff );
581 time = ekey->time - skey->time - time;
586 time = range( time, skey->time, ekey->time, &noff );
587 offset = noff * ( ekey->value - skey->value );
591 in = incoming( ekey->prev, ekey )
592 / ( ekey->time - ekey->prev->time );
593 return in * ( time - ekey->time ) + ekey->value;
597 /* get the endpoints of the interval being evaluated */
600 while ( time > key0->next->time )
604 /* check for singularities first */
606 if ( time == key0->time ) {
607 return key0->value + offset;
609 else if ( time == key1->time ) {
610 return key1->value + offset;
613 /* get interval length, time in [0, 1] */
615 t = ( time - key0->time ) / ( key1->time - key0->time );
619 switch ( key1->shape )
624 out = outgoing( key0, key1 );
625 in = incoming( key0, key1 );
626 hermite( t, &h1, &h2, &h3, &h4 );
627 return h1 * key0->value + h2 * key1->value + h3 * out + h4 * in + offset;
630 return bez2( key0, key1, time ) + offset;
633 return key0->value + t * ( key1->value - key0->value ) + offset;
636 return key0->value + offset;