/*	Tosnd.c -- read samples from stdin and write a NeXT/IRCAM format file
 *		stp based on frm - 8/89, last update - 4/92
 *
 *		usage: tosnd [-r # -s -x -f -u -w comment] file < input
 *		  -r  is to set arbitrary (integer) sample rate
 *		  -s  is stereo [mono assumed]
 *		  -x  to reverse bytes [normally not done]
 *		  -f  to read float samples [default is 16-bit]
 *		  -w  to include a comment in the sound file header
 *		  -u  to print usage
 *		  file is name of output file [.snd extension advised]
 */
#include <stdio.h>
#include "NeXTsfheader.h"		/* merged NeXT/IRCAM header */
#include <sys/file.h>
/* #include <stdlib.h> */
#include <errno.h>

#define BUF 16384

static SFCODE ampcode = {
	SF_MAXAMP, sizeof(SFMAXAMP) + sizeof(SFCODE)
}; 

static SFCODE commentcode = {
	SF_COMMENT, MINCOMM + sizeof(SFCODE)
};

main(argc, argv) int argc; char *argv[]; {
	int		i, chan = 1, rd, fd, floatin = 0;
	int		rate = 44100, byterev = 0;
	short	*snddata;
	float	fsamp, *fsnddata;
	char	*getenv(), name[64], dirname[64], c, comment[512];
	extern char		*optarg;
	extern int		optind, opterr;
	SFHEADER sfh;
	SFMAXAMP sfm;
	SFCOMMENT sfcm;

	comment[0] = '\0';
	sfclass(&sfh) = SF_SHORT;
	if (argc == 1)
		usage();
				/******* Process Command-line Arguments ***********/
	while ((c = getopt(argc, argv, "usxfr:w:")) != -1) 
		switch (c) {
		case 's':
			chan = 2;
			fprintf(stderr, "tosnd: set up for stereo\n");
			break;
		case 'x':
			byterev++;
			fprintf(stderr, "tosnd: set up for byte reversal\n");
			break;
		case 'r':
			rate = atoi(optarg);
			fprintf(stderr, "tosnd: using output sample rate %d\n", rate);
			break;
		case 'f':
			floatin++;
			fprintf(stderr, "tosnd: set up for floating-point input\n");
			break;
		case 'w':
			strcpy(comment, optarg);
			fprintf(stderr, "Comment: %s\n", comment);
			break;
		case 'u':
			usage();
			break;
	}
	if (floatin & byterev) {
		fprintf(stderr, "tosnd: can't byte-reverse float samples\n");
		exit(-1);
	}

		/********* Construct real file name *************/
	strcpy(name, argv[argc - 1]);
#ifdef REMOVED
/*
 *	This places sound files placed in the directory pointed to by $SFDIR
 *	unless the names given on the command line begin with '.' or '/'
 */
	strcpy(dirname, getenv("SFDIR"));
	if (strlen(dirname) == 0)
		goto literal_name;
	if ((*name == '.') || (*name == '/'))
		goto literal_name;
	if(strlen(dirname) > 0) {
		strcat(dirname, name);
		strcpy(name, dirname);
		fprintf(stderr, "writing soundfile %s\n", name);
	}
#endif
		/************* Open Output File ***************/
literal_name:
	if ((fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) {
		fprintf(stderr, "tosnd: Unable to open '%s'\n", name);
		perror();
		exit(-1);
	}

		/*********** Create Soundfile Header *************/
	nsfmagic(&sfh) = SND_MAGIC;
	sfmagic(&sfh) = SF_MAGIC;
	sfsrate(&sfh) = rate;
	sfchans(&sfh) = chan;
	for(i=0; i<sfchans(&sfh); i++)
		sfmaxamp(&sfm,i)=sfmaxamploc(&sfm,i)=sfmaxamploc(&sfm,i)=0;
	sfmaxamptime(&sfm) = 0;
	putsfcode(&sfh, &sfm, &ampcode);

		/*********** write comment *********************/
	if (strlen(comment) > 0) {
		strcpy(&sfcomm(&sfcm, 0), comment);
		commentcode.bsize = MAXCOMM + sizeof(SFCODE); 
		if (putsfcode(&sfh, &sfcm, &commentcode) < 0) {
			fprintf(stderr, "tosnd: couldn't write comment.\n");
			exit(-1);
		}
	}
	Nwheader(fd,&sfh);		/* write out header */

		/************* Main Read Loop ***************/
	if (floatin) {
		snddata = (short *) calloc(sizeof(short), BUF);
		fsnddata = (float *) calloc(sizeof(float), BUF);
		while ((rd = fread(fsnddata, sizeof(float), BUF, stdin)) != 0) {
			for (i = 0; i < BUF; i++) {
				fsamp = fsnddata[i];
				if (fsamp > 1.0) fsamp = 1.0;
				else if (fsamp < -1.0) fsamp = -1.0;
				snddata[i] = (short) (fsamp * 32767.0);
			}
			write(fd, snddata, rd << 1);
		}
	} else {
		snddata = (short *) calloc(sizeof(short), BUF);
		while ((rd = fread(snddata, sizeof(short), BUF, stdin)) != 0) {
			if (byterev)
				for (i = 0; i < BUF; i++)
					snddata[i] =
						(snddata[i] << 8) | ((snddata[i] >> 8) & 0xff);
			write(fd, snddata, rd << 1);
		}
	}
	close(fd);
	fd = open(name, O_WRONLY, 0644);
	putlength(name, fd, &sfh);
	close(fd);
}

usage() {

	fprintf(stderr,
		"\n\ntosnd [-r rate -s -x -f -u -w comment] file < input\n");
	fprintf(stderr,
		"  -r  is to set sample rate [default is 44100]\n");
	fprintf(stderr,
		"  -s  is for stereo [mono assumed]\n");
	fprintf(stderr,
		"  -x  means to reverse bytes [normally not done]\n");
	fprintf(stderr,
		"  -f  is for reading floats [default is 16-bit]\n");
	fprintf(stderr,
		"  -w  is for including a soundfile comment\n");
	fprintf(stderr,
		"  -u  is to print this usage message\n");
	fprintf(stderr,
		"   file is name of output file [.snd advised].\n\n\n");
	exit(0);

}

