ftp.nice.ch/pub/next/unix/music/cm.sd.tar.gz#/stella/merge.c

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.