ftp.nice.ch/pub/next/unix/audio/cmusic.bs.N.tar.gz#/src/gen/nodfun.c

This is nodfun.c in view mode; [Download] [Up]

#include "list.h"
#include <stdio.h>
#include <math.h>

/*
 * wfun - write function file name with node list nod.
 * File written is text, with x and y pairs on each line. 
 */

wfun(name, nod, cx, cy, cd, ysin)
	char *name; LIST *nod; int cx, cy; float cd; int ysin;
{
	LIST *p;
	FILE *of, *fopen();
	of = fopen(name, "w");
	if (of == NULL) return(-1);
	for (p = nod; p; p = p->next) fprintf(of, "%6.3f\t%6.3f\n", 
		cd * (p->x - cx), cd * (p->y - cy) * ysin);
	fclose(of);
	return(0);
}

/*
 * rfun - read function file name.  if head != NULL, append the function
 * to the end of it.  returns the head, which it creates if supplied one
 * is NULL.  cx, cy and cd are used to set meter distances of the nodes 
 * from the listener.  Typical values would be cx = cy = 0, cd = 1.0.
 * cd is interpreted in meters.
 */

LIST *rfun(head, name, cx, cy, cd, ysin)
	LIST *head; char *name; float cx, cy, cd; int ysin;
{
	LIST *p, *addnod();
	FILE *i, *fopen();
	float fx=0, fy=0;
	register int r;
	register float n = 0.0;
	i = fopen(name, "r");
	if (i == NULL) return(NULL);
	for (p = head; p; p = p->next) n = p->n + 1.0;	
	while ((r = fscanf(i, "%f%f", &fx, &fy)) != EOF && r == 2)
		{
		head = addnod(head, fy, fx, n, n, cx, cy, cd, ysin);
		n += 1.0;
		}
	fclose(i);
	return(head);
}


rmlist(nod)
	LIST *nod;
{
	LIST *s, *o;
	for (s = nod; s; )
		if (s->next != NULL)
			{ s = s->next; free(s->last); }
		else
			{ free(s); break; }
}


/* 
 * linearly interpolate node between this and the next for x and y 
 * where x,y are screen coordinates.
 */

LIST *ntrpnod(nod, cx, cy, cd)	
	LIST *nod; int cx, cy; float cd;
{
	LIST *newnod, *nxtnod, *t, *mknod();
	if (nod == NULL) return(NULL);
	if (nod->next == NULL) return(NULL);
	else nxtnod = nod->next;
	newnod = mknod();
	newnod->y = ((nxtnod->y - nod->y)/2) + nod->y;
	newnod->fy = -(newnod->y - cy) * cd;
	newnod->x = ((nxtnod->x - nod->x)/2) + nod->x;
	newnod->fx = (newnod->x - cx) * cd;
	newnod->time = ((nxtnod->time - nod->time)/2) + nod->time;
	newnod->n = nxtnod->n;
	for (t = nxtnod; t; t = t->next) t->n += 1.0;
	nod->next = newnod;
	newnod->last = nod;
	newnod->next = nxtnod;
	nxtnod->last = newnod;
	if (velocity(newnod))
		return(NULL);
	return(newnod);
}


LIST *mknod()
{
	return((LIST *) calloc(sizeof (LIST), 1));
}


/*adrnod - returns node with same values of y and x.*/

LIST *adrnod(head, y, x)
	LIST *head; int x, y;
{
	LIST *nod;
	for (nod = head; nod; nod = nod->next)
		if (nod->x == x && nod->y == y)
			return(nod);
	return(NULL);
}


/* putnod - position node to x,y coordinates where x,y are the integer
 * values of a screen location.  0,0 is the upper left hand corner.
 */

putnod(nod, y, x, cx, cy, cd)
	LIST *nod; int y, x, cx, cy; float cd;
{
	if (nod == NULL) return(-1);
	nod->x = x;
	nod->fx = (x - cx) * cd;
	nod->y = y;
	nod->fy = -(y - cy) * cd;
	if (velocity(nod))
		return(-1);
	return(0);
}

mvlist(head, cx, cy, cd, ysign)
	LIST *head; float cx, cy, cd; int ysign;
{
	LIST *n;
	for (n = head; n; n = n->next)
		{
		n->y = cy + ysign * n->fy / cd;
		n->x = cx + n->fx / cd;
		}
}

