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

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

#include <stdio.h>
#include <sys/file.h>
#include "../H/sfheader.h"

/* Find location in header for the coded information. 
   Return a pointer to the beginning of the SFCODE structure not
   to the information structure itself. The srate, number of channels, magic
   number, number of bytes per channel are NOT coded via these routines. */

char *getsfcode(hd,code)
	SFHEADER *hd;
{
	register char *sfc;
	register SFCODE *sp;
	char *hdend = (char *) hd + sizeof(SFHEADER);

	sfc = &sfcodes(hd); 
	while(sfc < hdend) {
		sp = (SFCODE *) sfc;
		if(sp->code == code)
			return(sfc);
		if(sp->code == SF_END)
			break;
		/* Catch possible wrap around on stack from bad header */
		/* or a zero struct size from bad header */
		if(sp->bsize == 0 || sfc + sp->bsize < &sfcodes(hd))
			break;
		else
			sfc += sp->bsize;
	}
	return(NULL);
}

SFCODE endcode = {
	SF_END,
	sizeof(SFCODE)
} ;

putsfcode(hd,ptr,codeptr)
	SFHEADER *hd;
	char *ptr;
	SFCODE *codeptr;
{
	register char *sfc;
	register SFCODE *sp;
	int wasendcode = 0;
	char *hdend = (char *) hd + sizeof(SFHEADER);

	sfc = &sfcodes(hd); 
	while(sfc < hdend) {
		sp = (SFCODE *) sfc;
		if(sp->code == codeptr->code)
			break;
		if(sp->code == SF_END) {
			wasendcode = 1;
			break;
		}
		/* Catch possible wrap around on stack from bad header */
		if(sp->bsize == 0 || sfc + sp->bsize < (char *) hd) 
			sp->code = SF_END; /* Force an end */
		else
			sfc += sp->bsize;
	}
	
	/* No space left */
	if(sfc + codeptr->bsize > hdend)
		return(-1);

	if(!wasendcode)  /* Not a new one */
		if(codeptr->bsize != sp->bsize) /* Size changed */
			return(-1);

	bcopy((char *) codeptr, sfc, sizeof(SFCODE));
	bcopy(ptr, sfc + sizeof(SFCODE), codeptr->bsize - sizeof(SFCODE));

	if(wasendcode) 
		bcopy(&endcode,sfc + codeptr->bsize,sizeof(endcode));

	return(0);
}

#if defined(NeXT) || defined(NEXT)

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

int
readHeader(sf,header)
SFHEADER *header;
int sf;
{
        int i;
	SFMAXAMP sfmnew;
        char *pointer;
        /* read in 1kb first, to see if hybrid header is present */
        if((i=read(sf,(char *) header,SIZEOF_BSD_HEADER)) != SIZEOF_BSD_HEADER)
                return 1;
        /* if file has IRCAM-style header */
        if((header)->sfinfo.NeXTheader.magic == SF_MAGIC)
                return(readIrcamHeader(header));
        /* if magic number is neither IRCAM nor local, we cant read it */
	/* in case it is byte-swapped, give a message saying so */
        if((header)->sfinfo.NeXTheader.magic == 1688404224) {
		fprintf(stderr, "This file must be byte-swapped before using!\n");
		return 1;
	}
        if((header)->sfinfo.NeXTheader.magic != SND_MAGIC)
                return 1;
        /* if hybrid header is there, we are done here */
        if((header)->sfinfo.sf_magic == SF_MAGIC) 
		return 0;

        /* else, if file being read is native NeXT soundfile... */

	/* zero out new header after NeXT portion */
	pointer = (char *)header;
	for(i=29; i<SIZEOF_BSD_HEADER; i++) *(pointer+i) = 0;
        /* set file pointer to beginning of sound data */
        if(lseek(sf, (long) header->sfinfo.NeXTheader.dataLocation, L_SET) < 0) {
                fprintf(stderr, "Unable to reset file pointer.\n");
                return 1;
        }
        /* load all values from native header into hybrid header */
        (header)->sfinfo.sf_magic = 0; /* so we know it is native NeXT file */
        (header)->sfinfo.sf_srate = (header)->sfinfo.NeXTheader.samplingRate;
        (header)->sfinfo.sf_chans = (header)->sfinfo.NeXTheader.channelCount;
        switch(header->sfinfo.NeXTheader.dataFormat) {
        case SND_FORMAT_FLOAT:
                (header)->sfinfo.sf_packmode = SF_FLOAT;
                break;
        case SND_FORMAT_LINEAR_16:
                (header)->sfinfo.sf_packmode = SF_SHORT;
                break;
        default:
                fprintf(stderr, "Cmix can only read float and short files.\n");
                return 1;
        }
	for(i=0; i<2 /*(header)->sfinfo.sf_chans*/; i++) {
			sfmaxamp(&sfmnew,i)=0;
			sfmaxamploc(&sfmnew,i)=0;
		}
		sfmaxamptime(&sfmnew) = 0;
		putsfcode(header,&sfmnew,&ampcode);
        return 0;
}

