--- DATlib-0.81/src/cmd/playtrack.c.orig	Mon Dec 15 13:32:18 1997
+++ DATlib-0.81/src/cmd/playtrack.c	Sun May  2 22:32:12 1999
@@ -36,6 +36,10 @@
 /* $Id: playtrack.c,v 1.5 1997/12/15 12:32:10 msmeissn Exp $
  *
  * $Log: playtrack.c,v $
+ * Continued without CVS: 2.5.99, jw:
+ * -wav option added to support writing .wav files.
+ * sox can do the same job, but I avoid sox whenever possible.
+ *
  * Revision 1.5  1997/12/15 12:32:10  msmeissn
  * *** empty log message ***
  *
@@ -69,16 +73,154 @@
 usage() {
 	fprintf(stderr,
 "Usage:\n"
-"	playtrack > file.au\n"
+"	playtrack [Options] > file.au\n"
+"	playtrack [Options] -wav > file.wav\n"
 "Options:\n"
 "	-r or --raw	write raw samples only\n"
 "	--noabs 	don't check for absolute time\n"
 "	--noprognr 	don't check for program number\n"
 "	-f <device>	use device <device> instead of $TAPE or "DEFAULTAUDIOTAPE"\n"
+"	-w or --wav	write .WAV output; default is SUN .au format\n"
 	);
 	exit(1);
 }
 
+int write_wav(int fd, unsigned char *buf, int len)
+{
+  static unsigned char tmp[2000];
+  unsigned char *o1, *o2;
+  int l;
+
+  if (len > 2000 || len & 1) 
+    {
+      fprintf(stderr, "write_wav error: packet length = %d is illegal. Must be less than 2000 and even.\n", len);
+      exit(1);
+    }
+
+  for (o1 = tmp+1, o2 = tmp, l = 0; l < len; l += 2)
+    {
+      *o1++ = *buf++;
+      *o2++ = *buf++;
+      o1++;
+      o2++;
+    }
+  
+  return write(fd, tmp, len);
+}
+
+int write_msb32(int fd, unsigned int val)
+{
+  unsigned char tmp[4];
+  tmp[3] = val & 0xff; val >>= 8;
+  tmp[2] = val & 0xff; val >>= 8;
+  tmp[1] = val & 0xff; val >>= 8;
+  tmp[0] = val & 0xff;
+  return write(fd, tmp, 4) - 4;
+}
+
+int write_lsb16(int fd, unsigned int val)
+{
+  unsigned char tmp[2];
+  tmp[0] = val & 0xff; val >>= 8;
+  tmp[1] = val & 0xff;
+  return write(fd, tmp, 2) - 2;
+}
+
+int write_lsb32(int fd, unsigned int val)
+{
+  unsigned char tmp[4];
+  tmp[0] = val & 0xff; val >>= 8;
+  tmp[1] = val & 0xff; val >>= 8;
+  tmp[2] = val & 0xff; val >>= 8;
+  tmp[3] = val & 0xff;
+  return write(fd, tmp, 4) - 4;
+}
+
+/* purloined from public Microsoft RIFF docs */
+/* found in sox. jw */
+ 
+#define WAVE_FORMAT_UNKNOWN             (0x0000)
+#define WAVE_FORMAT_PCM                 (0x0001)
+#define WAVE_FORMAT_ADPCM               (0x0002)
+#define WAVE_FORMAT_ALAW                (0x0006)
+#define WAVE_FORMAT_MULAW               (0x0007)
+#define WAVE_FORMAT_OKI_ADPCM           (0x0010)
+#define WAVE_FORMAT_DIGISTD             (0x0015)
+#define WAVE_FORMAT_DIGIFIX             (0x0016)
+#define IBM_FORMAT_MULAW                (0x0101)
+#define IBM_FORMAT_ALAW                 (0x0102)
+#define IBM_FORMAT_ADPCM                (0x0103)
+
+int
+write_wav_hdr(int fd, int samplerate, int channels, int nsamples)
+{
+  /* wave file characteristics */
+  unsigned short wFormatTag;              /* data format */
+  unsigned short wChannels;               /* number of channels */
+  unsigned long  wSamplesPerSecond;       /* samples per second per channel */
+  unsigned long  wAvgBytesPerSec;         /* estimate of bytes per second needed */
+  unsigned short wBlockAlign;             /* byte alignment of a basic sample block */
+  unsigned short wBitsPerSample;          /* bits per sample */
+  unsigned long  data_length;             /* length of sound data in bytes */
+  unsigned long  bytespersample;          /* bytes per sample (per channel) */
+
+  wBitsPerSample = 16;
+  wFormatTag = WAVE_FORMAT_PCM;
+  wSamplesPerSecond = samplerate;
+  bytespersample = (wBitsPerSample + 7)/8;
+  wAvgBytesPerSec = wSamplesPerSecond * channels * bytespersample;
+  wChannels = channels;
+  wBlockAlign = wChannels * bytespersample;
+  data_length = nsamples * bytespersample;
+
+  if (lseek(fd, 0L, 0))
+    {
+      perror("lseek output");
+      exit(2);
+    }
+  
+  write(fd, "RIFF", 4);
+  write_lsb32(fd, data_length + 8+16+12);	/* chunk size: FIXUP(4) */
+  write(fd, "WAVEfmt ", 8);
+  write_lsb32(fd, 16);
+  write_lsb16(fd, wFormatTag);
+  write_lsb16(fd, wChannels);
+  write_lsb32(fd, wSamplesPerSecond);
+  write_lsb32(fd, wAvgBytesPerSec);
+  write_lsb16(fd, wBlockAlign);
+  write_lsb16(fd, wBitsPerSample);
+  write(fd, "data", 4);
+  write_lsb32(fd, data_length);			/* chunk size: FIXUP(40) */
+  
+  return 0;
+}
+
+int
+write_au_hdr(int fd, int samplerate, int channels)
+{
+  Audio_filehdr	fhdr;
+  int curleft=0;
+  int res;
+
+  fhdr.sample_rate=samplerate;
+  fhdr.channels	= channels;
+  fhdr.magic	= AUDIO_FILE_MAGIC;
+  fhdr.encoding	= AUDIO_FILE_ENCODING_LINEAR_16;
+  fhdr.hdr_size	= sizeof(fhdr);
+  fhdr.data_size	= ~0;
+  while (curleft<sizeof(fhdr)) {
+	  res=write(fd, ((char*)(&fhdr))+curleft,sizeof(fhdr)-curleft);
+	  if (res==-1) {
+		  perror("write header");
+		  return -1;
+	  }
+	  curleft+=res;
+  }
+  if (res==-1)
+	  return -1;
+  return 0;
+}
+
 int
 main(int argc,char **argv) {
 	int	fd;
@@ -87,9 +229,10 @@
 	int	res;
 	int	written;
 	int	lastsamplerate=0,samplerate,xprognr,prognr=0;
+	int	do_wav = 0;
 	struct	da_time atime;
 	int	absfound=0,noabs,noprognr,i,raw,headerwritten,absmissing=0;
-	Audio_filehdr	fhdr;
+	int	channels;
 
 	tape=NULL;
 	raw=noabs=noprognr=0;
@@ -108,6 +251,12 @@
 			raw=1;
 			continue;
 		}