scalist(head, xscl, yscl, cx, cy, cd, ysign)
	LIST *head; float xscl, yscl, cx, cy, cd; int ysign;
{
	LIST *n;
	for (n = head; n; n = n->next)
		{
		n->fx *= xscl;
		n->fy *= yscl;
		n->y = cy + ysign * n->fy / cd;
		n->x = cx + n->fx / cd;
		if (velocity(n))
			return(-1);
		}
	return(0);
}

offlist(head, xoff, yoff, cx, cy, cd, ysign)
	LIST *head; float xoff, yoff, cx, cy, cd; int ysign;
{
	LIST *n;
	for (n = head; n; n = n->next)
		{
		n->fx += xoff;
		n->fy += yoff;
		n->y = cy + ysign * n->fy / cd;
		n->x = cx + n->fx / cd;
		}
}

float Pi;

float getheta(x, y)
	float x, y;
{
	register float theta;
	theta = atan2(y, x);
	if (theta < 0.0) theta = (Pi + theta) + Pi;
	return(theta);
}

float circlemod(x) 
	float x;
{
	register float twopi = 2.0 * Pi;
	while (x > twopi) x -= twopi;
	while (x < 0) x += twopi;
	return(x);
}

float getdistance(x, y)
	float x, y;
{
	return(sqrt(x*x+y*y));
}

rotlist(head, rot, cx, cy, cd, ysign)
	LIST *head; float rot, cx, cy, cd; int ysign;
{
	LIST *n;
	float theta, D;
	Pi = 4.0 * atan(1.0);
	rot = 2.0 * Pi * rot / 360.0;
	for (n = head; n; n = n->next)
		{
		D = getdistance(n->fx, n->fy);
		theta = getheta(n->fx, n->fy);
		theta = circlemod(theta + rot);
		n->fx = D * cos(theta);
		n->fy = D * sin(theta);
		n->y = cy + ysign * n->fy / cd;
		n->x = cx + n->fx / cd;
		}
}


LIST *endnod;

LIST *addnod(head, y, x, n, time, cx, cy, cd, ysign)
	LIST *head; float y, x, n, time, cx, cy, cd; int ysign;
{
	LIST *newnod, *mknod();
	if (head == NULL)
		newnod = endnod = head = mknod();
	else
		newnod = mknod();
	newnod->y = cy + ysign * y / cd;
	newnod->fy = y;
	newnod->x = cx + x / cd;
	newnod->fx = x;
	newnod->n = n;
	newnod->time = time;
	if (newnod != head) 	/* not starting new list */
		{
		endnod->next = newnod;
		newnod->last = endnod;
		}
	if (velocity(newnod))
		return(NULL);
	endnod = newnod;
	return(head);
}


/*
 * delnod - delete a node from the list.  returns the previous node if
 * possible, else the next node.  if the node is the only one, NULL is
 * returned.  if the node to be deleted is the head of the linked list,
 * assign the next element to be head.  Note that the ADDRESS of the
 * head of the linked list must be passed, not just its value.
 */

LIST *delnod(Hed, nod)
	LIST **Hed, *nod;
{
	LIST *s, *r = NULL;
	if (nod == NULL) return(NULL);
	if (nod->last != NULL)
		nod->last->next = nod->next;
	else
		*Hed = nod->next;	/* jump to new head */
	if (nod->next != NULL)
		nod->next->last = nod->last;
	for (s = nod->next; s; s = s->next) s->n -= 1.0;
	if (velocity(nod->next))
		return(NULL);
	if (nod->last != NULL) r = nod->last;
	else r = nod->next;
	free(nod);
	endnod = r;
	return(r);
}

velocity(nod)
	LIST *nod;
{
	register float y, x, d, delta;
	if (nod == NULL) return;
	if (nod->last != NULL)
		{
		y = nod->fy - nod->last->fy;
		x = nod->fx - nod->last->fx;
		d = sqrt(y*y + x*x);
		if (d == 0.0) {
			nod->velocity = 0;
			return(0);
		}
		if ((delta = nod->time - nod->last->time) == 0.0)
			return(-1);
		nod->velocity = d / delta;
		}
	return(0);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.