Пример #1
0
/* returns the rotation quat required to match v1 to v2    */
void vects_to_quat(double v1[3], double v2[3], double q[4]){
   double axis[3];
   double phi;
   double denom;
   
   /* first normalise each of em */
   vnormal(v1);
   vnormal(v2);
   
   /* check that someone isn't playing silly buggers */
   if((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2])){
      vcopy(axis, v1);
      phi = 0.0;
      }
   else{
      /* find the axis with a cross product          */
      vcross(axis, v2, v1);

      /* find the angle to rotate around that axis.  */
      /* v1.v2 = ||v1|| ||v2|| cos(angle)            */
      denom = vlength(v1) * vlength(v2);
      if(denom == 0){
         phi = 0.0;
         }
      else{
         phi = acos(vdot(v1, v2) / denom);
         }
      }
   
   /* create the quat */
   axis_to_quat(axis, phi, q);
   }
Пример #2
0
void quat_to_axis_angle(const Quat p, Vec4f axis, float* angle) {
    Quat q;
    quat_copy(p, q);
    quat_normalize(q, q); // if w>1 acos and sqrt will produce errors, this cant happen if quaternion is normalised

    *angle = (float)(2.0 * acos(q[3]));

    double s = sqrt(1.0 - q[3] * q[3]); // assuming quaternion normalised then w is less than 1, so term always positive.

    if( s < CUTE_EPSILON ) { // test to avoid divide by zero, s is always positive due to sqrt
        // if s close to zero then direction of axis not important
        axis[0] = q[0]; // if it is important that axis is normalised then replace with x=1; y=z=0;
        axis[1] = q[1];
        axis[2] = q[2];
        axis[3] = 1.0;
    } else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma warning(push)
#pragma warning(disable : 4244)
        axis[0] = q[0] / s; // normalise axis
        axis[1] = q[1] / s;
        axis[2] = q[2] / s;
        axis[3] = 1.0;
#pragma warning(pop)
#pragma GCC diagnostic pop

    }

    float length = vlength(axis);
    if( length < CUTE_EPSILON ) {
        *angle = 0.0f;
    }
}
Пример #3
0
/*
 * Ok, simulate a track-ball.  Project the points onto the virtual
 * trackball, then figure out the axis of rotation, which is the cross
 * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
 * Note:  This is a deformed trackball-- is a trackball in the center,
 * but is deformed into a hyperbolic sheet of rotation away from the
 * center.  This particular function was chosen after trying out
 * several variations.
 *
 * It is assumed that the arguments to this routine are in the range
 * (-1.0 ... 1.0)
 */
