/*
 * Source code parts taken from waveplay - Programmed by Y.Sonoda (Mar. 1998)
 */

#include "config.h"
#include <sys/types.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <unistd.h>
#include <fcntl.h>

#include "g711.h"
#include "wavefmt.h"

int
wav_read(char *name, u_char **pdata, size_t *pdatasize)
{
	int header = 0;
	int size = 0, i;
	char *buff;
	u_char *data, *p;
	size_t datasize, n;
	int16_t tmp[1024];
	WAVEFORMAT wavefmt;
	int fd;

	if ((fd = open(name, O_RDONLY, 0)) == -1)
		err(1, "open(%s)", name);

	datasize = 0;
	read(fd, (char *)&header, sizeof(int));
	if (header != H_RIFF)
		errx(1, "%s is not RIFF file", name);

	read(fd, (char *)&size, sizeof(int));
	read(fd, (char *)&header, sizeof(int));
	if (header != H_WAVE)
		errx(1, "%s is not a WAVE file", name);

	while (read(fd, (char *)&header, sizeof (int)) == sizeof (int)) {
		read(fd, (char *)&size, sizeof (int));

		if (header == H_FMT) {
			if ((size_t)size < sizeof (WAVEFORMAT))
				errx(1, "Illegal header");

			buff = malloc((size_t)size);
			read(fd, buff, size);
			memcpy((void *)&wavefmt, (void *)buff, sizeof(WAVEFORMAT));
			free(buff);
			if (wavefmt.wFormatTag != 1)
				errx(1, "Unsupported format: %d",
				     wavefmt.wFormatTag);
		} else if (header == H_DATA) {
			datasize = (u_int)size;
			break;
		} else
			lseek(fd, size, SEEK_CUR);
	}

	if (datasize == 0) 
		errx(1, "data chunk not found");

	fprintf(stderr,
		"Reading %s:\n"
		"\tChannels:    %d\n"
		"\tSamplesrate: %ld\n"
		"\tBits:        %d\n",
		name,
		wavefmt.nChannels,
		wavefmt.nSamplesPerSec,
		wavefmt.wBitsPerSample);
		
	if (wavefmt.nChannels != 1 ||
	    wavefmt.nSamplesPerSec != 8000 ||
	    wavefmt.wBitsPerSample != 16)
		errx(1, "unsupported format");

	if (datasize % sizeof (int16_t))
		errx(1, "bad data size");

	size = datasize;
	datasize /= sizeof (int16_t);

	if ((data = malloc(datasize)) == NULL)
		err(1, "malloc");

	p = data;
	while (size) {
		n = read(fd, tmp, sizeof(tmp) < size ? sizeof(tmp) : size);
		if (n == -1 || n % sizeof (int16_t))
			err(1, "read: %d", n);
		size -= n;

		n /= sizeof (int16_t);
		for (i = 0; i < n; i++)
			*p++ = linear2ulaw(tmp[i]);

	}
	
	*pdata = data;
	*pdatasize = datasize;

	close(fd);

	return (0);
}


syntax highlighted by Code2HTML, v. 0.9.1