/*
 * July 5, 1991
 * Copyright 1991 Lance Norskog And Sundry Contributors
 * This source code is freely redistributable and may be used for
 * any purpose.  This copyright notice must be maintained. 
 * Lance Norskog And Sundry Contributors are not responsible for 
 * the consequences of using this software.
 */

/*
 * Sound Tools IRCAM SoundFile format handler.
 * 
 * Derived from: Sound Tools skeleton handler file.
 */

#define IRCAM
#include "st.h"
#ifndef SIZEOF_BSD_HEADER
#define SIZEOF_BSD_HEADER 1024
#endif
#include "sfircam.h"
#include <string.h>

struct sfinfo {	
	long	  sf_magic;
	float	  sf_srate;
	long	  sf_chans;
	long	  sf_packmode;
/*	char	  sf_codes;		/* BOGUS! */
	SFCODE    sf_codes;
} ;

/* Private data for SF file */
typedef struct sfstuff {
	struct sfinfo info;
} *sf_t;

/*
 * Read the codes from the sound file, allocate space for the comment and
 * assign its pointer to the comment field in ft.
 */
readcodes(ft_t ft, SFHEADER *sfhead)
{
	char *commentbuf = NULL, *sfcharp, *newline;
	short bsize, finished = 0;
	SFCODE *sfcodep;

	sfcodep = (SFCODE *) &sfcodes(sfhead);
	do {
		sfcharp = (char *) sfcodep + sizeof(SFCODE);
		if (ft->swap) {
			sfcodep->bsize = swapl(sfcodep->bsize);
			sfcodep->code = swapl(sfcodep->code);
		}
		bsize = sfcodep->bsize - sizeof(SFCODE);
		switch(sfcodep->code) {
		case SF_END:
			finished = 1;
			break;
		case SF_COMMENT:
			if((commentbuf = (char *) malloc(bsize + 1)) != NULL) {
				memcpy(commentbuf, sfcharp, bsize);
//				report("IRCAM comment: %s", sfcharp);
				commentbuf[bsize] = '\0';
				if((newline = strchr(commentbuf, '\n')) != NULL)
					*newline = '\0';
			}
			break;
		}
		sfcodep = (SFCODE *) (sfcharp + bsize);
	} while(!finished);
	if(commentbuf != NULL)	/* handles out of memory condition as well */
		ft->comment = commentbuf;
}

/*
 * Do anything required before you start reading samples.
 * Read file header. 
 *	Find out sampling rate, 
 *	size and style of samples, 
 *	mono/stereo/quad.
 */
int sfstartread(ft_t ft) 
{
	sf_t sf = (sf_t) ft->priv;
	SFHEADER sfhead;
	int i;
	
	if (fread(&sfhead, 1, sizeof(SFHEADER), ft->fp) != sizeof(SFHEADER))
		return 0;
//		fail("unexpected EOF in SF header");
	memcpy(&sf->info, &sfhead.sfinfo, sizeof(struct sfinfo));
	if (ft->swap) {
#ifdef	IRCAM
		sf->info.sf_srate = swapf(sf->info.sf_srate);
#else
		sf->info.sf_magic = swapl(sf->info.sf_magic);
		sf->info.sf_srate = swapl(sf->info.sf_srate);
#endif
		sf->info.sf_packmode = swapl(sf->info.sf_packmode);
		sf->info.sf_chans = swapl(sf->info.sf_chans);
	}
#ifdef	IRCAM
	if ((sfmagic1(&sfhead) != SF_MAGIC1) ||
	    (sfmagic2(&sfhead) != SF_MAGIC2))
	    return 0;
//		fail("SF %s file: can't read, it is byte-swapped or it is not an IRCAM SoundFile", ft->filename);
#else
	if (sf->info.sf_magic != SF_MAGIC)
		return 0;
//		if (sf->info.sf_magic == swapl(SF_MAGIC))fail("SF %s file: can't read, it is probably byte-swapped");
//	        else fail("SF %s file: can't read, it is not an IRCAM SoundFile");
#endif


	/*
	 * If your format specifies or your file header contains
	 * any of the following information. 
	 */
	ft->info.rate = sf->info.sf_srate;
	switch(sf->info.sf_packmode) {
		case SF_SHORT:
			ft->info.size = WORD;
			ft->info.style = SIGN2;
			break;
		case SF_FLOAT:
			ft->info.size = FLOAT;
			ft->info.style = SIGN2;
			break;
		default:
			return 0;
//			fail("Soundfile input: unknown format 0x%x\n", sf->info.sf_packmode);
	}
	ft->info.channels = sf->info.sf_chans;

	/* Read codes and print as comments. */
	readcodes(ft, &sfhead);
	
	return 1;
}



