ftp.nice.ch/pub/next/unix/audio/Cmix.N.s.tar.gz#/cmix/sys/sound.c

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

/*   sound i/o routines 
*/
/* this version uses pointers to differentiate between different flavours
   of i/o, FLOAT and INT */
/* version that just writes/reads to standard UNIXFILES, with sfheader.*/
/* TODO: keep one file from being opened twice for writing.
	 implement mag tape reads and wipeouts 
	?BUG after using layout, should not call flushbuf
	?in zap and alter routines, (when else..?

	 to add tape read/write need additional arg in open to indicate
	 file number, and this show that it is tape.
	 also need label checking.  first record on each tape file will be
	 header.  
	 only other change for tape is to use read instead of lseek, and 
	 only allow getin and wipeout routines.  also have to add librarian
	 to keep track of what file we are on, and watch out for close, and 
	 thus screw up in eof marks.  (need to know whether we have been 
	 reading or writing.

	 6/6 tape seems to work, need to add positioning, and file finds

12/12/91 -- tape hooks are here, but are unimplemented, probably not
worth it.  PL
*/

#define SOUND
#include "../H/ugens.h"
#include "../H/sfheader.h"
#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/times.h>       /* obsolete on VAX replace with new proc */
#include <sys/time.h>       /* obsolete on VAX replace with new proc */


extern int NBYTES;           /* size of buffer to allocate */
extern float SR;

int  sfd[NFILES];            /* soundfile descriptors */
int  pointer[NFILES];	     /* to be used as pointer within sound buffer */
int  bufsize[NFILES];        /* word length of buffer */

char *sndbuf[NFILES];        /* address of buffer */
char *peak[NFILES];          /* array to store peak amplitude for nchannels */
char *peakloc[NFILES];       /* overall peak amplitude */
			   
char wipe_is_off[NFILES];    /* this is for wipeout */
char peakoff[NFILES];        /* this will set peak test on or off*/
float punch[NFILES];	     /* punch alteration flags */
char istape[NFILES];         /* flag to see if it is a tape unit */
double starttime[NFILES];    /* to save starting time of note */
long  originalsize[NFILES];  /* to save byte length of file */
long  filepointer[NFILES];   /* to save current pointer in file */
int status[NFILES];	     /* save read/write flage as well */
int isopen[NFILES];	     /* open status */
int headersize[NFILES];      /* to accomodate bsd and next headers */

SFHEADER      sfdesc[NFILES];
SFMAXAMP      sfm[NFILES];
struct stat   sfst[NFILES];

static SFCODE ampcode = {
	SF_MAXAMP,
	sizeof(SFMAXAMP) + sizeof(SFCODE)
};

struct tms    clockin[NFILES];
 
int _iaddout(),_faddout(),_iwipeout(),_fwipeout(),_ilayout(),_flayout();
int _igetin(),_fgetin();
int (*addoutpointer[NFILES])();
int (*layoutpointer[NFILES])();
int (*wipeoutpointer[NFILES])();
int (*getinpointer[NFILES])();

float SR;   /* now declared here rather than in the profile */
char *sfname[NFILES];

