/*
	Wav file format library
 */


#ifndef WAV_H
#define WAV_H

#include <sys/types.h>


/*
 *	Master version number:
 */
#define WavLibraryVersionMajor		3
#define WavLibraryVersionMinor		1


/*
 *	Wav file magic number:
 */
#define WavIDRIFF       0x46464952
#define WavIDWave	0x45564157


/*
 *	Wav chunk IDs:
 *
 *	Data type is a 4 byte int.
 */
#define WavFormatChunkCode	0x20746D66	/* Header. */
#define WavDataChunkCode	0x61746164	/* Audio data. */


/*
 *	Wav format chunk tags:
 *
 *	These tags are found within a WavFormatChunkCode chunk.
 *
 *	Data type is a 2 byte short.
 */
#define WavFormatTagUnknown	0x0000
#define WavFormatTagPCM		0x0001
#define WavFormatTagADPCM	0x0002
#define WavFormatTagIBM_CVSD	0x0005
#define WavFormatTagALAW	0x0006
#define WavFormatTagMULAW	0x0007
#define WavFormatTagOKI_ADPCM	0x0010
#define WavFormatTagDVI_ADPCM	0x0011	/* Or WAVE_FORMAT_IMA_ADPCM */
#define WavFormatTagDIGISTD	0x0015
#define WavFormatTagDIGIFIX	0x0016
#define WavFormatTagYAMAHA_ADPCM	0x0020
#define WavFormatTagSONARC	0x0021
#define WavFormatTagDSPGROUP_TRUESPEECH	0x0022
#define WavFormatTagECHOSCI	0x0023
#define WavFormatTagAUDIOFILE_18	0x0024
#define WavFormatTagIBM_MULAW	0x0101
#define WavFormatTagIBM_ALAW	0x0102
#define WavFormatTagIBM_ADPCM	0x0103
#define WavFormatTagCREATIVE_ADPCM	0x0200


/*
 *	Byte value shift options:
 *
 *	For function WavReadPartialData().
 *
 *	The wav PCM format stores the DSP as uncompressed u_int8_t
 *	values.
 *
 *	WavReadUnsigned8 specifies to leave each byte value
 *	`as is', so you get u_int8_t values.
 *
 *	WavReadSigned8 specifies to shift (subtract 128) the
 *	values, so you get int8_t values (more practical for
 *	mixing).
 */
#define WavReadUnsigned8	0
#define WavReadSigned8		1


/*
 *	Wav library function error codes:
 */
#define WavSuccess		0
#define WavErrorNoAccess	1
#define WavErrorNotWave		2
#define WavErrorNoBuffers	3
#define WavErrorCorrupt		4
#define WavErrorUnsupported	5
#define WavErrorBadValue	6
#define WavErrorNoHeader	7
#define WavErrorNoData		8
#define WavErrorEndOfData	9



/*
 *	Wav data structure:
 *
 *	Used by the Wav*() functions.
 */
typedef struct {

	/* Filename. */
	char *filename;
	FILE *fp;

	/* Used by internal functions only. */
	u_int16_t format_tag;

	/* Header and parms. */
	off_t header_pos;		/* Exact position of header on file. */
	off_t header_len;		/* Length of last header chunk. */
	u_int16_t channels;		/* In channels: 1 or 2. */
	u_int32_t samples_per_sec;	/* In samples. */
	u_int32_t bytes_per_sec;	/* In bytes. */
	u_int16_t block_align;

	/* Format specific fields. */
	u_int16_t bits_per_sample;	/* In bits, 8 or 16. */
	u_int16_t samples_per_block;
	u_int16_t coefficients;
	u_int16_t comp_type;
	u_int16_t revision;

	/* Exact starting position audio data on file. */
	off_t data_starting_pos;
	/* Entire size of audio data on file. */
	off_t data_chunk_size;


	/* Data loaded by WavReadPartialData(). */
	char *data;			/* The actual audio data. */
	off_t data_len;

} wav_data_struct;



/* ****************************************************************** */

/*
 *   Checks if given stream fp is a valid WAV file, returns
 *   WavSuccess if it is, WavErrorNotWave if it is not a valid
 *   WAV file, or appropriate error if an error occured.
 *
 *   fp will be rewinded first but after call may be at any
 *   undefined position.
 */
extern int WavIsFPWav(FILE *fp);

/*
 *   Checks if givin file name is a valid WAV file, returns
 *   WavSuccess if it is, WavErrorNotWave if it is not a valid
 *   WAV file, or appropriate error if an error occured.
 */
extern int WavIsFileWav(const char *filename);


/*
 *   Reads the header from the stream fp and initializes the given
 *   wd structure if fp is valid and a wav file.
 *
 *   The given filename is used as referance purposes, it can be NULL.
 *
 *   If WavSuccess is returned then the given fp will be transfered
 *   to the wd structure and should not be referanced again. For all
 *   other return values, the calling function is responsible for
 *   closing the given fp.
 */
extern int WavReadHeader(
	const char *filename, FILE *fp, wav_data_struct *wd
);


/*
 *   Reads a segment of data from the WAV file specified by
 *   the filename member of the givin wav_data_struct *wd structure.
 *
 *   The wav_data_struct *wd structure MUST HAVE VALID VALUES FROM
 *   A PRIOR SUCCESSFUL CALL TO WavReadHeader().
 *
 *   offset is the relative byte position FROM THE START OF THE AUDIO
 *   DATA AS A COMPLETE TRACK and not a position in the file.
 *   This value must be positive.
 *
 *   max_chunk_size is the number of bytes that you want to read from
 *   offset.   This value must be positive and greater than 0.
 * 
 *   read_opt can be WavReadFormatSHV or WavReadFormatRaw.
 *   WavReadFormatSHV will read the data from the WAV file then
 *   subtract 128 from it (this is often used as a convience should
 *   mixing be used later on).
 *   WavReadFormatRaw will read the data 'as is' from the WAV file. 
 *
 *   The loaded data will be placed into the member data of the   
 *   wav_data_struct *wd with the member data_len set appropriately.
 *   If member data is not NULL, then the old data will be first free()ed
 *   automatically before loading is performed.
 */
extern int WavReadPartialData(
	wav_data_struct *wd,
	long offset,		/* In bytes. */
	long max_chunk_size,	/* In bytes. */
	int read_opt
);


/*
 *   Frees all allocated data and resets all values of the
 *   wav_data_struct *wd members.
 *
 *   If wav_data_struct *wd is NULL then no action will be taken.
 */
extern void WavDestroyData(wav_data_struct *wd);



#endif	/* WAV_H */
