#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> // #include <kernel.h> -- ARM only ... /* The KLATT phoneme codes: ** ** IY bEEt IH bIt ** EY gAte EH gEt ** AE fAt AA fAther ** AO lAWn OW lOne ** UH fUll UW fOOl ** ER mURdER AX About ** AH bUt AY hIde ** AW hOW OY tOY ** ** p Pack b Back ** t Time d Dime ** k Coat g Goat ** f Fault v Vault ** TH eTHer DH eiTHer ** s Sue z Zoo ** SH leaSH ZH leiSure ** HH How m suM ** n suN NG suNG ** l Laugh w Wear ** y Young r Rate ** CH CHar j Jar ** WH WHere */ #define NONE_FOUND 1 #ifdef KLATT #undef NONE_FOUND #endif #ifdef TOAL #undef NONE_FOUND #endif #ifdef KLATT #undef NONE_FOUND #endif #ifdef NONE_FOUND #define KLATT #endif #define MAX_LENGTH 128 static FILE *In_file; static FILE *Out_file; static int Char, Char1, Char2, Char3; static char *Rep_code2[128][128]; static char *Rep_code[128]; /* ** main(argc, argv) ** int argc; ** char *argv[]; ** ** This is the main program. It takes up to two file names (input ** and output) and translates the input file to phoneme codes ** (see ENGLISH.C) on the output file. */ main(argc, argv) int argc; char *argv[]; { if (argc > 3) { fputs("Usage: PHONEME [infile [outfile]]\n", stderr); exit(1); } if (argc == 1) { #ifdef SUPERIOR // _kernel_oscli("say hello. this is my text to speech demo\r"); #endif fputs("Enter english text:\n", stderr); } if (argc > 1) { In_file = fopen(argv[1], "r"); if (In_file == 0) { fputs("Error: Cannot open input file.\n", stderr); fputs("Usage: PHONEME [infile [outfile]]\n", stderr); exit(1); } } else In_file = stdin; if (argc > 2) { Out_file = fopen(argv[2], "w"); if (Out_file == 0) { fputs("Error: Cannot create output file.\n", stderr); fputs("Usage: PHONEME [infile [outfile]]\n", stderr); exit(1); } } else Out_file = stdout; #ifndef ORIGINAL Init_Rules(); #endif { int i, j; for (i = 0; i < 128; i++) { Rep_code[i] = "<UNDEF>"; for (j = 0; j < 128; j++) { Rep_code2[i][j] = "<UNDEF>"; } } } Rep_code['a'] = "A4"; Rep_code['b'] = "B4"; Rep_code['c'] = "C4"; Rep_code['d'] = "D4"; Rep_code['e'] = "E4"; Rep_code['f'] = "F4"; Rep_code['g'] = "G4"; Rep_code['h'] = "H4"; Rep_code['i'] = "I4"; Rep_code['j'] = "J4"; Rep_code['k'] = "K4"; Rep_code['l'] = "L4"; Rep_code['m'] = "M4"; Rep_code['n'] = "N4"; Rep_code['o'] = "O4"; Rep_code['p'] = "P4"; Rep_code['q'] = "Q4"; Rep_code['r'] = "R4"; Rep_code['s'] = "S4"; Rep_code['t'] = "T4"; Rep_code['u'] = "U4"; Rep_code['v'] = "V4"; Rep_code['w'] = "W4"; Rep_code['x'] = "X4"; Rep_code['y'] = "Y4"; Rep_code['z'] = "Z4"; Rep_code['A'] = "A4"; Rep_code['B'] = "B4"; Rep_code['C'] = "C4"; Rep_code['D'] = "D4"; Rep_code['E'] = "E4"; Rep_code['F'] = "F4"; Rep_code['G'] = "G4"; Rep_code['H'] = "H4"; Rep_code['I'] = "I4"; Rep_code['J'] = "J4"; Rep_code['K'] = "K4"; Rep_code['L'] = "L4"; Rep_code['M'] = "M4"; Rep_code['N'] = "N4"; Rep_code['O'] = "O4"; Rep_code['P'] = "P4"; Rep_code['Q'] = "Q4"; Rep_code['R'] = "R4"; Rep_code['S'] = "S4"; Rep_code['T'] = "T4"; Rep_code['U'] = "U4"; Rep_code['V'] = "V4"; Rep_code['W'] = "W4"; Rep_code['X'] = "X4"; Rep_code['Y'] = "Y4"; Rep_code['Z'] = "Z4"; #ifdef KLATT Rep_code2['I']['Y'] = "IY"; Rep_code2['E']['Y'] = "EY"; Rep_code2['A']['E'] = "AE"; Rep_code2['A']['O'] = "AO"; Rep_code2['U']['H'] = "UH"; Rep_code2['E']['R'] = "ER"; Rep_code2['A']['H'] = "AH"; Rep_code2['A']['W'] = "AW"; Rep_code2['I']['H'] = "IH"; Rep_code2['E']['H'] = "EH"; Rep_code2['A']['A'] = "AA"; Rep_code2['O']['W'] = "OW"; Rep_code2['U']['W'] = "UW"; Rep_code2['A']['X'] = "AX"; Rep_code2['A']['Y'] = "AY"; Rep_code2['O']['Y'] = "OY"; Rep_code2['T']['H'] = "TH"; Rep_code2['S']['H'] = "SH"; Rep_code2['H']['H'] = "HH"; Rep_code2['C']['H'] = "CH"; Rep_code2['W']['H'] = "WH"; Rep_code2['D']['H'] = "DH"; Rep_code2['Z']['H'] = "ZH"; Rep_code2['N']['G'] = "NG"; #endif #ifdef SUPERIOR /* first iteration - guessing */ Rep_code2['I']['Y'] = "EE4"; Rep_code2['E']['Y'] = "AY4"; Rep_code2['A']['E'] = "AE4"; Rep_code2['A']['O'] = "OH4"; Rep_code2['U']['H'] = "UH4"; /* full ??? */ Rep_code2['E']['R'] = "AXR4"; Rep_code2['A']['H'] = "AH4"; Rep_code2['A']['W'] = "AW4"; Rep_code2['I']['H'] = "IH4"; Rep_code2['E']['H'] = "EH4"; Rep_code2['A']['A'] = "O4"; /* zombie -> ZAAMBIH */ Rep_code2['O']['W'] = "OW4"; Rep_code2['U']['W'] = "UW4";/* fool ??? Can't see any difference! */ Rep_code2['A']['X'] = "AX4"; /* *a*bout ??? */ Rep_code2['A']['Y'] = "IY4"; Rep_code2['O']['Y'] = "OY4"; Rep_code2['T']['H'] = "TH4"; /* The??? */ Rep_code2['S']['H'] = "SH4"; Rep_code2['H']['H'] = "H4"; Rep_code2['C']['H'] = "CH4"; Rep_code2['W']['H'] = "HW4"; Rep_code2['D']['H'] = "DH4"; /* This */ Rep_code2['Z']['H'] = "ZH4"; /* I did't have this one! - added! */ Rep_code2['N']['G'] = "NX4"; #endif #ifdef TOAL Rep_code2['I']['Y'] = "Ê"; Rep_code2['E']['Y'] = "Â"; Rep_code2['A']['E'] = "a"; Rep_code2['A']['O'] = "o"; Rep_code2['U']['H'] = "û"; /* full ??? */ Rep_code2['E']['R'] = "ør"; Rep_code2['A']['H'] = "u"; Rep_code2['A']['W'] = "ö"; Rep_code2['I']['H'] = "i"; Rep_code2['E']['H'] = "e"; Rep_code2['A']['A'] = "ø"; /* zombie -> ZAAMBIH */ Rep_code2['O']['W'] = "ô"; Rep_code2['U']['W'] = "û"; /* fool ??? Can't see any difference! */ Rep_code2['A']['X'] = "i"; /* *a*bout ??? */ Rep_code2['A']['Y'] = "ý"; Rep_code2['O']['Y'] = "ó"; Rep_code2['T']['H'] = "Ð"; /* The */ Rep_code2['S']['H'] = "§"; Rep_code2['H']['H'] = "h"; Rep_code2['C']['H'] = "Ç"; Rep_code2['W']['H'] = "µ"; Rep_code2['D']['H'] = "Ð"; /* This */ Rep_code2['Z']['H'] = "J"; /* I did't have this one! - added! */ Rep_code2['N']['G'] = "Ñ"; #endif xlate_file(); } outstring(string) char *string; { while (*string != '\0') outchar(*string++); } outchar(chr) int chr; { static int first; static int UC_PENDING = (0!=0); char action[256]; static char line[256] = { '\0' }; static char *linep = line; if (UC_PENDING) { linep += sprintf(linep, "%s", Rep_code2[first][chr]); fprintf(Out_file, "%s", Rep_code2[first][chr]); UC_PENDING = (0!=0); return; } if (isupper(chr&127)) { first = chr&127; UC_PENDING = (0==0); } else { if (chr == '\n' || chr == ' ') { sprintf(action, "speakw %s\r", line); fprintf(stderr, " (%s) ", line); #ifdef SUPERIOR // _kernel_oscli(action); #endif linep = line; *linep = '\0'; } else { linep += sprintf(linep, "%s", Rep_code[chr&127]); } if (chr != ' ') fputc(chr,Out_file); } } int makeupper(character) int character; { if (islower(character)) return toupper(character); else return character; } new_char() { /* If the cache is full of newline, time to prime the look-ahead again. If an EOF is found, fill the remainder of the queue with EOF's. */ if (Char == '\n' && Char1 == '\n' && Char2 == '\n' && Char3 == '\n') { /* prime the pump again */ Char = getc(In_file); if (Char == EOF) { Char1 = EOF; Char2 = EOF; Char3 = EOF; return Char; } if (Char == '\n') return Char; Char1 = getc(In_file); if (Char1 == EOF) { Char2 = EOF; Char3 = EOF; return Char; } if (Char1 == '\n') return Char; Char2 = getc(In_file); if (Char2 == EOF) { Char3 = EOF; return Char; } if (Char2 == '\n') return Char; Char3 = getc(In_file); } else { /* Buffer not full of newline, shuffle the characters and either get a new one or propagate a newline or EOF. */ Char = Char1; Char1 = Char2; Char2 = Char3; if (Char3 != '\n' && Char3 != EOF) Char3 = getc(In_file); } return Char; } /* ** xlate_file() ** ** This is the input file translator. It sets up the first character ** and uses it to determine what kind of text follows. */ xlate_file() { /* Prime the queue */ Char = '\n'; Char1 = '\n'; Char2 = '\n'; Char3 = '\n'; new_char(); /* Fill Char, Char1, Char2 and Char3 */ while (Char != EOF) /* All of the words in the file */ { if (isdigit(Char)) have_number(); else if (isalpha(Char) || Char == '\'') have_letter(); else if (Char == '$' && isdigit(Char1)) have_dollars(); else have_special(); } } have_dollars() { long int value; value = 0L; for (new_char() ; isdigit(Char) || Char == ',' ; new_char()) { if (Char != ',') value = 10 * value + (Char-'0'); } say_cardinal(value); /* Say number of whole dollars */ /* Found a character that is a non-digit and non-comma */ /* Check for no decimal or no cents digits */ if (Char != '.' || !isdigit(Char1)) { if (value == 1L) outstring("dAAlER "); else outstring("dAAlAArz "); return; } /* We have '.' followed by a digit */ new_char(); /* Skip the period */ /* If it is ".dd " say as " DOLLARS AND n CENTS " */ if (isdigit(Char1) && !isdigit(Char2)) { if (value == 1L) outstring("dAAlER "); else outstring("dAAlAArz "); if (Char == '0' && Char1 == '0') { new_char(); /* Skip tens digit */ new_char(); /* Skip units digit */ return; } outstring("AAnd "); value = (Char-'0')*10 + Char1-'0'; say_cardinal(value); if (value == 1L) outstring("sEHnt "); else outstring("sEHnts "); new_char(); /* Used Char (tens digit) */ new_char(); /* Used Char1 (units digit) */ return; } /* Otherwise say as "n POINT ddd DOLLARS " */ outstring("pOYnt "); for ( ; isdigit(Char) ; new_char()) { say_ascii(Char); } outstring("dAAlAArz "); return; } have_special() { if (Char == '\n') outchar('\n'); else if (!isspace(Char)) say_ascii(Char); new_char(); return; } have_number() { long int value; int lastdigit; value = Char - '0'; lastdigit = Char; for (new_char() ; isdigit(Char) ; new_char()) { value = 10 * value + (Char-'0'); lastdigit = Char; } /* Recognize ordinals based on last digit of number */ switch (lastdigit) { case '1': /* ST */ if (makeupper(Char) == 'S' && makeupper(Char1) == 'T' && !isalpha(Char2) && !isdigit(Char2)) { say_ordinal(value); new_char(); /* Used Char */ new_char(); /* Used Char1 */ return; } break; case '2': /* ND */ if (makeupper(Char) == 'N' && makeupper(Char1) == 'D' && !isalpha(Char2) && !isdigit(Char2)) { say_ordinal(value); new_char(); /* Used Char */ new_char(); /* Used Char1 */ return; } break; case '3': /* RD */ if (makeupper(Char) == 'R' && makeupper(Char1) == 'D' && !isalpha(Char2) && !isdigit(Char2)) { say_ordinal(value); new_char(); /* Used Char */ new_char(); /* Used Char1 */ return; } break; case '0': /* TH */ case '4': /* TH */ case '5': /* TH */ case '6': /* TH */ case '7': /* TH */ case '8': /* TH */ case '9': /* TH */ if (makeupper(Char) == 'T' && makeupper(Char1) == 'H' && !isalpha(Char2) && !isdigit(Char2)) { say_ordinal(value); new_char(); /* Used Char */ new_char(); /* Used Char1 */ return; } break; } say_cardinal(value); /* Recognize decimal points */ if (Char == '.' && isdigit(Char1)) { outstring("pOYnt "); for (new_char() ; isdigit(Char) ; new_char()) { say_ascii(Char); } } /* Spell out trailing abbreviations */ if (isalpha(Char)) { while (isalpha(Char)) { say_ascii(Char); new_char(); } } return; } have_letter() { char buff[MAX_LENGTH]; int count; count = 0; buff[count++] = ' '; /* Required initial blank */ buff[count++] = makeupper(Char); for (new_char() ; isalpha(Char) || Char == '\'' ; new_char()) { buff[count++] = makeupper(Char); if (count > MAX_LENGTH-2) { buff[count++] = ' '; buff[count++] = '\0'; xlate_word(buff); count = 1; } } buff[count++] = ' '; /* Required terminating blank */ buff[count++] = '\0'; /* Check for AAANNN type abbreviations */ if (isdigit(Char)) { spell_word(buff); return; } else if (strlen(buff) == 3) /* one character, two spaces */ say_ascii(buff[1]); else if (Char == '.') /* Possible abbreviation */ abbrev(buff); else { char *s; /*fprintf(Out_file, "<");*/ xlate_word(buff); s = buff; while (*s != '\0') { if (isalpha(*s) && isupper(*s)) *s = tolower(*s); s++; } if (*buff == ' ') fprintf(Out_file, "=%s", buff+1); /* was >= */ else fprintf(Out_file, "=%s", buff); /* was >= */ } if (Char == '-' && isalpha(Char1)) new_char(); /* Skip hyphens */ } /* Handle abbreviations. Text in buff was followed by '.' */ abbrev(buff) char buff[]; { if (strcmp(buff, " DR ") == 0) { xlate_word(" DOCTOR "); new_char(); } else if (strcmp(buff, " MR ") == 0) { xlate_word(" MISTER "); new_char(); } else if (strcmp(buff, " MRS ") == 0) { xlate_word(" MISSUS "); new_char(); } else if (strcmp(buff, " PHD ") == 0) { spell_word(" PHD "); new_char(); } else xlate_word(buff); }