m_open(p,n_args) 
float *p; 
{
	char  *name,*malloc(),*cp,*getsfcode();

	int   fno,i,new;
	float *opk;

	i = (int) p[0];
	name = (char *) i;
	fno = p[1];
	sfname[fno] = name;
	status[fno] = (n_args == 3) ? (int)p[2] : 2;

	if((fno >=  NFILES) || (fno < 0)) {
		fprintf(stderr," Only %d files allowed\n"
			,NFILES);
		closesf();
		}
	new = 0;
	if(isopen[fno])  close(sfd[fno]);
	else new = 1;
	isopen[fno] = 1;

	istape[fno] = (n_args == 4) ? 1 : 0;
			/* in the case of a tape, there will be a 
			   4th argument listing the file number */

	drwopensf(name,sfd[fno],sfdesc[fno],sfst[fno],"CMIX",i,status[fno])
	headersize[fno] = getheadersize(&sfdesc[fno]);
	if(i<0) closesf();
	printf("name: %s   sr: %f   nchans: %d  class: %d sfd[fno] %d \n",name,
		sfsrate(&sfdesc[fno]),sfchans(&sfdesc[fno]),
		sfclass(&sfdesc[fno]),sfd[fno]);

	if(headersize[fno] == SIZEOF_NeXT_HEADER)
		printf("This is a native NeXT soundfile.\n");
	else if(headersize[fno] == SIZEOF_BSD_HEADER) {
		if(nsfmagic(&sfdesc[fno]) == SND_MAGIC)	
			printf("This is a hybrid BSD/NeXT soundfile.\n");
		else printf("This is an IRCAM soundfile.\n");
	}

	printf("Duration of file is %f seconds.\n",(float)(sfst[fno].st_size - headersize[fno])/(float)sfclass(&sfdesc[fno])/(float)sfchans(&sfdesc[fno])/sfsrate(&sfdesc[fno]));

	originalsize[fno] = istape[fno] ? 999999999 : sfst[fno].st_size;
	/*
	sfstats(sfd[fno]);
	*/

	NBYTES = 16384;  /* hardwire this size to correct for os error */
	if(new) {
		if((sndbuf[fno] = (char *)malloc((unsigned)NBYTES)) == NULL) {
			sprintf(stderr," CMIX: malloc sound buffer error\n");
			closesf();
			}
		if((peakloc[fno] = malloc((unsigned)(sfchans(&sfdesc[fno]) * 
			LONG))) == NULL) {
			fprintf(stderr,"CMIX: malloc ovpeak buffer error\n");
			closesf();
		}
		if((peak[fno] = 
			malloc((unsigned)(sfchans(&sfdesc[fno])* FLOAT))) 
			== NULL) {
			fprintf(stderr,"CMIX: malloc peak buffer error!\n");
			closesf();
		}
		peakoff[fno] = 0; /* default to peakcheckon when opening file*/
		punch[fno] = 0; /* default to no punch when opening file*/
	}
	if(sfclass(&sfdesc[fno]) == SHORT) {
			addoutpointer[fno] = _iaddout;
			layoutpointer[fno] = _ilayout;
			wipeoutpointer[fno] = _iwipeout;
			getinpointer[fno] = _igetin;
	}
	else 			        {   
			addoutpointer[fno] = _faddout;
			layoutpointer[fno] = _flayout;
			wipeoutpointer[fno] = _fwipeout;
			getinpointer[fno] = _fgetin;
	}

	if(!SR) SR = sfsrate(&sfdesc[fno]);	

	if(sfsrate(&sfdesc[fno])!= SR)
		fprintf(stderr,"Note--> SR reset to %f\n",SR);

	/* read in former peak amplitudes, make sure zero'ed out to start.*/

	cp = getsfcode(&sfdesc[fno],SF_MAXAMP);
	if(cp == NULL) {
		printf("Trouble parsing header: cp=NULL\n");
		closesf();
		}

	bcopy(cp + sizeof(SFCODE), (char *) &sfm[fno], sizeof(SFMAXAMP));
	
	for(opk = (float *)peak[fno], i = 0; i<sfchans(&sfdesc[fno]); i++) 
		*(opk+i) = sfmaxamp(&sfm[fno],i);
	bufsize[fno] = NBYTES / sfclass(&sfdesc[fno]);/* set size in words */

}