static void
trackball ( float q[4], float p1x, float p1y, float p2x, float p2y )
{
    float a[3]; /* Axis of rotation */
    float phi;  /* how much to rotate about axis */
    float p1[3], p2[3], d[3];
    float t;

    if (p1x == p2x && p1y == p2y)
    {
        // Zero rotation
        vzero(q);
        q[3] = 1.0;
        return;
    }

    // First, figure out z-coordinates for projection of P1 and P2 to
    // deformed sphere
    vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y));
    vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y));

    // Now, we want the cross product of P1 and P2
    vcross(p2,p1,a);

    // Figure out how much to rotate around that axis.
    vsub(p1,p2,d);
    t = vlength(d) / (2.0*TRACKBALLSIZE);

    // Avoid problems with out-of-control values...
    if (t > 1.0) t = 1.0;
    if (t < -1.0) t = -1.0;
    phi = 2.0 * asin(t);

    axis_to_quat(a,phi,q);
}
Пример #4
0
void Trackball :: spin ( float friction )
{
    const int RENORMCOUNT = 97 ;
    static int count=0;
    //float * q1, * q2, * dest ;
    float q1[4], * q2, * dest ;
    float t1[4], t2[4], t3[4];
    float tf[4];

    //q1 = m_lastquat ;
    if( friction != 1.0 )
    {
      float temp ;
      temp = vlength(m_lastquat);
      if( temp != 0 )
      {
         vcopy(m_lastquat,q1);
         vnormal(q1) ;
         temp = asin(temp)*friction ;
         q1[0] *= sin(temp) ;
         q1[1] *= sin(temp) ;
         q1[2] *= sin(temp) ;
         q1[3] = cos(temp) ;
      }
      else
      {
         vcopy(m_lastquat,q1);
         q1[3] = m_lastquat[3] ;
      }
    }
    else
    {
        vcopy(m_lastquat,q1);
        q1[3] = m_lastquat[3] ;
    }
    q2 = m_currquat ;
    dest = m_currquat ;

    vcopy(q1,t1);
    vscale(t1,q2[3]);

    vcopy(q2,t2);
    vscale(t2,q1[3]);

    vcross(q2,q1,t3);
    vadd(t1,t2,tf);
    vadd(t3,tf,tf);
    tf[3] = q1[3] * q2[3] - vdot(q1,q2);

    dest[0] = tf[0];
    dest[1] = tf[1];
    dest[2] = tf[2];
    dest[3] = tf[3];

    if (++count > RENORMCOUNT) {
        count = 0;
        normalize_quat(dest);
    }
}
Пример #5
0
void vnormalize( triple* x ){
  f32 len = vlength( x );
  if( len == 0 ){
    x->x = 0; x->y = 0; x->z = 1;
  }else{
    len = (f32)1.0 / len;
    vscale( x, len );
  }
}
/*
Split contours so that each length is at most the second argument (length).
*/
vector<ContourEQW> splitContours(vector<ContourEQW>& contours, 
								 int length)
{
	vector<ContourEQW> splitted;
	for(int i=0; i<contours.size(); ++i)
	{
		int m = contours[i].size()/length;
		int rem = contours[i].size() % length;
		m++;
		//figure out how to split a contour of length m 
		vector<int> vlength(m, 0);
		int dif = contours[i].size() - m * length;
		float inc = (float)dif / (float)vlength.size();
		float sum = 0;
		int total = 0;
		for(int k=0; k<vlength.size(); ++k)
		{
			sum += inc;
			vlength[k] = length + (int)sum;
			sum -= (int)sum;
			total += vlength[k];
		}
		if(total > contours[i].size()) //this case may happen due to rounding error
		{
			vlength[0] -= (total - contours[i].size());
		}

		int acc = 0;
		float gap = 1.0e-3;
		for(int j=0; j<m; ++j)
		{
			ContourEQW c = extractContourFragment(contours[i], acc, acc+vlength[j]-1);
			if(c.size()>=2)
			{
				//add a little gap to the end points so that we will have different view angle at the shared point.
				int sz = c.size();
				c.X[0] += (c.X[1]>c.X[0]) ? gap: -gap;
				c.Y[0] += (c.Y[1]>c.Y[0]) ? gap: -gap;
				c.X[sz-1] += (c.X[sz-2]>c.X[sz-1]) ? gap: -gap;
				c.Y[sz-1] += (c.Y[sz-2]>c.Y[sz-1]) ? gap: -gap;
			}
			splitted.push_back(c);
			acc += vlength[j];
		}
	}
	return splitted;
}
Пример #7
0
/*
 * Ok, simulate a track-ball.  Project the points onto the virtual
 * trackball, then figure out the axis of rotation, which is the cross
 * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
 * Note:  This is a deformed trackball-- is a trackball in the center,
 * but is deformed into a hyperbolic sheet of rotation away from the
 * center.  This particular function was chosen after trying out
 * several variations.
 *
 * It is assumed that the arguments to this routine are in the range
 * (-1.0 ... 1.0)
 */
void trackball( double q[4], double p1x, double p1y, double p2x, double p2y )
{
    double a[3]; /* Axis of rotation */
    double phi;  /* how much to rotate about axis */
    double p1[3], p2[3], d[3];
    double t;

    if( p1x == p2x && p1y == p2y )
    {
        /* Zero rotation */
        vzero( q );
        q[3] = 1.0;
        return;
    }

    /*
     * First, figure out z-coordinates for projection of P1 and P2 to
     * deformed sphere
     */
    vset( p1, p1x, p1y, tb_project_to_sphere( TRACKBALLSIZE, p1x, p1y ) );
    vset( p2, p2x, p2y, tb_project_to_sphere( TRACKBALLSIZE, p2x, p2y ) );

    /*
     *  Now, we want the cross product of P1 and P2
     */
    vcross(p2,p1,a);

    /*
     *  Figure out how much to rotate around that axis.
     */
    vsub( p1, p2, d );
    t = vlength( d ) / (2.0f * TRACKBALLSIZE);

    /*
     * Avoid problems with out-of-control values...
     */
    if( t > 1.0 )
        t = 1.0;

    if( t < -1.0 )
        t = -1.0;

    phi = 2.0f * (double) asin( t );

    axis_to_quat( a, phi, q );
}
Пример #8
0
/* Ok, simulate a track-ball.  Project the points onto the virtual
 * trackball, then figure out the axis of rotation, which is the cross
 * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
 * Note:  This is a deformed trackball-- is a trackball in the center,
 * but is deformed into a hyperbolic sheet of rotation away from the
 * center.  This particular function was chosen after trying out
 * several variations.
 *
 * It is assumed that the arguments to this routine are in the range
 * (-1.0 ... 1.0)
 */
