/* quasi-minimal IFF 8SVX sample file reader
 * by Karl Lehenbauer
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <stdio.h>
#include <fcntl.h>
#include <assert.h>

#include "iff/iff.h"
#include "iff/8svx.h"

#define N_PER_LINE 15

SplashForm(bufp,nbytes)
char *bufp;
int nbytes;
{
	int n_thisline = 0;

	fputs("{",stdout);

	while (--nbytes)
	{
		printf("%4d,",*bufp++);
		if (++n_thisline >= N_PER_LINE)
		{
			fputs("\n ",stdout);
			n_thisline = 0;
		}
	}
	printf("%4d};\n",*bufp);
}

PutID(id)
ID id;
{
    fprintf(stderr,"%c%c%c%c",
	   (char)((id>>24L) & 0x7f),
	   (char)((id>>16L) & 0x7f),
	   (char)((id>>8)   & 0x7f),
	   (char)(id        & 0x7f) );
}

LONG chunkuntil(fd,chunktype)
int fd;
ULONG chunktype;
{
	ChunkHeader untilheader;
	int sawsize;

	while (1)
	{
		if ((sawsize = read(fd,&untilheader,sizeof(untilheader))) != sizeof(untilheader))
		{
			printf("Something's wrong with chunkuntil! (sawsize %d)\n",sawsize);
			return(-1);
		}
		/* fputs("chunkuntil: checking ",stderr);
		PutID(untilheader.ckID);
		fprintf(stderr,", size is %d...",untilheader.ckSize); */

		if (untilheader.ckID == chunktype)
		{
			/* fputs("found it\n",stderr); */
			return(untilheader.ckSize);
		}

		/* fputs("skipped\n",stderr); */

		/* skip over chunk data and skip an extra byte if length is odd */
		lseek(fd,untilheader.ckSize,1);
		if (untilheader.ckSize & 1)
			lseek(fd,1L,1);
	}
}

svx_to_c(fname,ofname)
char *fname, *ofname;
{
	int iffile;
	ChunkHeader chunkhead;
	Voice8Header voicehead;
	LONG samplebytes;
	LONG formtype;
    char *sampbufp;

	/* fputs("svx_to_c",stderr); */
	assert(sizeof(chunkhead) == 8);

	if (fname[strlen(fname)-2] != '.')
	{
		fputs("svx_to_c: IFF sample file name must end with a period and a single char\n",stderr);
		exit(-1);
	}

	if ((iffile = open(fname, O_RDONLY)) < 0)
	{
		fprintf(stderr,"svx_to_c: can't open IFF sample file %s\n",fname);
		return(-1);
	}

	if (freopen(ofname,"w", stdout) == NULL)
	{
		fprintf(stderr,"svx_to_c: can't open output file %s\n",ofname);
		return(-1);
	}

	if (read(iffile, &chunkhead, sizeof(chunkhead)) < 0)
	{
		fprintf(stderr,"svx_to_c: initial read from IFF sample file %s failed!\n",fname);
		return(-1);
	}

	if (chunkhead.ckID != FORM)
	{
		fprintf(stderr,"svx_to_c: File %s isn't IFF, is too complex, or doesn't start with FORM\n",fname);
		return(-1);
	}
	/* fprintf(stderr,"svx_to_c: FORM found, size is %d\n",chunkhead.ckSize); */

	read(iffile, &formtype, sizeof(formtype));

	if (formtype != ID_8SVX)
	{
		fprintf(stderr,"svx_to_c: File %s is IFF but is not 8SVX\n",fname);
		return(-1);
	}
	/* fputs("svx_to_c: IFF FORM is 8SVX\n",stderr); */

	if (chunkuntil(iffile,ID_VHDR) != 20)
	{
		fputs("svx_to_c: IFF 8SVX VHDR chunk search failed or length not 20\n",stderr);
		return(-1);
	}
	assert(sizeof(voicehead) == 20);

	if (read(iffile,&voicehead,sizeof(voicehead)) != sizeof(voicehead))
	{
		fputs("svx_to_c: read of IFF VHDR chunk failed\n",stderr);
		return(-1);
	}
	/* fprintf(stderr,"Samples per second: %d\n",voicehead.samplesPerSec); */

	if ((samplebytes = chunkuntil(iffile,ID_BODY)) < 0)
	{
		fputs("svx_to_c: IFF 8SVX BODY chunk search failed\n",stderr);
		return(-1);
	}

	/* fprintf(stderr,"Number of bytes in waveform: %d\n",samplebytes); */

    if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_CHIP)) == (char *)NULL)
	{
		fputs("svx_to_c: unable to allocate memory for waveform\n",stderr);
		return(-1);
	}
    if (read(iffile,sampbufp,samplebytes) != samplebytes)
	{
		fputs("Read of sample data failed!\n",stderr);
		return(-1);
	}

	/* write out C program containing IFF sample */

	puts("#include <exec/types.h>");
	puts("#include \"audio:sample.h\"\n");

	fname[strlen(fname)-2] = '\0';
	printf("GLOBAL BYTE %swave[] = \n",fname);
	SplashForm(sampbufp,samplebytes);

	printf("\nGLOBAL Sample %sSample = {%d, %d , &%swave[0]};\n",fname,voicehead.samplesPerSec,samplebytes,fname);

	FreeMem(sampbufp,samplebytes);
	/* fputs("svx_to_c: TTFN\n",stderr); */
	return(1);
}

/* end of file */