setnote(start,dur,fno)
float start,dur;
int fno;
{
	int nsamps,offset;
	int i;

	if(!isopen[fno]) {
		fprintf(stderr,"You haven't opened file %d yet!\n",fno);
		closesf();
	}
	if(start > 0.) /* if start < 0 it indicates number of samples to skip*/
		offset = (int) (start * SR + .5) * sfchans(&sfdesc[fno])

	    		* sfclass(&sfdesc[fno]);

	else    offset = -start * sfchans(&sfdesc[fno]) * sfclass(&sfdesc[fno]);
		       /* if dur < 0, it indicates number of samples to play*/

		/* make sure it falls on channel/block boundary */
	offset -= offset % (sfchans(&sfdesc[fno]) * sfclass(&sfdesc[fno]));
	offset = (offset < 0) ? 0 : offset;

	nsamps = (dur > 0.) ? (int)((start+dur) * SR -
	(offset/(sfchans(&sfdesc[fno])*sfclass(&sfdesc[fno])))+ .5) : (int)-dur;

	if(!istape[fno]) {
		if((filepointer[fno] = 
		   lseek(sfd[fno],offset+headersize[fno],0)) == -1) {
			fprintf(stderr,"CMIX: bad lseek in setnote\n");
			closesf();
		}
	}
	pointer[fno] = 0;
//printf("%d %d %d %d\n",filepointer[fno],fno,offset,headersize[fno]);
	_readit(fno);   /* read in first buffer */

	for(i=0; i<(sfchans(&sfdesc[fno]) * FLOAT); i++)
		*(peak[fno] + i) = 0;

	wipe_is_off[fno] = 1;          /* for wipeout */

	starttime[fno] = (start<0) ? -start/SR : start;

	times(&clockin[fno]);       /* read in starting time */

	return(nsamps);
}

_iaddout(out,fno)
register float *out;
{
	register int i;
	register int ipoint = pointer[fno];
	register int incr = sfchans(&sfdesc[fno]);
	register short *ibuf;

	for(i=0,ibuf = (short *)sndbuf[fno] + ipoint; i<incr; i++)  
	          *(ibuf + i) +=  *(out+i); 

	if((pointer[fno] += i) >= bufsize[fno] ) {
		_backup(fno);
		if(!peakoff[fno]) _chkpeak(fno);
		_writeit(fno);
		_readit(fno);
		pointer[fno] = 0;
	}
}

_faddout(out,fno)
register float *out;
{
	register int i;
	register int ipoint = pointer[fno];
	register int incr = sfchans(&sfdesc[fno]);
	register float *fbuf;

	for(i=0,fbuf = (float *)sndbuf[fno] + ipoint; i<incr; i++)  
		*(fbuf + i) +=  *(out+i);

	if((pointer[fno] += i) >= bufsize[fno] ) {
		_backup(fno);
		if(!peakoff[fno]) _chkpeak(fno);
		_writeit(fno);
		_readit(fno);
		pointer[fno] = 0;
	}
}

_igetin(in,fno)
register float *in;
{
	register i;
	register int ipoint = pointer[fno];
	register int incr = sfchans(&sfdesc[fno]);
	register short *ibuf;

	for(i=0,ibuf = (short *)sndbuf[fno] + ipoint; i<incr; i++)  
		*(in+i) = *(ibuf + i);

	if((pointer[fno] += i) >= bufsize[fno] ) {
		pointer[fno] = 0;
		return(_readit(fno));
	}
	return(NBYTES);
}

_fgetin(in,fno)
register float *in;
{
	register i;
	register int ipoint = pointer[fno];
	register int incr = sfchans(&sfdesc[fno]);
	register float *fbuf;

	for(i=0,fbuf = (float *)sndbuf[fno] + ipoint; i<incr; i++)  
		*(in+i) =  *(fbuf + i);

	if((pointer[fno] += i) >= bufsize[fno] ) {
		pointer[fno] = 0;
		return(_readit(fno));
	}
	return(NBYTES);
}

_ilayout(out,chlist,fno)
register float *out;
int *chlist;

{
	register i;
	register int ipoint = pointer[fno];
	register int incr = sfchans(&sfdesc[fno]);
	register short *ibuf;

	for(i=0,ibuf = (short *)sndbuf[fno] + ipoint; i<incr; i++)  
           if(chlist[i])  
	   	*(ibuf + i) = *(out+i); 

	if((pointer[fno] += i) >= bufsize[fno] ) {
		_backup(fno);
		if(!peakoff[fno]) _chkpeak(fno);
		_writeit(fno);
		_readit(fno);
		pointer[fno] = 0;
	}
}

