#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include <allegro.h>
#include "speechy.h"

#define NUM_ALLOPHONES	64

typedef struct
{
	SAMPLE *sample;
	char name[5];
}PHON_DEF;

PHON_DEF *phon_list;

unsigned int phon_count;
SPEECHY_VOICE *voice;

int load_speech(char *filename)
{
	FILE *fp;
	char str[81];
	char path[256]="";
	char sample_path[256];
	int ret=!EOF, index, delay_count=0;

	phon_count=0;

	// Open file
	fp=fopen(filename, "rb");

	if(!fp)
		return FALSE;

	// Scan and count all "delay" and "phon" to get allophone count
	while(ret!=EOF)
	{
		ret=fscanf(fp, "%s", str);
		if(!ret)
			ret=EOF;

		if(!strcmp(str, "delay")||!strcmp(str, "phon"))
			phon_count++;
	}
	
	// Allocate sample list
	phon_list=(PHON_DEF*)calloc(sizeof(PHON_DEF), phon_count);
	voice=speechy_init(phon_count);

	// Load/add delays or allophones
	fseek(fp, 0, SEEK_SET);
	fscanf(fp, "%s", str);
	if(!strcmp(str, "name"))
	{
		fscanf(fp, "%s", str);
		sprintf(path, "allophones/%s/", str);
	}

	index=0;
	fseek(fp, 0, SEEK_SET);
	ret=!EOF;
	while(ret!=EOF)
	{
		ret=fscanf(fp, "%s", str);
		if(!ret)
		{
			ret=EOF;
			continue;
		}

		if(!strcmp(str, "delay"))
		{
			unsigned int delay;

			fscanf(fp, "%s", str);
			strncpy(phon_list[index].name, str, 4);
			phon_list[index].name[4]=0;

			fscanf(fp, "%d", &delay);

			speechy_add_silence(voice, delay);
			index++;
		}
		else if(!strcmp(str, "phon"))
		{
			fscanf(fp, "%s", str);
			strncpy(phon_list[index].name, str, 4);
			phon_list[index].name[4]=0;

			fscanf(fp, "%s", str);
			sprintf(sample_path, "%s%s", path, str);

			phon_list[index].sample=load_sample(sample_path);
			if(!phon_list[index].sample)
			{
				ret=EOF;
			}
			speechy_add(voice, phon_list[index].sample->data, 
				phon_list[index].sample->len, FALSE);

			index++;
		}
		else
		{
			// Ignore it
		}
	}
	
	fclose(fp);

	return TRUE;
}


void free_speech()
{
	unsigned int i;

	for(i=0; i<phon_count; i++)
	{
		if(phon_list[i].sample)
			destroy_sample(phon_list[i].sample);
	}

	free(phon_list);
}


int parse_allophones(char *str, short *buf, unsigned int size)
{
	char *ptr=str;
	unsigned int count=0, i, pos=0, quit=FALSE;

	while(*ptr&&isspace(*ptr))
		ptr++;

	while(*ptr)
	{
		char *end=ptr;

		while(*end&&!isspace(*end))
			end++;

		for(i=0; i<phon_count; i++)
		{
			if(!memcmp(ptr, phon_list[i].name, end-ptr))
			{
				buf[pos]=i;
				pos++;
				break;
			}

		}

		if(pos>=size)
		{
			pos-=1;
			break;
		}

		ptr=end;
	
		while(*ptr&&isspace(*ptr))
			ptr++;
	}

	buf[pos]=END_SEQ;

	return pos;
}


int main()
{
	SAMPLE *speak;
	unsigned length, length2;
	int id;
	short codes[256];
	FILE *fp;
/*	char *str="ww iy pa3 kk3 ax nn tt rr2 ow ll pa4 dh1 ax "
		"yy2 uw1 nn ih vv er1 ss ss";

	char *str="ww iy pa3 kk1 ey mm pa3 ih ih nn pa3 pp iy ss ss pa4 ff or pa3 "
		"ao ll ll pa3 mm ae nn pa3 kk1 ay nn dd1";


	char *str="dd2 pa2 ey vv pa3 bb1 rr2 ax pa1 jh uw2 pa3 kk3 ax pa4 ih zz pa3 dh1 ax pa3 "
		"ww er2 pa1 dd1 pa3 dd2 aa aa pa2 kk3 uw1 pa2 mm eh nn1 pa2 tt2 pa3 vv iy pa3 bb2 iy pa3 "
		"ss ss kk1 rr2 ih pp tt2 pa3 mm ae ae ss ss pa2 tt2 er1 pa5 "
		"hh1 iy pa3 ih zz pa3 dh1 ax pa3 ax ax ll tt ih mm eh tt pa3 ss kk3 rr2 ih pp tt2 pa3 "
		"kk1 ih pa1 dd1 iy pa5 ff iy er2 pa3 hh1 ih zz pa3 ll iy tt2 nn1 eh ss ss";
*/
	char *str="ay pa3 ww ax zz pa3 pp rr2 ow pa1 gg rr1 ae mm pa1 dd1 pa3 tt2 uw2 pa3 "
		"ih ih nn1 vv eh eh ss pa2 tt2 ih pa1 gg1 ey pa2 tt2 pa5 ay pa3 mm ax ss tt1 pa3 "
		"rr1 iy pa3 iy vv ae ll pa1 yy2 uw1 ey tt";

	allegro_init();
	install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);

	if(!load_speech("allophones/spo256.txt"))
		return -1;

	parse_allophones(str, codes, 256);
	length=speechy_sequence(voice, codes);

	speak=create_sample(8, FALSE, 8000, length);
	length2=speechy_read(voice, speak->data, length);

	id=play_sample(speak, 255, 128, 1000, 0);

	while(voice_check(id));

	fp=fopen("out.raw", "wb");
	fwrite(speak->data, length2, 1, fp);
	fclose(fp);	

	destroy_sample(speak);

	free_speech();

	return 0;
}
END_OF_MAIN()