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.