int
readIrcamHeader(hd)
        SFHEADER *hd;
{
        char *ptr = (char *) hd;
	int i;
	SFMAXAMP sfmnew;
        /* copy everything in header (minus a small chunk) to the location
           in the header it needs to be in a hybrid header.  We loose 28 chars
           from the end of the comment, but who uses that much comment?  */
        bcopy(ptr, ptr + SIZEOF_NeXT_HEADER,
                sizeof(SFHEADER) - SIZEOF_NeXT_HEADER);
        /* and then zero out beginning and set the new magic number */
        bzero(ptr, SIZEOF_NeXT_HEADER);
	/* if no amp code in header, put one */
	if(getsfcode(hd, SF_MAXAMP) == NULL) {
		for(i=0; i<2; i++) {
			sfmaxamp(&sfmnew,i)=0;
			sfmaxamploc(&sfmnew,i)=0;
		}
		sfmaxamptime(&sfmnew) = 0;
		putsfcode(hd,&sfmnew,&ampcode);
	}
	/* set the magic number at the beginning to be the IRCAM magic number,
	   to signal that this should be written back out as such.	*/
        hd->sfinfo.NeXTheader.magic = SF_MAGIC;
        return 0;
}

writeHeader(sf,header)	/* writes out whatever type of header was read in */
SFHEADER  *header;
int sf;
{
	int headersize, dataloc, bytes;
	static char blank[SIZEOF_NeXT_HEADER];
	switch((header)->sfinfo.NeXTheader.magic) {
	case SND_MAGIC:		/* native or hybrid NeXT soundfile */
		if((header)->sfinfo.sf_packmode == SF_FLOAT)
			(header)->sfinfo.NeXTheader.dataFormat =
				SND_FORMAT_FLOAT;
		else (header)->sfinfo.NeXTheader.dataFormat =
			SND_FORMAT_LINEAR_16;
		(header)->sfinfo.NeXTheader.samplingRate =
			(header)->sfinfo.sf_srate;
		(header)->sfinfo.NeXTheader.channelCount =
			(header)->sfinfo.sf_chans;
		if((header)->sfinfo.sf_magic == 0) {	/* Native */
			dataloc = SIZEOF_NeXT_HEADER;
			headersize = SIZEOF_NeXT_HEADER; 
		}
		else {					/* Hybrid */
			dataloc = SIZEOF_BSD_HEADER;
			headersize = SIZEOF_BSD_HEADER; 
		}
		(header)->sfinfo.NeXTheader.dataLocation = dataloc;
		if((bytes=write(sf,header,headersize)) != headersize)
			return 1;
		else return 0;
		break;
	case SF_MAGIC:		/* IRCAM style soundfile */
		/* try to write out 1 Kbyte starting right after NeXT header */
		headersize = sizeof(SFHEADER) - SIZEOF_NeXT_HEADER;
		if((bytes=write(sf,(char *) header + SIZEOF_NeXT_HEADER, headersize)) != headersize)
			return 1;
		/* this fills in the last 28 bytes */
		if((bytes=write(sf, blank, SIZEOF_NeXT_HEADER)) != SIZEOF_NeXT_HEADER)
			return 1;
		else return 0;
		break;
	default:
		fprintf(stderr, "Unknown magic number: %d\n",
			(header)->sfinfo.NeXTheader.magic);
		return 1;
		break;
	}
}
#endif /* NeXT */

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