ftp.nice.ch/pub/next/unix/audio/shorten.1.12.s.tar.gz#/shorten-1.12/shorten.c

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

/******************************************************************************
*                                                                             *
*       Copyright (C) 1992,1993,1994 Tony Robinson                            *
*                                                                             *
*       See the file LICENSE for conditions on distribution and usage         *
*                                                                             *
******************************************************************************/

/* SAL ---
   Inserted (unsigned long) before first argument in all calls to
   uvar_put and ulong_put.
*/

# include <math.h>
# include <stdio.h>
# include <setjmp.h>
# include <varargs.h>
# include "shorten.h"

#ifdef unix
char *readmode = "r";
char *writemode = "w";
#else
char *readmode = "rb";
char *writemode = "wb";
#endif

char	*argv0 = "shorten";
int	getc_exit_val;

# define ALPHA0 (3.0 / 2.0)
# define ALPHA1 M_LN2

/* SAL --- put (unsigned long) into macro */
# define UINT_PUT(val, nbit, file) \
  if(version == 0) uvar_put((unsigned long) val, nbit, file); \
  else ulong_put((unsigned long) val, file)

# define UINT_GET(nbit, file) \
  ((version == 0) ? uvar_get(nbit, file) : ulong_get(file))

/* SAL --- put (unsigned long) into macro */
# define VAR_PUT(val, nbit, file) \
  if(version == 0) var_put((unsigned long) val, nbit - 1, file); \
  else var_put((unsigned long) val, nbit, file)

int init_offset(offset, nchan, nblock, ftype) long **offset; int nchan,
       nblock, ftype; {
  long mean = 0;
  int  chan, i;

  /* initialise offset */
  switch(ftype) {
  case TYPE_AU:
  case TYPE_S8:
  case TYPE_S16HL:
  case TYPE_S16LH:
  case TYPE_ULAW:
    mean = 0;
    break;
  case TYPE_U8:
    mean = 0x80;
    break;
  case TYPE_U16HL:
  case TYPE_U16LH:
    mean = 0x8000;
    break;
  default:
    update_exit(1, "unknown file type: %d\n", ftype);
  }

  for(chan = 0; chan < nchan; chan++)
    for(i = 0; i < nblock; i++)
      offset[chan][i] = mean;

  return(mean);
}

