This is merge.c in view mode; [Download] [Up]
/* merge sound files -- this is equivalent to a very simple add-sound call */ /* the assumption here is that we're being called from open-input and can */ /* take advantage of the fact that the two files are the compatible and no */ /* processing at all is going on. We get the main file, the start point */ /* in that file, the number of samples to merge, and the merged-in file. */ /* This all takes place when all other files are assumed to be closed. */ /* On the 68040 it can read/merge/write about .5 million samples per second */ #include <stdio.h> #include <fcntl.h> #define MERGEBUFLIM 64*1024 static char *mergebuf,*mainbuf; static int mergebuf_ok = -1; check_mergebuf(void) { if (mergebuf_ok == -1) { mergebuf = (char *)calloc((MERGEBUFLIM),sizeof(char)); mainbuf = (char *)calloc((MERGEBUFLIM),sizeof(char)); } mergebuf_ok = 0; } int soundmerge(char *mainfile, int main_byte_location, int samples, char *mergefile, int merge_byte_location) { /* main_byte_location should be the actual byte location in the main file where we start merging. */ /* For NeXT sound files, this needs to take into account the header length and so on */ /* Similarly for merge_byte_location. Samples is the number of 16-bit integers to merge. */ int mainfd,mergefd; char *i,*j; int k,maini,mergei,bytes,rtn_main,rtn_merge,num,lim,n,bufnum,left,curloc,curbytes; if ((mainfd=open(mainfile,O_RDWR,0))==-1) return(-1); lseek(mainfd,main_byte_location,0); if ((mergefd=open(mergefile,O_RDONLY,0))==-1) return(-2); lseek(mergefd,merge_byte_location,0); check_mergebuf(); /* now loop through both files, reading a bufferfull, merging and writing it back out */ bufnum = (MERGEBUFLIM); lim=samples*2; left=lim; curloc=main_byte_location; for (n=0;n<lim;n+=bufnum) { if (left<bufnum) curbytes=left; else curbytes=bufnum; rtn_merge=read(mergefd,mergebuf,curbytes); rtn_main=read(mainfd,mainbuf,curbytes); if (rtn_merge<rtn_main) bytes=rtn_merge; else bytes=rtn_main; for (i=mainbuf,j=mergebuf,k=0;k<bytes;k+=2,i+=2,j+=2) { maini = ( (((*i)<<8)&0xff00) | ((*(i+1))&0xff)); if (maini & 0x8000) maini |= 0xffff0000; mergei = ( (((*j)<<8)&0xff00) | ((*(j+1))&0xff)); if (mergei & 0x8000) mergei |= 0xffff0000; maini += mergei; /* to scale the merged-in file, you could do the multiply here (we're in 32-bit integer land here) */ /* For example, scale the fractional scaler by 2**16, maini += ((mergei*scaler)>>16 (with sign confusion)) */ /* scale factors that are powers of two can be folded in at no cost, of course */ *(i+1)=(maini & 0xff); *i=((maini >> 8) & 0xff); } if (rtn_main<rtn_merge) { for (i=mainbuf+bytes,j=mergebuf+bytes,k=bytes;k<rtn_merge;k++,j++,i++) *i = *j; } lseek(mainfd,curloc,0); write(mainfd,mainbuf,rtn_merge); curloc += rtn_merge; left -= bufnum; } return 0; } /* now tie that into sound.lisp in a slightly more user-friendly way */ /* Here we take care of channels, header lengths */ /* All files better be linear 16 bit format */ int mixsound(char *mainfile, int main_sample, char *mergefile, int merge_sample, int samples) { /* first srates/channels have to be compatible (who to believe if not?) */ int mainfd,mergefd,maindataloc,mergedataloc,chans,datasize,mainloc,mergeloc; char *i,*j; if ((mainfd=open(mainfile,O_RDWR,0))==-1) return(-1); if ((mergefd=open(mergefile,O_RDONLY,0))==-1) return(-2); check_mergebuf(); read(mainfd,mainbuf,24); read(mergefd,mergebuf,24); i=mainbuf+4; j=mergebuf+4; maindataloc=((*i)<<24)+((*(i+1))<<16)+((*(i+2)<<8))+(*(i+3)); mergedataloc=((*j)<<24)+((*(j+1))<<16)+((*(j+2)<<8))+(*(j+3)); i=mainbuf+20; chans=((*i)<<24)+((*(i+1))<<16)+((*(i+2)<<8))+(*(i+3)); i=mainbuf+8; datasize=((*i)<<24)+((*(i+1))<<16)+((*(i+2)<<8))+(*(i+3)); mainloc=maindataloc+(chans*main_sample); mergeloc=mergedataloc+(chans*merge_sample); soundmerge(mainfile,mainloc,(chans*samples),mergefile,mergeloc); if ((mainloc+(chans*samples*2))>datasize) { datasize=mainloc+(chans*samples*2); read(mainfd,mainbuf,12); i=mainbuf+8; *i=((datasize>>24) & 0xff); *(i+1)=((datasize>>16) & 0xff); *(i+2)=((datasize>>8) & 0xff); *(i+3)=(datasize & 0xff); write(mainfd,mainbuf,12); } return 0; } /* this needs to be merged into kcl-clm-c.lisp, all.lisp */ /* (ff:defforeign 'c-merge-sounds :entry-point "_soundmerge" :arguments '(string fixnum fixnum string fixnum) :return-type :integer) */ /* (ff:defforeign 'c-mix-sound :entry-point "_mixsound" :arguments '(string fixnum string fixnum fixnum) :return-type :integer) */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.