_flayout(out,chlist,fno)
register float *out;
int *chlist;

{
	register i;
	register int ipoint = pointer[fno];
	register int incr = sfchans(&sfdesc[fno]);
	register float *fbuf;

	for(i=0,fbuf = (float *)sndbuf[fno] + ipoint; i<incr; i++)  
		if(chlist[i]) 	
			*(fbuf + i) =  *(out+i);
	
	if((pointer[fno] += i) >= bufsize[fno] ) {
		_backup(fno);
		if(!peakoff[fno]) _chkpeak(fno);
		_writeit(fno);
		_readit(fno);
		pointer[fno] = 0;
	}
}

_iwipeout(out,fno)
register float *out;
			/* to force destructive writes */ 
{
	register i;
	register int ipoint = pointer[fno];
	register int incr = sfchans(&sfdesc[fno]);
	register short *ibuf;

	for(i=0,ibuf = (short *)sndbuf[fno] + ipoint; i<incr; i++)  
	   	*(ibuf + i) = *(out+i); 
	
	if((pointer[fno] += i) >= bufsize[fno] ) {
		if(wipe_is_off[fno]) {   /*setnot positions after first read*/
			_backup(fno);
			wipe_is_off[fno] = 0;
			}
		if(!peakoff[fno])
			_chkpeak(fno);
		_writeit(fno);
		pointer[fno] = 0;
	}
}

_fwipeout(out,fno)
register float *out;
			/* to force destructive writes */ 
{
	register i;
	register int ipoint = pointer[fno];
	register int incr = sfchans(&sfdesc[fno]);
	register float *fbuf;

	for(i=0,fbuf = (float *)sndbuf[fno] + ipoint; i<incr; i++)  
		*(fbuf + i) =  *(out+i);
	
	if((pointer[fno] += i) >= bufsize[fno] ) {
		if(wipe_is_off[fno]) {   /*setnot positions after first read*/
			_backup(fno);
			wipe_is_off[fno] = 0;
			}
		if(!peakoff[fno])
			_chkpeak(fno);
		_writeit(fno);
		pointer[fno] = 0;
	}
}

bgetin(input,fno,size)
register float *input;   
{
	register int i;
	register short *ibuf;
	register float *fbuf;
	register int todo,remains;
	int n;
	int len = bufsize[fno]; 
	
refill:	todo = ((pointer[fno] + size) > len) 
				? len - pointer[fno] : size;

	if(sfclass(&sfdesc[fno]) == SHORT) 
		for(i=0,ibuf = (short *)sndbuf[fno] + pointer[fno];i<todo;i++) 
			*(input++) = (float) *(ibuf++);
	else 
		for(i=0,fbuf = (float *)sndbuf[fno] + pointer[fno];i<todo;i++) 
			*(input++) =  *(fbuf++);

	pointer[fno] += todo;

	if(pointer[fno] == len) {
		n = _readit(fno);
		pointer[fno] = 0;
		if(!n) return(n);
	}
	if(size -= todo) goto refill;
	return(i);
}
blayout(out,chlist,fno,size)
register float *out;   
register int *chlist;
{
	register int i,j;
	register short *ibuf;
	register float *fbuf;
	register int todo,remains;
	register int nchans;
	int len = bufsize[fno]; 

	nchans = sfchans(&sfdesc[fno]);

refill:	todo = ((pointer[fno] + size) > len) 
				? len - pointer[fno] : size;
	if(sfclass(&sfdesc[fno]) == SF_SHORT) {
		for(i=0,ibuf = (short *)sndbuf[fno] + pointer[fno];i<todo;
								i += nchans)
			for(j=0; j<nchans; j++,ibuf++,out++)
				if(chlist[j]) *ibuf = (short) *out;	
	}
	
	else {
		for(i=0,fbuf = (float *)sndbuf[fno] + pointer[fno];i<todo;
								i += nchans)
			for(j=0; j<nchans; j++,fbuf++,out++)
				if(chlist[j]) *fbuf = *out;
	}
	pointer[fno] += todo;

	if(pointer[fno] == len) {
		_backup(fno);
		if(!peakoff[fno])
			_chkpeak(fno);
		_writeit(fno);
		_readit(fno);
		pointer[fno] = 0;
	}

	if(size -= todo) goto refill;
}