+		if (	!strcmp(argv[i],"--wav") ||
+			!strncmp(argv[i],"-w", 2)
+		) {
+			do_wav = 1;
+			continue;
+		}
 		if (!strcmp(argv[i],"-f") && (i<argc-1)) {
 			tape=argv[i+1];
 			i++;
@@ -148,33 +297,20 @@
 				perror("da_get_prognr");
 		}
 		if (!raw && !headerwritten) {
-			int	channels;
 			/* time to dump the header */
 			if (-1==da_control(fd,DA_GET_SAMPLERATE,(long)&samplerate)) {
 				perror("da_control DA_GET_SAMPLERATE");
 				break;
 			}
-			fhdr.sample_rate=samplerate;
 			if (-1==da_control(fd,DA_GET_CHANNELS,(long)&channels)) {
 				perror("da_control DA_GET_CHANNELS");
 				break;
 			}
-			fhdr.channels	= channels;
-			fhdr.magic	= AUDIO_FILE_MAGIC;
-			fhdr.encoding	= AUDIO_FILE_ENCODING_LINEAR_16;
-			fhdr.hdr_size	= sizeof(fhdr);
-			fhdr.data_size	= ~0;
-			curleft=0;
-			while (curleft<sizeof(fhdr)) {
-				res=write(fileno(stdout),((char*)(&fhdr))+curleft,sizeof(fhdr)-curleft);
-				if (res==-1) {
-					perror("write header");
-					break;
-				}
-				curleft+=res;
-			}
-			if (res==-1)
-				break;
+
+			if (do_wav ?
+			    write_wav_hdr(fileno(stdout), samplerate, channels, 0) : 
+			    write_au_hdr(fileno(stdout), samplerate, channels))
+			  break;
 			headerwritten=1;
 		}
 		if (!noprognr) {
@@ -208,7 +344,10 @@
 		}
 		curleft=0;
 		while (curleft<2000) {
-			res=write(fileno(stdout),buf+curleft,2000-curleft);
+		        if (do_wav)
+			  res = write_wav(fileno(stdout), buf + curleft, 2000 - curleft);
+			else
+			  res=write(fileno(stdout),buf+curleft,2000-curleft);
 			if (res==-1) {
 				perror("write");
 				break;
@@ -217,6 +356,9 @@
 			written+=res;
 		}
 	}
+        if (do_wav)
+	  write_wav_hdr(fileno(stdout), samplerate, channels, written >> 1);
+          
 	fprintf(stderr,"Written: %d bytes\n",written);
 	/*da_close(fd);*/
 	return 0;
--- DATlib-0.81/src/Makefile.common.orig	Mon Dec 15 13:52:56 1997
+++ DATlib-0.81/src/Makefile.common	Sun May  2 17:20:32 1999
@@ -58,6 +58,7 @@
 ## SunOS 5.x
 ##
 INCDIR		=	$(TOP)/include
+LIBDIR		=	/local/dat/lib
 INCLUDE		=	-I$(INCDIR)
 AR		=	ar rc		# command for merging files into a lib
 CC		=	gcc -g -O4
@@ -87,9 +88,9 @@
 ## OS independent stuff follows
 ##
 
-DATLIB		=	$(TOP)/lib/datlib/libdat.a
-DATALIB		=	$(TOP)/lib/dataudiolib/libdataudio.a
-GENLIB		=	$(TOP)/lib/generic/libgeneric.a
+DATLIB		=	$(LIBDIR)/libdat.a
+DATALIB		=	$(LIBDIR)/libdataudio.a
+#GENLIB		=	$(LIBDIR)/generic/libgeneric.a
 
 INSTBINDIR	=	$(TOP)/../bin
 INSTMANDIR	=	$(TOP)/../man

