#include <stdio.h>
#include <math.h>
#ifdef AMIGA
#include <exec/types.h>
#else
typedef long LONG;
typedef unsigned long  ULONG;
typedef unsigned char  UBYTE;
typedef unsigned short UWORD;
#endif

#define MAGIC		0x2e736e64
#define LINEAR_16	3

#define Unity 0x10000L

typedef LONG Fixed;
typedef struct {
  ULONG oneShotHiSamples,
    repeatHiSamples,
    samplesPerHiCycle;
  UWORD samplesPerSec;
  UBYTE ctOctave,
	sCompression;
  Fixed volume;
} Voice8Header;

main(int argc, char *argv[])
{
  Voice8Header v;
  long i, nsamples, voffset, lengthoffset, nsamplesoffset;
  int magic, offset, size, format, rate, nchannels;
  unsigned short s16;
  FILE *in, *out;
  unsigned char s8;

  if (argc != 3) {
    fprintf(stderr, "Usage: %s sndfile 8svxfile\n", argv[0]);
    exit(1);
  }
  in = fopen(argv[1], "r");
  if (!in) {
    fprintf(stderr, "Can't open %s!\n", argv[1]);
    exit(1);
  }
  fread((void *)&magic,     sizeof(magic),     1, in);
  fread((void *)&offset,    sizeof(offset),    1, in);
  fread((void *)&size,      sizeof(size),      1, in);
  fread((void *)&format,    sizeof(format),    1, in);
  fread((void *)&rate,      sizeof(rate),      1, in);
  fread((void *)&nchannels, sizeof(nchannels), 1, in);

  if (magic != MAGIC) {
    fprintf(stderr, "%s Is not a NeXT sound file!\n", argv[1]);
    fclose(in);
    exit(1);
  }
  if (format != LINEAR_16 || nchannels != 1) {
    fprintf(stderr, "I can only handle linear 16 format with 1 channel!\n");
    if (format != LINEAR_16 && nchannels == 1) {
      fprintf(stderr, "Use sndconvert on the NeXT to convert to this format\n");
    }
    fclose(in);
    exit(1);
  }
  out = fopen(argv[2], "w");
  if (!out) {
    fprintf(stderr, "Can't open %s!\n", argv[2]);
    fclose(in);
    exit(1);
  }
  fwrite((void *)"FORM", sizeof(char), 4, out);
  lengthoffset = ftell(out);
  i = 0;	/* update this later */
  fwrite((void *)&i, sizeof(i), 1, out);
  fwrite((void *)"8SVX", sizeof(char), 4, out);
  fwrite((void *)"VHDR", sizeof(char), 4, out);
  i = 20;
  fwrite((void *)&i, sizeof(i), 1, out);
  voffset = ftell(out);
  v.oneShotHiSamples = 0;	/* Update this later */
  v.repeatHiSamples = 0;
  v.samplesPerHiCycle = 0;
  v.samplesPerSec = rate;
  v.ctOctave = 1;
  v.sCompression = 0;
  v.volume = Unity;
  fwrite((void *)&v, sizeof(v), 1, out);
  fwrite((void *)"BODY", sizeof(char), 4, out);
  nsamplesoffset = ftell(out);
  i = 0;	/* update this later */
  fwrite((void *)&i, sizeof(i), 1, out);

  fseek(in, (long)offset, 0);
  nsamples = 0;
  while (fread((void *)&s16, sizeof(s16), 1, in)) {
    s8 = s16 >> 8;
    fwrite((void *)&s8, sizeof(s8), 1, out);
    nsamples++;
  }
  fclose(in);
  if (nsamples % 2) {
    s8 = 0;
    fwrite((void *)&s8, sizeof(s8), 1, out);	/* pad to even length */
  }
  fseek(out, voffset, 0);
  v.oneShotHiSamples = nsamples;
  fwrite((void *)&v, sizeof(v), 1, out);
  fseek(out, lengthoffset, 0);
  i = 40 + nsamples;
  fwrite((void *)&i, sizeof(i), 1, out);
  fseek(out, nsamplesoffset, 0);
  fwrite((void *)&nsamples, sizeof(nsamples), 1, out);
  fclose(out);
  exit(0);
}