int shorten(stdi, stdo, argc, argv) FILE *stdi, *stdo; int argc; char **argv; {
  long 	**buffer, *buffer1, **offset;
  long	default_offset;
  int   version = FORMAT_VERSION, extract = 0, bitshift = 0;
  int   hiloint = 1, hilo = !(*((char*) &hiloint));
  int   ftype = hilo ? TYPE_S16HL : TYPE_S16LH;
  char  *magic = MAGIC, *filenamei = NULL, *filenameo = NULL;
  char	*tmpfilename = NULL, *minusstr = "-", *filesuffix = ".shn";
  FILE  *filei, *fileo;
  int	 blocksize = DEFAULT_BLOCK_SIZE, nchan = DEFAULT_NCHAN;
  int	 i, chan, nwrap, nskip = DEFAULT_NSKIP, ndiscard = DEFAULT_NDISCARD;
  int	*qlpc = NULL, maxnlpc = DEFAULT_MAXNLPC, nmean = DEFAULT_NMEAN;
  int	maxresn = DEFAULT_MAXBITRATE, quanterror = DEFAULT_QUANTERROR;
  int	nfilename;
  extern char *hs_optarg;
  extern int   hs_optind;

  /* this block just processes the command line arguments */
  { int c;

    hs_resetopt();
    while((c = hs_getopt(argc, argv, "a:b:c:d:hm:p:q:r:t:xv:")) != -1)
      switch(c) {
      case 'a':
	if((nskip = atoi(hs_optarg)) < 0)
	  usage_exit(1, "number of bytes to copy must be positive\n");
	break;
      case 'b':
	if((blocksize = atoi(hs_optarg)) <= 0)
	  usage_exit(1, "block size must be greater than zero\n");
	break;
      case 'c':
	if((nchan = atoi(hs_optarg)) <= 0)
	  usage_exit(1, "number of channels must be greater than zero\n");
	break;
      case 'd':
	if((ndiscard = atoi(hs_optarg)) < 0)
	  usage_exit(1, "number of bytes to discard must be positive\n");
	break;
      case 'h':
	printf("%s: version %d.%s\n",argv0,FORMAT_VERSION,BUGFIX_RELEASE);
	printf("usage: %s [-hx] [-a #byte] [-b #sample] [-c #channel] [-d #discard]\n\t[-m #block] [-p #delay] [-q #bit] [-r #bit] [-t filetype]\n\t[input file] [output file]\n", argv0);
	printf("\t-a %d\tbytes to copy verbatim to align file\n",
	       DEFAULT_NSKIP);
	printf("\t-b %d\tblock size\n", DEFAULT_BLOCK_SIZE); 
	printf("\t-c %d\tnumber of channels\n", DEFAULT_NCHAN); 
	printf("\t-d %d\tbytes to discard before compression or decompression\n", DEFAULT_NDISCARD); 
	printf("\t-h\thelp (this message)\n");
	printf("\t-m %d\tnumber of past block for mean estimation\n",
	       DEFAULT_NMEAN);
	printf("\t-p %d\tmaximum LPC predictor order (0 == fast polynomial predictor)\n", DEFAULT_MAXNLPC);
	printf("\t-q %d\tacceptable quantisation error in bits\n",
	       DEFAULT_QUANTERROR);
	printf("\t-r %d\tmaximum number of coded bits per sample\n",
	       DEFAULT_MAXBITRATE);
	printf("\t-t s16\tfiletype {au,ulaw,{s,u}{8,16,16x,16hl,16lh}}\n");
	printf("\t-v %d\tformat version number\n", FORMAT_VERSION);
	printf("\t-x\textract (all other options except -d are ignored)\n");

	basic_exit(0);
	break;
      case 'm':
	if((nmean = atoi(hs_optarg)) < 0)
	  usage_exit(1,	"number of blocks for mean estimation must be positive\n");
	break;
      case 'p':
	maxnlpc = atoi(hs_optarg);
	if(maxnlpc < 0 || maxnlpc > MAX_LPC_ORDER)
	  usage_exit(1, "linear prediction order must be in the range 0 ... %d\n", MAX_LPC_ORDER);
	break;
      case 'q':
	if((quanterror = atoi(hs_optarg)) < 0)
	  usage_exit(1, "quantisation level must be positive\n");
	break;
      case 'r':
	if((maxresn = atoi(hs_optarg) - 3) < 0)
	  usage_exit(1, "expected bit rate must be >= 3\n");
	break;
      case 't':
	if     (!strcmp(hs_optarg, "au"))   ftype = TYPE_AU;
	else if(!strcmp(hs_optarg, "s8"))   ftype = TYPE_S8;
	else if(!strcmp(hs_optarg, "u8"))   ftype = TYPE_U8;
	else if(!strcmp(hs_optarg, "s16"))  ftype = hilo?TYPE_S16HL:TYPE_S16LH;
	else if(!strcmp(hs_optarg, "u16"))  ftype = hilo?TYPE_U16HL:TYPE_U16LH;
	else if(!strcmp(hs_optarg, "s16x")) ftype = hilo?TYPE_S16LH:TYPE_S16HL;
	else if(!strcmp(hs_optarg, "u16x")) ftype = hilo?TYPE_U16LH:TYPE_U16HL;
	else if(!strcmp(hs_optarg, "s16hl"))ftype = TYPE_S16HL;
	else if(!strcmp(hs_optarg, "u16hl"))ftype = TYPE_U16HL;
	else if(!strcmp(hs_optarg, "s16lh"))ftype = TYPE_S16LH;
	else if(!strcmp(hs_optarg, "u16lh"))ftype = TYPE_U16LH;
	else if(!strcmp(hs_optarg, "ulaw")) ftype = TYPE_ULAW;
	else usage_exit(1, "unknown file type: %s\n", hs_optarg);
	break;
      case 'v':
	version = atoi(hs_optarg);
	if(version < 0 || version > FORMAT_VERSION)
	  usage_exit(1, "currently supported versions are in the range 0 ... %d\n", FORMAT_VERSION);
	break;
      case 'x':
	extract = 1;
	break;
      default:
	usage_exit(1, "unknown option: -%c\n", c);
	break;
      }
  }

  if(maxnlpc >= blocksize)
    usage_exit(1, "the predictor order must be less than the block size\n");

  if(ftype == TYPE_AU && (maxresn != DEFAULT_MAXBITRATE || quanterror !=
			  DEFAULT_QUANTERROR))
    usage_exit(1, "lossy compression currently not supported for file type au\n");

  if(nmean != 0 && (maxresn != DEFAULT_MAXBITRATE || quanterror !=
		   DEFAULT_QUANTERROR))
    usage_exit(1, "mean estimation currently not supported for lossy compression\n");

  /* this chunk just sets up the input and output files */
  nfilename = argc - hs_optind;
  switch(nfilename) {
  case 0:
    filenamei = minusstr;
    filenameo = minusstr;
    break;
  case 1: {
    int oldfilelen, suffixlen, maxlen;

    filenamei  = argv[argc - 1];
    oldfilelen = strlen(filenamei);
    suffixlen  = strlen(filesuffix);
    maxlen     = oldfilelen + suffixlen;
    tmpfilename = pmalloc((ulong) (maxlen + 1));
    strcpy(tmpfilename, filenamei);
    
    if(extract) {
      int newfilelen = oldfilelen - suffixlen;
      if(strcmp(filenamei + newfilelen, filesuffix))
	usage_exit(1,"file name does not end in %s: %s\n", filesuffix,
		   filenamei);
      tmpfilename[newfilelen] = '\0';
    }
    else
      strcat(tmpfilename, filesuffix);

    filenameo = tmpfilename;
    break;
  }
  case 2:
    filenamei = argv[argc - 2];
    filenameo = argv[argc - 1];
    break;
  default:
    usage_exit(1, NULL);
  }

  if(strcmp(filenamei, minusstr)) {
    if((filei = fopen(filenamei, readmode)) == NULL)
      perror_exit("fopen(\"%s\", \"%s\")", filenamei, readmode);
  }	
  else filei = stdi;

  if(strcmp(filenameo, minusstr)) {
    if((fileo = fopen(filenameo, writemode)) == NULL)
      perror_exit("fopen(\"%s\", \"%s\")", filenameo, writemode);
  }
  else fileo = stdo;

  /* discard header on input file - can't rely on fseek() here */
  if(ndiscard != 0) {
    char discardbuf[BUFSIZ];

    for(i = 0; i < ndiscard / BUFSIZ; i++)
      if(fread(discardbuf, BUFSIZ, 1, filei) != 1)
	usage_exit(1, "EOF on input when discarding header\n");

    if(ndiscard % BUFSIZ != 0)
      if(fread(discardbuf, ndiscard % BUFSIZ, 1, filei) != 1)
	usage_exit(1, "EOF on input when discarding header\n");
  }

  if(!extract) {
    float alpha;
    int nread, nscan = 0;

    nwrap = MAX(NWRAP, maxnlpc);

    /* grab some space for the input buffers */
    buffer  = long2d((ulong) nchan, (ulong) (blocksize + nwrap));
    buffer1 = (long*) pmalloc((ulong) (blocksize * sizeof(*buffer1)));
    offset  = long2d((ulong) nchan, (ulong) nmean);
    
    for(chan = 0; chan < nchan; chan++) {
      for(i = 0; i < nwrap; i++) buffer[chan][i] = 0;
      buffer[chan] += nwrap;
    }

    if(maxnlpc > 0)
      qlpc = (int*) pmalloc((ulong) (maxnlpc * sizeof(*qlpc)));
    
    default_offset = init_offset(offset, nchan, nmean, ftype);
    
    /* verbatim copy of skip bytes from input to output checking for the
       existence of magic number in header, and defaulting to internal storage
       if that happens */
    if(version >= 2) {
      while(nskip - nscan > 0 && magic[nscan] != '\0') {
	int byte = getc_exit(filei);
	if(byte == magic[nscan]) nscan++;
	else {
	  for(i = 0; i < nscan; i++)
	    putc_exit(magic[i], fileo);
	  if(byte == magic[0]) {
	    nskip -= nscan;
	    nscan = 1;
	  }
	  else {
	    putc_exit(byte, fileo);
	    nskip -= nscan + 1;
	    nscan = 0;
	  }
	}
      }
      if(magic[nscan] != '\0') {
	for(i = 0; i < nscan; i++)
	  putc_exit(magic[i], fileo);
	nskip -= nscan;
	nscan = 0;
      }
    }

    /* write magic number */
    if(fwrite(magic, strlen(magic), 1, fileo) != 1)
      usage_exit(1, "could not write the magic number\n");

    /* write version number */
    putc_exit(version, fileo);

    /* initialise the fixed length file read for the uncompressed stream */
    fread_type_init();

    /* initialise the variable length file write for the compressed stream */
    var_put_init(fileo);

    /* put file type and number of channels */
    UINT_PUT(ftype, TYPESIZE, fileo);
    UINT_PUT(nchan, CHANSIZE, fileo);

    /* put blocksize if version > 0 */
    if(version == 0) {
      alpha = ALPHA0;
      if(blocksize != DEFAULT_BLOCK_SIZE) {
	uvar_put((ulong) FN_BLOCKSIZE, FNSIZE, fileo);
	UINT_PUT(blocksize, (int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),
		 fileo);
      }
    }
    else {
      alpha = ALPHA1;
      UINT_PUT(blocksize, (int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),
	       fileo);
      UINT_PUT(maxnlpc, LPCQSIZE, fileo);
      UINT_PUT(nmean, 0, fileo);
      UINT_PUT(nskip, NSKIPSIZE, fileo);
      for(i = 0; i < nscan; i++)
	uvar_put((ulong) magic[i], XBYTESIZE, fileo);
      for(i = 0; i < nskip - nscan; i++) {
	int byte = getc_exit(filei);
	uvar_put((ulong) byte, XBYTESIZE, fileo);
      }
    }

    while((nread = fread_type(buffer, ftype, nchan, blocksize, filei)) != 0) {
      /* put blocksize if changed */
      if(nread != blocksize) {
	uvar_put((ulong) FN_BLOCKSIZE, FNSIZE, fileo);
	UINT_PUT(nread, (int) (log((double) blocksize) / M_LN2), fileo);
	blocksize = nread;
      }

      for(chan = 0; chan < nchan; chan++) {
	long coffset, *cbuffer = buffer[chan];
	long sum, fnd;
	int  resn, nlpc, newbitshift;

	/* force the lower quanterror bits to be zero */
	if(quanterror != 0) {
	  int offset = (1 << (quanterror - 1));
	  for(i = 0; i < blocksize; i++)
	    cbuffer[i] = (cbuffer[i] + offset) >> quanterror;
	}
	
	/* test for excessive and exploitable quantisation, and exploit!! */
	newbitshift = find_bitshift(cbuffer, blocksize, ftype) + quanterror;
	if(newbitshift > NBITPERLONG) newbitshift = NBITPERLONG;
	  
	/* deduct mean if appropriate */
	if(nmean == 0) coffset = default_offset;
	else {
	  sum = 0;
	  for(i = 0; i < nmean; i++) sum += offset[chan][i];
	  coffset = sum / nmean;
	  
	  sum = 0;
	  for(i = 0; i < blocksize; i++)
	    sum += cbuffer[i];

	  for(i = 1; i < nmean; i++)
	    offset[chan][i - 1] = offset[chan][i];
	  offset[chan][nmean - 1] = sum / blocksize;
	}
	if(coffset != 0)
	  for(i = -nwrap; i < blocksize; i++)
	    cbuffer[i] -= coffset;

	/* find the best model */
	if(newbitshift == NBITPERLONG && version >= 2) {
	  fnd = FN_ZERO;
	}
	else if(maxnlpc == 0) {
	  long sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, last0, last1, last2;

	  last2 = (last1 = (last0 = cbuffer[-1]) - cbuffer[-2]) - (cbuffer[-2]
								 -cbuffer[-3]);
	  for(i = 0; i < blocksize; i++) {
	    long diff0, diff1, diff2, diff3;

	    sum0 += abs(diff0 = cbuffer[i]);
	    sum1 += abs(diff1 = diff0 - last0);
	    sum2 += abs(diff2 = diff1 - last1);
	    sum3 += abs(diff3 = diff2 - last2);

	    last0 = diff0;
	    last1 = diff1;
	    last2 = diff2;
	  }

	  if(sum0 < MIN(MIN(sum1, sum2), sum3)) {
	    sum = sum0;
	    fnd = FN_DIFF0;
	  }
	  else if(sum1 < MIN(sum2, sum3)) {
	    sum = sum1;
	    fnd = FN_DIFF1;
	  }
	  else if(sum2 < sum3) {
	    sum = sum2;
	    fnd = FN_DIFF2;
	  }
	  else {
	    sum = sum3;
	    fnd = FN_DIFF3;
	  }

	  if(alpha * sum < blocksize) resn = 0;
	  else resn = floor(log(alpha * sum / (double) blocksize)/M_LN2 + 0.5);
	}
	else
	  nlpc = wav2lpc(cbuffer, blocksize, qlpc, maxnlpc, &resn);

	if(resn > maxresn) {
	  int extrabitshift = resn - maxresn;
	  int offset = (1 << (extrabitshift - 1));
	  for(i = 0; i < blocksize; i++)
	    cbuffer[i] = (cbuffer[i] + offset) >> extrabitshift;
	  resn = maxresn;
	  newbitshift += extrabitshift;
	}

	if(newbitshift != bitshift) {
	  uvar_put((ulong) FN_BITSHIFT, FNSIZE, fileo);
	  uvar_put((ulong) newbitshift, BITSHIFTSIZE, fileo);
	  bitshift = newbitshift;
	}

	if(newbitshift == NBITPERLONG && version >= 2) {
	  uvar_put(fnd, FNSIZE, fileo);
	}
	else if(maxnlpc == 0) {
	  uvar_put(fnd, FNSIZE, fileo);
	  uvar_put((ulong) resn, ENERGYSIZE, fileo);
	  
	  switch(fnd) {
	  case FN_DIFF0:
	    for(i = 0; i < blocksize; i++)
	      VAR_PUT(cbuffer[i], resn, fileo);
	    break;
	  case FN_DIFF1:
	    for(i = 0; i < blocksize; i++)
	      VAR_PUT(cbuffer[i] - cbuffer[i - 1], resn, fileo);
	    break;
	  case FN_DIFF2:
	    for(i = 0; i < blocksize; i++)
	      VAR_PUT(cbuffer[i] - 2 * cbuffer[i - 1] + cbuffer[i - 2],
		      resn, fileo);
	    break;
	  case FN_DIFF3:
	    for(i = 0; i < blocksize; i++)
	      VAR_PUT(cbuffer[i] - 3 * (cbuffer[i - 1] - cbuffer[i - 2]) -
		      cbuffer[i - 3], resn, fileo);
	    break;
	  }

#ifdef DEBUG_STATS_FOR_ICASSP_PAPER
	  /* print stats */
	  if(resn == 2)
	    switch(fnd) {
	    case FN_DIFF0:
	      for(i = 0; i < blocksize; i++)
		printf("%d\n", cbuffer[i]);
	      break;
	    case FN_DIFF1:
	      for(i = 0; i < blocksize; i++)
		printf("%d\n", (cbuffer[i] - cbuffer[i - 1]));
	      break;
	    case FN_DIFF2:
	      for(i = 0; i < blocksize; i++)
		printf("%d\n", (cbuffer[i] - 2 * cbuffer[i - 1] + cbuffer[i - 2]));
	      break;
	    case FN_DIFF3:
	      for(i = 0; i < blocksize; i++)
		printf("%d\n", (cbuffer[i] - 3 * cbuffer[i - 1] + 3 * cbuffer[i - 2] - cbuffer[i - 3]));
	      break;
	    }
#endif /* DEBUG_STATS */
	}
	else {
	  uvar_put((ulong) FN_QLPC, FNSIZE, fileo);
	  uvar_put((ulong) resn, ENERGYSIZE, fileo);
	  uvar_put((ulong) nlpc, LPCQSIZE, fileo);
	  for(i = 0; i < nlpc; i++)
	    var_put((long) qlpc[i], LPCQUANT, fileo);

	  /* use the quantised LPC coefficients to generate the residual */
	  for(i = 0; i < blocksize; i++) {
	    int j;
	    long sum = 0;

	    for(j = 0; j < nlpc; j++)
	      sum += qlpc[j] * cbuffer[i - j - 1];
	    var_put(cbuffer[i] - (sum >> LPCQUANT), resn, fileo);
/*ICASSP  printf("%f\n", (float) (cbuffer[i] - (sum >> LPCQUANT)) / ( 1 << resn)); */
	  }
	}
	
	/* do the wrap */
	for(i = -nwrap; i < 0; i++)
	  cbuffer[i] = cbuffer[i + blocksize] + coffset;
      }
    }

    /* wind up */
    fread_type_quit();
    uvar_put((ulong) FN_QUIT, FNSIZE, fileo);
    var_put_quit(fileo);

    /* and free the space used */
    free((char*) buffer);
    free((char*) buffer1);
    free((char*) offset);
    if(maxnlpc > 0)
      free((char*) qlpc);
  }
  else {
    /***********************/
    /* EXTRACT starts here */
    /***********************/

    int i, cmd;

    /* read magic number */
    if(FORMAT_VERSION < 2) {
      for(i = 0; i < strlen(magic); i++)
	if(getc_exit(filei) != magic[i])
	  usage_exit(1, "Bad magic number\n");
    }
    else {
      int nscan = 0;
      
      while(magic[nscan] != '\0') {
	int byte = getc(filei);
	if(byte == EOF)
	  usage_exit(1, "No magic number\n");
	if(byte == magic[nscan]) nscan++;
	else {
	  for(i = 0; i < nscan; i++) putc_exit(magic[i], fileo);
	  if(byte == magic[0]) nscan = 1;
	  else {
	    putc_exit(byte, fileo);
	    nscan = 0;
	  }
	}
      }
    }

    /* get and check version number */
    version = getc_exit(filei);
    if(version > FORMAT_VERSION)
      update_exit(1, "can't decode version %d\n", version);

    /* initialise the variable length file read for the compressed stream */
    var_get_init(filei);

    /* initialise the fixed length file write for the uncompressed stream */
    fwrite_type_init();

    /* get file type and set up appropriately, ignoring command line state */
    ftype = UINT_GET(TYPESIZE, filei);
    if(ftype >= TYPE_EOF)
      update_exit(1, "can't decode file type %d\n", ftype);

    nchan = UINT_GET(CHANSIZE, filei);

    /* get blocksize if version > 0 */
    if(version > 0) {
      blocksize = UINT_GET((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),
			   filei);
      maxnlpc = UINT_GET(LPCQSIZE, filei);
      nmean = UINT_GET(0, fileo);
      nskip = UINT_GET(NSKIPSIZE, filei);
      for(i = 0; i < nskip; i++) {
	int byte = uvar_get(XBYTESIZE, filei);
	putc_exit(byte, fileo);
      }
    }
    else
      blocksize = DEFAULT_BLOCK_SIZE;
    nwrap = MAX(NWRAP, maxnlpc);

    /* grab some space for the input buffer */
    buffer  = long2d((ulong) nchan, (ulong) (blocksize + nwrap));
    offset  = long2d((ulong) nchan, (ulong) nmean);

    for(chan = 0; chan < nchan; chan++) {
      for(i = 0; i < nwrap; i++) buffer[chan][i] = 0;
      buffer[chan] += nwrap;
    }

    if(maxnlpc > 0)
      qlpc = (int*) pmalloc((ulong) (maxnlpc * sizeof(*qlpc)));
    
    default_offset = init_offset(offset, nchan, nmean, ftype);

    /* get commands from file and execute them */
    chan = 0;
    while((cmd = uvar_get(FNSIZE, filei)) != FN_QUIT)
      switch(cmd) {
      case FN_ZERO:
      case FN_DIFF0:
      case FN_DIFF1:
      case FN_DIFF2:
      case FN_DIFF3:
      case FN_QLPC:
  	{ long coffset, *cbuffer = buffer[chan];
	  int resn, nlpc, j;
		  
	  if(cmd != FN_ZERO) {
	    resn = uvar_get(ENERGYSIZE, filei);
	    /* this is a hack as version 0 differed in definition of var_get */
	    if(version == 0) resn--;
	  }

	  /* find offset */
	  if(nmean == 0) coffset = default_offset;
	  else {
	    long sum = 0;
	    for(i = 0; i < nmean; i++) sum += offset[chan][i];
	    coffset = sum / nmean;
	  }
	  
	  switch(cmd) {
	  case FN_ZERO:
	    for(i = 0; i < blocksize; i++)
	      cbuffer[i] = 0;
	    break;
	  case FN_DIFF0:
	    for(i = 0; i < blocksize; i++)
	      cbuffer[i] = var_get(resn, filei) + coffset;
	    break;
	  case FN_DIFF1:
	    for(i = 0; i < blocksize; i++)
	      cbuffer[i] = var_get(resn, filei) + cbuffer[i - 1];
	    break;
	  case FN_DIFF2:
	    for(i = 0; i < blocksize; i++)
	      cbuffer[i] = var_get(resn, filei) + (2 * cbuffer[i - 1] -
						   cbuffer[i - 2]);
	    break;
	  case FN_DIFF3:
	    for(i = 0; i < blocksize; i++)
	      cbuffer[i] = var_get(resn, filei) + 3 * (cbuffer[i - 1] -
					     cbuffer[i - 2]) + cbuffer[i - 3];
	    break;
	   case FN_QLPC:
	    nlpc = uvar_get(LPCQSIZE, filei);
	    for(i = 0; i < nlpc; i++)
	      qlpc[i] = var_get(LPCQUANT, filei);
	    for(i = 0; i < nlpc; i++)
	      cbuffer[i - nlpc] -= coffset;
	    for(i = 0; i < blocksize; i++) {
	      long sum = 0;
	      for(j = 0; j < nlpc; j++)
		sum += qlpc[j] * cbuffer[i - j - 1];
	      cbuffer[i] = var_get(resn, filei) + (sum >> LPCQUANT);
	    }
	    if(coffset != 0)
	      for(i = 0; i < blocksize; i++)
		cbuffer[i] += coffset;
	    break;
	  }

	  /* store mean value if appropriate */
	  if(nmean > 0) {
	    long sum = 0;

	    for(i = 1; i < nmean; i++)
	      offset[chan][i - 1] = offset[chan][i];
	  
	    for(i = 0; i < blocksize; i++)
	      sum += cbuffer[i];

	    offset[chan][nmean - 1] = sum / blocksize;
	  }

	  /* do the wrap */
	  for(i = -nwrap; i < 0; i++) cbuffer[i] = cbuffer[i + blocksize];

	  fix_bitshift(cbuffer, blocksize, bitshift, ftype);
	  
	  if(chan == nchan - 1)
	    fwrite_type(buffer, ftype, nchan, blocksize, fileo);
	  chan = (chan + 1) % nchan;
	}
	break;
      case FN_BLOCKSIZE:
	blocksize = UINT_GET((int) (log((double) blocksize) / M_LN2), filei);
	break;
      case FN_BITSHIFT:
	bitshift = uvar_get(BITSHIFTSIZE, filei);
	break;
      default:
	update_exit(1, "sanity check fails trying to decode function: %d\n",
		    cmd);
      }
    
    /* wind up */
    var_get_quit(filei);
    fwrite_type_quit();

    free((char*) buffer);
    free((char*) offset);
    if(maxnlpc > 0)
      free((char*) qlpc);
  }    

  /* close the files */
  if(filei != stdi) fclose(filei);
  if(fileo != stdo) fclose(fileo);
     
  /* make the compressed file look like the original if possible */
  if((filei != stdi) && (fileo != stdo))
    (void) dupfileinfo(filenamei, filenameo);

  if(nfilename == 1)
    if(unlink(filenamei))
      perror_exit("unlink(\"%s\")", filenamei);

  if(tmpfilename != NULL)
    free(tmpfilename);
  
  /* quit happy */   
  return(0);
}

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