void trackball(double q[4], double p1x, double p1y, double p2x, double p2y){
   double axis[3];             /* Axis of rotation              */
   double phi;                 /* how much to rotate about axis */
   double p1[3], p2[3], d[3];
   double t;

   /* if zero rotation */
   if(p1x == p2x && p1y == p2y){
      vset(q, 0.0, 0.0, 0.0);
      q[3] = 1.0;
      return;
      }

   /* First, figure out z-coordinates for projection of P1 and P2 to  */
   /* the deformed sphere                                                 */
   p1[0] = p1x;
   p1[1] = p1y;
   p1[2] = tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y);

   p2[0] = p2x;
   p2[1] = p2y;
   p2[2] = tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y);

   /* Now, we want the cross product of P1 and P2     */
   vcross(axis, p2, p1);

   /* Figure out how much to rotate around that axis. */
   vsub(d, p1, p2);
   t = vlength(d)/(2.0*TRACKBALLSIZE);

   /* Avoid problems with out-of-control values.      */
   if(t >  1.0){ t =  1.0; }
   if(t < -1.0){ t = -1.0; }
   phi = 2.0 * asin(t);

   axis_to_quat(axis, phi, q);
   }
Пример #9
0
/*
 * Ok, simulate a track-ball.  Project the points onto the virtual
 * trackball, then figure out the axis of rotation, which is the cross
 * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
 * Note:  This is a deformed trackball-- is a trackball in the center,
 * but is deformed into a hyperbolic sheet of rotation away from the
 * center.  This particular function was chosen after trying out
 * several variations.
 *
 * It is assumed that the arguments to this routine are in the range
 * (-1.0 ... 1.0)
 */
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y,  float tbSize)
{
    float a[3];		// Axis of rotation
    float phi;		// how much to rotate about axis
    float p1[3], p2[3], d[3];
    float t;

    if( p1x == p2x && p1y == p2y ) {
        /* Zero rotation */
        vzero(q);
        q[3] = 1.0;
        return;
    }

    // First, figure out z-coordinates for projection of P1 and P2 to deformed sphere
    vset( p1, p1x, p1y, tb_project_to_sphere(tbSize, p1x, p1y) );
    vset( p2, p2x, p2y, tb_project_to_sphere(tbSize, p2x, p2y) );

    // Now, we want the cross product of P1 and P2
    vcross( p2, p1, a);

    // Figure out how much to rotate around that axis
    vsub( p1, p2, d);
    t = vlength(d) / ( 2.0f * tbSize );

    // Avoid problems with out-of-control values
    if (t > 1.0) {
		t = 1.0;
	}
    if (t < -1.0) {
		t = -1.0;
	}
    phi = 2.0f * (float)asin(t);

    axis_to_quat( a, phi, q );
}
Пример #10
0
static void addMeasurement(Packet_t *packet)
{
    xvector[vectorPos] = packet->accX;
    yvector[vectorPos] = packet->accY;
    zvector[vectorPos] = packet->accZ;
    vectorPos++;
    if (vectorPos < NUM_SAMPLES) return;

    vectorPos = 0;

    float s = stdev(xvector) + stdev(yvector) + stdev(zvector);
//    PRINTF("stdev = %u\n", (uint16_t) s);
    float accelVector[3] = {
        average(xvector) - groundVector[0],
        average(yvector) - groundVector[1],
        average(zvector) - groundVector[2]
    };

    // PRINTF("accel=(%d %d %d)\n", (int)accelVector[0], (int)accelVector[1], (int)accelVector[2]);

    bool nowFwd, nowBack;
    float accLen = vlength(accelVector);
    if (accLen < ONE_G / 10) {
        nowBack = nowFwd = false;
    } else {
        normalizeQuick(accelVector, accLen);
        nowFwd = sameDirection(fwdVector, accelVector);
        nowBack = inverseDirection(fwdVector, accelVector);
    }
    int now = nowFwd ? 1 : (nowBack ? -1 : 0);

    bool diffFromPrevious;
    static bool notFirstTime;
    if (notFirstTime) {
        // float difference = (calcDiff(xvector, prevxvector) 
        //     + calcDiff(yvector, prevyvector)           
        //     + calcDiff(zvector, prevzvector)) / 3.0;
        float difference = calcDiff(xvector, prevavgxvector) 
                + calcDiff(yvector, prevavgyvector)           
                + calcDiff(zvector, prevavgzvector);
        // PRINTF("difference=%d\n", (int)difference);
        diffFromPrevious = (difference >= 30 * (ONE_G / 10));
    } else {
        notFirstTime = true;
        diffFromPrevious = false;
    }

    bool pastBack = false;
    bool pastFwd = false;
    if (past[0] + past[1] + past[2] >= 1) {
        pastFwd = true;
    } else if (past[0] + past[1] + past[2] <= -1) {
        pastBack = true;
    }
    past[0] = past[1];
    past[1] = past[2];
    past[2] = now;

    bool wasMoving = !bayesStandingMode;

#if 0
    PRINTF("SSD       \t%d\n",  (int)(s >= THRESH_LOW));
    PRINTF("MSD       \t%d\n",  (int)(s >= THRESH_MEDIUM));
    PRINTF("LSD       \t%d\n" , (int)(s > THRESH_HIGH));
    PRINTF("Accelerating\t%d\n", (int)(nowFwd));
    PRINTF("PastAccel \t%d\n", (int)(pastFwd));
    PRINTF("PastBrake \t%d\n", (int)(pastBack));
    PRINTF("WasMoving \t%d\n", (int)(wasMoving));
    PRINTF("Diff      \t%d\n", (int)(diffFromPrevious));
#endif

    calcNewProb(s, wasMoving, pastBack, pastFwd, nowFwd, diffFromPrevious);
}
Пример #11
0
static inline void
vnormal(float *v)
{
    vscale(v,1.0/vlength(v));
}
Пример #12
0
f32 vdistance( const triple* x, const triple* y ){
  triple v = *y;
  vsub( &v, x );
  return vlength( &v );
}
Пример #13
0
void
vnormal(float *v)
{
    vscale(v,1.0/vlength(v));
}
Пример #14
0
/* normalise a vector */
void vnormal(double *v){
   vscale(v, 1.0 / vlength(v));
   }
