home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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)));
- }
-