baddout(out,fno,size)
register float *out;   
{
	register int i;
	register short *ibuf;
	register float *fbuf;
	register int todo,remains;
	int len = bufsize[fno]; 
	
refill:	todo = ((pointer[fno] + size) > len) 
				? len - pointer[fno] : size;

	if(sfclass(&sfdesc[fno]) == SHORT) 
		for(i=0,ibuf = (short *)sndbuf[fno] + pointer[fno];i<todo;i++) 
			*(ibuf++) += (short) *(out++);
	else 
		for(i=0,fbuf = (float *)sndbuf[fno] + pointer[fno];i<todo;i++) 
			*(fbuf++) += *(out++);

	pointer[fno] += todo;

	if(pointer[fno] == len) {
		_backup(fno);
		if(!peakoff[fno])
			_chkpeak(fno);
		_writeit(fno);
		_readit(fno);
		pointer[fno] = 0;
	}
	
	if(size -= todo) goto refill;
}

bwipeout(out,fno,size)
register float *out;   
{
	register int i;
	register short *ibuf;
	register float *fbuf;
	register int todo,remains;
	int len = bufsize[fno]; 
	
refill:	todo = ((pointer[fno] + size) > len) 
				? len - pointer[fno] : size;

	if(sfclass(&sfdesc[fno]) == SHORT) 
		for(i=0,ibuf = (short *)sndbuf[fno] + pointer[fno];i<todo;i++) 
			*(ibuf++) = (short)*(out++);
	else 
		for(i=0,fbuf = (float *)sndbuf[fno] + pointer[fno];i<todo;i++) 
			*(fbuf++) = *(out++);

	pointer[fno] += todo;

	if(pointer[fno] == len) {
		if(wipe_is_off[fno]) {   
			_backup(fno);
			wipe_is_off[fno] = 0;
			}
		if(!peakoff[fno])
			_chkpeak(fno);
		_writeit(fno);
		pointer[fno] = 0;
	}
	if(size -= todo) goto refill;
}

