/* * 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 #include #include #include /* * 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))); }