Пример #15
0
bool arcball_event(struct Arcball* arcball, SDL_Event event) {
    static int32_t mouse_down = 0;
    static const float rotation_slowness_factor = 0.25f;
    static int32_t next_flipped = 0;

    // - arcball rotation is performed by dragging the mouse, so I just keep track of when
    // a mouse button is pressed and released between calls to this function by setting a
    // static variable mouse_down to the button number when a button is pressed and back
    // to 0 when that button is released
    if( event.type == SDL_MOUSEBUTTONDOWN && mouse_down == 0 ) {
        mouse_down = event.button.button;
    } else if( event.type == SDL_MOUSEBUTTONUP && mouse_down == event.button.button ) {
        arcball->flipped = next_flipped;
        mouse_down = 0;
    }

    if( mouse_down == arcball->translate_button && event.type == SDL_MOUSEMOTION ) {
        SDL_MouseMotionEvent mouse = event.motion;
        float eye_distance = arcball->camera.pivot.eye_distance;

        // - when an mouse motion event occurs, and mouse_down to the translation_button so we compute
        // a camera translation
        // - the camera should pan around on the x-z-plane, keeping its height and orientation
        Quat inverted_orientation = {0};
        quat_invert(arcball->camera.pivot.orientation, inverted_orientation);

        // - the sideways translation is computed by taking the right_axis and orienting it with
        // the cameras orientation, the way I set up the lookat implementation this should always
        // result in a vector parallel to the x-z-plane
        Vec4f right_axis = RIGHT_AXIS;
        vec_rotate4f(right_axis, inverted_orientation, right_axis);
        if( mouse.xrel != 0 ) {
            // - then we'll just multiply the resulting axis with the mouse x relative movement, inversely
            // scaled by how far we are away from what we are looking at (farer means faster, nearer
            // means slower), the translation_factor is just a value that felt good when this was implemented
            Vec4f x_translation = {0};
            vec_mul1f(right_axis, (float)mouse.xrel/arcball->translate_factor*eye_distance, x_translation);

            // - finally just add the x_translation to the target and position so that the whole arcball moves
            vec_add(arcball->target, x_translation, arcball->target);
            vec_add(arcball->camera.pivot.position, x_translation, arcball->camera.pivot.position);
        }

        // - the z translation can't be done along the orientated forward axis because that would include
        // the camera pitch, here, same as above, we need an axis that is parallel to the x-z-plane
        Vec4f up_axis = UP_AXIS;
        if( mouse.yrel != 0 ) {
            // - luckily such an axis is easily computed from the crossproduct of the orientated right_axis and
            // the default up_axis, the result is an axis pointing in the direction of the cameras forward axis,
            // while still being parallel to the x-z-plane
            Vec4f forward_axis;
            vec_cross(right_axis, up_axis, forward_axis);

            // - same as above
            Vec4f z_translation;
            vec_mul1f(forward_axis, (float)mouse.yrel/arcball->translate_factor*eye_distance, z_translation);

            // - dito
            vec_add(arcball->target, z_translation, arcball->target);
            vec_add(arcball->camera.pivot.position, z_translation, arcball->camera.pivot.position);
        }
    } else if( mouse_down == arcball->rotate_button && event.type == SDL_MOUSEMOTION ) {
        SDL_MouseMotionEvent mouse = event.motion;

        // - above case was translation, this is an rotation occuring: mouse_down is equal to the
        // rotation_button and the event is a mouse motion
        // - the camera needs to rotate around the target while keeping its height, orientation and
        // without _any_ rolling

        // - we want only yaw and pitch movement
        // - yaw is easy, just use the fixed up_axis and create a rotation the rotates around it
        // by the mouse x relative movement (converted to radians)
        // - the flipped value indicates if the camera is flipped over, so we'll just use that to
        // change the sign of the yaw to make the mouse movement on the screen always correctly
        // relates to the movement of the rotation
        Vec4f up_axis = UP_AXIS;
        Quat yaw_rotation = {0};
        quat_from_axis_angle(up_axis, arcball->flipped * PI/180 * mouse.xrel * rotation_slowness_factor, yaw_rotation);

        // - pitch is a little more involved, I need to compute the orientated right axis and use
        // that to compute the pitch_rotation
        Quat inverted_orientation = {0};
        quat_invert(arcball->camera.pivot.orientation, inverted_orientation);

        Vec4f right_axis = RIGHT_AXIS;
        vec_rotate4f(right_axis, inverted_orientation, right_axis);

        Quat pitch_rotation = {0};
        quat_from_axis_angle(right_axis, -PI/180 * mouse.yrel * rotation_slowness_factor, pitch_rotation);

        // - combine yaw and pitch into a single rotation
        Quat rotation = {0};
        quat_mul(yaw_rotation, pitch_rotation, rotation);

        // - orbit is the position translated to the coordinate root
        // - the yaw and pitch rotation is applied to the orbit
        // - orbit is translated back and replaces the camera position
        Vec4f orbit = {0};
        vec_sub(arcball->camera.pivot.position, arcball->target, orbit);
        vec_rotate4f(orbit, rotation, orbit);
        vec_add(arcball->target, orbit, arcball->camera.pivot.position);

        // - after updating the position we just call lookat to compute the new
        // orientation, and also set the flipped state
        next_flipped = pivot_lookat(&arcball->camera.pivot, arcball->target);
    }

    if( event.type == SDL_MOUSEWHEEL ) {
        SDL_MouseWheelEvent wheel = event.wheel;

        // - zooming when mouse wheel event happens
        float* eye_distance = &arcball->camera.pivot.eye_distance;
        if( (*eye_distance > arcball->camera.frustum.z_near || wheel.y < 0) &&
            (*eye_distance < arcball->camera.frustum.z_far || wheel.y > 0))
        {
            // - just going back and forth along the oriented forward axis, using wheel
            // y motion inversly scaled by the eye_distance, similar to what is done
            // for the translation above (farer == faster zoom, nearer == slower zoom)
            Quat inverted_orientation = {0};
            quat_invert(arcball->camera.pivot.orientation, inverted_orientation);

            Vec4f forward_axis = FORWARD_AXIS;
            vec_rotate4f(forward_axis, inverted_orientation, forward_axis);

            Vec4f zoom = {0};
            vec_mul1f(forward_axis, wheel.y/arcball->zoom_factor*(*eye_distance), zoom);
            vec_add(arcball->camera.pivot.position, zoom, arcball->camera.pivot.position);

            // - eye_distance is kept in camera state, so we need to update it here
            *eye_distance = vlength(arcball->camera.pivot.position);
        }
    }

    return true;
}
Пример #16
0
static void trackcsv(FILE *fo, const int trackno,
    	    	     byte *trk, long trklen, const int ppq)
{
    int levt = 0, evt, channel, note, vel, control, value,
	type;
    vlint len;
    byte *titem;
    vlint abstime = 0;		      /* Absolute time in track */
#ifdef XDD
byte *strk = trk;
#endif

    while (trklen > 0) {
	vlint tlapse = vlength(&trk, &trklen);
	abstime += tlapse;

        fprintf(fo, "%d, %ld, ", trackno, abstime);

	/* Handle running status; if the next byte is a data byte,
	   reuse the last command seen in the track. */

	if (*trk & 0x80) {
#ifdef XDD
fprintf(fo, " (Trk: %02x NS: %02X : %d) ", *trk, evt, trk - strk);
#endif
	    evt = *trk++;
	    
	    /* One subtlety: we only save channel voice messages
	       for running status.  System messages and file
	       meta-events (all of which are in the 0xF0-0xFF
	       range) are not saved, as it is possible to carry a
	       running status across them.  You may have never seen
	       this done in a MIDI file, but I have. */
	       
	    if ((evt & 0xF0) != 0xF0) {
	    	levt = evt;
	    }
	    trklen--;
	} else {
	    evt = levt;
#ifdef XDD
fprintf(fo, " (Trk: %02x RS: %02X : %d) ", *trk, evt, trk - strk);
#endif
	}

	channel = evt & 0xF;

	/* Channel messages */

	switch (evt & 0xF0) {

	    case NoteOff:	 /* Note off */
		if (trklen < 2) {
		    return;
		}
		trklen -= 2;
		note = *trk++;
		vel = *trk++;
                fprintf(fo, "Note_off_c, %d, %d, %d\n", channel, note, vel);
		continue;

	    case NoteOn:	 /* Note on */
		if (trklen < 2) {
		    return;
		}
		trklen -= 2;
		note = *trk++;
		vel = *trk++;
		/*  A note on with a velocity of 0 is actually a note
		    off.  We do not translate it to a Note_off record
		    in order to preserve the original structure of the
		    MIDI file.	*/
                fprintf(fo, "Note_on_c, %d, %d, %d\n", channel, note, vel);
		continue;

	    case PolyphonicKeyPressure: /* Aftertouch */
		if (trklen < 2) {
		    return;
		}
		trklen -= 2;
		note = *trk++;
		vel = *trk++;
                fprintf(fo, "Poly_aftertouch_c, %d, %d, %d\n", channel, note, vel);
		continue;

	    case ControlChange:  /* Control change */
		if (trklen < 2) {
		    return;
		}
		trklen -= 2;
		control = *trk++;
		value = *trk++;
                fprintf(fo, "Control_c, %d, %d, %d\n", channel, control, value);
		continue;

	    case ProgramChange:  /* Program change */
		if (trklen < 1) {
		  return;
		}
		trklen--;
		note = *trk++;
                fprintf(fo, "Program_c, %d, %d\n", channel, note);
		continue;

	    case ChannelPressure: /* Channel pressure (aftertouch) */
		if (trklen < 1) {
		    return;
		}
		trklen--;
		vel = *trk++;
                fprintf(fo, "Channel_aftertouch_c, %d, %d\n", channel, vel);
		continue;

	    case PitchBend:	 /* Pitch bend */
	       if (trklen < 1) {
		   return;
		}
		trklen--;
		value = *trk++;
		value = value | ((*trk++) << 7);
                fprintf(fo, "Pitch_bend_c, %d, %d\n", channel, value);
		continue;

	    default:
		break;
	}

	switch (evt) {

	    /* System exclusive messages */

	    case SystemExclusive:
	    case SystemExclusivePacket:
		len = vlength(&trk, &trklen);
                fprintf(fo, "System_exclusive%s, %lu",
                    evt == SystemExclusivePacket ? "_packet" : "",
		    len);
		{
		    vlint i;

		    for (i = 0; i < len; i++) {
                        fprintf(fo, ", %d", *trk++);
		    }
                    fprintf(fo, "\n");
		}
		break;

	    /* File meta-events */

	    case FileMetaEvent:

		if (trklen < 2) {
		    return;
		}
		trklen -= 2;
		type = *trk++;
		len = vlength(&trk, &trklen);
		titem = trk;
		trk += len;
		trklen -= len;

		switch (type) {
		    case SequenceNumberMetaEvent:
                        fprintf(fo, "Sequence_number, %d\n", (titem[0] << 8) | titem[1]);
			break;

		    case TextMetaEvent:
#ifdef XDD
fprintf(fo, " (Len=%ld  Trk=%02x) ", len, *trk);
#endif
    	    	    	fputs("Text_t, ", fo);
			textcsv(fo, titem, len);
			putc('\n', fo);
			break;

		    case CopyrightMetaEvent:
    	    	    	fputs("Copyright_t, ", fo);
			textcsv(fo, titem, len);
			putc('\n', fo);
			break;

		    case TrackTitleMetaEvent:
    	    	    	fputs("Title_t, ", fo);
			textcsv(fo, titem, len);
			putc('\n', fo);
			break;

		    case TrackInstrumentNameMetaEvent:
    	    	    	fputs("Instrument_name_t, ", fo);
			textcsv(fo, titem, len);
			putc('\n', fo);
			break;

		    case LyricMetaEvent:
    	    	    	fputs("Lyric_t, ", fo);
			textcsv(fo, titem, len);
			putc('\n', fo);
			break;

		    case MarkerMetaEvent:
    	    	    	fputs("Marker_t, ", fo);
			textcsv(fo, titem, len);
			putc('\n', fo);
			break;

		    case CuePointMetaEvent:
    	    	    	fputs("Cue_point_t, ", fo);
			textcsv(fo, titem, len);
			putc('\n', fo);
			break;

		    case ChannelPrefixMetaEvent:
                        fprintf(fo, "Channel_prefix, %d\n", titem[0]);
			break;

		    case PortMetaEvent:
                        fprintf(fo, "MIDI_port, %d\n", titem[0]);
			break;

		    case EndTrackMetaEvent:
                        fprintf(fo, "End_track\n");
			trklen = -1;
			break;

		    case SetTempoMetaEvent:
                        fprintf(fo, "Tempo, %d\n", (titem[0] << 16) |
			       (titem[1] << 8) | titem[2]);
			break;

		    case SMPTEOffsetMetaEvent:
                        fprintf(fo, "SMPTE_offset, %d, %d, %d, %d, %d\n",
			    titem[0], titem[1], titem[2], titem[3], titem[4]);
			break;

		    case TimeSignatureMetaEvent:
                        fprintf(fo, "Time_signature, %d, %d, %d, %d\n",
				titem[0], titem[1], titem[2], titem[3]);
			break;

		    case KeySignatureMetaEvent:
                        fprintf(fo, "Key_signature, %d, \"%s\"\n", ((signed char) titem[0]),
                                titem[1] ? "minor" : "major");
			break;

		    case SequencerSpecificMetaEvent:
                        fprintf(fo, "Sequencer_specific, %lu", len);
			{
			    vlint i;

			    for (i = 0; i < len; i++) {
                                fprintf(fo, ", %d", titem[i]);
			    }
                            fprintf(fo, "\n");
			}
			break;

		    default:
			if (verbose) {
                            fprintf(stderr, "Unknown meta event type 0x%02X, %ld bytes of data.\n",
				    type, len);
			}
                        fprintf(fo, "Unknown_meta_event, %d, %lu", type, len);
			{
			    vlint i;

			    for (i = 0; i < len; i++) {
                                fprintf(fo, ", %d", titem[i]);
			    }
                            fprintf(fo, "\n");
			}
			break;
	      }
	      break;

	   default:
	      if (verbose) {
                  fprintf(stderr, "Unknown event type 0x%02X.\n", evt);
	      }
              fprintf(fo, "Unknown_event, %02Xx\n", evt);
	      break;
	}
    }
}
Пример #17
0
static void normalize(float vector[3]) {
    float invlength = 1 / vlength(vector);
    vector[0] *= invlength;
    vector[1] *= invlength;
    vector[2] *= invlength;
}