endnote(xno)
{
	struct timeval tp;	
	struct timezone tzp;	
	int i,j,final_bytes,fno;
	float notepeak,*pk;
	double total;
	long *pkloc;
	struct tms timbuf;

	fno = ABS(xno);  /* if fno is negative it means don't write
				final buffer,just pretend to */
	if(wipe_is_off[fno]) _backup(fno); 
		/* else _flushbuf(fno); */
	if(!peakoff[fno]) _chkpeak(fno);

	/* write out only fractional part of last record, god bless unix!*/
	i=0;
	if(pointer[fno]) {
		final_bytes = 
			 pointer[fno]  * sfclass(&sfdesc[fno]);
		if(xno >= 0) {
			if((i = write(sfd[fno],sndbuf[fno],final_bytes)) 
							!= final_bytes) {
				fprintf(stderr,
               		       "CMIX: Bad UNIX write, file %d, NBYTES = %ld\n",
									fno,i);
			perror("write");
			closesf();
			}
		}
		else i = final_bytes;
	}

	if((filepointer[fno] += final_bytes) > originalsize[fno]) 
		if(xno >0)  originalsize[fno] = filepointer[fno];

	pk = (float *)peak[fno];
	pkloc = (long *)peakloc[fno];
	total = ((double)filepointer[fno]-headersize[fno])
		/((double)sfclass(&sfdesc[fno]))
		/(double)sfchans(&sfdesc[fno])/SR;

	/* _writeit(fno);  /*  write out final record */

	for(i = 0,notepeak=0; i<sfchans(&sfdesc[fno]); i++) { 
		if(*(pk+i) > sfmaxamp(&sfm[fno],i)) {
			sfmaxamp(&sfm[fno],i) = *(pk+i);
			sfmaxamploc(&sfm[fno],i) = *(pkloc+i);
		}
		if(*(pk+i) > notepeak) notepeak = *(pk+i);
	}
	
	gettimeofday(&tp,&tzp);
	sfmaxamptime(&sfm[fno]) = tp.tv_sec;
		
	if((filepointer[fno] = lseek(sfd[fno],0L,0)) < 0) {
		fprintf(stderr,"Bad lseek to beginning of file\n");
		perror("lseek");
		closesf();
	}

	putsfcode(&sfdesc[fno],&sfm[fno],&ampcode);

	if(headersize[fno] == SIZEOF_BSD_HEADER) //only rewrite if bsd header
		if(wheader(sfd[fno],(char *)&sfdesc[fno])) {
			fprintf(stderr,"Bad header write\n");
			perror("write");
			closesf();
		}

	times(&timbuf);

        fprintf(stderr,"(%6.2f)",(float)(
		(timbuf.tms_stime-clockin[fno].tms_stime)+
		(timbuf.tms_utime-clockin[fno].tms_utime))/60.);
	fprintf(stderr," %9.4f .. %9.4f MM ",starttime[fno],total);
	
	if(!peakoff[fno]) {
		for(j=0;j<sfchans(&sfdesc[fno]);j++)
			fprintf(stderr," c%d=%e",j,*(pk+j));
		fprintf(stderr,"\n");
		if(punch[fno]) {
			fprintf(stderr,"alter(%e,%e,%e/%e",
			(double)starttime[fno],(double)(total-starttime[fno]),
							  punch[fno],notepeak);
			for(i=0; i<sfchans(&sfdesc[fno]); i++)
				fprintf(stderr,",1 ");
			fprintf(stderr,")\n");
			fprintf(stderr,"mix(%g,%g,%g,%g/%g",
			(double)starttime[fno],(double)starttime[fno],-(double)(total-starttime[fno]),punch[fno],notepeak);
			for(i=0; i<sfchans(&sfdesc[fno]); i++)
				fprintf(stderr,",%d ",i);
			fprintf(stderr,")\n");
		}
	}
}

_flushbuf(fno)
int fno;
{
	register i;
	for(i=pointer[fno]*sfclass(&sfdesc[fno]); i<NBYTES; i++)
		*(sndbuf[fno] + i) = 0;
}

_chkpeak(fno)
int fno;
{
	register int i,incr;
	register short *ibuf,*bufend;
	register float *fbuf,*fbufend,*pk;
	short *ibufx;
	float *fbufx;
	long *pkloc,currentloc;

	pk = (float *)peak[fno];
	incr = sfchans(&sfdesc[fno]);
	pkloc = (long *)peakloc[fno];

	if(sfclass(&sfdesc[fno]) == SHORT) {
		ibufx = ibuf = (short *)sndbuf[fno];
		bufend = ibuf + pointer[fno]; /* to allow for final check */
		currentloc = (long)
			     ((filepointer[fno]-headersize[fno])/(SHORT * incr));
		while(ibuf<bufend)  {
			for(i=0; i<incr; i++)  {
				if(ABS(*(ibuf + i)) > (int)*(pk+i)) {
					*(pk+i) = ABS(*(ibuf + i)); 
					*(pkloc+i) = currentloc + 
					  (long)((ibuf - ibufx)/incr);
				}
			}
			ibuf += incr;
		}
	}
	else	{
		fbufx = fbuf = (float *)sndbuf[fno];
		fbufend = fbuf + pointer[fno];
		currentloc = (long)
			     ((filepointer[fno]-headersize[fno])/(FLOAT * incr));
		while(fbuf<fbufend) {
			for(i=0; i<incr; i++)  {
				if(ABS(*(fbuf + i)) > *(pk+i)) {
					*(pk+i) = ABS(*(fbuf + i));
					*(pkloc+i) = currentloc +
					(long)((fbuf - fbufx)/incr);
				}
			}
		fbuf += incr;	
		} 
	} 
} 


