home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
newc_dev
/
newtalk.arc
/
talk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-06-18
|
11KB
|
534 lines
/*
* TALK.C Written by Jon L. Sherling, 6/18/88
* This program may be distributed anywhere provided that the
* source including these credits are provided as well.
*/
#include <stdio.h>
#include <ctype.h>
#include <exec/types.h>
#include <exec/memory.h>
/*
* External functions
*/
extern void *OpenLibrary();
extern int strlen();
extern long Translate();
extern void fclose();
extern FILE *fopen();
extern char *fgets();
extern void *AllocMem();
extern struct MsgPort *CreatePort();
/*
* local functions
*/
void bye(),
hello(),
main();
#define BUFLEN 80L /* Translation buffer size */
char phoneme[BUFLEN+1]; /* Translation buffer output */
char english[BUFLEN+1]; /* Translation buffer input */
char errormsg[80];
struct Library *TranslatorBase = 0L; /* Translator library base ptr */
FILE *infile = 0L;
#define NUMBUFS 56
struct SOUNDBUFFER
{ char *data;
ULONG len;
UWORD rate;
} buffer[NUMBUFS];
struct IOAudio *ioa = 0L;
struct MsgPort *port;
char *PortName;
/*
* Phoneme file names. The $ should be interpreted as a /
*/
char names[NUMBUFS][3] =
{
"$C",
"$H",
"AA",
"AE",
"AH",
"AO",
"AW",
"AX",
"AY",
"B",
"CH",
"D",
"DH",
"DX",
"EH",
"ER",
"EY",
"F",
"G",
"IH",
"IL",
"IM",
"IN",
"IX",
"IY",
"J",
"K",
"L",
"LX",
"M",
"N",
"NX",
"OH",
"OW",
"OY",
"P",
"Q",
"QX",
"R",
"RX",
"S",
"SH",
"T",
"TH",
"UH",
"UL",
"UM",
"UN",
"UW",
"V",
"W",
"WH",
"Y",
"Z",
"ZH",
"__",
};
/*
* Start of program
*/
void main(argc,argv)
int argc;
char *argv[];
{ register int i;
for (i = 0; i < NUMBUFS; i++)
buffer[i].data = 0L;
if (argc != 2)
bye("Usage: talk file");
hello(argv[1]);
while (fgets(english,(int)BUFLEN,infile))
GenPhonemeStr();
bye("\0");
}
/*
* GenPhonemeStr() is used to generate phoneme strings from
* english text. It then calls GenPhoneme to generate
* individual phoneme references.
*/
GenPhonemeStr()
{ register long p,pp;
int len;
for (pp = 0; p; pp += p)
{ len = strlen(&english[-pp])-1;
p = Translate(&english[-pp],(long)len,phoneme,BUFLEN);
if (p)
Translate(&english[-pp],(long)-p,phoneme,BUFLEN);
GenPhoneme(phoneme);
}
}
#define PACK(a,b) ((((int)(a)) << 8) + ((int)(b)))
/*
* GenPhoneme() separates a phoneme string into individual
* phonemes.
*/
GenPhoneme(s)
char *s;
{ register char *current,*next;
int value;
printf("%s\n",s);
for (current = s,next = &s[1]; *current; current++,next++)
{ if (isdigit(*current))
{ /*
* stress value
*/
value = *current - '0';
}
else
{ switch(*current)
{ case ' ':
value = 10;
break;
case 'B': case 'F': case 'G': case 'J': case 'K':
case 'M': case 'P': case 'V': case 'Y':
value = PACK(*current,0);
break;
case 'Z': case 'T': case 'S': case 'D': case 'W':
case 'L': case 'N': case 'Q': case 'R':
if (*next == 'H' || *next == 'X')
{ value = PACK(*current,*next);
current++;next++;
}
else
{ value = PACK(*current,0);
}
break;
case 'A': case 'I': case 'O': case 'U': case 'E':
case 'C': case '/':
value = PACK(*current,*next);
current++;next++;break;
case '.': case '?': case '-': case ',': case '(':
case ')':
value = 11;
break;
default:
value = 12;
break;
}
}
speak(value);
}
}
/*
* speak(value) will speak the phoneme associated with the value.
*/
speak(value)
int value;
{ /*
* 0-9 is stress value
* 10 is pause
* 11 is punctuation
* 12 is error
* all others are phoneme combinations
*/
if (value < 10)
return;
switch(value)
{ case PACK('/','C'):
playbuf(0);
break;
case PACK('/','H'):
playbuf(1);
break;
case PACK('A','A'):
playbuf(2);
break;
case PACK('A','E'):
playbuf(3);
break;
case PACK('A','H'):
playbuf(4);
break;
case PACK('A','O'):
playbuf(5);
break;
case PACK('A','W'):
playbuf(6);
break;
case PACK('A','X'):
playbuf(7);
break;
case PACK('A','Y'):
playbuf(8);
break;
case PACK('B',0):
playbuf(9);
break;
case PACK('C','H'):
playbuf(10);
break;
case PACK('D',0):
playbuf(11);
break;
case PACK('D','H'):
playbuf(12);
break;
case PACK('D','X'):
playbuf(13);
break;
case PACK('E','H'):
playbuf(14);
break;
case PACK('E','R'):
playbuf(15);
break;
case PACK('E','Y'):
playbuf(16);
break;
case PACK('F',0):
playbuf(17);
break;
case PACK('G',0):
playbuf(18);
break;
case PACK('I','H'):
playbuf(19);
break;
case PACK('I','L'):
playbuf(20);
break;
case PACK('I','M'):
playbuf(21);
break;
case PACK('I','N'):
playbuf(22);
break;
case PACK('I','X'):
playbuf(23);
break;
case PACK('I','Y'):
playbuf(24);
break;
case PACK('J',0):
playbuf(25);
break;
case PACK('K',0):
playbuf(26);
break;
case PACK('L',0):
playbuf(27);
break;
case PACK('L','X'):
playbuf(28);
break;
case PACK('M',0):
playbuf(29);
break;
case PACK('N',0):
playbuf(30);
break;
case PACK('N','X'):
playbuf(31);
break;
case PACK('O','H'):
playbuf(32);
break;
case PACK('O','W'):
playbuf(33);
break;
case PACK('O','Y'):
playbuf(34);
break;
case PACK('P',0):
playbuf(35);
break;
case PACK('Q',0):
playbuf(36);
break;
case PACK('Q','X'):
playbuf(37);
break;
case PACK('R',0):
playbuf(38);
break;
case PACK('R','X'):
playbuf(39);
break;
case PACK('S',0):
playbuf(40);
break;
case PACK('S','H'):
playbuf(41);
break;
case PACK('T',0):
playbuf(42);
break;
case PACK('T','H'):
playbuf(43);
break;
case PACK('U','H'):
playbuf(44);
break;
case PACK('U','L'):
playbuf(45);
break;
case PACK('U','M'):
playbuf(46);
break;
case PACK('U','N'):
playbuf(47);
break;
case PACK('U','W'):
playbuf(48);
break;
case PACK('V',0):
playbuf(49);
break;
case PACK('W',0):
playbuf(50);
break;
case PACK('W','H'):
playbuf(51);
break;
case PACK('Y',0):
playbuf(52);
break;
case PACK('Z',0):
playbuf(53);
break;
case PACK('Z','H'):
playbuf(54);
break;
default:
/*
* Treat this as a pause for now....
*/
playbuf(55);
break;
}
}
/*
* playbuf takes its index and plays the buffer specified.
*/
playbuf(idx)
int idx;
{ PlaySound(buffer[idx].data,buffer[idx].len,1,(int)(3579545/buffer[idx].rate),64);
WaitIO(ioa);
}
/*
* The initialization routine
*/
void hello(file)
char *file;
{ int i;
if (!(TranslatorBase = OpenLibrary("translator.library",0L)))
bye("Error opening translator device");
if (!(infile = fopen(file,"r")))
{ sprintf(errormsg,"Could not open \"%s\"",file);
bye(errormsg);
}
for (i = 0; i < NUMBUFS; i++)
loadsound(names[i],&buffer[i]);
StartSound();
}
/*
* The cleanup routine
*/
void bye(s)
char *s;
{ int i;
if (s[0]) printf("%s\n",s);
if (ioa) StopSound();
for (i = 0; i < NUMBUFS; i++)
{ if (buffer[i].data)
FreeMem(buffer[i].data,buffer[i].len);
}
if (TranslatorBase) CloseLibrary(TranslatorBase);
if (infile) fclose(infile);
exit(0);
}
loadsound(filename,buffer)
char *filename;
struct SOUNDBUFFER *buffer;
{ FILE *fp;
ULONG len;
UWORD rec_rate;
if (!(fp = fopen(filename,"r")))
{ printf("Missing sound file : \"%s\"\n",filename);
if (!(buffer->data = AllocMem(1000L,MEMF_CHIP|MEMF_CLEAR)))
bye("Out of memory");
buffer->rate = 10000;
buffer->len = 1000;
return;
}
if (!fread(&len,sizeof(len),1,fp))
{ fclose(fp);
sprintf(errormsg,"Error reading sound file: \"%s\"",filename);
bye(errormsg);
}
if (!fread(&rec_rate,sizeof(rec_rate),1,fp))
{ fclose(fp);
sprintf(errormsg,"Error reading sound file: \"%s\"",filename);
bye(errormsg);
}
if (!(buffer->data = AllocMem(len,MEMF_CHIP|MEMF_CLEAR)))
{ fclose(fp);
bye("Out of memory");
}
buffer->rate = rec_rate;
buffer->len = len;
if (!fread(buffer->data,len,1,fp))
{ fclose(fp);
sprintf(errormsg,"Error reading sound file: \"%s\"",filename);
bye(errormsg);
}
fclose(fp);
}
#include "devices/audio.h"
#define LEFT0F 1
#define RIGHT0F 2
#define RIGHT1F 4
#define LEFT1F 8
UBYTE allocationMap[] = {LEFT0F,LEFT1F,RIGHT0F,RIGHT1F};
StartSound()
{
if (!(ioa = AllocMem((long)(sizeof(struct IOAudio)),MEMF_PUBLIC|MEMF_CLEAR)))
bye("Could not allocate IOAudio structure");
ioa->ioa_Request.io_Message.mn_Node.ln_Pri = 10;
PortName = "Sound Channel";
if (!(port = CreatePort(PortName,0L)))
{ FreeMem(ioa,(long)(sizeof(struct IOAudio)));
bye("Could not create port");
}
ioa->ioa_Request.io_Message.mn_ReplyPort = port;
ioa->ioa_Data = allocationMap;
ioa->ioa_Length = sizeof(allocationMap);
if (OpenDevice(AUDIONAME,0L,ioa,0L))
{ DeletePort(port);
FreeMem(ioa,(long)(sizeof(struct IOAudio)));
bye("Could not open audio device");
}
}
PlaySound(buffer,buflen,repeat,period,volume)
char *buffer;
ULONG buflen;
int repeat,period,volume;
{
ioa->ioa_Request.io_Flags = ADIOF_PERVOL;
ioa->ioa_Request.io_Command = CMD_WRITE;
ioa->ioa_Period = period;
ioa->ioa_Volume = volume;
ioa->ioa_Cycles = repeat;
ioa->ioa_Length = buflen;
ioa->ioa_Data = (UBYTE *)buffer;
BeginIO(ioa);
}
StopSound()
{
AbortIO(ioa);
if (ioa->ioa_Request.io_Device)
CloseDevice(ioa);
if (ioa->ioa_Request.io_Message.mn_ReplyPort)
DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort);
if (ioa)
FreeMem(ioa,(long)(sizeof(struct IOAudio)));
}