peak_off(p,n_args)
float *p;
{
	peakoff[(int)p[0]] = (char)p[1];
	if(p[1]) fprintf(stderr,
		     "      peak check turned off for file %d\n",(int)p[0]);
		else
		 fprintf(stderr,
		     "      peak check turned on for file %d\n",(int)p[0]);
}
punch_on(p,n_args)
float *p;
{
	punch[(int)p[0]] = p[1];
	if(!p[1]) fprintf(stderr,
		     "      punch turned off for file %d\n",(int)p[0]);
		else
		 fprintf(stderr,
		     "      punch check turned on for file %d\n",(int)p[0]);
}

_readit(fno)
int fno;
{
	int n,maxread;

	/* check to see if we are attempting to read beyond current
	 * EOF, and if so adjust amount to be read and flush rest of buffer
	 */

	if(filepointer[fno] > originalsize[fno]) maxread = 0;

	else 
		if((filepointer[fno]+NBYTES) > originalsize[fno]) 
	                   maxread = originalsize[fno]-filepointer[fno];
		else
		           maxread = NBYTES;

	if((n = read(sfd[fno],sndbuf[fno],maxread)) != maxread) {
		/*if(istape[fno] && n) continue;*/
		perror("read");
		fprintf(stderr,
                	"CMIX: Bad UNIX read, NBYTES = %ld\n",n);
			printf(" sfd[fno]= %d\n",sfd[fno]);
	        closesf();
		}

	/*  if we haven't read in full buffer, zero out rest of buffer,
	 *  and adjust filepointer with lseek.  Otherwise just update 
	 *  filepointer.  This will position pointer properly for any
	 *  situation.  Only a write will change physical size of file.
	 */
	if(maxread < NBYTES) {
		for(n=maxread; n<NBYTES; n++)
			*(sndbuf[fno] + n) = 0;
		filepointer[fno] = lseek(sfd[fno],(long)(NBYTES-maxread),1);
		}               
	else
		filepointer[fno] += NBYTES;
//printf("%d %d %d %d %d\n",fno,filepointer[fno],originalsize[fno],n,maxread);
	return(maxread ? n : maxread);
}



_writeit(fno)
int fno;
{
	int n;
	if(!status[fno]) {
		fprintf(stderr,"File %d is write-protected!\n",fno);
		closesf();
	}
	if((n = write(sfd[fno],sndbuf[fno],NBYTES)) != NBYTES) {
		fprintf(stderr,
                      "CMIX: Bad UNIX write, file %d, NBYTES = %ld\n",fno,n);
		perror("write");
		closesf();
	}
	if((filepointer[fno] += NBYTES) > originalsize[fno]) 
				originalsize[fno] = filepointer[fno];
	
	return(n);
}

_backup(fno)     /* utility routine to backspace one 'record' */
{
	if((filepointer[fno] = lseek(sfd[fno],(long)-NBYTES,1)) < 0) {
		fprintf(stderr,"CMIX: bad back space in file %d\n",fno);
		perror("lseek");
		closesf();
	}
}

_forward(fno)     /* utility routine to forwardspace one 'record' */
{
//printf("%d \n",filepointer[fno]);
	if((filepointer[fno] = lseek(sfd[fno],(long)NBYTES,1)) < 0) {
		fprintf(stderr,"CMIX: bad forward space  in file %d\n",fno);
		perror("lseek");
		closesf();
	}
//printf("%d \n",filepointer[fno]);

}

closesf()
{
	int i;

	for(i = 0; i<NFILES; i++) {
		if(isopen[i]) {
			if(status[i]) 
				putlength(sfname[i],sfd[i],&sfdesc[i]);  /* for NeXT header */
			close(sfd[i]);
		}
	}
	exit(0);
}
m_clean(p,n_args)
float *p;		/* a fast clean of file, after header */
{
/* if p1-> = 0, clean whole file, else skip=p1, dur=p2, ch-on? p3--> */
	int i,todo,nwrite,n;
	char *point;
	int fno,segment,zapsize,chlist[4];
	int skipbytes;

	fno = (int) p[0];
	skipbytes = 0;
	if(!status[fno]) {
		fprintf(stderr,"fno %d is write-protected!\n",fno);
		closesf();
	}
	todo = originalsize[fno] - sizeof(SFHEADER);

	segment = (n_args > 1) ? 1 : 0;

	if(segment) {
		skipbytes = (p[1] > 0) ? p[1] * sfclass(&sfdesc[fno]) *
			    SR * sfchans(&sfdesc[fno]) 
			    : -p[1] * sfclass(&sfdesc[fno]) * 
							 sfchans(&sfdesc[fno]);
		todo =  (p[2] > 0) ? p[2] * sfclass(&sfdesc[fno]) * 
			SR * sfchans(&sfdesc[fno])
			: -p[2] * sfclass(&sfdesc[fno]) * 
						sfchans(&sfdesc[fno]);
		for(i=0; i<sfchans(&sfdesc[fno]); i++) chlist[i] = p[i+3];
	}
	point = (char *)sndbuf[fno];
	if(!segment) for(i=0; i<NBYTES; i++) *(point+i) = 0;

	if((filepointer[fno] = 
	   lseek(sfd[fno],skipbytes+headersize[fno],0)) == -1) {
		fprintf(stderr,"CMIX: bad sflseek in clean\n");
		closesf();
	}
	fprintf(stderr,"Clean %d bytes\n",todo);
	while(todo) {
		nwrite = (todo > NBYTES) ? NBYTES : todo;
		if(segment) {
			if((n = read(sfd[fno],sndbuf[fno],nwrite)) 
					== 0) { /* allow for fractional reads*/
				fprintf(stderr,
                 		"CMIX: Apparent eof in clean\n",n);
				return;
			}
			if(lseek(sfd[fno],-n,1) < 0) {
				fprintf(stderr,"Bad UNIX lseek in clean\n");
				closesf();
			}
			m_zapout(fno,sndbuf[fno],n,chlist);
			nwrite = n;
		}
		if((n = write(sfd[fno],sndbuf[fno],nwrite)) == 0) {
			fprintf(stderr,
                 	"CMIX: Apparent eof in clean\n",n);
	        	closesf();
		}
		todo -= n;
	}
	if(!segment) {
		if((lseek(sfd[fno],0,0)) == -1) {
			fprintf(stderr,"CMIX: bad lseek in clean\n");
			closesf();
		}

		for(i = 0; i<sfchans(&sfdesc[fno]); i++) { 
			sfmaxamp(&sfm[fno],i) = 0;
			sfmaxamploc(&sfm[fno],i) = 0;
		}

		putsfcode(&sfdesc[fno],&sfm[fno],&ampcode);

		if(wheader(sfd[fno],(char *)&sfdesc[fno])) {
			fprintf(stderr,"Bad header write\n");
			perror("write");
			closesf();
		}
	}
	else 
		if((lseek(sfd[fno],headersize[fno],0)) == -1) {
			fprintf(stderr,"CMIX: bad lseek in clean\n");
			closesf();
		}
	filepointer[fno] = headersize[fno];
	fprintf(stderr,"Clean successfully finished.\n");
}

m_zapout(fno,buffer,nwrite,chlist)
char *buffer;
int *chlist;
{
	float *fbuf;
	int i,j,nchunks,chans;
	short *ibuf;

	chans = sfchans(&sfdesc[fno]);

	if(sfclass(&sfdesc[fno]) == SF_SHORT) {
		ibuf = (short *) buffer;
		nchunks = nwrite/SF_SHORT;
		for(i=0; i<nchunks; i += chans)
			for(j=0; j<chans; j++)
				if(chlist[j]) *(ibuf+j+i) = 0;
	}
	else {
		fbuf = (float *) buffer;
		nchunks = nwrite/SF_FLOAT;
		for(i=0; i<nchunks; i += chans) 
			for(j=0; j<chans; j++)
				if(chlist[j]) *(fbuf+j+i) = 0;
	}
}

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