}; | }; | ||||
if (path == NULL) | if (path == NULL) | ||||
return (2); | |||||
return 2; | |||||
while (isspace(*path)) path++; | while (isspace(*path)) path++; | ||||
if (f_wavfile == NULL) { | if (f_wavfile == NULL) { | ||||
fprintf(stderr, "Can't write to: '%s'\n", path); | fprintf(stderr, "Can't write to: '%s'\n", path); | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
Write4Bytes(f_wavfile, rate); | Write4Bytes(f_wavfile, rate); | ||||
Write4Bytes(f_wavfile, rate * 2); | Write4Bytes(f_wavfile, rate * 2); | ||||
fwrite(&wave_hdr[32], 1, 12, f_wavfile); | fwrite(&wave_hdr[32], 1, 12, f_wavfile); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
{ | { | ||||
char fname[210]; | char fname[210]; | ||||
if (quiet) return (0); // -q quiet mode | |||||
if (quiet) return 0; // -q quiet mode | |||||
if (wav == NULL) { | if (wav == NULL) { | ||||
CloseWavFile(); | CloseWavFile(); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
while (events->type != 0) { | while (events->type != 0) { | ||||
if (samples_split > 0) { | if (samples_split > 0) { | ||||
sprintf(fname, "%s_%.2d%s", wavefile, wavefile_count+1, filetype); | sprintf(fname, "%s_%.2d%s", wavefile, wavefile_count+1, filetype); | ||||
if (OpenWavFile(fname, samplerate) != 0) | if (OpenWavFile(fname, samplerate) != 0) | ||||
return (1); | |||||
return 1; | |||||
} else { | } else { | ||||
if (OpenWavFile(wavefile, samplerate) != 0) | if (OpenWavFile(wavefile, samplerate) != 0) | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
} | } | ||||
samples_total += numsamples; | samples_total += numsamples; | ||||
fwrite(wav, numsamples*2, 1, f_wavfile); | fwrite(wav, numsamples*2, 1, f_wavfile); | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (f_phonemes_out != stdout) | if (f_phonemes_out != stdout) | ||||
fclose(f_phonemes_out); // needed for WinCE | fclose(f_phonemes_out); // needed for WinCE | ||||
return (0); | |||||
return 0; | |||||
} | } |
while (ktab->mnem != NULL) { | while (ktab->mnem != NULL) { | ||||
if (ktab->data == value) { | if (ktab->data == value) { | ||||
if ((type == -1) || (type == ktab->type)) | if ((type == -1) || (type == ktab->type)) | ||||
return (ktab->mnem); | |||||
return ktab->mnem; | |||||
} | } | ||||
ktab++; | ktab++; | ||||
} | } | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
static void DecompilePhoneme(FILE *f_out, PHONEME_TAB *ph, int compile_phoneme) | static void DecompilePhoneme(FILE *f_out, PHONEME_TAB *ph, int compile_phoneme) | ||||
if (ix != 0) | if (ix != 0) | ||||
return ix; | return ix; | ||||
return (p1->ph_mnemonic - p2->ph_mnemonic); | |||||
return p1->ph_mnemonic - p2->ph_mnemonic; | |||||
} | } | ||||
if (f_log != NULL) | if (f_log != NULL) | ||||
fprintf(f_log, "Can't access (%s) file '%s'\n", access, fname); | fprintf(f_log, "Can't access (%s) file '%s'\n", access, fname); | ||||
} | } | ||||
return (f); | |||||
return f; | |||||
} | } | ||||
unsigned int word; | unsigned int word; | ||||
if (string == NULL) | if (string == NULL) | ||||
return (0); | |||||
return 0; | |||||
word = 0; | word = 0; | ||||
for (ix = 0; ix < 4; ix++) { | for (ix = 0; ix < 4; ix++) { | ||||
c = string[ix]; | c = string[ix]; | ||||
word |= (c << (ix*8)); | word |= (c << (ix*8)); | ||||
} | } | ||||
return (word); | |||||
return word; | |||||
} | } | ||||
unsigned int word; | unsigned int word; | ||||
if (strcmp(string, "NULL") == 0) | if (strcmp(string, "NULL") == 0) | ||||
return (1); | |||||
return 1; | |||||
ix = strlen(string); | ix = strlen(string); | ||||
if ((ix == 0) || (ix > 4)) { | if ((ix == 0) || (ix > 4)) { | ||||
use = 0; | use = 0; | ||||
for (ix = start; ix < n_phcodes; ix++) { | for (ix = start; ix < n_phcodes; ix++) { | ||||
if (phoneme_tab2[ix].mnemonic == word) | if (phoneme_tab2[ix].mnemonic == word) | ||||
return (ix); | |||||
return ix; | |||||
if ((use == 0) && (phoneme_tab2[ix].mnemonic == 0)) { | if ((use == 0) && (phoneme_tab2[ix].mnemonic == 0)) { | ||||
use = ix; | use = ix; | ||||
if (use == 0) { | if (use == 0) { | ||||
if (control == 0) | if (control == 0) | ||||
return (-1); | |||||
return -1; | |||||
if (n_phcodes >= N_PHONEME_TAB-1) | if (n_phcodes >= N_PHONEME_TAB-1) | ||||
return (-1); // phoneme table is full | |||||
return -1; // phoneme table is full | |||||
use = n_phcodes++; | use = n_phcodes++; | ||||
} | } | ||||
phoneme_tab2[use].mnemonic = word; | phoneme_tab2[use].mnemonic = word; | ||||
phoneme_tab2[use].type = phINVALID; | phoneme_tab2[use].type = phINVALID; | ||||
phoneme_tab2[use].program = linenum; // for error report if the phoneme remains undeclared | phoneme_tab2[use].program = linenum; // for error report if the phoneme remains undeclared | ||||
return (use); | |||||
return use; | |||||
} | } | ||||
c = fgetc(f_in); | c = fgetc(f_in); | ||||
if (c == '\n') | if (c == '\n') | ||||
linenum++; | linenum++; | ||||
return (c); | |||||
return c; | |||||
} | } | ||||
static void unget_char(unsigned int c) | static void unget_char(unsigned int c) | ||||
int c; | int c; | ||||
while (((c = get_char()) == ' ') || (c == '\t')) ; | while (((c = get_char()) == ' ') || (c == '\t')) ; | ||||
unget_char(c); | unget_char(c); | ||||
return (c); | |||||
return c; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
if (feof(f_in)) | if (feof(f_in)) | ||||
return (-2); | |||||
return -2; | |||||
if (c == '(') { | if (c == '(') { | ||||
if (type == tOPENBRACKET) | if (type == tOPENBRACKET) | ||||
return (1); | |||||
return (-1); | |||||
return 1; | |||||
return -1; | |||||
} | } | ||||
ix = 0; | ix = 0; | ||||
unget_char(c); | unget_char(c); | ||||
if (type == tSTRING) { | if (type == tSTRING) { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((type == tNUMBER) || (type == tSIGNEDNUMBER)) { | if ((type == tNUMBER) || (type == tSIGNEDNUMBER)) { | ||||
acc += (*p - '0'); | acc += (*p - '0'); | ||||
p++; | p++; | ||||
} | } | ||||
return (acc * sign); | |||||
return acc * sign; | |||||
} | } | ||||
while (pk->mnem != NULL) { | while (pk->mnem != NULL) { | ||||
if (strcmp(item_string, pk->mnem) == 0) { | if (strcmp(item_string, pk->mnem) == 0) { | ||||
item_type = pk->type; | item_type = pk->type; | ||||
return (pk->data); | |||||
return pk->data; | |||||
} | } | ||||
pk++; | pk++; | ||||
} | } | ||||
item_type = -1; | item_type = -1; | ||||
return (-1); // keyword not found | |||||
return -1; // keyword not found | |||||
} | } | ||||
if (type == tPHONEMEMNEM) { | if (type == tPHONEMEMNEM) { | ||||
return (LookupPhoneme(item_string, 2)); | |||||
return LookupPhoneme(item_string, 2); | |||||
} | } | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
error(msg, NULL); | error(msg, NULL); | ||||
value = max; | value = max; | ||||
} | } | ||||
return (value); | |||||
return value; | |||||
} | } | ||||
value = NextItem(type); | value = NextItem(type); | ||||
if ((control & 2) && (item_terminator == ',')) | if ((control & 2) && (item_terminator == ',')) | ||||
return (value); | |||||
return value; | |||||
if (item_terminator != ')') { | if (item_terminator != ')') { | ||||
error("Expected ')'", NULL); | error("Expected ')'", NULL); | ||||
} | } | ||||
return (value); | |||||
return value; | |||||
} | } | ||||
value = max; | value = max; | ||||
if (value < min) | if (value < min) | ||||
value = min; | value = min; | ||||
return (value - min); | |||||
return value - min; | |||||
} | } | ||||
prog_out[3] = word2; | prog_out[3] = word2; | ||||
prog_out += 4; | prog_out += 4; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
spectseq = SpectSeqCreate(); | spectseq = SpectSeqCreate(); | ||||
if (spectseq == NULL) { | if (spectseq == NULL) { | ||||
Error("Failed to create SpectSeq"); | Error("Failed to create SpectSeq"); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
snprintf(filename, sizeof(filename), "%s/../phsource/%s", path_home, path); | snprintf(filename, sizeof(filename), "%s/../phsource/%s", path_home, path); | ||||
if (spectseq->frames == NULL) { | if (spectseq->frames == NULL) { | ||||
error("Bad vowel file, no frames: '%s'", path); | error("Bad vowel file, no frames: '%s'", path); | ||||
SpectSeqDestroy(spectseq); | SpectSeqDestroy(spectseq); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
// do we need additional klatt data ? | // do we need additional klatt data ? | ||||
} | } | ||||
SpectSeqDestroy(spectseq); | SpectSeqDestroy(spectseq); | ||||
return (displ); | |||||
return displ; | |||||
} | } | ||||
error("WAV file is not mono: %s", fname); | error("WAV file is not mono: %s", fname); | ||||
} | } | ||||
remove(fname_temp); | remove(fname_temp); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
f = fopen(fname_temp, "rb"); | f = fopen(fname_temp, "rb"); | ||||
if (f == NULL) { | if (f == NULL) { | ||||
error("Can't read temp file: %s", fname_temp); | error("Can't read temp file: %s", fname_temp); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (f_report != NULL) | if (f_report != NULL) | ||||
fprintf(f_report, "resampled %s\n", fname); | fprintf(f_report, "resampled %s\n", fname); | ||||
fclose(f); | fclose(f); | ||||
remove(fname_temp); | remove(fname_temp); | ||||
} | } | ||||
return (displ | 0x800000); // set bit 23 to indicate a wave file rather than a spectrum | |||||
return displ | 0x800000; // set bit 23 to indicate a wave file rather than a spectrum | |||||
} | } | ||||
n_envelopes++; | n_envelopes++; | ||||
} | } | ||||
return (displ); | |||||
return displ; | |||||
} | } | ||||
chars++; | chars++; | ||||
} | } | ||||
return ((hash+chars) & 0xff); | |||||
return (hash+chars) & 0xff; | |||||
} | } | ||||
displ = ftell(f_phdata); | displ = ftell(f_phdata); | ||||
fwrite(env, 1, 128, f_phdata); | fwrite(env, 1, 128, f_phdata); | ||||
return (displ); | |||||
return displ; | |||||
} | } | ||||
static int LoadDataFile(const char *path, int control) | static int LoadDataFile(const char *path, int control) | ||||
char buf[sizeof(path_home)+150]; | char buf[sizeof(path_home)+150]; | ||||
if (strcmp(path, "NULL") == 0) | if (strcmp(path, "NULL") == 0) | ||||
return (0); | |||||
return 0; | |||||
if (strcmp(path, "DFT") == 0) | if (strcmp(path, "DFT") == 0) | ||||
return (1); | |||||
return 1; | |||||
count_references++; | count_references++; | ||||
sprintf(buf, "%s/../phsource/%s.wav", path_home, path); | sprintf(buf, "%s/../phsource/%s.wav", path_home, path); | ||||
if ((f = fopen(buf, "rb")) == NULL) { | if ((f = fopen(buf, "rb")) == NULL) { | ||||
error("Can't read file: %s", path); | error("Can't read file: %s", path); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
ref_hash_tab[hash] = p2; | ref_hash_tab[hash] = p2; | ||||
} | } | ||||
return (addr); | |||||
return addr; | |||||
} | } | ||||
*prog_out++ = amp_env; | *prog_out++ = amp_env; | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
*prog_out++ = sound_instns[keyword-kFMT] + ((value & 0xff) << 4) + ((addr >> 16) & 0xf); | *prog_out++ = sound_instns[keyword-kFMT] + ((value & 0xff) << 4) + ((addr >> 16) & 0xf); | ||||
*prog_out++ = addr & 0xffff; | *prog_out++ = addr & 0xffff; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
word2 = 0; | word2 = 0; | ||||
if (prog_out >= prog_out_max) { | if (prog_out >= prog_out_max) { | ||||
error("Phoneme program too large", NULL); | error("Phoneme program too large", NULL); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((key = NextItem(tCONDITION)) < 0) | if ((key = NextItem(tCONDITION)) < 0) | ||||
error("Unexpected keyword '%s'", item_string); | error("Unexpected keyword '%s'", item_string); | ||||
if ((strcmp(item_string, "phoneme") == 0) || (strcmp(item_string, "endphoneme") == 0)) | if ((strcmp(item_string, "phoneme") == 0) || (strcmp(item_string, "endphoneme") == 0)) | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
// output the word | // output the word | ||||
if_stack[if_level].p_then = prog_out; | if_stack[if_level].p_then = prog_out; | ||||
*prog_out++ = i_JUMP_FALSE; | *prog_out++ = i_JUMP_FALSE; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (if_level < 1) { | if (if_level < 1) { | ||||
error("ELSE not expected", NULL); | error("ELSE not expected", NULL); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (if_stack[if_level].returned == 0) { | if (if_stack[if_level].returned == 0) { | ||||
if_stack[if_level].p_else = ref; | if_stack[if_level].p_else = ref; | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
{ | { | ||||
if (if_level < 1) { | if (if_level < 1) { | ||||
error("ELIF not expected", NULL); | error("ELIF not expected", NULL); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
CompileElse(); | CompileElse(); | ||||
CompileIf(1); | CompileIf(1); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (if_level < 1) { | if (if_level < 1) { | ||||
error("ENDIF not expected", NULL); | error("ENDIF not expected", NULL); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
FillThen(0); | FillThen(0); | ||||
} | } | ||||
if_level--; | if_level--; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (type == 0) { | if (type == 0) { | ||||
// check the instructions in the Switch | // check the instructions in the Switch | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (type == 1) | if (type == 1) | ||||
*prog_out++ = i_SWITCH_PREVVOWEL+6; | *prog_out++ = i_SWITCH_PREVVOWEL+6; | ||||
if (type == 2) | if (type == 2) | ||||
*prog_out++ = i_SWITCH_NEXTVOWEL+6; | *prog_out++ = i_SWITCH_NEXTVOWEL+6; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
for (ix = 0; ix < n_phoneme_tabs; ix++) { | for (ix = 0; ix < n_phoneme_tabs; ix++) { | ||||
if (strcmp(phoneme_tab_list2[ix].name, string) == 0) { | if (strcmp(phoneme_tab_list2[ix].name, string) == 0) { | ||||
return (&phoneme_tab_list2[ix]); | |||||
return &phoneme_tab_list2[ix]; | |||||
} | } | ||||
} | } | ||||
error("Unknown phoneme table: '%s'", string); | error("Unknown phoneme table: '%s'", string); | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
// is this the name of a phoneme which is in scope | // is this the name of a phoneme which is in scope | ||||
if ((strlen(string) <= 4) && ((ix = LookupPhoneme(string, 0)) != -1)) { | if ((strlen(string) <= 4) && ((ix = LookupPhoneme(string, 0)) != -1)) { | ||||
return (&phoneme_tab2[ix]); | |||||
return &phoneme_tab2[ix]; | |||||
} | } | ||||
// no, treat the name as phonemetable/phoneme | // no, treat the name as phonemetable/phoneme | ||||
phtab = FindPhonemeTable(buf); | phtab = FindPhonemeTable(buf); | ||||
if (phtab == NULL) { | if (phtab == NULL) { | ||||
return (NULL); // phoneme table not found | |||||
return NULL; // phoneme table not found | |||||
} | } | ||||
mnem = StringToWord(phname); | mnem = StringToWord(phname); | ||||
for (ix = 1; ix < 256; ix++) { | for (ix = 1; ix < 256; ix++) { | ||||
if (mnem == phtab->phoneme_tab_ptr[ix].mnemonic) { | if (mnem == phtab->phoneme_tab_ptr[ix].mnemonic) { | ||||
return (&phtab->phoneme_tab_ptr[ix]); | |||||
return &phtab->phoneme_tab_ptr[ix]; | |||||
} | } | ||||
} | } | ||||
error("Phoneme reference not found: '%s'", string); | error("Phoneme reference not found: '%s'", string); | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
NextItem(tSTRING); | NextItem(tSTRING); | ||||
if (compile_phoneme) { | if (compile_phoneme) { | ||||
phcode = LookupPhoneme(item_string, 1); // declare phoneme if not already there | phcode = LookupPhoneme(item_string, 1); // declare phoneme if not already there | ||||
if (phcode == -1) return (0); | |||||
if (phcode == -1) return 0; | |||||
phoneme_out = &phoneme_tab2[phcode]; | phoneme_out = &phoneme_tab2[phcode]; | ||||
} else { | } else { | ||||
// declare a procedure | // declare a procedure | ||||
if (n_procs >= N_PROCS) { | if (n_procs >= N_PROCS) { | ||||
error("Too many procedures", NULL); | error("Too many procedures", NULL); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
strcpy(proc_names[n_procs], item_string); | strcpy(proc_names[n_procs], item_string); | ||||
phoneme_out = &phoneme_out2; | phoneme_out = &phoneme_out2; | ||||
fwrite(prog_buf, sizeof(USHORT), prog_out - prog_buf, f_phindex); | fwrite(prog_buf, sizeof(USHORT), prog_out - prog_buf, f_phindex); | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int LookupEnvelopeName(const char *name) | int LookupEnvelopeName(const char *name) | ||||
{ | { | ||||
return (LookupMnem(envelope_names, name)); | |||||
return LookupMnem(envelope_names, name); | |||||
} | } | ||||
int c2; | int c2; | ||||
if (((c2 = (c & 0xff)) == 0) || (c > ' ')) | if (((c2 = (c & 0xff)) == 0) || (c > ' ')) | ||||
return (0); | |||||
return (1); | |||||
return 0; | |||||
return 1; | |||||
} | } | ||||
if (f_log != NULL) | if (f_log != NULL) | ||||
fprintf(f_log, "Can't access (%s) file '%s'\n", access, fname); | fprintf(f_log, "Can't access (%s) file '%s'\n", access, fname); | ||||
} | } | ||||
return (f); | |||||
return f; | |||||
} | } | ||||
{ | { | ||||
while (table->mnem != NULL) { | while (table->mnem != NULL) { | ||||
if (table->value == value) | if (table->value == value) | ||||
return (table->mnem); | |||||
return table->mnem; | |||||
table++; | table++; | ||||
} | } | ||||
return (""); /* not found */ | |||||
return ""; /* not found */ | |||||
} | } | ||||
while (ix < 8) | while (ix < 8) | ||||
output[ix++] = ' '; | output[ix++] = ' '; | ||||
output[ix] = 0; | output[ix] = 0; | ||||
return (output); | |||||
return output; | |||||
} | } | ||||
} | } | ||||
if (word[0] == 0) { | if (word[0] == 0) { | ||||
return (0); /* blank line */ | |||||
return 0; /* blank line */ | |||||
} | } | ||||
if (text_mode) | if (text_mode) | ||||
dict_line[0] = length; | dict_line[0] = length; | ||||
return (length); | |||||
return length; | |||||
} | } | ||||
if ((f_in = fopen(fname, "r")) == NULL) { | if ((f_in = fopen(fname, "r")) == NULL) { | ||||
sprintf(fname, "%s%s", path, filename); | sprintf(fname, "%s%s", path, filename); | ||||
if ((f_in = fopen(fname, "r")) == NULL) | if ((f_in = fopen(fname, "r")) == NULL) | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
if (f_log != NULL) | if (f_log != NULL) | ||||
if (f_log != NULL) | if (f_log != NULL) | ||||
fprintf(f_log, "\t%d entries\n", count); | fprintf(f_log, "\t%d entries\n", count); | ||||
fclose(f_in); | fclose(f_in); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int isHexDigit(int c) | int isHexDigit(int c) | ||||
{ | { | ||||
if ((c >= '0') && (c <= '9')) | if ((c >= '0') && (c <= '9')) | ||||
return (c - '0'); | |||||
return c - '0'; | |||||
if ((c >= 'a') && (c <= 'f')) | if ((c >= 'a') && (c <= 'f')) | ||||
return (c - 'a' + 10); | |||||
return c - 'a' + 10; | |||||
if ((c >= 'A') && (c <= 'F')) | if ((c >= 'A') && (c <= 'F')) | ||||
return (c - 'A' + 10); | |||||
return (-1); | |||||
return c - 'A' + 10; | |||||
return -1; | |||||
} | } | ||||
fprintf(f_log, "%5d: Syntax error\n", linenum); | fprintf(f_log, "%5d: Syntax error\n", linenum); | ||||
error_count++; | error_count++; | ||||
} | } | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
EncodePhonemes(rule_phonemes, buf, &bad_phoneme); | EncodePhonemes(rule_phonemes, buf, &bad_phoneme); | ||||
output[len++] = 0; | output[len++] = 0; | ||||
prule = (char *)malloc(len); | prule = (char *)malloc(len); | ||||
memcpy(prule, output, len); | memcpy(prule, output, len); | ||||
return (prule); | |||||
return prule; | |||||
} | } | ||||
int ix; | int ix; | ||||
if ((ix = strcmp(pa = *a, pb = *b)) != 0) | if ((ix = strcmp(pa = *a, pb = *b)) != 0) | ||||
return (ix); | |||||
return ix; | |||||
pa += (strlen(pa)+1); | pa += (strlen(pa)+1); | ||||
pb += (strlen(pb)+1); | pb += (strlen(pb)+1); | ||||
return (strcmp(pa, pb)); | |||||
return strcmp(pa, pb); | |||||
} | } | ||||
// Sort long names before short names | // Sort long names before short names | ||||
int ix; | int ix; | ||||
ix = strlen(b->name) - strlen(a->name); | ix = strlen(b->name) - strlen(a->name); | ||||
if (ix != 0) return (ix); | |||||
if (ix != 0) return ix; | |||||
ix = strcmp(a->name, b->name); | ix = strcmp(a->name, b->name); | ||||
if (ix != 0) return (ix); | |||||
return (a->start-b->start); | |||||
if (ix != 0) return ix; | |||||
return a->start-b->start; | |||||
} | } | ||||
if (!IsDigit09(p[0]) || !IsDigit09(p[1])) { | if (!IsDigit09(p[0]) || !IsDigit09(p[1])) { | ||||
fprintf(f_log, "%5d: Expected 2 digits after '.L'\n", linenum); | fprintf(f_log, "%5d: Expected 2 digits after '.L'\n", linenum); | ||||
error_count++; | error_count++; | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
group = atoi(&p[0]); | group = atoi(&p[0]); | ||||
if (group >= N_LETTER_GROUPS) { | if (group >= N_LETTER_GROUPS) { | ||||
fprintf(f_log, "%5d: lettergroup out of range (01-%.2d)\n", linenum, N_LETTER_GROUPS-1); | fprintf(f_log, "%5d: lettergroup out of range (01-%.2d)\n", linenum, N_LETTER_GROUPS-1); | ||||
error_count++; | error_count++; | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
while (!isspace2(*p)) p++; | while (!isspace2(*p)) p++; | ||||
fputc(RULE_GROUP_END, f_out); | fputc(RULE_GROUP_END, f_out); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
group_name[0] = 0; | group_name[0] = 0; | ||||
if ((f_temp = fopen_log(fname_temp, "wb")) == NULL) | if ((f_temp = fopen_log(fname_temp, "wb")) == NULL) | ||||
return (1); | |||||
return 1; | |||||
for (;;) { | for (;;) { | ||||
linenum++; | linenum++; | ||||
qsort((void *)rgroup, n_rgroups, sizeof(rgroup[0]), (int(__cdecl *)(const void *, const void *))rgroup_sorter); | qsort((void *)rgroup, n_rgroups, sizeof(rgroup[0]), (int(__cdecl *)(const void *, const void *))rgroup_sorter); | ||||
if ((f_temp = fopen(fname_temp, "rb")) == NULL) | if ((f_temp = fopen(fname_temp, "rb")) == NULL) | ||||
return (2); | |||||
return 2; | |||||
prev_rgroup_name = "\n"; | prev_rgroup_name = "\n"; | ||||
remove(fname_temp); | remove(fname_temp); | ||||
fprintf(f_log, "\t%d rules, %d groups (%d)\n\n", count, n_rgroups, n_groups3); | fprintf(f_log, "\t%d rules, %d groups (%d)\n\n", count, n_rgroups, n_groups3); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((f_in = fopen_log(fname_in, "r")) == NULL) { | if ((f_in = fopen_log(fname_in, "r")) == NULL) { | ||||
if (fname_err) | if (fname_err) | ||||
strcpy(fname_err, fname_in); | strcpy(fname_err, fname_in); | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
} | } | ||||
if (fname_err) | if (fname_err) | ||||
strcpy(fname_err, fname_out); | strcpy(fname_err, fname_out); | ||||
fclose(f_in); | fclose(f_in); | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
sprintf(fname_temp, "%s%ctemp", path_home, PATHSEP); | sprintf(fname_temp, "%s%ctemp", path_home, PATHSEP); | ||||
LoadDictionary(translator, dict_name, 0); | LoadDictionary(translator, dict_name, 0); | ||||
return (error_count); | |||||
return error_count; | |||||
} | } |
unsigned int word; | unsigned int word; | ||||
if (string == NULL) | if (string == NULL) | ||||
return (0); | |||||
return 0; | |||||
word = 0; | word = 0; | ||||
for (ix = 0; ix < 4; ix++) { | for (ix = 0; ix < 4; ix++) { | ||||
c = string[ix]; | c = string[ix]; | ||||
word |= (c << (ix*8)); | word |= (c << (ix*8)); | ||||
} | } | ||||
return (word); | |||||
return word; | |||||
} | } | ||||
#pragma GCC visibility push(default) | #pragma GCC visibility push(default) |
word2 = word2 << 8; | word2 = word2 << 8; | ||||
word2 |= (word >> ix) & 0xff; | word2 |= (word >> ix) & 0xff; | ||||
} | } | ||||
return (word2); | |||||
return word2; | |||||
#else | #else | ||||
return (word); | |||||
return word; | |||||
#endif | #endif | ||||
} | } | ||||
{ | { | ||||
while (table->mnem != NULL) { | while (table->mnem != NULL) { | ||||
if (strcmp(string, table->mnem) == 0) | if (strcmp(string, table->mnem) == 0) | ||||
return (table->value); | |||||
return table->value; | |||||
table++; | table++; | ||||
} | } | ||||
return (table->value); | |||||
return table->value; | |||||
} | } | ||||
} | } | ||||
if (f != NULL) | if (f != NULL) | ||||
fclose(f); | fclose(f); | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
tr->data_dictlist = Alloc(size); | tr->data_dictlist = Alloc(size); | ||||
if (size <= (N_HASH_DICT + sizeof(int)*2)) { | if (size <= (N_HASH_DICT + sizeof(int)*2)) { | ||||
fprintf(stderr, "Empty _dict file: '%s\n", fname); | fprintf(stderr, "Empty _dict file: '%s\n", fname); | ||||
return (2); | |||||
return 2; | |||||
} | } | ||||
if ((Reverse4Bytes(pw[0]) != N_HASH_DICT) || | if ((Reverse4Bytes(pw[0]) != N_HASH_DICT) || | ||||
(length <= 0) || (length > 0x8000000)) { | (length <= 0) || (length > 0x8000000)) { | ||||
fprintf(stderr, "Bad data: '%s' (%x length=%x)\n", fname, Reverse4Bytes(pw[0]), length); | fprintf(stderr, "Bad data: '%s' (%x length=%x)\n", fname, Reverse4Bytes(pw[0]), length); | ||||
return (2); | |||||
return 2; | |||||
} | } | ||||
tr->data_dictrules = &(tr->data_dictlist[length]); | tr->data_dictrules = &(tr->data_dictlist[length]); | ||||
fprintf(stderr, "Full dictionary is not installed for '%s'\n", name); | fprintf(stderr, "Full dictionary is not installed for '%s'\n", name); | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
chars++; | chars++; | ||||
} | } | ||||
return ((hash+chars) & 0x3ff); // a 10 bit hash code | |||||
return (hash+chars) & 0x3ff; // a 10 bit hash code | |||||
} | } | ||||
utf8_in(bad_phoneme, p); | utf8_in(bad_phoneme, p); | ||||
} | } | ||||
*outptr++ = 0; | *outptr++ = 0; | ||||
return (p+1); | |||||
return p+1; | |||||
} | } | ||||
if (max <= 0) | if (max <= 0) | ||||
if (c == 0) { | if (c == 0) { | ||||
if (strcmp(p_lang, "en") == 0) { | if (strcmp(p_lang, "en") == 0) { | ||||
*p_lang = 0; // don't need "en", it's assumed by default | *p_lang = 0; // don't need "en", it's assumed by default | ||||
return (p); | |||||
return p; | |||||
} | } | ||||
} else { | } else { | ||||
*outptr++ = '|'; // more phonemes follow, terminate language string with separator | *outptr++ = '|'; // more phonemes follow, terminate language string with separator | ||||
} | } | ||||
/* terminate the encoded string */ | /* terminate the encoded string */ | ||||
*outptr = 0; | *outptr = 0; | ||||
return (p); | |||||
return p; | |||||
} | } | ||||
if (ph->code == phonEND_WORD) { | if (ph->code == phonEND_WORD) { | ||||
// ignore | // ignore | ||||
phon_out[0] = 0; | phon_out[0] = 0; | ||||
return (phon_out); | |||||
return phon_out; | |||||
} | } | ||||
if (ph->code == phonSWITCH) { | if (ph->code == phonSWITCH) { | ||||
// the tone_ph field contains a phoneme table number | // the tone_ph field contains a phoneme table number | ||||
p = phoneme_tab_list[plist->tone_ph].name; | p = phoneme_tab_list[plist->tone_ph].name; | ||||
sprintf(phon_out, "(%s)", p); | sprintf(phon_out, "(%s)", p); | ||||
return (phon_out + strlen(phon_out)); | |||||
return phon_out + strlen(phon_out); | |||||
} | } | ||||
if (use_ipa) { | if (use_ipa) { | ||||
if (*p == 0x20) { | if (*p == 0x20) { | ||||
// indicates no name for this phoneme | // indicates no name for this phoneme | ||||
*phon_out = 0; | *phon_out = 0; | ||||
return (phon_out); | |||||
return phon_out; | |||||
} | } | ||||
if ((*p != 0) && ((*p & 0xff) < 0x20)) { | if ((*p != 0) && ((*p & 0xff) < 0x20)) { | ||||
// name starts with a flags byte | // name starts with a flags byte | ||||
strcpy(phon_out, p); | strcpy(phon_out, p); | ||||
phon_out += len; | phon_out += len; | ||||
*phon_out = 0; | *phon_out = 0; | ||||
return (phon_out); | |||||
return phon_out; | |||||
} | } | ||||
} | } | ||||
phon_out = &phon_out[ix]; | phon_out = &phon_out[ix]; | ||||
*phon_out = 0; | *phon_out = 0; | ||||
return (phon_out); | |||||
return phon_out; | |||||
} | } | ||||
phon_out_size = N_PHON_OUT; | phon_out_size = N_PHON_OUT; | ||||
if ((phon_out_buf = (char *)realloc(phon_out_buf, phon_out_size)) == NULL) { | if ((phon_out_buf = (char *)realloc(phon_out_buf, phon_out_size)) == NULL) { | ||||
phon_out_size = 0; | phon_out_size = 0; | ||||
return (""); | |||||
return ""; | |||||
} | } | ||||
} | } | ||||
phon_out_size = phon_out_ix + len + N_PHON_OUT; | phon_out_size = phon_out_ix + len + N_PHON_OUT; | ||||
if ((phon_out_buf = (char *)realloc(phon_out_buf, phon_out_size)) == NULL) { | if ((phon_out_buf = (char *)realloc(phon_out_buf, phon_out_size)) == NULL) { | ||||
phon_out_size = 0; | phon_out_size = 0; | ||||
return (""); | |||||
return ""; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
if (!phon_out_buf) | if (!phon_out_buf) | ||||
return (""); | |||||
return ""; | |||||
phon_out_buf[phon_out_ix] = 0; | phon_out_buf[phon_out_ix] = 0; | ||||
return (phon_out_buf); | |||||
return phon_out_buf; | |||||
} | } | ||||
p = tr->letterGroups[group]; | p = tr->letterGroups[group]; | ||||
if (p == NULL) | if (p == NULL) | ||||
return (0); | |||||
return 0; | |||||
while (*p != RULE_GROUP_END) { | while (*p != RULE_GROUP_END) { | ||||
if (pre) { | if (pre) { | ||||
} | } | ||||
if (*p == 0) { | if (*p == 0) { | ||||
if (pre) | if (pre) | ||||
return (len); | |||||
return (w-word); // matched a complete string | |||||
return len; | |||||
return w-word; // matched a complete string | |||||
} | } | ||||
while (*p++ != 0) ; // skip to end of string | while (*p++ != 0) ; // skip to end of string | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (tr->letter_groups[group] != NULL) { | if (tr->letter_groups[group] != NULL) { | ||||
if (wcschr(tr->letter_groups[group], letter)) | if (wcschr(tr->letter_groups[group], letter)) | ||||
return (1); | |||||
return (0); | |||||
return 1; | |||||
return 0; | |||||
} | } | ||||
if (group > 7) | if (group > 7) | ||||
return (0); | |||||
return 0; | |||||
if (tr->letter_bits_offset > 0) { | if (tr->letter_bits_offset > 0) { | ||||
if (((letter2 = (letter - tr->letter_bits_offset)) > 0) && (letter2 < 0x100)) | if (((letter2 = (letter - tr->letter_bits_offset)) > 0) && (letter2 < 0x100)) | ||||
letter = letter2; | letter = letter2; | ||||
else | else | ||||
return (0); | |||||
return 0; | |||||
} else { | } else { | ||||
if ((letter >= 0xc0) && (letter < N_REMOVE_ACCENT)) | if ((letter >= 0xc0) && (letter < N_REMOVE_ACCENT)) | ||||
return (tr->letter_bits[remove_accent[letter-0xc0]] & (1L << group)); | |||||
return tr->letter_bits[remove_accent[letter-0xc0]] & (1L << group); | |||||
} | } | ||||
if ((letter >= 0) && (letter < 0x100)) | if ((letter >= 0) && (letter < 0x100)) | ||||
return (tr->letter_bits[letter] & (1L << group)); | |||||
return tr->letter_bits[letter] & (1L << group); | |||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int IsVowel(Translator *tr, int letter) | int IsVowel(Translator *tr, int letter) | ||||
{ | { | ||||
return (IsLetter(tr, letter, LETTERGP_VOWEL2)); | |||||
return IsLetter(tr, letter, LETTERGP_VOWEL2); | |||||
} | } | ||||
end_flags = TranslateRules(tr, word, ph_buf, sizeof(ph_buf), NULL, FLAG_UNPRON_TEST, NULL); | end_flags = TranslateRules(tr, word, ph_buf, sizeof(ph_buf), NULL, FLAG_UNPRON_TEST, NULL); | ||||
word[-1] = c; | word[-1] = c; | ||||
if ((end_flags == 0) || (end_flags & SUFX_UNPRON)) | if ((end_flags == 0) || (end_flags & SUFX_UNPRON)) | ||||
return (1); | |||||
return (0); | |||||
return 1; | |||||
return 0; | |||||
} | } | ||||
utf8_in(&c, word); | utf8_in(&c, word); | ||||
if ((tr->letter_bits_offset > 0) && (c < 0x241)) { | if ((tr->letter_bits_offset > 0) && (c < 0x241)) { | ||||
// Latin characters for a language with a non-latin alphabet | // Latin characters for a language with a non-latin alphabet | ||||
return (0); // so we can re-translate the word as English | |||||
return 0; // so we can re-translate the word as English | |||||
} | } | ||||
if (((alphabet = AlphabetFromChar(c)) != NULL) && (alphabet->offset != tr->letter_bits_offset)) { | if (((alphabet = AlphabetFromChar(c)) != NULL) && (alphabet->offset != tr->letter_bits_offset)) { | ||||
// Character is not in our alphabet | // Character is not in our alphabet | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 1) | if (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 1) | ||||
return (0); | |||||
return 0; | |||||
if (((c = *word) == ' ') || (c == 0) || (c == '\'')) | if (((c = *word) == ' ') || (c == 0) || (c == '\'')) | ||||
return (0); | |||||
return 0; | |||||
index = 0; | index = 0; | ||||
count = 0; | count = 0; | ||||
} | } | ||||
if ((c != '\'') && !iswalpha2(c)) | if ((c != '\'') && !iswalpha2(c)) | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((vowel_posn > 2) && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 2)) { | if ((vowel_posn > 2) && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 2)) { | ||||
// Lookup unpronounable rules in *_rules | // Lookup unpronounable rules in *_rules | ||||
return (Unpronouncable2(tr, word)); | |||||
return Unpronouncable2(tr, word); | |||||
} | } | ||||
if (c1 == tr->langopts.param[LOPT_UNPRONOUNCABLE]) | if (c1 == tr->langopts.param[LOPT_UNPRONOUNCABLE]) | ||||
vowel_posn--; // disregard this as the initial letter when counting | vowel_posn--; // disregard this as the initial letter when counting | ||||
if (vowel_posn > (tr->langopts.max_initial_consonants+1)) | if (vowel_posn > (tr->langopts.max_initial_consonants+1)) | ||||
return (1); // no vowel, or no vowel in first few letters | |||||
return 1; // no vowel, or no vowel in first few letters | |||||
return (0); | |||||
return 0; | |||||
} | } | ||||
*stressed_syllable = primary_posn; | *stressed_syllable = primary_posn; | ||||
*vowel_count = count; | *vowel_count = count; | ||||
return (max_stress); | |||||
return max_stress; | |||||
} | } | ||||
static const char str_pause[2] = { phonPAUSE_NOLINK, 0 }; | static const char str_pause[2] = { phonPAUSE_NOLINK, 0 }; | ||||
if (tr->data_dictrules == NULL) | if (tr->data_dictrules == NULL) | ||||
return (0); | |||||
return 0; | |||||
if (dict_flags != NULL) | if (dict_flags != NULL) | ||||
dict_flags0 = dict_flags[0]; | dict_flags0 = dict_flags[0]; | ||||
// not a Latin alphabet, switch to the default Latin alphabet language | // not a Latin alphabet, switch to the default Latin alphabet language | ||||
if ((letter <= 0x241) && iswalpha2(letter)) { | if ((letter <= 0x241) && iswalpha2(letter)) { | ||||
sprintf(phonemes, "%c%s", phonSWITCH, tr->langopts.ascii_language); | sprintf(phonemes, "%c%s", phonSWITCH, tr->langopts.ascii_language); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
if (((alphabet = AlphabetFromChar(letter)) != NULL) && (alphabet->offset != tr->letter_bits_offset)) { | if (((alphabet = AlphabetFromChar(letter)) != NULL) && (alphabet->offset != tr->letter_bits_offset)) { | ||||
if (tr->langopts.alt_alphabet == alphabet->offset) { | if (tr->langopts.alt_alphabet == alphabet->offset) { | ||||
sprintf(phonemes, "%c%s", phonSWITCH, WordToString2(tr->langopts.alt_alphabet_lang)); | sprintf(phonemes, "%c%s", phonSWITCH, WordToString2(tr->langopts.alt_alphabet_lang)); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (alphabet->flags & AL_WORDS) { | if (alphabet->flags & AL_WORDS) { | ||||
// switch to the nominated language for this alphabet | // switch to the nominated language for this alphabet | ||||
sprintf(phonemes, "%c%s", phonSWITCH, WordToString2(alphabet->language)); | sprintf(phonemes, "%c%s", phonSWITCH, WordToString2(alphabet->language)); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
if (match1.points > 0) { | if (match1.points > 0) { | ||||
if (word_flags & FLAG_UNPRON_TEST) | if (word_flags & FLAG_UNPRON_TEST) | ||||
return (match1.end_type | 1); | |||||
return match1.end_type | 1; | |||||
if ((match1.phonemes[0] == phonSWITCH) && ((word_flags & FLAG_DONT_SWITCH_TRANSLATOR) == 0)) { | if ((match1.phonemes[0] == phonSWITCH) && ((word_flags & FLAG_DONT_SWITCH_TRANSLATOR) == 0)) { | ||||
// an instruction to switch language, return immediately so we can re-translate | // an instruction to switch language, return immediately so we can re-translate | ||||
strcpy(phonemes, match1.phonemes); | strcpy(phonemes, match1.phonemes); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((option_phonemes & espeakPHONEMES_TRACE) && ((word_flags & FLAG_NO_TRACE) == 0)) { | if ((option_phonemes & espeakPHONEMES_TRACE) && ((word_flags & FLAG_NO_TRACE) == 0)) { | ||||
} | } | ||||
strcpy(end_phonemes, match1.phonemes); | strcpy(end_phonemes, match1.phonemes); | ||||
memcpy(p_start, word_copy, strlen(word_copy)); | memcpy(p_start, word_copy, strlen(word_copy)); | ||||
return (match1.end_type); | |||||
return match1.end_type; | |||||
} | } | ||||
} | } | ||||
if (match1.del_fwd != NULL) | if (match1.del_fwd != NULL) | ||||
memcpy(p_start, word_copy, strlen(word_copy)); | memcpy(p_start, word_copy, strlen(word_copy)); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
*p2 = 0; | *p2 = 0; | ||||
ix = p2 - buf; | ix = p2 - buf; | ||||
memcpy(text, buf, ix); | memcpy(text, buf, ix); | ||||
return (ix | 0x40); // bit 6 indicates compressed characters | |||||
return ix | 0x40; // bit 6 indicates compressed characters | |||||
} else { | } else { | ||||
return (strlen(text)); | |||||
return strlen(text); | |||||
} | } | ||||
} | } | ||||
if (p == NULL) { | if (p == NULL) { | ||||
if (flags != NULL) | if (flags != NULL) | ||||
*flags = 0; | *flags = 0; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
// Find the first entry in the list for this hash value which matches. | // Find the first entry in the list for this hash value which matches. | ||||
print_dictionary_flags(flags, dict_flags_buf, sizeof(dict_flags_buf)); | print_dictionary_flags(flags, dict_flags_buf, sizeof(dict_flags_buf)); | ||||
fprintf(f_trans, "Flags: %s %s\n", word1, dict_flags_buf); | fprintf(f_trans, "Flags: %s %s\n", word1, dict_flags_buf); | ||||
} | } | ||||
return (0); // no phoneme translation found here, only flags. So use rules | |||||
return 0; // no phoneme translation found here, only flags. So use rules | |||||
} | } | ||||
if (flags != NULL) | if (flags != NULL) | ||||
if ((word[ix] == 0) && !IsAlpha(c)) { | if ((word[ix] == 0) && !IsAlpha(c)) { | ||||
flags[0] |= FLAG_MAX3; | flags[0] |= FLAG_MAX3; | ||||
} | } | ||||
return (word_end); | |||||
return word_end; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
// set the skip words flag | // set the skip words flag | ||||
flags[0] |= FLAG_SKIPWORDS; | flags[0] |= FLAG_SKIPWORDS; | ||||
dictionary_skipwords = length; | dictionary_skipwords = length; | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
ph_out[0] = 0; | ph_out[0] = 0; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
ph_out[0] = 0; | ph_out[0] = 0; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
strcpy(ph_out, word_phonemes); | strcpy(ph_out, word_phonemes); | ||||
option_sayas = say_as; | option_sayas = say_as; | ||||
} | } | ||||
return (flags0); | |||||
return flags0; | |||||
} | } | ||||
flags[0] = flags[1] = 0; | flags[0] = flags[1] = 0; | ||||
LookupDictList(tr, &word1, buf, flags, 0, NULL); | LookupDictList(tr, &word1, buf, flags, 0, NULL); | ||||
*flags_out = flags; | *flags_out = flags; | ||||
return (flags[0]); | |||||
return flags[0]; | |||||
} | } | ||||
if (ending[0] == '\'') | if (ending[0] == '\'') | ||||
end_flags &= ~FLAG_SUFX; // don't consider 's as an added suffix | end_flags &= ~FLAG_SUFX; // don't consider 's as an added suffix | ||||
return (end_flags); | |||||
return end_flags; | |||||
} | } |
int fifo_is_command_enabled() | int fifo_is_command_enabled() | ||||
{ | { | ||||
SHOW("ENTER fifo_is_command_enabled=%d\n", (int)(0 == my_stop_is_required)); | SHOW("ENTER fifo_is_command_enabled=%d\n", (int)(0 == my_stop_is_required)); | ||||
return (0 == my_stop_is_required); | |||||
return 0 == my_stop_is_required; | |||||
} | } | ||||
typedef struct t_node { | typedef struct t_node { |
if (stress >= min_stress) | if (stress >= min_stress) | ||||
count++; | count++; | ||||
} | } | ||||
return (count); | |||||
return count; | |||||
} | } | ||||
if (syllable_tab[ix].stress >= limit) | if (syllable_tab[ix].stress >= limit) | ||||
break; | break; | ||||
} | } | ||||
return (ix - start); | |||||
return ix - start; | |||||
} | } | ||||
static int SetHeadIntonation(TUNE *tune, int syl_ix, int end_ix, int control) | static int SetHeadIntonation(TUNE *tune, int syl_ix, int end_ix, int control) | ||||
syl_ix++; | syl_ix++; | ||||
} | } | ||||
return (syl_ix); | |||||
return syl_ix; | |||||
} | } | ||||
ix++; | ix++; | ||||
} | } | ||||
return (ix); | |||||
return ix; | |||||
} | } | ||||
ix = SetHeadIntonation(tune, ix, tone_posn, 0); | ix = SetHeadIntonation(tune, ix, tone_posn, 0); | ||||
if (no_tonic) | if (no_tonic) | ||||
return (0); | |||||
return 0; | |||||
/* tonic syllable */ | /* tonic syllable */ | ||||
/******************/ | /******************/ | ||||
SetPitchGradient(ix, end, tune->tail_start, tune->tail_end); | SetPitchGradient(ix, end, tune->tail_start, tune->tail_end); | ||||
return (tone_pitch_env); | |||||
return tone_pitch_env; | |||||
} | } | ||||
int continuing = 0; | int continuing = 0; | ||||
if (control == 0) { | if (control == 0) { | ||||
return (calc_pitches2(start, end, tune_number)); | |||||
return calc_pitches2(start, end, tune_number); | |||||
} | } | ||||
if (start > 0) | if (start > 0) | ||||
ix = calc_pitch_segment(ix, tone_posn, th, tn, PRIMARY, continuing); | ix = calc_pitch_segment(ix, tone_posn, th, tn, PRIMARY, continuing); | ||||
if (no_tonic) | if (no_tonic) | ||||
return (0); | |||||
return 0; | |||||
/* tonic syllable */ | /* tonic syllable */ | ||||
/******************/ | /******************/ | ||||
SetPitchGradient(ix, end, tn->tail_start, tn->tail_end); | SetPitchGradient(ix, end, tn->tail_start, tn->tail_end); | ||||
return (tone_pitch_env); | |||||
return tone_pitch_env; | |||||
} | } | ||||
} else { | } else { | ||||
result = 0; | result = 0; | ||||
} | } | ||||
return (result); | |||||
return result; | |||||
} | } | ||||
sample_count++; | sample_count++; | ||||
if (out_ptr >= out_end) { | if (out_ptr >= out_end) { | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
vwave = 0.0; | vwave = 0.0; | ||||
} | } | ||||
return (resonator(&(kt_globals.rsn[RGL]), vwave)); | |||||
return resonator(&(kt_globals.rsn[RGL]), vwave); | |||||
} | } | ||||
vwave += kt_globals.pulse_shape_a; | vwave += kt_globals.pulse_shape_a; | ||||
lgtemp = vwave * 0.028; | lgtemp = vwave * 0.028; | ||||
return (lgtemp); | |||||
return lgtemp; | |||||
} else { | } else { | ||||
vwave = 0.0; | vwave = 0.0; | ||||
return (0.0); | |||||
return 0.0; | |||||
} | } | ||||
} | } | ||||
noise = kt_globals.nrand + (0.75 * nlast); | noise = kt_globals.nrand + (0.75 * nlast); | ||||
nlast = noise; | nlast = noise; | ||||
return (noise); | |||||
return noise; | |||||
} | } | ||||
}; | }; | ||||
if ((dB < 0) || (dB > 87)) { | if ((dB < 0) || (dB > 87)) { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
return ((double)(amptable[dB]) * 0.001); | |||||
return (double)(amptable[dB]) * 0.001; | |||||
} | } | ||||
frame_init(&kt_frame); /* get parameters for next frame of speech */ | frame_init(&kt_frame); /* get parameters for next frame of speech */ | ||||
if (parwave(&kt_frame) == 1) { | if (parwave(&kt_frame) == 1) { | ||||
return (1); // output buffer is full | |||||
return 1; // output buffer is full | |||||
} | } | ||||
} | } | ||||
sample_count -= fade; | sample_count -= fade; | ||||
kt_globals.nspfr = fade; | kt_globals.nspfr = fade; | ||||
if (parwave(&kt_frame) == 1) { | if (parwave(&kt_frame) == 1) { | ||||
return (1); // output buffer is full | |||||
return 1; // output buffer is full | |||||
} | } | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (resume == 0) | if (resume == 0) | ||||
SetSynth_Klatt(length, modulation, fr1, fr2, wvoice, 1); | SetSynth_Klatt(length, modulation, fr1, fr2, wvoice, 1); | ||||
return (Wavegen_Klatt(resume)); | |||||
return Wavegen_Klatt(resume); | |||||
} | } | ||||
p = (char *)memchr(buffer, ')', sizeof(buffer)); | p = (char *)memchr(buffer, ')', sizeof(buffer)); | ||||
if (!p || (unsigned)(p - buffer) >= sizeof(buffer) - 2) | if (!p || (unsigned)(p - buffer) >= sizeof(buffer) - 2) | ||||
return 0; | return 0; | ||||
return (p[1] == ' ' && p[2] == 'S'); | |||||
return p[1] == ' ' && p[2] == 'S'; | |||||
} | } | ||||
static ssize_t receive_from_mbrola(void *buffer, size_t bufsize) | static ssize_t receive_from_mbrola(void *buffer, size_t bufsize) |
TranslateRules(tr, &single_letter[2], ph_buf, 20, NULL, 0, NULL); | TranslateRules(tr, &single_letter[2], ph_buf, 20, NULL, 0, NULL); | ||||
} | } | ||||
} | } | ||||
return (ph_buf[0]); | |||||
return ph_buf[0]; | |||||
} | } | ||||
if (letter < base) | if (letter < base) | ||||
break; // not found | break; // not found | ||||
if (letter < (base+10)) | if (letter < (base+10)) | ||||
return (letter-base+'0'); | |||||
return letter-base+'0'; | |||||
} | } | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
#define L_SUB 0x4000 // subscript | #define L_SUB 0x4000 // subscript | ||||
if (c > letter) | if (c > letter) | ||||
break; | break; | ||||
if (c == letter) | if (c == letter) | ||||
return (derived_letters[ix+1]); | |||||
return derived_letters[ix+1]; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (ph_buf[0] == phonSWITCH) { | if (ph_buf[0] == phonSWITCH) { | ||||
strcpy(phonemes, ph_buf); | strcpy(phonemes, ph_buf); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((len + strlen(ph_buf2)) < N_WORD_PHONEMES) { | if ((len + strlen(ph_buf2)) < N_WORD_PHONEMES) { | ||||
strcpy(&phonemes[len], ph_buf2); | strcpy(&phonemes[len], ph_buf2); | ||||
} | } | ||||
return (n_bytes); | |||||
return n_bytes; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return (ordinal); | |||||
return ordinal; | |||||
} | } | ||||
if ((word[0] == 'a') || (word[0] == 'e')) { | if ((word[0] == 'a') || (word[0] == 'e')) { | ||||
if ((word[1] == ' ') || (word[1] == 'z') || ((word[1] == 't') && (word[2] == 't'))) | if ((word[1] == ' ') || (word[1] == 'z') || ((word[1] == 't') && (word[2] == 't'))) | ||||
return (0); | |||||
return 0; | |||||
if (((thousandplex == 1) || ((value % 1000) == 0)) && (word[1] == 'l')) | if (((thousandplex == 1) || ((value % 1000) == 0)) && (word[1] == 'l')) | ||||
return (0); // 1000-el | |||||
return 0; // 1000-el | |||||
return (1); | |||||
return 1; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
flags[1] = 0; | flags[1] = 0; | ||||
if (((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && !(wtab[0].flags & FLAG_ALL_UPPER)) || IsDigit09(word[-2])) | if (((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && !(wtab[0].flags & FLAG_ALL_UPPER)) || IsDigit09(word[-2])) | ||||
return (0); // not '2xx' | |||||
return 0; // not '2xx' | |||||
if (word[1] == ' ') { | if (word[1] == ' ') { | ||||
if ((tr->langopts.numbers & (NUM_ROMAN_CAPITALS | NUM_ROMAN_ORDINAL | NUM_ORDINAL_DOT)) && (wtab[0].flags & FLAG_HAS_DOT)) { | if ((tr->langopts.numbers & (NUM_ROMAN_CAPITALS | NUM_ROMAN_ORDINAL | NUM_ORDINAL_DOT)) && (wtab[0].flags & FLAG_HAS_DOT)) { | ||||
// allow single letter Roman ordinal followed by dot. | // allow single letter Roman ordinal followed by dot. | ||||
} else | } else | ||||
return (0); // only one letter, don't speak as a Roman Number | |||||
return 0; // only one letter, don't speak as a Roman Number | |||||
} | } | ||||
word_start = word; | word_start = word; | ||||
while ((c = *word++) != ' ') { | while ((c = *word++) != ' ') { | ||||
if ((p2 = strchr(roman_numbers, c)) == NULL) | if ((p2 = strchr(roman_numbers, c)) == NULL) | ||||
return (0); | |||||
return 0; | |||||
value = roman_values[p2 - roman_numbers]; | value = roman_values[p2 - roman_numbers]; | ||||
if (value == prev) { | if (value == prev) { | ||||
repeat++; | repeat++; | ||||
if (repeat >= 3) | if (repeat >= 3) | ||||
return (0); | |||||
return 0; | |||||
} else | } else | ||||
repeat = 0; | repeat = 0; | ||||
if ((prev > 1) && (prev != 10) && (prev != 100)) { | if ((prev > 1) && (prev != 10) && (prev != 100)) { | ||||
if (value >= prev) | if (value >= prev) | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((prev != 0) && (prev < value)) { | if ((prev != 0) && (prev < value)) { | ||||
if (((acc % 10) != 0) || ((prev*10) < value)) | if (((acc % 10) != 0) || ((prev*10) < value)) | ||||
return (0); | |||||
return 0; | |||||
subtract = prev; | subtract = prev; | ||||
value -= subtract; | value -= subtract; | ||||
} else if (value >= subtract) | } else if (value >= subtract) | ||||
return (0); | |||||
return 0; | |||||
else | else | ||||
acc += prev; | acc += prev; | ||||
prev = value; | prev = value; | ||||
} | } | ||||
if (IsDigit09(word[0])) | if (IsDigit09(word[0])) | ||||
return (0); // eg. 'xx2' | |||||
return 0; // eg. 'xx2' | |||||
acc += prev; | acc += prev; | ||||
if (acc < tr->langopts.min_roman) | if (acc < tr->langopts.min_roman) | ||||
return (0); | |||||
return 0; | |||||
if (acc > tr->langopts.max_roman) | if (acc > tr->langopts.max_roman) | ||||
return (0); | |||||
return 0; | |||||
Lookup(tr, "_roman", ph_roman); // precede by "roman" if _rom is defined in *_list | Lookup(tr, "_roman", ph_roman); // precede by "roman" if _rom is defined in *_list | ||||
if (word[0] == '.') { | if (word[0] == '.') { | ||||
// dot has not been removed. This implies that there was no space after it | // dot has not been removed. This implies that there was no space after it | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (CheckDotOrdinal(tr, word_start, word, wtab, 1)) | if (CheckDotOrdinal(tr, word_start, word, wtab, 1)) | ||||
// should use the 'e' form of the number | // should use the 'e' form of the number | ||||
num_control |= 1; | num_control |= 1; | ||||
} else | } else | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} else { | } else { | ||||
wtab[0].flags |= FLAG_ORDINAL; | wtab[0].flags |= FLAG_ORDINAL; | ||||
if (tr->langopts.numbers & NUM_ROMAN_AFTER) | if (tr->langopts.numbers & NUM_ROMAN_AFTER) | ||||
strcat(ph_out, ph_roman); | strcat(ph_out, ph_roman); | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
{ | { | ||||
case 1: // lang=ru use singular for xx1 except for x11 | case 1: // lang=ru use singular for xx1 except for x11 | ||||
if ((teens == 0) && ((value % 10) == 1)) | if ((teens == 0) && ((value % 10) == 1)) | ||||
return ("1M"); | |||||
return "1M"; | |||||
break; | break; | ||||
case 2: // lang=cs,sk | case 2: // lang=cs,sk | ||||
if ((value >= 2) && (value <= 4)) | if ((value >= 2) && (value <= 4)) | ||||
return ("0MA"); | |||||
return "0MA"; | |||||
break; | break; | ||||
case 3: // lang=pl | case 3: // lang=pl | ||||
if ((teens == 0) && (((value % 10) >= 2) && ((value % 10) <= 4))) | if ((teens == 0) && (((value % 10) >= 2) && ((value % 10) <= 4))) | ||||
return ("0MA"); | |||||
return "0MA"; | |||||
break; | break; | ||||
case 4: // lang=lt | case 4: // lang=lt | ||||
if ((teens == 1) || ((value % 10) == 0)) | if ((teens == 1) || ((value % 10) == 0)) | ||||
return ("0MB"); | |||||
return "0MB"; | |||||
if ((value % 10) == 1) | if ((value % 10) == 1) | ||||
return ("0MA"); | |||||
return "0MA"; | |||||
break; | break; | ||||
case 5: // lang=bs,hr,sr | case 5: // lang=bs,hr,sr | ||||
if (teens == 0) { | if (teens == 0) { | ||||
if ((value % 10) == 1) | if ((value % 10) == 1) | ||||
return ("1M"); | |||||
return "1M"; | |||||
if (((value % 10) >= 2) && ((value % 10) <= 4)) | if (((value % 10) >= 2) && ((value % 10) <= 4)) | ||||
return ("0MA"); | |||||
return "0MA"; | |||||
} | } | ||||
break; | break; | ||||
} | } | ||||
return ("0M"); | |||||
return "0M"; | |||||
} | } | ||||
sprintf(ph_out, "%s%s", ph_of, ph_thousands); | sprintf(ph_out, "%s%s", ph_of, ph_thousands); | ||||
if ((value == 1) && (thousandplex == 1) && (tr->langopts.numbers & NUM_OMIT_1_THOUSAND)) | if ((value == 1) && (thousandplex == 1) && (tr->langopts.numbers & NUM_OMIT_1_THOUSAND)) | ||||
return (1); | |||||
return 1; | |||||
return (found_value); | |||||
return found_value; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return (used_and); | |||||
return used_and; | |||||
} | } | ||||
sprintf(ph_out, "%s%s%c%s", buf1, ph_hundred_and, phonEND_WORD, buf2); | sprintf(ph_out, "%s%s%c%s", buf1, ph_hundred_and, phonEND_WORD, buf2); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int ix; | int ix; | ||||
if (IsDigit09(word[group_len]) || IsDigit09(-1)) | if (IsDigit09(word[group_len]) || IsDigit09(-1)) | ||||
return (false); | |||||
return false; | |||||
for (ix = 0; ix < group_len; ix++) { | for (ix = 0; ix < group_len; ix++) { | ||||
if (!IsDigit09(word[ix])) | if (!IsDigit09(word[ix])) | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
return (true); | |||||
return true; | |||||
} | } | ||||
} else { | } else { | ||||
if (n_digits > 3) { | if (n_digits > 3) { | ||||
flags[0] &= ~FLAG_SKIPWORDS; | flags[0] &= ~FLAG_SKIPWORDS; | ||||
return (0); // long number string with leading zero, speak as individual digits | |||||
return 0; // long number string with leading zero, speak as individual digits | |||||
} | } | ||||
// speak leading zeros | // speak leading zeros | ||||
// Look for special pronunciation for this number in isolation (LANG=kl) | // Look for special pronunciation for this number in isolation (LANG=kl) | ||||
sprintf(string, "_%dn", value); | sprintf(string, "_%dn", value); | ||||
if (Lookup(tr, string, ph_out)) { | if (Lookup(tr, string, ph_out)) { | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
} | } | ||||
if (skipwords) | if (skipwords) | ||||
dictionary_skipwords = skipwords; | dictionary_skipwords = skipwords; | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | ||||
{ | { | ||||
if ((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS)) | if ((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS)) | ||||
return (0); // speak digits individually | |||||
return 0; // speak digits individually | |||||
if (tr->langopts.numbers != 0) { | if (tr->langopts.numbers != 0) { | ||||
return (TranslateNumber_1(tr, word1, ph_out, flags, wtab, control)); | |||||
return TranslateNumber_1(tr, word1, ph_out, flags, wtab, control); | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } |
plist_out[n_plist_out].type = plist_out[n_plist_out].ph->type; | plist_out[n_plist_out].type = plist_out[n_plist_out].ph->type; | ||||
n_plist_out++; | n_plist_out++; | ||||
} | } | ||||
return (n_plist_out); | |||||
return n_plist_out; | |||||
} | } | ||||
int iswalpha(int c) | int iswalpha(int c) | ||||
{ | { | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (isalpha(c)); | |||||
return isalpha(c); | |||||
if ((c > 0x3040) && (c <= 0xa700)) | if ((c > 0x3040) && (c <= 0xa700)) | ||||
return (1); // japanese, chinese characters | |||||
return 1; // japanese, chinese characters | |||||
if (c > MAX_WALPHA) | if (c > MAX_WALPHA) | ||||
return (0); | |||||
return (walpha_tab[c-0x80]); | |||||
return 0; | |||||
return walpha_tab[c-0x80]; | |||||
} | } | ||||
int iswdigit(int c) | int iswdigit(int c) | ||||
{ | { | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (isdigit(c)); | |||||
return (0); | |||||
return isdigit(c); | |||||
return 0; | |||||
} | } | ||||
int iswalnum(int c) | int iswalnum(int c) | ||||
{ | { | ||||
if (iswdigit(c)) | if (iswdigit(c)) | ||||
return (1); | |||||
return (iswalpha(c)); | |||||
return 1; | |||||
return iswalpha(c); | |||||
} | } | ||||
int towlower(int c) | int towlower(int c) | ||||
int ix; | int ix; | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (tolower(c)); | |||||
return tolower(c); | |||||
if ((c > MAX_WALPHA) || ((x = walpha_tab[c-0x80]) >= 0xfe)) | if ((c > MAX_WALPHA) || ((x = walpha_tab[c-0x80]) >= 0xfe)) | ||||
return (c); | |||||
return c; | |||||
if (x == 0xfd) { | if (x == 0xfd) { | ||||
// special cases, lookup translation table | // special cases, lookup translation table | ||||
for (ix = 0; wchar_tolower[ix] != 0; ix += 2) { | for (ix = 0; wchar_tolower[ix] != 0; ix += 2) { | ||||
if (wchar_tolower[ix] == c) | if (wchar_tolower[ix] == c) | ||||
return (wchar_tolower[ix+1]); | |||||
return wchar_tolower[ix+1]; | |||||
} | } | ||||
} | } | ||||
return (c + x); // convert to lower case | |||||
return c + x; // convert to lower case | |||||
} | } | ||||
int towupper(int c) | int towupper(int c) | ||||
int ix; | int ix; | ||||
// check whether a previous character code is the upper-case equivalent of this character | // check whether a previous character code is the upper-case equivalent of this character | ||||
if (towlower(c-32) == c) | if (towlower(c-32) == c) | ||||
return (c-32); // yes, use it | |||||
return c-32; // yes, use it | |||||
if (towlower(c-1) == c) | if (towlower(c-1) == c) | ||||
return (c-1); | |||||
return c-1; | |||||
for (ix = 0; wchar_toupper[ix] != 0; ix += 2) { | for (ix = 0; wchar_toupper[ix] != 0; ix += 2) { | ||||
if (wchar_toupper[ix] == c) | if (wchar_toupper[ix] == c) | ||||
return (wchar_toupper[ix+1]); | |||||
return wchar_toupper[ix+1]; | |||||
} | } | ||||
return (c); // no | |||||
return c; // no | |||||
} | } | ||||
int iswupper(int c) | int iswupper(int c) | ||||
{ | { | ||||
int x; | int x; | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (isupper(c)); | |||||
return isupper(c); | |||||
if (((c > MAX_WALPHA) || (x = walpha_tab[c-0x80]) == 0) || (x == 0xff)) | if (((c > MAX_WALPHA) || (x = walpha_tab[c-0x80]) == 0) || (x == 0xff)) | ||||
return (0); | |||||
return (1); | |||||
return 0; | |||||
return 1; | |||||
} | } | ||||
int iswlower(int c) | int iswlower(int c) | ||||
{ | { | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (islower(c)); | |||||
return islower(c); | |||||
if ((c > MAX_WALPHA) || (walpha_tab[c-0x80] != 0xff)) | if ((c > MAX_WALPHA) || (walpha_tab[c-0x80] != 0xff)) | ||||
return (0); | |||||
return (1); | |||||
return 0; | |||||
return 1; | |||||
} | } | ||||
int iswspace(int c) | int iswspace(int c) | ||||
{ | { | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (isspace(c)); | |||||
return isspace(c); | |||||
if (c == 0xa0) | if (c == 0xa0) | ||||
return (1); | |||||
return (0); | |||||
return 1; | |||||
return 0; | |||||
} | } | ||||
int iswpunct(int c) | int iswpunct(int c) | ||||
{ | { | ||||
if (c < 0x100) | if (c < 0x100) | ||||
return (ispunct(c)); | |||||
return (0); | |||||
return ispunct(c); | |||||
return 0; | |||||
} | } | ||||
const wchar_t *wcschr(const wchar_t *str, int c) | const wchar_t *wcschr(const wchar_t *str, int c) | ||||
{ | { | ||||
while (*str != 0) { | while (*str != 0) { | ||||
if (*str == c) | if (*str == c) | ||||
return (str); | |||||
return str; | |||||
str++; | str++; | ||||
} | } | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
#ifndef WINCE | #ifndef WINCE | ||||
while (*str != 0) { | while (*str != 0) { | ||||
ix++; | ix++; | ||||
} | } | ||||
return (ix); | |||||
return ix; | |||||
} | } | ||||
#endif | #endif | ||||
break; | break; | ||||
} | } | ||||
*tailptr = (wchar_t *)&str[ix]; | *tailptr = (wchar_t *)&str[ix]; | ||||
return (atof(buf)); | |||||
return atof(buf); | |||||
} | } | ||||
#endif | #endif | ||||
int iswalpha2(int c) | int iswalpha2(int c) | ||||
{ | { | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (isalpha(c)); | |||||
return isalpha(c); | |||||
if ((c > 0x3040) && (c <= 0xa700)) | if ((c > 0x3040) && (c <= 0xa700)) | ||||
return (1); // japanese, chinese characters | |||||
return 1; // japanese, chinese characters | |||||
if (c > MAX_WALPHA) | if (c > MAX_WALPHA) | ||||
return (iswalpha(c)); | |||||
return (walpha_tab[c-0x80]); | |||||
return iswalpha(c); | |||||
return walpha_tab[c-0x80]; | |||||
} | } | ||||
int iswlower2(int c) | int iswlower2(int c) | ||||
{ | { | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (islower(c)); | |||||
return islower(c); | |||||
if (c > MAX_WALPHA) | if (c > MAX_WALPHA) | ||||
return (iswlower(c)); | |||||
return iswlower(c); | |||||
if (walpha_tab[c-0x80] == 0xff) | if (walpha_tab[c-0x80] == 0xff) | ||||
return (1); | |||||
return (0); | |||||
return 1; | |||||
return 0; | |||||
} | } | ||||
int iswupper2(int c) | int iswupper2(int c) | ||||
{ | { | ||||
int x; | int x; | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (isupper(c)); | |||||
return isupper(c); | |||||
if (c > MAX_WALPHA) | if (c > MAX_WALPHA) | ||||
return (iswupper(c)); | |||||
return iswupper(c); | |||||
if (((x = walpha_tab[c-0x80]) > 0) && (x < 0xfe)) | if (((x = walpha_tab[c-0x80]) > 0) && (x < 0xfe)) | ||||
return (1); | |||||
return (0); | |||||
return 1; | |||||
return 0; | |||||
} | } | ||||
int towlower2(unsigned int c) | int towlower2(unsigned int c) | ||||
} | } | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (tolower(c)); | |||||
return tolower(c); | |||||
if (c > MAX_WALPHA) | if (c > MAX_WALPHA) | ||||
return (towlower(c)); | |||||
return towlower(c); | |||||
if ((x = walpha_tab[c-0x80]) >= 0xfe) | if ((x = walpha_tab[c-0x80]) >= 0xfe) | ||||
return (c); // this is not an upper case letter | |||||
return c; // this is not an upper case letter | |||||
if (x == 0xfd) { | if (x == 0xfd) { | ||||
// special cases, lookup translation table | // special cases, lookup translation table | ||||
for (ix = 0; wchar_tolower[ix] != 0; ix += 2) { | for (ix = 0; wchar_tolower[ix] != 0; ix += 2) { | ||||
if (wchar_tolower[ix] == (int)c) | if (wchar_tolower[ix] == (int)c) | ||||
return (wchar_tolower[ix+1]); | |||||
return wchar_tolower[ix+1]; | |||||
} | } | ||||
} | } | ||||
return (c + x); // convert to lower case | |||||
return c + x; // convert to lower case | |||||
} | } | ||||
int towupper2(unsigned int c) | int towupper2(unsigned int c) | ||||
{ | { | ||||
int ix; | int ix; | ||||
if (c > MAX_WALPHA) | if (c > MAX_WALPHA) | ||||
return (towupper(c)); | |||||
return towupper(c); | |||||
// check whether a previous character code is the upper-case equivalent of this character | // check whether a previous character code is the upper-case equivalent of this character | ||||
if (towlower2(c-32) == (int)c) | if (towlower2(c-32) == (int)c) | ||||
return (c-32); // yes, use it | |||||
return c-32; // yes, use it | |||||
if (towlower2(c-1) == (int)c) | if (towlower2(c-1) == (int)c) | ||||
return (c-1); | |||||
return c-1; | |||||
for (ix = 0; wchar_toupper[ix] != 0; ix += 2) { | for (ix = 0; wchar_toupper[ix] != 0; ix += 2) { | ||||
if (wchar_toupper[ix] == (int)c) | if (wchar_toupper[ix] == (int)c) | ||||
return (wchar_toupper[ix+1]); | |||||
return wchar_toupper[ix+1]; | |||||
} | } | ||||
return (c); // no | |||||
return c; // no | |||||
} | } | ||||
static int IsRomanU(unsigned int c) | static int IsRomanU(unsigned int c) | ||||
{ | { | ||||
if ((c == 'I') || (c == 'V') || (c == 'X') || (c == 'L')) | if ((c == 'I') || (c == 'V') || (c == 'X') || (c == 'L')) | ||||
return (1); | |||||
return (0); | |||||
return 1; | |||||
return 0; | |||||
} | } | ||||
int Eof(void) | int Eof(void) | ||||
{ | { | ||||
if (ungot_char != 0) | if (ungot_char != 0) | ||||
return (0); | |||||
return 0; | |||||
if (f_input != 0) | if (f_input != 0) | ||||
return (feof(f_input)); | |||||
return feof(f_input); | |||||
return (end_of_input); | |||||
return end_of_input; | |||||
} | } | ||||
if (feof(f_input)) c2 = 0; | if (feof(f_input)) c2 = 0; | ||||
c = c + (c2 << 8); | c = c + (c2 << 8); | ||||
} | } | ||||
return (c); | |||||
return c; | |||||
} | } | ||||
if (option_multibyte == espeakCHARS_WCHAR) { | if (option_multibyte == espeakCHARS_WCHAR) { | ||||
if (*p_wchar_input == 0) { | if (*p_wchar_input == 0) { | ||||
end_of_input = 1; | end_of_input = 1; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (!end_of_input) | if (!end_of_input) | ||||
return (*p_wchar_input++); | |||||
return *p_wchar_input++; | |||||
} else { | } else { | ||||
if (*p_textinput == 0) { | if (*p_textinput == 0) { | ||||
end_of_input = 1; | end_of_input = 1; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (!end_of_input) { | if (!end_of_input) { | ||||
if (option_multibyte == espeakCHARS_16BIT) { | if (option_multibyte == espeakCHARS_16BIT) { | ||||
c = p_textinput[0] + (p_textinput[1] << 8); | c = p_textinput[0] + (p_textinput[1] << 8); | ||||
p_textinput += 2; | p_textinput += 2; | ||||
return (c); | |||||
return c; | |||||
} | } | ||||
return (*p_textinput++ & 0xff); | |||||
return *p_textinput++ & 0xff; | |||||
} | } | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((c1 = ungot_char) != 0) { | if ((c1 = ungot_char) != 0) { | ||||
ungot_char = 0; | ungot_char = 0; | ||||
return (c1); | |||||
return c1; | |||||
} | } | ||||
if (ungot2 != 0) { | if (ungot2 != 0) { | ||||
if ((option_multibyte == espeakCHARS_WCHAR) || (option_multibyte == espeakCHARS_16BIT)) { | if ((option_multibyte == espeakCHARS_WCHAR) || (option_multibyte == espeakCHARS_16BIT)) { | ||||
count_characters++; | count_characters++; | ||||
return (c1); // wchar_t text | |||||
return c1; // wchar_t text | |||||
} | } | ||||
if ((option_multibyte < 2) && (c1 & 0x80)) { | if ((option_multibyte < 2) && (c1 & 0x80)) { | ||||
} | } | ||||
if (ix == 0) { | if (ix == 0) { | ||||
count_characters++; | count_characters++; | ||||
return (c); | |||||
return c; | |||||
} | } | ||||
} | } | ||||
// top-bit-set character is not utf8, drop through to 8bit charset case | // top-bit-set character is not utf8, drop through to 8bit charset case | ||||
// 8 bit character set, convert to unicode if | // 8 bit character set, convert to unicode if | ||||
count_characters++; | count_characters++; | ||||
if (c1 >= 0xa0) | if (c1 >= 0xa0) | ||||
return (translator->charset_a0[c1-0xa0]); | |||||
return (c1); | |||||
return translator->charset_a0[c1-0xa0]; | |||||
return c1; | |||||
} | } | ||||
p++; | p++; | ||||
} | } | ||||
*p = 0; | *p = 0; | ||||
return (buf); | |||||
return buf; | |||||
} | } | ||||
SetWordStress(tr, phonemes, flags, -1, 0); | SetWordStress(tr, phonemes, flags, -1, 0); | ||||
DecodePhonemes(phonemes, phonemes2); | DecodePhonemes(phonemes, phonemes2); | ||||
sprintf(text_out, "[\002%s]]", phonemes2); | sprintf(text_out, "[\002%s]]", phonemes2); | ||||
return (text_out); | |||||
return text_out; | |||||
} | } | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
strcpy(buf, "[\002(X1)(X1)(X1)]]"); | strcpy(buf, "[\002(X1)(X1)(X1)]]"); | ||||
} | } | ||||
return (buf); | |||||
return buf; | |||||
} | } | ||||
int Read4Bytes(FILE *f) | int Read4Bytes(FILE *f) | ||||
c = fgetc(f) & 0xff; | c = fgetc(f) & 0xff; | ||||
acc += (c << (ix*8)); | acc += (c << (ix*8)); | ||||
} | } | ||||
return (acc); | |||||
return acc; | |||||
} | } | ||||
} | } | ||||
if (fname == NULL) | if (fname == NULL) | ||||
return (1); | |||||
return 1; | |||||
if (fname[0] != '/') { | if (fname[0] != '/') { | ||||
// a relative path, look in espeak-data/soundicons | // a relative path, look in espeak-data/soundicons | ||||
f = fopen(fname, "rb"); | f = fopen(fname, "rb"); | ||||
if (f == NULL) { | if (f == NULL) { | ||||
fprintf(stderr, "Can't read temp file: %s\n", fname); | fprintf(stderr, "Can't read temp file: %s\n", fname); | ||||
return (3); | |||||
return 3; | |||||
} | } | ||||
} | } | ||||
fseek(f, 0, SEEK_SET); | fseek(f, 0, SEEK_SET); | ||||
if ((p = (char *)realloc(soundicon_tab[index].data, length)) == NULL) { | if ((p = (char *)realloc(soundicon_tab[index].data, length)) == NULL) { | ||||
fclose(f); | fclose(f); | ||||
return (4); | |||||
return 4; | |||||
} | } | ||||
length = fread(p, 1, length, f); | length = fread(p, 1, length, f); | ||||
fclose(f); | fclose(f); | ||||
ip = (int *)(&p[40]); | ip = (int *)(&p[40]); | ||||
soundicon_tab[index].length = (*ip) / 2; // length in samples | soundicon_tab[index].length = (*ip) / 2; // length in samples | ||||
soundicon_tab[index].data = p; | soundicon_tab[index].data = p; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (soundicon_tab[ix].name == c) { | if (soundicon_tab[ix].name == c) { | ||||
if (soundicon_tab[ix].length == 0) { | if (soundicon_tab[ix].length == 0) { | ||||
if (LoadSoundFile(NULL, ix) != 0) | if (LoadSoundFile(NULL, ix) != 0) | ||||
return (-1); // sound file is not available | |||||
return -1; // sound file is not available | |||||
} | } | ||||
return (ix); | |||||
return ix; | |||||
} | } | ||||
} | } | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
for (ix = 0; ix < n_soundicon_tab; ix++) { | for (ix = 0; ix < n_soundicon_tab; ix++) { | ||||
if (((soundicon_tab[ix].filename != NULL) && strcmp(fname, soundicon_tab[ix].filename) == 0)) | if (((soundicon_tab[ix].filename != NULL) && strcmp(fname, soundicon_tab[ix].filename) == 0)) | ||||
return (ix); // already loaded | |||||
return ix; // already loaded | |||||
} | } | ||||
// load the file into the next slot | // load the file into the next slot | ||||
slot = 0; | slot = 0; | ||||
if (LoadSoundFile(fname, slot) != 0) | if (LoadSoundFile(fname, slot) != 0) | ||||
return (-1); | |||||
return -1; | |||||
soundicon_tab[slot].filename = (char *)realloc(soundicon_tab[ix].filename, strlen(fname)+1); | soundicon_tab[slot].filename = (char *)realloc(soundicon_tab[ix].filename, strlen(fname)+1); | ||||
strcpy(soundicon_tab[slot].filename, fname); | strcpy(soundicon_tab[slot].filename, fname); | ||||
return (slot); | |||||
return slot; | |||||
} | } | ||||
} | } | ||||
if (punctname == NULL) | if (punctname == NULL) | ||||
return (-1); | |||||
return -1; | |||||
if ((*bufix == 0) || (end_clause == 0) || (tr->langopts.param[LOPT_ANNOUNCE_PUNCT] & 2)) { | if ((*bufix == 0) || (end_clause == 0) || (tr->langopts.param[LOPT_ANNOUNCE_PUNCT] & 2)) { | ||||
punct_count = 1; | punct_count = 1; | ||||
*bufix += len; | *bufix += len; | ||||
if (end_clause == 0) | if (end_clause == 0) | ||||
return (-1); | |||||
return -1; | |||||
if (c1 == '-') | if (c1 == '-') | ||||
return (CLAUSE_NONE); // no pause | |||||
return CLAUSE_NONE; // no pause | |||||
attributes = punct_attributes[lookupwchar(punct_chars, c1)]; | attributes = punct_attributes[lookupwchar(punct_chars, c1)]; | ||||
if ((bufix1 > 0) && !(tr->langopts.param[LOPT_ANNOUNCE_PUNCT] & 2)) { | if ((bufix1 > 0) && !(tr->langopts.param[LOPT_ANNOUNCE_PUNCT] & 2)) { | ||||
if ((attributes & ~0x8000) == CLAUSE_SEMICOLON) | if ((attributes & ~0x8000) == CLAUSE_SEMICOLON) | ||||
return (CLAUSE_SHORTFALL); | |||||
return (short_pause); | |||||
return CLAUSE_SHORTFALL; | |||||
return short_pause; | |||||
} | } | ||||
if (attributes & CLAUSE_BIT_SENTENCE) | if (attributes & CLAUSE_BIT_SENTENCE) | ||||
return (attributes); | |||||
return attributes; | |||||
return (short_pause); | |||||
return short_pause; | |||||
} | } | ||||
#define SSML_SPEAK 1 | #define SSML_SPEAK 1 | ||||
voice_select.languages = language; | voice_select.languages = language; | ||||
v_id = SelectVoice(&voice_select, &voice_found); | v_id = SelectVoice(&voice_select, &voice_found); | ||||
if (v_id == NULL) | if (v_id == NULL) | ||||
return ("default"); | |||||
return "default"; | |||||
if ((strchr(v_id, '+') == NULL) && ((voice_select.gender == 0) || (voice_select.gender == base_voice.gender)) && (base_voice_variant_name[0] != 0)) { | if ((strchr(v_id, '+') == NULL) && ((voice_select.gender == 0) || (voice_select.gender == base_voice.gender)) && (base_voice_variant_name[0] != 0)) { | ||||
// a voice variant has not been selected, use the original voice variant | // a voice variant has not been selected, use the original voice variant | ||||
sprintf(buf, "%s+%s", v_id, base_voice_variant_name); | sprintf(buf, "%s+%s", v_id, base_voice_variant_name); | ||||
strncpy0(voice_name, buf, sizeof(voice_name)); | strncpy0(voice_name, buf, sizeof(voice_name)); | ||||
return (voice_name); | |||||
return voice_name; | |||||
} | } | ||||
return (v_id); | |||||
return v_id; | |||||
} | } | ||||
for (ix = 0; ix < N_SPEECH_PARAM; ix++) { | for (ix = 0; ix < N_SPEECH_PARAM; ix++) { | ||||
sp->parameter[ix] = -1; | sp->parameter[ix] = -1; | ||||
} | } | ||||
return (sp); | |||||
return sp; | |||||
} | } | ||||
if (*pw == '=') pw++; | if (*pw == '=') pw++; | ||||
while (iswspace(*pw)) pw++; | while (iswspace(*pw)) pw++; | ||||
if ((*pw == '"') || (*pw == '\'')) // allow single-quotes ? | if ((*pw == '"') || (*pw == '\'')) // allow single-quotes ? | ||||
return (pw+1); | |||||
return pw+1; | |||||
else | else | ||||
return (empty); | |||||
return empty; | |||||
} | } | ||||
} | } | ||||
pw++; | pw++; | ||||
} | } | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
int ix; | int ix; | ||||
if (string1 == NULL) | if (string1 == NULL) | ||||
return (1); | |||||
return 1; | |||||
for (ix = 0; (string1[ix] == string2[ix]) && (string1[ix] != 0); ix++) { | for (ix = 0; (string1[ix] == string2[ix]) && (string1[ix] != 0); ix++) { | ||||
} | } | ||||
if (((string1[ix] == '"') || (string1[ix] == '\'')) && (string2[ix] == 0)) | if (((string1[ix] == '"') || (string1[ix] == '\'')) && (string2[ix] == 0)) | ||||
return (0); | |||||
return (1); | |||||
return 0; | |||||
return 1; | |||||
} | } | ||||
for (ix = 0; mtab[ix].mnem != NULL; ix++) { | for (ix = 0; mtab[ix].mnem != NULL; ix++) { | ||||
if (attrcmp(string1, mtab[ix].mnem) == 0) | if (attrcmp(string1, mtab[ix].mnem) == 0) | ||||
return (mtab[ix].value); | |||||
return mtab[ix].value; | |||||
} | } | ||||
return (mtab[ix].value); | |||||
return mtab[ix].value; | |||||
} | } | ||||
int value = 0; | int value = 0; | ||||
if ((pw == NULL) || !IsDigit09(*pw)) | if ((pw == NULL) || !IsDigit09(*pw)) | ||||
return (default_value); | |||||
return default_value; | |||||
while (IsDigit09(*pw)) { | while (IsDigit09(*pw)) { | ||||
value = value*10 + *pw++ - '0'; | value = value*10 + *pw++ - '0'; | ||||
// time: seconds rather than ms | // time: seconds rather than ms | ||||
value *= 1000; | value *= 1000; | ||||
} | } | ||||
return (value); | |||||
return value; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
buf[ix] = 0; | buf[ix] = 0; | ||||
return (ix); | |||||
return ix; | |||||
} | } | ||||
if (tail == pw) { | if (tail == pw) { | ||||
// failed to find a number, return 100% | // failed to find a number, return 100% | ||||
*value_out = 100; | *value_out = 100; | ||||
return (2); | |||||
return 2; | |||||
} | } | ||||
if (*tail == '%') { | if (*tail == '%') { | ||||
if (sign != 0) | if (sign != 0) | ||||
value = 100 + (sign * value); | value = 100 + (sign * value); | ||||
*value_out = (int)value; | *value_out = (int)value; | ||||
return (2); // percentage | |||||
return 2; // percentage | |||||
} | } | ||||
if ((tail[0] == 's') && (tail[1] == 't')) { | if ((tail[0] == 's') && (tail[1] == 't')) { | ||||
x = pow((double)2.0, (double)((value*sign)/12)) * 100; | x = pow((double)2.0, (double)((value*sign)/12)) * 100; | ||||
*value_out = (int)x; | *value_out = (int)x; | ||||
#endif | #endif | ||||
return (2); // percentage | |||||
return 2; // percentage | |||||
} | } | ||||
if (param_type == espeakRATE) { | if (param_type == espeakRATE) { | ||||
*value_out = (int)(value * 100); | *value_out = (int)(value * 100); | ||||
else | else | ||||
*value_out = 100 + (int)(sign * value * 100); | *value_out = 100 + (int)(sign * value * 100); | ||||
return (2); // percentage | |||||
return 2; // percentage | |||||
} | } | ||||
*value_out = (int)value; | *value_out = (int)value; | ||||
return (sign); // -1, 0, or 1 | |||||
return sign; // -1, 0, or 1 | |||||
} | } | ||||
if (namedata_ix+len >= n_namedata) { | if (namedata_ix+len >= n_namedata) { | ||||
// allocate more space for marker names | // allocate more space for marker names | ||||
if ((vp = realloc(namedata, namedata_ix+len + 1000)) == NULL) | if ((vp = realloc(namedata, namedata_ix+len + 1000)) == NULL) | ||||
return (-1); // failed to allocate, original data is unchanged but ignore this new name | |||||
return -1; // failed to allocate, original data is unchanged but ignore this new name | |||||
// !!! Bug?? If the allocated data shifts position, then pointers given to user application will be invalid | // !!! Bug?? If the allocated data shifts position, then pointers given to user application will be invalid | ||||
namedata = (char *)vp; | namedata = (char *)vp; | ||||
} | } | ||||
memcpy(&namedata[ix = namedata_ix], name, len); | memcpy(&namedata[ix = namedata_ix], name, len); | ||||
namedata_ix += len; | namedata_ix += len; | ||||
return (ix); | |||||
return ix; | |||||
} | } | ||||
} | } | ||||
if ((tag_type != SSML_VOICE) && (lang == NULL)) | if ((tag_type != SSML_VOICE) && (lang == NULL)) | ||||
return (0); // <s> or <p> without language spec, nothing to do | |||||
return 0; // <s> or <p> without language spec, nothing to do | |||||
ssml_sp = &ssml_stack[n_ssml_stack++]; | ssml_sp = &ssml_stack[n_ssml_stack++]; | ||||
if (strcmp(new_voice_id, current_voice_id) != 0) { | if (strcmp(new_voice_id, current_voice_id) != 0) { | ||||
// add an embedded command to change the voice | // add an embedded command to change the voice | ||||
strcpy(current_voice_id, new_voice_id); | strcpy(current_voice_id, new_voice_id); | ||||
return (CLAUSE_BIT_VOICE); // change of voice | |||||
return CLAUSE_BIT_VOICE; // change of voice | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((letter = LookupMnem(keynames, p)) != 0) { | if ((letter = LookupMnem(keynames, p)) != 0) { | ||||
ix = utf8_out(letter, p); | ix = utf8_out(letter, p); | ||||
*outix = index + ix; | *outix = index + ix; | ||||
return (letter); | |||||
return letter; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
if (self_closing && ignore_if_self_closing[tag_type]) | if (self_closing && ignore_if_self_closing[tag_type]) | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
// This is the marker we are waiting for before starting to speak | // This is the marker we are waiting for before starting to speak | ||||
clear_skipping_text = 1; | clear_skipping_text = 1; | ||||
skip_marker[0] = 0; | skip_marker[0] = 0; | ||||
return (CLAUSE_NONE); | |||||
return CLAUSE_NONE; | |||||
} | } | ||||
if ((index = AddNameData(buf, 0)) >= 0) { | if ((index = AddNameData(buf, 0)) >= 0) { | ||||
PopParamStack(tag_type, outbuf, outix); | PopParamStack(tag_type, outbuf, outix); | ||||
else | else | ||||
audio_text = 1; | audio_text = 1; | ||||
return (CLAUSE_NONE); | |||||
return CLAUSE_NONE; | |||||
case SSML_AUDIO + SSML_CLOSE: | case SSML_AUDIO + SSML_CLOSE: | ||||
PopParamStack(tag_type, outbuf, outix); | PopParamStack(tag_type, outbuf, outix); | ||||
audio_text = 0; | audio_text = 0; | ||||
return (CLAUSE_NONE); | |||||
return CLAUSE_NONE; | |||||
case SSML_BREAK: | case SSML_BREAK: | ||||
value = 21; | value = 21; | ||||
value = 0xfff; | value = 0xfff; | ||||
terminator |= CLAUSE_PAUSE_LONG; | terminator |= CLAUSE_PAUSE_LONG; | ||||
} | } | ||||
return (terminator + value); | |||||
return terminator + value; | |||||
} | } | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (GetVoiceAttributes(px, tag_type) == 0) | if (GetVoiceAttributes(px, tag_type) == 0) | ||||
return (0); // no voice change | |||||
return (CLAUSE_VOICE); | |||||
return 0; // no voice change | |||||
return CLAUSE_VOICE; | |||||
case SSML_VOICE: | case SSML_VOICE: | ||||
if (GetVoiceAttributes(px, tag_type) == 0) | if (GetVoiceAttributes(px, tag_type) == 0) | ||||
return (0); // no voice change | |||||
return (CLAUSE_VOICE); | |||||
return 0; // no voice change | |||||
return CLAUSE_VOICE; | |||||
case SSML_SPEAK + SSML_CLOSE: | case SSML_SPEAK + SSML_CLOSE: | ||||
// unwind stack until the previous <voice> or <speak> tag | // unwind stack until the previous <voice> or <speak> tag | ||||
while ((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_SPEAK)) { | while ((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_SPEAK)) { | ||||
n_ssml_stack--; | n_ssml_stack--; | ||||
} | } | ||||
return (CLAUSE_PERIOD + GetVoiceAttributes(px, tag_type)); | |||||
return CLAUSE_PERIOD + GetVoiceAttributes(px, tag_type); | |||||
case SSML_VOICE + SSML_CLOSE: | case SSML_VOICE + SSML_CLOSE: | ||||
// unwind stack until the previous <voice> or <speak> tag | // unwind stack until the previous <voice> or <speak> tag | ||||
} | } | ||||
terminator = 0; // ?? Sentence intonation, but no pause ?? | terminator = 0; // ?? Sentence intonation, but no pause ?? | ||||
return (terminator + GetVoiceAttributes(px, tag_type)); | |||||
return terminator + GetVoiceAttributes(px, tag_type); | |||||
case HTML_BREAK: | case HTML_BREAK: | ||||
case HTML_BREAK + SSML_CLOSE: | case HTML_BREAK + SSML_CLOSE: | ||||
return (CLAUSE_COLON); | |||||
return CLAUSE_COLON; | |||||
case SSML_SENTENCE: | case SSML_SENTENCE: | ||||
if (ssml_sp->tag_type == SSML_SENTENCE) { | if (ssml_sp->tag_type == SSML_SENTENCE) { | ||||
voice_change_flag = GetVoiceAttributes(px, SSML_SENTENCE+SSML_CLOSE); | voice_change_flag = GetVoiceAttributes(px, SSML_SENTENCE+SSML_CLOSE); | ||||
} | } | ||||
voice_change_flag |= GetVoiceAttributes(px, tag_type); | voice_change_flag |= GetVoiceAttributes(px, tag_type); | ||||
return (CLAUSE_PARAGRAPH + voice_change_flag); | |||||
return CLAUSE_PARAGRAPH + voice_change_flag; | |||||
case SSML_PARAGRAPH: | case SSML_PARAGRAPH: | ||||
voice_change_flag |= GetVoiceAttributes(px, SSML_PARAGRAPH+SSML_CLOSE); | voice_change_flag |= GetVoiceAttributes(px, SSML_PARAGRAPH+SSML_CLOSE); | ||||
} | } | ||||
voice_change_flag |= GetVoiceAttributes(px, tag_type); | voice_change_flag |= GetVoiceAttributes(px, tag_type); | ||||
return (CLAUSE_PARAGRAPH + voice_change_flag); | |||||
return CLAUSE_PARAGRAPH + voice_change_flag; | |||||
case SSML_SENTENCE + SSML_CLOSE: | case SSML_SENTENCE + SSML_CLOSE: | ||||
// end of a sentence which specified a language | // end of a sentence which specified a language | ||||
voice_change_flag = GetVoiceAttributes(px, tag_type); | voice_change_flag = GetVoiceAttributes(px, tag_type); | ||||
} | } | ||||
return (CLAUSE_PERIOD + voice_change_flag); | |||||
return CLAUSE_PERIOD + voice_change_flag; | |||||
case SSML_PARAGRAPH + SSML_CLOSE: | case SSML_PARAGRAPH + SSML_CLOSE: | ||||
if ((ssml_sp->tag_type == SSML_SENTENCE) || (ssml_sp->tag_type == SSML_PARAGRAPH)) { | if ((ssml_sp->tag_type == SSML_SENTENCE) || (ssml_sp->tag_type == SSML_PARAGRAPH)) { | ||||
// End of a paragraph which specified a language. | // End of a paragraph which specified a language. | ||||
// (End-of-paragraph also implies end-of-sentence) | // (End-of-paragraph also implies end-of-sentence) | ||||
return (GetVoiceAttributes(px, tag_type) + CLAUSE_PARAGRAPH); | |||||
return GetVoiceAttributes(px, tag_type) + CLAUSE_PARAGRAPH; | |||||
} | } | ||||
return (CLAUSE_PARAGRAPH); | |||||
return CLAUSE_PARAGRAPH; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (!iswalnum(c1)) { | if (!iswalnum(c1)) { | ||||
if ((end_character_position > 0) && (count_characters > end_character_position)) { | if ((end_character_position > 0) && (count_characters > end_character_position)) { | ||||
end_of_input = 1; | end_of_input = 1; | ||||
return (CLAUSE_EOF); | |||||
return CLAUSE_EOF; | |||||
} | } | ||||
if ((skip_characters > 0) && (count_characters >= skip_characters)) { | if ((skip_characters > 0) && (count_characters >= skip_characters)) { | ||||
clear_skipping_text = 1; | clear_skipping_text = 1; | ||||
skip_characters = 0; | skip_characters = 0; | ||||
UngetC(c2); | UngetC(c2); | ||||
return (CLAUSE_NONE); | |||||
return CLAUSE_NONE; | |||||
} | } | ||||
} | } | ||||
ungot_char2 = c1; | ungot_char2 = c1; | ||||
buf[ix] = ' '; | buf[ix] = ' '; | ||||
buf[ix+1] = 0; | buf[ix+1] = 0; | ||||
return (CLAUSE_NONE); | |||||
return CLAUSE_NONE; | |||||
} | } | ||||
// SSML Tag | // SSML Tag | ||||
if (terminator & CLAUSE_BIT_VOICE) { | if (terminator & CLAUSE_BIT_VOICE) { | ||||
strcpy(voice_change, current_voice_id); | strcpy(voice_change, current_voice_id); | ||||
} | } | ||||
return (terminator); | |||||
return terminator; | |||||
} | } | ||||
c1 = ' '; | c1 = ' '; | ||||
c2 = GetC(); | c2 = GetC(); | ||||
} | } | ||||
buf[ix] = ' '; | buf[ix] = ' '; | ||||
buf[ix+1] = 0; | buf[ix+1] = 0; | ||||
return (terminator); | |||||
return terminator; | |||||
} | } | ||||
if ((c1 == CTRL_EMBEDDED) || (c1 == ctrl_embedded)) { | if ((c1 == CTRL_EMBEDDED) || (c1 == ctrl_embedded)) { | ||||
while (!iswspace(c1 = GetC()) && !Eof() && (ix < (n_buf-1))) | while (!iswspace(c1 = GetC()) && !Eof() && (ix < (n_buf-1))) | ||||
buf[ix++] = c1; // add voice name to end of buffer, after the text | buf[ix++] = c1; // add voice name to end of buffer, after the text | ||||
buf[ix++] = 0; | buf[ix++] = 0; | ||||
return (CLAUSE_VOICE); | |||||
return CLAUSE_VOICE; | |||||
} else if (c2 == 'B') { | } else if (c2 == 'B') { | ||||
// set the punctuation option from an embedded command | // set the punctuation option from an embedded command | ||||
// B0 B1 B<punct list><space> | // B0 B1 B<punct list><space> | ||||
ungot_word = "i "; | ungot_word = "i "; | ||||
UngetC(c2); | UngetC(c2); | ||||
p_word[0] = 0; | p_word[0] = 0; | ||||
return (CLAUSE_PERIOD); | |||||
return CLAUSE_PERIOD; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
if (parag > 3) | if (parag > 3) | ||||
parag = 3; | parag = 3; | ||||
if (option_ssml) parag = 1; | if (option_ssml) parag = 1; | ||||
return ((CLAUSE_PARAGRAPH-30) + 30*parag); // several blank lines, longer pause | |||||
return (CLAUSE_PARAGRAPH-30) + 30*parag; // several blank lines, longer pause | |||||
} | } | ||||
if (linelength <= option_linelength) { | if (linelength <= option_linelength) { | ||||
UngetC(c2); | UngetC(c2); | ||||
buf[ix] = ' '; | buf[ix] = ' '; | ||||
buf[ix+1] = 0; | buf[ix+1] = 0; | ||||
return (CLAUSE_COLON); | |||||
return CLAUSE_COLON; | |||||
} | } | ||||
linelength = 0; | linelength = 0; | ||||
ungot_char2 = c1; | ungot_char2 = c1; | ||||
buf[end_clause_index] = ' '; // delete the end-clause punctuation | buf[end_clause_index] = ' '; // delete the end-clause punctuation | ||||
buf[end_clause_index+1] = 0; | buf[end_clause_index+1] = 0; | ||||
return (end_clause_after_tag); | |||||
return end_clause_after_tag; | |||||
} | } | ||||
end_clause_after_tag = 0; | end_clause_after_tag = 0; | ||||
} | } | ||||
if ((option_punctuation == 1) || (wcschr(option_punctlist, c1) != NULL)) { | if ((option_punctuation == 1) || (wcschr(option_punctlist, c1) != NULL)) { | ||||
tr->phonemes_repeat_count = 0; | tr->phonemes_repeat_count = 0; | ||||
if ((terminator = AnnouncePunctuation(tr, c1, &c2, buf, &ix, is_end_clause)) >= 0) | if ((terminator = AnnouncePunctuation(tr, c1, &c2, buf, &ix, is_end_clause)) >= 0) | ||||
return (terminator); | |||||
return terminator; | |||||
announced_punctuation = c1; | announced_punctuation = c1; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (nl_count > 1) { | if (nl_count > 1) { | ||||
if ((punct_data == CLAUSE_QUESTION) || (punct_data == CLAUSE_EXCLAMATION)) | if ((punct_data == CLAUSE_QUESTION) || (punct_data == CLAUSE_EXCLAMATION)) | ||||
return (punct_data + 35); // with a longer pause | |||||
return (CLAUSE_PARAGRAPH); | |||||
return punct_data + 35; // with a longer pause | |||||
return CLAUSE_PARAGRAPH; | |||||
} | } | ||||
return (punct_data); // only recognise punctuation if followed by a blank or bracket/quote | |||||
return punct_data; // only recognise punctuation if followed by a blank or bracket/quote | |||||
} else { | } else { | ||||
if (!Eof()) { | if (!Eof()) { | ||||
if (iswspace(c2)) | if (iswspace(c2)) | ||||
buf[ix] = ' '; | buf[ix] = ' '; | ||||
buf[ix+1] = 0; | buf[ix+1] = 0; | ||||
UngetC(c2); | UngetC(c2); | ||||
return (CLAUSE_NONE); | |||||
return CLAUSE_NONE; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
buf[ix] = ' '; | buf[ix] = ' '; | ||||
buf[ix+1] = 0; | buf[ix+1] = 0; | ||||
return (CLAUSE_EOF); // end of file | |||||
return CLAUSE_EOF; // end of file | |||||
} | } | ||||
out_samplerate = voice_samplerate; | out_samplerate = voice_samplerate; | ||||
if (!wave_init(voice_samplerate)) { | if (!wave_init(voice_samplerate)) { | ||||
err = EE_INTERNAL_ERROR; | err = EE_INTERNAL_ERROR; | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
wave_set_callback_is_output_enabled(fifo_is_command_enabled); | wave_set_callback_is_output_enabled(fifo_is_command_enabled); | ||||
my_audio = wave_open("alsa"); | my_audio = wave_open("alsa"); | ||||
SHOW_TIME("LEAVE dispatch_audio\n"); | SHOW_TIME("LEAVE dispatch_audio\n"); | ||||
return (a_wave_can_be_played == 0); // 1 = stop synthesis, -1 = error | |||||
return a_wave_can_be_played == 0; // 1 = stop synthesis, -1 = error | |||||
} | } | ||||
struct stat statbuf; | struct stat statbuf; | ||||
if (stat(filename, &statbuf) != 0) | if (stat(filename, &statbuf) != 0) | ||||
return (0); | |||||
return 0; | |||||
if (S_ISDIR(statbuf.st_mode)) | if (S_ISDIR(statbuf.st_mode)) | ||||
return (-2); // a directory | |||||
return -2; // a directory | |||||
return (statbuf.st_size); | |||||
return statbuf.st_size; | |||||
} | } | ||||
#pragma GCC visibility pop | #pragma GCC visibility pop | ||||
char *p; | char *p; | ||||
if ((p = (char *)malloc(size)) == NULL) | if ((p = (char *)malloc(size)) == NULL) | ||||
fprintf(stderr, "Can't allocate memory\n"); // I was told that size+1 fixes a crash on 64-bit systems | fprintf(stderr, "Can't allocate memory\n"); // I was told that size+1 fixes a crash on 64-bit systems | ||||
return (p); | |||||
return p; | |||||
} | } | ||||
void Free(void *ptr) | void Free(void *ptr) | ||||
for (param = 0; param < N_SPEECH_PARAM; param++) | for (param = 0; param < N_SPEECH_PARAM; param++) | ||||
param_stack[0].parameter[param] = param_defaults[param]; | param_stack[0].parameter[param] = param_defaults[param]; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
#endif | #endif | ||||
if ((outbuf == NULL) || (event_list == NULL)) | if ((outbuf == NULL) || (event_list == NULL)) | ||||
return (EE_INTERNAL_ERROR); // espeak_Initialize() has not been called | |||||
return EE_INTERNAL_ERROR; // espeak_Initialize() has not been called | |||||
option_multibyte = flags & 7; | option_multibyte = flags & 7; | ||||
option_ssml = flags & espeakSSML; | option_ssml = flags & espeakSSML; | ||||
if (SynthOnTimer() != 0) | if (SynthOnTimer() != 0) | ||||
break; | break; | ||||
} | } | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
for (;;) { | for (;;) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
#ifdef DEBUG_ENABLED | #ifdef DEBUG_ENABLED | ||||
aStatus = Synthesize(unique_identifier, text, flags | espeakSSML); | aStatus = Synthesize(unique_identifier, text, flags | espeakSSML); | ||||
SHOW_TIME("LEAVE sync_espeak_Synth_Mark"); | SHOW_TIME("LEAVE sync_espeak_Synth_Mark"); | ||||
return (aStatus); | |||||
return aStatus; | |||||
} | } | ||||
outbuf_size = (buf_length * samplerate)/500; | outbuf_size = (buf_length * samplerate)/500; | ||||
outbuf = (unsigned char *)realloc(outbuf, outbuf_size); | outbuf = (unsigned char *)realloc(outbuf, outbuf_size); | ||||
if ((out_start = outbuf) == NULL) | if ((out_start = outbuf) == NULL) | ||||
return (EE_INTERNAL_ERROR); | |||||
return EE_INTERNAL_ERROR; | |||||
// allocate space for event list. Allow 200 events per second. | // allocate space for event list. Allow 200 events per second. | ||||
// Add a constant to allow for very small buf_length | // Add a constant to allow for very small buf_length | ||||
n_event_list = (buf_length*200)/1000 + 20; | n_event_list = (buf_length*200)/1000 + 20; | ||||
if ((event_list = (espeak_EVENT *)realloc(event_list, sizeof(espeak_EVENT) * n_event_list)) == NULL) | if ((event_list = (espeak_EVENT *)realloc(event_list, sizeof(espeak_EVENT) * n_event_list)) == NULL) | ||||
return (EE_INTERNAL_ERROR); | |||||
return EE_INTERNAL_ERROR; | |||||
option_phonemes = 0; | option_phonemes = 0; | ||||
option_phoneme_events = (options & (espeakINITIALIZE_PHONEME_EVENTS | espeakINITIALIZE_PHONEME_IPA)); | option_phoneme_events = (options & (espeakINITIALIZE_PHONEME_EVENTS | espeakINITIALIZE_PHONEME_IPA)); | ||||
fifo_init(); | fifo_init(); | ||||
#endif | #endif | ||||
return (samplerate); | |||||
return samplerate; | |||||
} | } | ||||
*unique_identifier = 0; | *unique_identifier = 0; | ||||
if (synchronous_mode) { | if (synchronous_mode) { | ||||
return (sync_espeak_Synth(0, text, size, position, position_type, end_position, flags, user_data)); | |||||
return sync_espeak_Synth(0, text, size, position, position_type, end_position, flags, user_data); | |||||
} | } | ||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
*unique_identifier = 0; | *unique_identifier = 0; | ||||
if (synchronous_mode) { | if (synchronous_mode) { | ||||
return (sync_espeak_Synth_Mark(0, text, size, index_mark, end_position, flags, user_data)); | |||||
return sync_espeak_Synth_Mark(0, text, size, index_mark, end_position, flags, user_data); | |||||
} | } | ||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
if (synchronous_mode) { | if (synchronous_mode) { | ||||
sync_espeak_Key(key); | sync_espeak_Key(key); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
if (synchronous_mode) { | if (synchronous_mode) { | ||||
sync_espeak_Char(character); | sync_espeak_Char(character); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
t_espeak_command *c = create_espeak_char(character, NULL); | t_espeak_command *c = create_espeak_char(character, NULL); | ||||
return a_error; | return a_error; | ||||
#else | #else | ||||
sync_espeak_Char(character); | sync_espeak_Char(character); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
#endif | #endif | ||||
} | } | ||||
{ | { | ||||
ENTER("espeak_SetVoiceByName"); | ENTER("espeak_SetVoiceByName"); | ||||
return (SetVoiceByName(name)); | |||||
return SetVoiceByName(name); | |||||
} | } | ||||
{ | { | ||||
ENTER("espeak_SetVoiceByProperties"); | ENTER("espeak_SetVoiceByProperties"); | ||||
return (SetVoiceByProperties(voice_selector)); | |||||
return SetVoiceByProperties(voice_selector); | |||||
} | } | ||||
ENTER("espeak_GetParameter"); | ENTER("espeak_GetParameter"); | ||||
// current: 0=default value, 1=current value | // current: 0=default value, 1=current value | ||||
if (current) { | if (current) { | ||||
return (param_stack[0].parameter[parameter]); | |||||
return param_stack[0].parameter[parameter]; | |||||
} else { | } else { | ||||
return (param_defaults[parameter]); | |||||
return param_defaults[parameter]; | |||||
} | } | ||||
} | } | ||||
if (synchronous_mode) { | if (synchronous_mode) { | ||||
SetParameter(parameter, value, relative); | SetParameter(parameter, value, relative); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
t_espeak_command *c = create_espeak_parameter(parameter, value, relative); | t_espeak_command *c = create_espeak_parameter(parameter, value, relative); | ||||
return a_error; | return a_error; | ||||
#else | #else | ||||
SetParameter(parameter, value, relative); | SetParameter(parameter, value, relative); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
#endif | #endif | ||||
} | } | ||||
if (synchronous_mode) { | if (synchronous_mode) { | ||||
sync_espeak_SetPunctuationList(punctlist); | sync_espeak_SetPunctuationList(punctlist); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
t_espeak_command *c = create_espeak_punctuation_list(punctlist); | t_espeak_command *c = create_espeak_punctuation_list(punctlist); | ||||
return a_error; | return a_error; | ||||
#else | #else | ||||
sync_espeak_SetPunctuationList(punctlist); | sync_espeak_SetPunctuationList(punctlist); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
#endif | #endif | ||||
} | } | ||||
option_multibyte = textmode & 7; | option_multibyte = textmode & 7; | ||||
*textptr = TranslateClause(translator, NULL, *textptr, NULL, NULL); | *textptr = TranslateClause(translator, NULL, *textptr, NULL, NULL); | ||||
return (GetTranslatedPhonemeString(phonememode)); | |||||
return GetTranslatedPhonemeString(phonememode); | |||||
} | } | ||||
{ | { | ||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
if ((my_mode == AUDIO_OUTPUT_PLAYBACK) && wave_is_busy(my_audio)) | if ((my_mode == AUDIO_OUTPUT_PLAYBACK) && wave_is_busy(my_audio)) | ||||
return (1); | |||||
return 1; | |||||
return (fifo_is_busy()); | |||||
return fifo_is_busy(); | |||||
#else | #else | ||||
return (0); | |||||
return 0; | |||||
#endif | #endif | ||||
} | } | ||||
if (ptr != NULL) { | if (ptr != NULL) { | ||||
*ptr = path_home; | *ptr = path_home; | ||||
} | } | ||||
return (version_string); | |||||
return version_string; | |||||
} | } | ||||
#pragma GCC visibility pop | #pragma GCC visibility pop |
hp = xa[i+m]-x; | hp = xa[i+m]-x; | ||||
w = c[i+1]-d[i]; | w = c[i+1]-d[i]; | ||||
if ((den = ho-hp) == 0.0) { | if ((den = ho-hp) == 0.0) { | ||||
return (ya[2]); // two input xa are identical | |||||
return ya[2]; // two input xa are identical | |||||
} | } | ||||
den = w/den; | den = w/den; | ||||
d[i] = hp*den; | d[i] = hp*den; | ||||
} | } | ||||
y += ((2*ns < (n-m) ? c[ns+1] : d[ns--])); | y += ((2*ns < (n-m) ? c[ns+1] : d[ns--])); | ||||
} | } | ||||
return (y); | |||||
return y; | |||||
} | } | ||||
if (spect_data == NULL) { | if (spect_data == NULL) { | ||||
fprintf(stderr, "Failed to allocate memory\n"); | fprintf(stderr, "Failed to allocate memory\n"); | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
frame->max_y = 0; | frame->max_y = 0; | ||||
} | } | ||||
frame->spect = spect_data; | frame->spect = spect_data; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
total += ((htab[h] * htab[h]) >> 10); | total += ((htab[h] * htab[h]) >> 10); | ||||
} | } | ||||
frame->rms = sqrt(total) / 7.25; | frame->rms = sqrt(total) / 7.25; | ||||
return (frame->rms); | |||||
return frame->rms; | |||||
} | } | ||||
int ix; | int ix; | ||||
float adjust = 0; | float adjust = 0; | ||||
if (frame >= spect->numframes-1) return (0); | |||||
if (frame >= spect->numframes-1) return 0; | |||||
for (ix = frame+1; ix < spect->numframes-1; ix++) { | for (ix = frame+1; ix < spect->numframes-1; ix++) { | ||||
if (spect->frames[ix]->keyframe) break; // reached next keyframe | if (spect->frames[ix]->keyframe) break; // reached next keyframe | ||||
adjust += spect->frames[ix]->length_adjust; | adjust += spect->frames[ix]->length_adjust; | ||||
} | } | ||||
return ((spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust); | |||||
return (spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust; | |||||
} | } | ||||
FILE *stream = fopen(filename, "rb"); | FILE *stream = fopen(filename, "rb"); | ||||
if (stream == NULL) { | if (stream == NULL) { | ||||
fprintf(stderr, "Failed to open: '%s'", filename); | fprintf(stderr, "Failed to open: '%s'", filename); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
fread(&id1, sizeof(uint32_t), 1, stream); | fread(&id1, sizeof(uint32_t), 1, stream); | ||||
} else { | } else { | ||||
fprintf(stderr, "Unsupported spectral file format.\n"); | fprintf(stderr, "Unsupported spectral file format.\n"); | ||||
fclose(stream); | fclose(stream); | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
fread(&name_len, sizeof(uint32_t), 1, stream); | fread(&name_len, sizeof(uint32_t), 1, stream); | ||||
if (n == 0) { | if (n == 0) { | ||||
fclose(stream); | fclose(stream); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (spect->frames != NULL) { | if (spect->frames != NULL) { | ||||
spect->frames[ix]->length_adjust = spect->frames[ix]->length - GetFrameLength(spect, ix); | spect->frames[ix]->length_adjust = spect->frames[ix]->length - GetFrameLength(spect, ix); | ||||
} | } | ||||
fclose(stream); | fclose(stream); | ||||
return (0); | |||||
return 0; | |||||
} | } |
if (mbrola_voice == NULL) { | if (mbrola_voice == NULL) { | ||||
samplerate = samplerate_native; | samplerate = samplerate_native; | ||||
SetParameter(espeakVOICETYPE, 0, 0); | SetParameter(espeakVOICETYPE, 0, 0); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
sprintf(path, "%s/mbrola/%s", path_home, mbrola_voice); | sprintf(path, "%s/mbrola/%s", path_home, mbrola_voice); | ||||
#ifdef PLATFORM_WINDOWS | #ifdef PLATFORM_WINDOWS | ||||
if (load_MBR() == FALSE) { // load mbrola.dll | if (load_MBR() == FALSE) { // load mbrola.dll | ||||
fprintf(stderr, "Can't load mbrola.dll\n"); | fprintf(stderr, "Can't load mbrola.dll\n"); | ||||
return (EE_INTERNAL_ERROR); | |||||
return EE_INTERNAL_ERROR; | |||||
} | } | ||||
#endif | #endif | ||||
if (init_MBR(path) != 0) // initialise the required mbrola voice | if (init_MBR(path) != 0) // initialise the required mbrola voice | ||||
return (EE_NOT_FOUND); | |||||
return EE_NOT_FOUND; | |||||
setNoError_MBR(1); // don't stop on phoneme errors | setNoError_MBR(1); // don't stop on phoneme errors | ||||
size = GetFileLength(path); | size = GetFileLength(path); | ||||
if ((f_in = fopen(path, "rb")) == NULL) { | if ((f_in = fopen(path, "rb")) == NULL) { | ||||
close_MBR(); | close_MBR(); | ||||
return (EE_NOT_FOUND); | |||||
return EE_NOT_FOUND; | |||||
} | } | ||||
if ((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab, size)) == NULL) { | if ((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab, size)) == NULL) { | ||||
fclose(f_in); | fclose(f_in); | ||||
close_MBR(); | close_MBR(); | ||||
return (EE_INTERNAL_ERROR); | |||||
return EE_INTERNAL_ERROR; | |||||
} | } | ||||
mbrola_control = Read4Bytes(f_in); | mbrola_control = Read4Bytes(f_in); | ||||
SetParameter(espeakVOICETYPE, 1, 0); | SetParameter(espeakVOICETYPE, 1, 0); | ||||
strcpy(mbrola_name, mbrola_voice); | strcpy(mbrola_name, mbrola_voice); | ||||
mbrola_delay = 1000; // improve synchronization of events | mbrola_delay = 1000; // improve synchronization of events | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
if (pr->control & 0x10) { | if (pr->control & 0x10) { | ||||
mbr_name_prefix = pr->mbr_name; | mbr_name_prefix = pr->mbr_name; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
mnem = pr->mbr_name; | mnem = pr->mbr_name; | ||||
break; | break; | ||||
mnem = (mnem << 8) | (mbr_name_prefix & 0xff); | mnem = (mnem << 8) | (mbr_name_prefix & 0xff); | ||||
} | } | ||||
mbr_name_prefix = 0; | mbr_name_prefix = 0; | ||||
return (mnem); | |||||
return mnem; | |||||
} | } | ||||
if (final) | if (final) | ||||
sprintf(output, "\t100 %d\n", p_end); | sprintf(output, "\t100 %d\n", p_end); | ||||
return (output); | |||||
return output; | |||||
} | } | ||||
FILE *f_mbrola = NULL; | FILE *f_mbrola = NULL; | ||||
if (*n_ph == 0) | if (*n_ph == 0) | ||||
return (0); | |||||
return 0; | |||||
if (option_phonemes & espeakPHONEMES_MBROLA) { | if (option_phonemes & espeakPHONEMES_MBROLA) { | ||||
// send mbrola data to a file, not to the mbrola library | // send mbrola data to a file, not to the mbrola library | ||||
espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate) | espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate) | ||||
{ | { | ||||
return (EE_INTERNAL_ERROR); | |||||
return EE_INTERNAL_ERROR; | |||||
} | } | ||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | ||||
{ | { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int MbrolaFill(int length, int resume, int amplitude) | int MbrolaFill(int length, int resume, int amplitude) | ||||
{ | { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
void MbrolaReset(void) | void MbrolaReset(void) |
if ((f_in = fopen(buf, "rb")) == NULL) { | if ((f_in = fopen(buf, "rb")) == NULL) { | ||||
fprintf(stderr, "Can't read data file: '%s'\n", buf); | fprintf(stderr, "Can't read data file: '%s'\n", buf); | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
if (ptr != NULL) | if (ptr != NULL) | ||||
if ((p = Alloc(length)) == NULL) { | if ((p = Alloc(length)) == NULL) { | ||||
fclose(f_in); | fclose(f_in); | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
if (fread(p, 1, length, f_in) != length) { | if (fread(p, 1, length, f_in) != length) { | ||||
fclose(f_in); | fclose(f_in); | ||||
Free(p); | Free(p); | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
fclose(f_in); | fclose(f_in); | ||||
if (size != NULL) | if (size != NULL) | ||||
*size = length; | *size = length; | ||||
return (p); | |||||
return p; | |||||
} | } | ||||
int *pw; | int *pw; | ||||
if ((phoneme_tab_data = (unsigned char *)ReadPhFile((void *)(phoneme_tab_data), "phontab", NULL)) == NULL) | if ((phoneme_tab_data = (unsigned char *)ReadPhFile((void *)(phoneme_tab_data), "phontab", NULL)) == NULL) | ||||
return (-1); | |||||
return -1; | |||||
if ((phoneme_index = (USHORT *)ReadPhFile((void *)(phoneme_index), "phonindex", NULL)) == NULL) | if ((phoneme_index = (USHORT *)ReadPhFile((void *)(phoneme_index), "phonindex", NULL)) == NULL) | ||||
return (-1); | |||||
return -1; | |||||
if ((phondata_ptr = ReadPhFile((void *)(phondata_ptr), "phondata", NULL)) == NULL) | if ((phondata_ptr = ReadPhFile((void *)(phondata_ptr), "phondata", NULL)) == NULL) | ||||
return (-1); | |||||
return -1; | |||||
if ((tunes = (TUNE *)ReadPhFile((void *)(tunes), "intonations", &length)) == NULL) | if ((tunes = (TUNE *)ReadPhFile((void *)(tunes), "intonations", &length)) == NULL) | ||||
return (-1); | |||||
return -1; | |||||
wavefile_data = (unsigned char *)phondata_ptr; | wavefile_data = (unsigned char *)phondata_ptr; | ||||
n_tunes = length / sizeof(TUNE); | n_tunes = length / sizeof(TUNE); | ||||
if (srate != NULL) | if (srate != NULL) | ||||
*srate = rate; | *srate = rate; | ||||
return (result); | |||||
return result; | |||||
} | } | ||||
if (phoneme_tab[ix] == NULL) | if (phoneme_tab[ix] == NULL) | ||||
continue; | continue; | ||||
if (phoneme_tab[ix]->mnemonic == mnem) | if (phoneme_tab[ix]->mnemonic == mnem) | ||||
return (phoneme_tab[ix]->code); | |||||
return phoneme_tab[ix]->code; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
mnem |= (c << (ix*8)); | mnem |= (c << (ix*8)); | ||||
} | } | ||||
return (PhonemeCode(mnem)); | |||||
return PhonemeCode(mnem); | |||||
} | } | ||||
} | } | ||||
*n_frames = nf; | *n_frames = nf; | ||||
return (frames); | |||||
return frames; | |||||
} | } | ||||
{ | { | ||||
if (index == 0) { | if (index == 0) { | ||||
fprintf(stderr, "espeak: No envelope\n"); | fprintf(stderr, "espeak: No envelope\n"); | ||||
return (envelope_data[0]); // not found, use a default envelope | |||||
return envelope_data[0]; // not found, use a default envelope | |||||
} | } | ||||
return ((unsigned char *)&phondata_ptr[index]); | |||||
return (unsigned char *)&phondata_ptr[index]; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
if (ix == n_phoneme_tables) | if (ix == n_phoneme_tables) | ||||
return (-1); | |||||
return -1; | |||||
return (ix); | |||||
return ix; | |||||
} | } | ||||
int ix; | int ix; | ||||
if ((ix = LookupPhonemeTable(name)) == -1) | if ((ix = LookupPhonemeTable(name)) == -1) | ||||
return (-1); | |||||
return -1; | |||||
SelectPhonemeTable(ix); | SelectPhonemeTable(ix); | ||||
return (ix); | |||||
return ix; | |||||
} | } | ||||
if (phoneme_tab[plist[1].phcode]->type == phVOWEL) { | if (phoneme_tab[plist[1].phcode]->type == phVOWEL) { | ||||
pl = &plist[1]; | pl = &plist[1]; | ||||
} else | } else | ||||
return (false); // no stress elevel for this consonant | |||||
return false; // no stress elevel for this consonant | |||||
} | } | ||||
stress_level = pl->stresslevel & 0xf; | stress_level = pl->stresslevel & 0xf; | ||||
if (tr != NULL) { | if (tr != NULL) { | ||||
if ((control & 1) && (plist->synthflags & SFLAG_DICTIONARY) && ((tr->langopts.param[LOPT_REDUCE] & 1) == 0)) { | if ((control & 1) && (plist->synthflags & SFLAG_DICTIONARY) && ((tr->langopts.param[LOPT_REDUCE] & 1) == 0)) { | ||||
// change phoneme. Don't change phonemes which are given for the word in the dictionary. | // change phoneme. Don't change phonemes which are given for the word in the dictionary. | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
if ((tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= pl->wordstress)) { | if ((tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= pl->wordstress)) { | ||||
} | } | ||||
if (condition == 4) { | if (condition == 4) { | ||||
return (stress_level >= pl->wordstress); | |||||
return stress_level >= pl->wordstress; | |||||
} | } | ||||
if (condition == 3) { | if (condition == 3) { | ||||
// if stressed | // if stressed | ||||
if (stress_level > 3) | if (stress_level > 3) | ||||
return (true); | |||||
return true; | |||||
} else { | } else { | ||||
if (stress_level < condition_level[condition]) | if (stress_level < condition_level[condition]) | ||||
return (true); | |||||
return true; | |||||
} | } | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
break; | break; | ||||
plist--; | plist--; | ||||
} | } | ||||
return (count); | |||||
return count; | |||||
} | } | ||||
if (which == 4) { | if (which == 4) { | ||||
// nextPhW not word boundary | // nextPhW not word boundary | ||||
if (plist[1].sourceix) | if (plist[1].sourceix) | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
if (which == 5) { | if (which == 5) { | ||||
// prevPhW, not word boundary | // prevPhW, not word boundary | ||||
if (plist[0].sourceix) | if (plist[0].sourceix) | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
if (which == 6) { | if (which == 6) { | ||||
// next2PhW, not word boundary | // next2PhW, not word boundary | ||||
if (plist[1].sourceix || plist[2].sourceix) | if (plist[1].sourceix || plist[2].sourceix) | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
// nextVowel, not word boundary | // nextVowel, not word boundary | ||||
for (which = 1;; which++) { | for (which = 1;; which++) { | ||||
if (plist[which].sourceix) | if (plist[which].sourceix) | ||||
return (false); | |||||
return false; | |||||
if (phoneme_tab[plist[which].phcode]->type == phVOWEL) { | if (phoneme_tab[plist[which].phcode]->type == phVOWEL) { | ||||
plist = &plist[which]; | plist = &plist[which]; | ||||
break; | break; | ||||
case 8: // prevVowel in this word | case 8: // prevVowel in this word | ||||
if ((worddata == NULL) || (worddata->prev_vowel.ph == NULL)) | if ((worddata == NULL) || (worddata->prev_vowel.ph == NULL)) | ||||
return (false); // no previous vowel | |||||
return false; // no previous vowel | |||||
plist = &(worddata->prev_vowel); | plist = &(worddata->prev_vowel); | ||||
check_endtype = 1; | check_endtype = 1; | ||||
break; | break; | ||||
case 9: // next3PhW | case 9: // next3PhW | ||||
for (ix = 1; ix <= 3; ix++) { | for (ix = 1; ix <= 3; ix++) { | ||||
if (plist[ix].sourceix) | if (plist[ix].sourceix) | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
plist = &plist[3]; | plist = &plist[3]; | ||||
break; | break; | ||||
case 10: // prev2PhW | case 10: // prev2PhW | ||||
if ((plist[0].sourceix) || (plist[-1].sourceix)) | if ((plist[0].sourceix) || (plist[-1].sourceix)) | ||||
return (false); | |||||
return false; | |||||
plist -= 2; | plist -= 2; | ||||
check_endtype = 1; | check_endtype = 1; | ||||
break; | break; | ||||
if (instn2 < 7) { | if (instn2 < 7) { | ||||
// 'data' is a phoneme number | // 'data' is a phoneme number | ||||
if ((phoneme_tab[data]->mnemonic == ph->mnemonic) == true) | if ((phoneme_tab[data]->mnemonic == ph->mnemonic) == true) | ||||
return (true); | |||||
return true; | |||||
// not an exact match, check for a vowel type (eg. #i ) | // not an exact match, check for a vowel type (eg. #i ) | ||||
if ((check_endtype) && (ph->type == phVOWEL)) | if ((check_endtype) && (ph->type == phVOWEL)) | ||||
return (data == ph->end_type); // prevPh() match on end_type | |||||
return (data == ph->start_type); // thisPh() or nextPh(), match on start_type | |||||
return data == ph->end_type; // prevPh() match on end_type | |||||
return data == ph->start_type; // thisPh() or nextPh(), match on start_type | |||||
} | } | ||||
data = instn & 0x1f; | data = instn & 0x1f; | ||||
{ | { | ||||
case 0x00: | case 0x00: | ||||
// phoneme type, vowel, nasal, fricative, etc | // phoneme type, vowel, nasal, fricative, etc | ||||
return (ph->type == data); | |||||
return ph->type == data; | |||||
break; | break; | ||||
case 0x20: | case 0x20: | ||||
// place of articulation | // place of articulation | ||||
return (((ph->phflags >> 16) & 0xf) == data); | |||||
return ((ph->phflags >> 16) & 0xf) == data; | |||||
break; | break; | ||||
case 0x40: | case 0x40: | ||||
// is a bit set in phoneme flags | // is a bit set in phoneme flags | ||||
return ((ph->phflags & (1 << data)) != 0); | |||||
return (ph->phflags & (1 << data)) != 0; | |||||
break; | break; | ||||
case 0x80: | case 0x80: | ||||
case 2: | case 2: | ||||
case 3: | case 3: | ||||
case 4: | case 4: | ||||
return (StressCondition(tr, plist, data, 0)); | |||||
return StressCondition(tr, plist, data, 0); | |||||
case 5: // isBreak, Either pause phoneme, or (stop/vstop/vfric not followed by vowel or (liquid in same word)) | case 5: // isBreak, Either pause phoneme, or (stop/vstop/vfric not followed by vowel or (liquid in same word)) | ||||
return ((ph->type == phPAUSE) || (plist_this->synthflags & SFLAG_NEXT_PAUSE)); | |||||
return (ph->type == phPAUSE) || (plist_this->synthflags & SFLAG_NEXT_PAUSE); | |||||
case 6: // isWordStart | case 6: // isWordStart | ||||
return (plist->sourceix != 0); | |||||
return plist->sourceix != 0; | |||||
case 7: // notWordStart | case 7: // notWordStart | ||||
return (plist->sourceix == 0); | |||||
return plist->sourceix == 0; | |||||
case 8: // isWordEnd | case 8: // isWordEnd | ||||
return (plist[1].sourceix || (plist[1].ph->type == phPAUSE)); | |||||
return plist[1].sourceix || (plist[1].ph->type == phPAUSE); | |||||
break; | break; | ||||
case 9: // isAfterStress | case 9: // isAfterStress | ||||
if (plist->sourceix != 0) | if (plist->sourceix != 0) | ||||
return (false); | |||||
return false; | |||||
do { | do { | ||||
plist--; | plist--; | ||||
if ((plist->stresslevel & 0xf) >= 4) | if ((plist->stresslevel & 0xf) >= 4) | ||||
return (true); | |||||
return true; | |||||
} while (plist->sourceix == 0); | } while (plist->sourceix == 0); | ||||
break; | break; | ||||
case 10: // isNotVowel | case 10: // isNotVowel | ||||
return (ph->type != phVOWEL); | |||||
return ph->type != phVOWEL; | |||||
case 11: // isFinalVowel | case 11: // isFinalVowel | ||||
for (;;) { | for (;;) { | ||||
plist++; | plist++; | ||||
// plist->ph = phoneme_tab[plist->phcode]; // Why was this line here?? It corrupts plist if we have language switching if phoneme_tab is wrong language | // plist->ph = phoneme_tab[plist->phcode]; // Why was this line here?? It corrupts plist if we have language switching if phoneme_tab is wrong language | ||||
if (plist->sourceix != 0) | if (plist->sourceix != 0) | ||||
return (true); // start of next word, without finding another vowel | |||||
return true; // start of next word, without finding another vowel | |||||
if (plist->ph->type == phVOWEL) | if (plist->ph->type == phVOWEL) | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
break; | break; | ||||
case 12: // isVoiced | case 12: // isVoiced | ||||
return ((ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED)); | |||||
return (ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED); | |||||
case 13: // isFirstVowel | case 13: // isFirstVowel | ||||
return (CountVowelPosition(plist) == 1); | |||||
return CountVowelPosition(plist) == 1; | |||||
case 14: // isSecondVowel | case 14: // isSecondVowel | ||||
return (CountVowelPosition(plist) == 2); | |||||
return CountVowelPosition(plist) == 2; | |||||
case 15: // isSeqFlag1 | case 15: // isSeqFlag1 | ||||
// is this preceded by a sequence if 1 or more vowels which have 'flag1' ? (lang=hi) | // is this preceded by a sequence if 1 or more vowels which have 'flag1' ? (lang=hi) | ||||
if (plist->sourceix != 0) | if (plist->sourceix != 0) | ||||
return (false); // this is the first phoneme in the word, so no. | |||||
return false; // this is the first phoneme in the word, so no. | |||||
count = 0; | count = 0; | ||||
for (;;) { | for (;;) { | ||||
if (plist->sourceix != 0) | if (plist->sourceix != 0) | ||||
break; | break; | ||||
} | } | ||||
return (count > 0); | |||||
return count > 0; | |||||
case 0x10: // isTranslationGiven | case 0x10: // isTranslationGiven | ||||
return ((plist->synthflags & SFLAG_DICTIONARY) != 0); | |||||
return (plist->synthflags & SFLAG_DICTIONARY) != 0; | |||||
} | } | ||||
break; | break; | ||||
} | } | ||||
return (false); | |||||
return false; | |||||
} else if (instn2 == 0xf) { | } else if (instn2 == 0xf) { | ||||
// Other conditions | // Other conditions | ||||
switch (data) | switch (data) | ||||
{ | { | ||||
case 1: // PreVoicing | case 1: // PreVoicing | ||||
return (control & 1); | |||||
return control & 1; | |||||
case 2: // KlattSynth | case 2: // KlattSynth | ||||
return (voice->klattv[0] != 0); | |||||
return voice->klattv[0] != 0; | |||||
case 3: // MbrolaSynth | case 3: // MbrolaSynth | ||||
return (mbrola_name[0] != 0); | |||||
return mbrola_name[0] != 0; | |||||
} | } | ||||
} | } | ||||
return (false); | |||||
return false; | |||||
} | } | ||||
instn = *prog; | instn = *prog; | ||||
instn_type = instn >> 12; | instn_type = instn >> 12; | ||||
if ((n = n_words[instn_type]) > 0) | if ((n = n_words[instn_type]) > 0) | ||||
return (n); | |||||
return n; | |||||
switch (instn_type) | switch (instn_type) | ||||
{ | { | ||||
case 0: | case 0: | ||||
if (((instn & 0xf00) >> 8) == i_IPA_NAME) { | if (((instn & 0xf00) >> 8) == i_IPA_NAME) { | ||||
n = ((instn & 0xff) + 1) / 2; | n = ((instn & 0xff) + 1) / 2; | ||||
return (n+1); | |||||
return n+1; | |||||
} | } | ||||
return (1);; | |||||
return 1; | |||||
case 6: | case 6: | ||||
type2 = (instn & 0xf00) >> 9; | type2 = (instn & 0xf00) >> 9; | ||||
if ((type2 == 5) || (type2 == 6)) | if ((type2 == 5) || (type2 == 6)) | ||||
return (12); // switch on vowel type | |||||
return (1); | |||||
return 12; // switch on vowel type | |||||
return 1; | |||||
case 2: | case 2: | ||||
case 3: | case 3: | ||||
// a condition, check for a 2-word instruction | // a condition, check for a 2-word instruction | ||||
if (((n = instn & 0x0f00) == 0x600) || (n == 0x0d00)) | if (((n = instn & 0x0f00) == 0x600) || (n == 0x0d00)) | ||||
return (2); | |||||
return (1); | |||||
return 2; | |||||
return 1; | |||||
default: | default: | ||||
// instn_type 11 to 15, 2 words | // instn_type 11 to 15, 2 words | ||||
instn2 = prog[2]; | instn2 = prog[2]; | ||||
if ((instn2 >> 12) == 0xf) { | if ((instn2 >> 12) == 0xf) { | ||||
// This instruction is followed by addWav(), 2 more words | // This instruction is followed by addWav(), 2 more words | ||||
return (4); | |||||
return 4; | |||||
} | } | ||||
if (instn2 == i_CONTINUE) { | if (instn2 == i_CONTINUE) { | ||||
return (3); | |||||
return 3; | |||||
} | } | ||||
return (2); | |||||
return 2; | |||||
} | } | ||||
} | } | ||||
for (ix = 0; ix < 4; ix++) | for (ix = 0; ix < 4; ix++) | ||||
buf[ix] = word >> (ix*8); | buf[ix] = word >> (ix*8); | ||||
buf[4] = 0; | buf[4] = 0; | ||||
return (buf); | |||||
return buf; | |||||
} | } | ||||
if (len < speed.min_pause) { | if (len < speed.min_pause) { | ||||
len = speed.min_pause; // mS, limit the amount to which pauses can be shortened | len = speed.min_pause; // mS, limit the amount to which pauses can be shortened | ||||
} | } | ||||
return (len); | |||||
return len; | |||||
} | } | ||||
wav_length += p[0]; // length in bytes | wav_length += p[0]; // length in bytes | ||||
if (wav_length == 0) | if (wav_length == 0) | ||||
return (0); | |||||
return 0; | |||||
min_length = speed.min_sample_len; | min_length = speed.min_sample_len; | ||||
} | } | ||||
if (amp < 0) | if (amp < 0) | ||||
return (length); | |||||
return length; | |||||
len4 = wav_length / 4; | len4 = wav_length / 4; | ||||
q[2] = (intptr_t)(&wavefile_data[index]); | q[2] = (intptr_t)(&wavefile_data[index]); | ||||
q[3] = wav_scale + (amp << 8); | q[3] = wav_scale + (amp << 8); | ||||
WcmdqInc(); | WcmdqInc(); | ||||
return (length); | |||||
return length; | |||||
} | } | ||||
if (length > wav_length) { | if (length > wav_length) { | ||||
WcmdqInc(); | WcmdqInc(); | ||||
} | } | ||||
return (length); | |||||
return length; | |||||
} | } | ||||
len = DoSample2(phdata->sound_addr[pd_WAV], 2, phdata->pd_param[pd_LENGTHMOD]*2, phdata->pd_control, length_mod, amp2); | len = DoSample2(phdata->sound_addr[pd_WAV], 2, phdata->pd_param[pd_LENGTHMOD]*2, phdata->pd_control, length_mod, amp2); | ||||
} | } | ||||
last_frame = NULL; | last_frame = NULL; | ||||
return (len); | |||||
return len; | |||||
} | } | ||||
ix++; | ix++; | ||||
if (ix >= N_FRAME_POOL) | if (ix >= N_FRAME_POOL) | ||||
ix = 0; | ix = 0; | ||||
return (&frame_pool[ix]); | |||||
return &frame_pool[ix]; | |||||
} | } | ||||
if ((copy == 0) && (frame1->frflags & FRFLAG_COPIED)) { | if ((copy == 0) && (frame1->frflags & FRFLAG_COPIED)) { | ||||
// this frame has already been copied in temporary rw memory | // this frame has already been copied in temporary rw memory | ||||
return (frame1); | |||||
return frame1; | |||||
} | } | ||||
frame2 = AllocFrame(); | frame2 = AllocFrame(); | ||||
frame2->length = 0; | frame2->length = 0; | ||||
frame2->frflags |= FRFLAG_COPIED; | frame2->frflags |= FRFLAG_COPIED; | ||||
} | } | ||||
return (frame2); | |||||
return frame2; | |||||
} | } | ||||
int f1; | int f1; | ||||
if ((f1 = fr->ffreq[1]) < 300) | if ((f1 = fr->ffreq[1]) < 300) | ||||
return (3); | |||||
return 3; | |||||
if (f1 < 400) | if (f1 < 400) | ||||
return (2); | |||||
return 2; | |||||
if (f1 < 500) | if (f1 < 500) | ||||
return (1); | |||||
return (0); | |||||
return 1; | |||||
return 0; | |||||
} | } | ||||
frame_t *fr = NULL; | frame_t *fr = NULL; | ||||
if (*n_frames < 2) | if (*n_frames < 2) | ||||
return (0); | |||||
return 0; | |||||
len = (data1 & 0x3f) * 2; | len = (data1 & 0x3f) * 2; | ||||
rms = (data1 >> 6) & 0x3f; | rms = (data1 >> 6) & 0x3f; | ||||
DoPause(20, 0); // add a short pause after the consonant | DoPause(20, 0); // add a short pause after the consonant | ||||
if (flags & 16) | if (flags & 16) | ||||
return (len); | |||||
return (0); | |||||
return len; | |||||
return 0; | |||||
} | } | ||||
int frame_lengths[N_SEQ_FRAMES]; | int frame_lengths[N_SEQ_FRAMES]; | ||||
if (fmt_params->fmt_addr == 0) | if (fmt_params->fmt_addr == 0) | ||||
return (0); | |||||
return 0; | |||||
length_mod = plist->length; | length_mod = plist->length; | ||||
if (length_mod == 0) length_mod = 256; | if (length_mod == 0) length_mod = 256; | ||||
modn_flags = 0; | modn_flags = 0; | ||||
frames = LookupSpect(this_ph, which, fmt_params, &n_frames, plist); | frames = LookupSpect(this_ph, which, fmt_params, &n_frames, plist); | ||||
if (frames == NULL) | if (frames == NULL) | ||||
return (0); // not found | |||||
return 0; // not found | |||||
if (fmt_params->fmt_amp != fmt_amplitude) { | if (fmt_params->fmt_amp != fmt_amplitude) { | ||||
// an amplitude adjustment is specified for this sequence | // an amplitude adjustment is specified for this sequence | ||||
} | } | ||||
return (total_len); | |||||
return total_len; | |||||
} | } | ||||
static WORD_PH_DATA worddata; | static WORD_PH_DATA worddata; | ||||
if (option_quiet) | if (option_quiet) | ||||
return (0); | |||||
return 0; | |||||
if (option_phoneme_events & espeakINITIALIZE_PHONEME_IPA) | if (option_phoneme_events & espeakINITIALIZE_PHONEME_IPA) | ||||
use_ipa = 1; | use_ipa = 1; | ||||
if (mbrola_name[0] != 0) | if (mbrola_name[0] != 0) | ||||
return (MbrolaGenerate(phoneme_list, n_ph, resume)); | |||||
return MbrolaGenerate(phoneme_list, n_ph, resume); | |||||
if (resume == 0) { | if (resume == 0) { | ||||
ix = 1; | ix = 1; | ||||
free_min = MIN_WCMDQ; // 25 | free_min = MIN_WCMDQ; // 25 | ||||
if (WcmdqFree() <= free_min) | if (WcmdqFree() <= free_min) | ||||
return (1); // wait | |||||
return 1; // wait | |||||
prev = &phoneme_list[ix-1]; | prev = &phoneme_list[ix-1]; | ||||
next = &phoneme_list[ix+1]; | next = &phoneme_list[ix+1]; | ||||
*n_ph = 0; | *n_ph = 0; | ||||
} | } | ||||
return (0); // finished the phoneme list | |||||
return 0; // finished the phoneme list | |||||
} | } | ||||
int SynthOnTimer() | int SynthOnTimer() | ||||
{ | { | ||||
if (!timer_on) { | if (!timer_on) { | ||||
return (WavegenCloseSound()); | |||||
return WavegenCloseSound(); | |||||
} | } | ||||
do { | do { | ||||
} | } | ||||
} while (skipping_text); | } while (skipping_text); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int SynthStatus() | int SynthStatus() | ||||
{ | { | ||||
return (timer_on | paused); | |||||
return timer_on | paused; | |||||
} | } | ||||
if (control == 4) { | if (control == 4) { | ||||
if ((f_text == NULL) && (p_text == NULL)) | if ((f_text == NULL) && (p_text == NULL)) | ||||
return (0); | |||||
return 0; | |||||
else | else | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
if (control == 2) { | if (control == 2) { | ||||
n_phoneme_list = 0; | n_phoneme_list = 0; | ||||
WcmdqStop(); | WcmdqStop(); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (control == 3) { | if (control == 3) { | ||||
paused = 0; | paused = 0; | ||||
Generate(phoneme_list, &n_phoneme_list, 0); // re-start from beginning of clause | Generate(phoneme_list, &n_phoneme_list, 0); // re-start from beginning of clause | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (control == 5) { | if (control == 5) { | ||||
// stop speaking, but continue looking for text | // stop speaking, but continue looking for text | ||||
n_phoneme_list = 0; | n_phoneme_list = 0; | ||||
WcmdqStop(); | WcmdqStop(); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((f_in != NULL) || (text_in != NULL)) { | if ((f_in != NULL) || (text_in != NULL)) { | ||||
if ((f_text == NULL) && (p_text == NULL)) { | if ((f_text == NULL) && (p_text == NULL)) { | ||||
skipping_text = 0; | skipping_text = 0; | ||||
timer_on = 0; | timer_on = 0; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((f_text != NULL) && feof(f_text)) { | if ((f_text != NULL) && feof(f_text)) { | ||||
timer_on = 0; | timer_on = 0; | ||||
fclose(f_text); | fclose(f_text); | ||||
f_text = NULL; | f_text = NULL; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (current_phoneme_table != voice->phoneme_tab_ix) { | if (current_phoneme_table != voice->phoneme_tab_ix) { | ||||
if (skipping_text) { | if (skipping_text) { | ||||
n_phoneme_list = 0; | n_phoneme_list = 0; | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
Generate(phoneme_list, &n_phoneme_list, 0); | Generate(phoneme_list, &n_phoneme_list, 0); | ||||
new_voice = NULL; | new_voice = NULL; | ||||
} | } | ||||
return (1); | |||||
return 1; | |||||
} | } |
for (alphabet = alphabets; alphabet->name != NULL; alphabet++) { | for (alphabet = alphabets; alphabet->name != NULL; alphabet++) { | ||||
if (strcmp(name, &alphabet->name[1]) == 0) | if (strcmp(name, &alphabet->name[1]) == 0) | ||||
return (alphabet); | |||||
return alphabet; | |||||
} | } | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
while (alphabet->name != NULL) { | while (alphabet->name != NULL) { | ||||
if (c <= alphabet->range_max) { | if (c <= alphabet->range_max) { | ||||
if (c >= alphabet->range_min) | if (c >= alphabet->range_min) | ||||
return (alphabet); | |||||
return alphabet; | |||||
else | else | ||||
break; | break; | ||||
} | } | ||||
alphabet++; | alphabet++; | ||||
} | } | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
tr = (Translator *)Alloc(sizeof(Translator)); | tr = (Translator *)Alloc(sizeof(Translator)); | ||||
if (tr == NULL) | if (tr == NULL) | ||||
return (NULL); | |||||
return NULL; | |||||
tr->charset_a0 = charsets[1]; // ISO-8859-1, this is for when the input is not utf8 | tr->charset_a0 = charsets[1]; // ISO-8859-1, this is for when the input is not utf8 | ||||
dictionary_name[0] = 0; | dictionary_name[0] = 0; | ||||
memcpy(tr->langopts.tunes, default_tunes, sizeof(tr->langopts.tunes)); | memcpy(tr->langopts.tunes, default_tunes, sizeof(tr->langopts.tunes)); | ||||
return (tr); | |||||
return tr; | |||||
} | } | ||||
// common letter pairs, encode these as a single byte | // common letter pairs, encode these as a single byte | ||||
tr->translator_name = name2; | tr->translator_name = name2; | ||||
ProcessLanguageOptions(&tr->langopts); | ProcessLanguageOptions(&tr->langopts); | ||||
return (tr); | |||||
return tr; | |||||
} | } | ||||
}; | }; | ||||
if (iswalpha2(c)) | if (iswalpha2(c)) | ||||
return (1); | |||||
return 1; | |||||
if (c < 0x300) | if (c < 0x300) | ||||
return (0); | |||||
return 0; | |||||
if ((c >= 0x901) && (c <= 0xdf7)) { | if ((c >= 0x901) && (c <= 0xdf7)) { | ||||
// Indic scripts: Devanagari, Tamil, etc | // Indic scripts: Devanagari, Tamil, etc | ||||
if ((c & 0x7f) < 0x64) | if ((c & 0x7f) < 0x64) | ||||
return (1); | |||||
return 1; | |||||
if (lookupwchar(extra_indic_alphas, c) != 0) | if (lookupwchar(extra_indic_alphas, c) != 0) | ||||
return (1); | |||||
return 1; | |||||
if ((c >= 0xd7a) && (c <= 0xd7f)) | if ((c >= 0xd7a) && (c <= 0xd7f)) | ||||
return (1); // malaytalam chillu characters | |||||
return 1; // malaytalam chillu characters | |||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((c >= 0x5b0) && (c <= 0x5c2)) | if ((c >= 0x5b0) && (c <= 0x5c2)) | ||||
return (1); // Hebrew vowel marks | |||||
return 1; // Hebrew vowel marks | |||||
if (c == 0x0605) | if (c == 0x0605) | ||||
return (1); | |||||
return 1; | |||||
if ((c == 0x670) || ((c >= 0x64b) && (c <= 0x65e))) | if ((c == 0x670) || ((c >= 0x64b) && (c <= 0x65e))) | ||||
return (1); // arabic vowel marks | |||||
return 1; // arabic vowel marks | |||||
if ((c >= 0x300) && (c <= 0x36f)) | if ((c >= 0x300) && (c <= 0x36f)) | ||||
return (1); // combining accents | |||||
return 1; // combining accents | |||||
if ((c >= 0x780) && (c <= 0x7b1)) | if ((c >= 0x780) && (c <= 0x7b1)) | ||||
return (1); // taani/divehi (maldives) | |||||
return 1; // taani/divehi (maldives) | |||||
if ((c >= 0xf40) && (c <= 0xfbc)) | if ((c >= 0xf40) && (c <= 0xfbc)) | ||||
return (1); // tibetan | |||||
return 1; // tibetan | |||||
if ((c >= 0x1100) && (c <= 0x11ff)) | if ((c >= 0x1100) && (c <= 0x11ff)) | ||||
return (1); // Korean jamo | |||||
return 1; // Korean jamo | |||||
if ((c >= 0x2800) && (c <= 0x28ff)) | if ((c >= 0x2800) && (c <= 0x28ff)) | ||||
return (1); // braille | |||||
return 1; // braille | |||||
if ((c > 0x3040) && (c <= 0xa700)) | if ((c > 0x3040) && (c <= 0xa700)) | ||||
return (1); // Chinese/Japanese. Should never get here, but Mac OS 10.4's iswalpha seems to be broken, so just make sure | |||||
return 1; // Chinese/Japanese. Should never get here, but Mac OS 10.4's iswalpha seems to be broken, so just make sure | |||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int IsDigit09(unsigned int c) | int IsDigit09(unsigned int c) | ||||
{ | { | ||||
if ((c >= '0') && (c <= '9')) | if ((c >= '0') && (c <= '9')) | ||||
return (1); | |||||
return (0); | |||||
return 1; | |||||
return 0; | |||||
} | } | ||||
int IsDigit(unsigned int c) | int IsDigit(unsigned int c) | ||||
{ | { | ||||
if (iswdigit(c)) | if (iswdigit(c)) | ||||
return (1); | |||||
return 1; | |||||
if ((c >= 0x966) && (c <= 0x96f)) | if ((c >= 0x966) && (c <= 0x96f)) | ||||
return (1); | |||||
return 1; | |||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int IsSpace(unsigned int c) | int IsSpace(unsigned int c) | ||||
{ | { | ||||
if (c == 0) | if (c == 0) | ||||
return (0); | |||||
return 0; | |||||
if ((c >= 0x2500) && (c < 0x25a0)) | if ((c >= 0x2500) && (c < 0x25a0)) | ||||
return (1); // box drawing characters | |||||
return 1; // box drawing characters | |||||
if ((c >= 0xfff9) && (c <= 0xffff)) | if ((c >= 0xfff9) && (c <= 0xffff)) | ||||
return (1); // unicode specials | |||||
return (iswspace(c)); | |||||
return 1; // unicode specials | |||||
return iswspace(c); | |||||
} | } | ||||
for (ix = 0; list[ix] != 0; ix++) { | for (ix = 0; list[ix] != 0; ix++) { | ||||
if (list[ix] == c) | if (list[ix] == c) | ||||
return (ix+1); | |||||
return ix+1; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
for (ix = 0; list[ix] != 0; ix += 2) { | for (ix = 0; list[ix] != 0; ix += 2) { | ||||
if (list[ix] == c) | if (list[ix] == c) | ||||
return (list[ix+1]); | |||||
return list[ix+1]; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int IsBracket(int c) | int IsBracket(int c) | ||||
{ | { | ||||
if ((c >= 0x2014) && (c <= 0x201f)) | if ((c >= 0x2014) && (c <= 0x201f)) | ||||
return (1); | |||||
return (lookupwchar(brackets, c)); | |||||
return 1; | |||||
return lookupwchar(brackets, c); | |||||
} | } | ||||
if (c < 0x80) { | if (c < 0x80) { | ||||
buf[0] = c; | buf[0] = c; | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
if (c >= 0x110000) { | if (c >= 0x110000) { | ||||
buf[0] = ' '; // out of range character code | buf[0] = ' '; // out of range character code | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
if (c < 0x0800) | if (c < 0x0800) | ||||
n_bytes = 1; | n_bytes = 1; | ||||
shift -= 6; | shift -= 6; | ||||
buf[j+1] = 0x80 + ((c >> shift) & 0x3f); | buf[j+1] = 0x80 + ((c >> shift) & 0x3f); | ||||
} | } | ||||
return (n_bytes+1); | |||||
return n_bytes+1; | |||||
} | } | ||||
// Returns the number of bytes for the first UTF-8 character in buf | // Returns the number of bytes for the first UTF-8 character in buf | ||||
unsigned char c = (unsigned char)buf[0]; | unsigned char c = (unsigned char)buf[0]; | ||||
if (c < 0x80) | if (c < 0x80) | ||||
return (1); | |||||
return 1; | |||||
if (c < 0xe0) | if (c < 0xe0) | ||||
return (2); | |||||
return 2; | |||||
if (c < 0xf0) | if (c < 0xf0) | ||||
return (3); | |||||
return (4); | |||||
return 3; | |||||
return 4; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
*c = c1; | *c = c1; | ||||
return (n_bytes+1); | |||||
return n_bytes+1; | |||||
} | } | ||||
{ | { | ||||
// Read a unicode characater from a UTF8 string | // Read a unicode characater from a UTF8 string | ||||
// Returns the number of UTF8 bytes used. | // Returns the number of UTF8 bytes used. | ||||
return (utf8_in2(c, buf, 0)); | |||||
return utf8_in2(c, buf, 0); | |||||
} | } | ||||
#pragma GCC visibility pop | #pragma GCC visibility pop | ||||
{ | { | ||||
// return NULL for any non-ascii character | // return NULL for any non-ascii character | ||||
if (c >= 0x80) | if (c >= 0x80) | ||||
return (NULL); | |||||
return (strchr((char *)s, c)); // (char *) is needed for Borland compiler | |||||
return NULL; | |||||
return strchr((char *)s, c); // (char *) is needed for Borland compiler | |||||
} | } | ||||
while ((*word != 0) && !isspace2(*word)) { | while ((*word != 0) && !isspace2(*word)) { | ||||
word += utf8_in(&c, word); | word += utf8_in(&c, word); | ||||
if (!iswupper2(c)) | if (!iswupper2(c)) | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
if (phonemes[0] == phonSWITCH) { | if (phonemes[0] == phonSWITCH) { | ||||
// change to another language in order to translate this word | // change to another language in order to translate this word | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
} | } | ||||
SetSpellingStress(tr, phonemes, spell_word, posn); | SetSpellingStress(tr, phonemes, spell_word, posn); | ||||
return (word); | |||||
return word; | |||||
} | } | ||||
word1[ix++] = ' '; | word1[ix++] = ' '; | ||||
dictionary_skipwords = (count - 1)*2; | dictionary_skipwords = (count - 1)*2; | ||||
} | } | ||||
return (count); | |||||
return count; | |||||
} | } | ||||
// has a phoneme equivalence table been specified for thus language pair? | // has a phoneme equivalence table been specified for thus language pair? | ||||
if ((ix = phoneme_tab_list[tr->phoneme_tab_ix].equivalence_tables) == 0) | if ((ix = phoneme_tab_list[tr->phoneme_tab_ix].equivalence_tables) == 0) | ||||
return (0); | |||||
return 0; | |||||
pb = (unsigned char *)&phondata_ptr[ix]; | pb = (unsigned char *)&phondata_ptr[ix]; | ||||
for (;;) { | for (;;) { | ||||
if (pb[0] == 0) | if (pb[0] == 0) | ||||
return (0); // table not found | |||||
return 0; // table not found | |||||
if (pb[0] == lang2) | if (pb[0] == lang2) | ||||
break; | break; | ||||
DecodePhonemes(phonemes, phonbuf); | DecodePhonemes(phonemes, phonbuf); | ||||
fprintf(f_trans, "%s\n\n", phonbuf); | fprintf(f_trans, "%s\n\n", phonbuf); | ||||
} | } | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
if (tr->data_dictlist == NULL) { | if (tr->data_dictlist == NULL) { | ||||
// dictionary is not loaded | // dictionary is not loaded | ||||
word_phonemes[0] = 0; | word_phonemes[0] = 0; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
// count the length of the word | // count the length of the word | ||||
if (phonemes[0] == phonSWITCH) { | if (phonemes[0] == phonSWITCH) { | ||||
// change to another language in order to translate this word | // change to another language in order to translate this word | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((wmark > 0) && (wmark < 8)) { | if ((wmark > 0) && (wmark < 8)) { | ||||
if (!found && iswdigit(first_char)) { | if (!found && iswdigit(first_char)) { | ||||
Lookup(tr, "_0lang", word_phonemes); | Lookup(tr, "_0lang", word_phonemes); | ||||
if (word_phonemes[0] == phonSWITCH) | if (word_phonemes[0] == phonSWITCH) | ||||
return (0); | |||||
return 0; | |||||
if ((tr->langopts.numbers2 & NUM2_ENGLISH_NUMERALS) && !(wtab->flags & FLAG_CHAR_REPLACED)) { | if ((tr->langopts.numbers2 & NUM2_ENGLISH_NUMERALS) && !(wtab->flags & FLAG_CHAR_REPLACED)) { | ||||
// for this language, speak English numerals (0-9) with the English voice | // for this language, speak English numerals (0-9) with the English voice | ||||
sprintf(word_phonemes, "%c", phonSWITCH); | sprintf(word_phonemes, "%c", phonSWITCH); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
found = TranslateNumber(tr, word1, phonemes, dictionary_flags, wtab, 0); | found = TranslateNumber(tr, word1, phonemes, dictionary_flags, wtab, 0); | ||||
if (SpeakIndividualLetters(tr, word1, phonemes, spell_word) == NULL) { | if (SpeakIndividualLetters(tr, word1, phonemes, spell_word) == NULL) { | ||||
if (word_length > 1) | if (word_length > 1) | ||||
return (FLAG_SPELLWORD); // a mixture of languages, retranslate as individual letters, separated by spaces | |||||
return (0); | |||||
return FLAG_SPELLWORD; // a mixture of languages, retranslate as individual letters, separated by spaces | |||||
return 0; | |||||
} | } | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
if (wflags & FLAG_TRANSLATOR2) | if (wflags & FLAG_TRANSLATOR2) | ||||
return (0); | |||||
return (dictionary_flags[0] & FLAG_SKIPWORDS); // for "b.c.d" | |||||
return 0; | |||||
return dictionary_flags[0] & FLAG_SKIPWORDS; // for "b.c.d" | |||||
} else if (found == 0) { | } else if (found == 0) { | ||||
int posn; | int posn; | ||||
int non_initial; | int non_initial; | ||||
// change to another language in order to translate this word | // change to another language in order to translate this word | ||||
strcpy(word_phonemes, unpron_phonemes); | strcpy(word_phonemes, unpron_phonemes); | ||||
if (strcmp(&unpron_phonemes[1], "en") == 0) | if (strcmp(&unpron_phonemes[1], "en") == 0) | ||||
return (FLAG_SPELLWORD); // _^_en must have been set in TranslateLetter(), not *_rules which uses only _^_ | |||||
return (0); | |||||
return FLAG_SPELLWORD; // _^_en must have been set in TranslateLetter(), not *_rules which uses only _^_ | |||||
return 0; | |||||
} | } | ||||
length = 0; | length = 0; | ||||
if (phonemes[0] == phonSWITCH) { | if (phonemes[0] == phonSWITCH) { | ||||
// change to another language in order to translate this word | // change to another language in order to translate this word | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if ((phonemes[0] == 0) && (end_phonemes[0] == 0)) { | if ((phonemes[0] == 0) && (end_phonemes[0] == 0)) { | ||||
utf8_in(&wc, wordx); | utf8_in(&wc, wordx); | ||||
if ((word_length == 1) && (IsAlpha(wc) || IsSuperscript(wc))) { | if ((word_length == 1) && (IsAlpha(wc) || IsSuperscript(wc))) { | ||||
if ((wordx = SpeakIndividualLetters(tr, wordx, phonemes, spell_word)) == NULL) { | if ((wordx = SpeakIndividualLetters(tr, wordx, phonemes, spell_word)) == NULL) { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
// change to another language in order to translate this word | // change to another language in order to translate this word | ||||
wordx[-1] = c_temp; | wordx[-1] = c_temp; | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
// change to another language in order to translate this word | // change to another language in order to translate this word | ||||
memcpy(wordx, word_copy, strlen(word_copy)); | memcpy(wordx, word_copy, strlen(word_copy)); | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (dictionary_flags[0] == 0) { | if (dictionary_flags[0] == 0) { | ||||
dictionary_flags[0] = dictionary_flags2[0]; | dictionary_flags[0] = dictionary_flags2[0]; | ||||
// change to another language in order to translate this word | // change to another language in order to translate this word | ||||
memcpy(wordx, word_copy, strlen(word_copy)); | memcpy(wordx, word_copy, strlen(word_copy)); | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (dictionary_flags2[0] & FLAG_ABBREV) { | if (dictionary_flags2[0] & FLAG_ABBREV) { | ||||
strcpy(word_phonemes, phonemes); | strcpy(word_phonemes, phonemes); | ||||
memcpy(wordx, word_copy, strlen(word_copy)); | memcpy(wordx, word_copy, strlen(word_copy)); | ||||
wordx[-1] = c_temp; | wordx[-1] = c_temp; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
dictionary_flags[0] |= was_unpronouncable; | dictionary_flags[0] |= was_unpronouncable; | ||||
memcpy(word_start, word_copy2, word_copy_length); | memcpy(word_start, word_copy2, word_copy_length); | ||||
return (dictionary_flags[0]); | |||||
return dictionary_flags[0]; | |||||
} | } | ||||
if (phoneme_tab[phon]->type == phVOWEL) | if (phoneme_tab[phon]->type == phVOWEL) | ||||
count++; | count++; | ||||
} | } | ||||
return (count); | |||||
return count; | |||||
} | } | ||||
} | } | ||||
if (translator2 != NULL) | if (translator2 != NULL) | ||||
translator2->phonemes_repeat[0] = 0; | translator2->phonemes_repeat[0] = 0; | ||||
return (new_phoneme_tab); | |||||
return new_phoneme_tab; | |||||
} | } | ||||
embedded_flag = 0; | embedded_flag = 0; | ||||
} | } | ||||
word_phonemes[0] = 0; | word_phonemes[0] = 0; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
// after a $pause word attribute, ignore a $pause attribute on the next two words | // after a $pause word attribute, ignore a $pause attribute on the next two words | ||||
if (flags & FLAG_SPELLWORD) { | if (flags & FLAG_SPELLWORD) { | ||||
// re-translate the word as individual letters, separated by spaces | // re-translate the word as individual letters, separated by spaces | ||||
memcpy(word, word_copy, word_copy_len); | memcpy(word, word_copy, word_copy_len); | ||||
return (flags); | |||||
return flags; | |||||
} | } | ||||
if ((flags & FLAG_COMBINE) && !(wtab[1].flags & FLAG_PHONEMES)) { | if ((flags & FLAG_COMBINE) && !(wtab[1].flags & FLAG_PHONEMES)) { | ||||
// strcpy((char *)p,translator2->word_phonemes); | // strcpy((char *)p,translator2->word_phonemes); | ||||
if (p[0] == phonSWITCH) | if (p[0] == phonSWITCH) | ||||
return (FLAG_SPELLWORD); | |||||
return FLAG_SPELLWORD; | |||||
if (switch_phonemes < 0) { | if (switch_phonemes < 0) { | ||||
// language code is not recognised or 2nd translator won't translate it | // language code is not recognised or 2nd translator won't translate it | ||||
} | } | ||||
tr->prev_dict_flags[0] = flags; | tr->prev_dict_flags[0] = flags; | ||||
return (flags); | |||||
return flags; | |||||
} | } | ||||
c = source[source_index++]; | c = source[source_index++]; | ||||
if (embedded_ix >= (N_EMBEDDED_LIST - 2)) | if (embedded_ix >= (N_EMBEDDED_LIST - 2)) | ||||
return (0); // list is full | |||||
return 0; // list is full | |||||
if ((p = strchr_w(commands, c)) == NULL) | if ((p = strchr_w(commands, c)) == NULL) | ||||
return (0); | |||||
return 0; | |||||
cmd = (p - commands)+1; | cmd = (p - commands)+1; | ||||
if (value == -1) { | if (value == -1) { | ||||
value = embedded_default[cmd]; | value = embedded_default[cmd]; | ||||
embedded_list[embedded_ix++] = cmd + sign + (value << 8); | embedded_list[embedded_ix++] = cmd + sign + (value << 8); | ||||
*source_index_out = source_index; | *source_index_out = source_index; | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
if (ignore_next) { | if (ignore_next) { | ||||
ignore_next = 0; | ignore_next = 0; | ||||
return (8); | |||||
return 8; | |||||
} | } | ||||
if (c == 0) return (0); | |||||
if (c == 0) return 0; | |||||
if ((replace_chars = tr->langopts.replace_chars) == NULL) | if ((replace_chars = tr->langopts.replace_chars) == NULL) | ||||
return (c); | |||||
return c; | |||||
// there is a list of character codes to be substituted with alternative codes | // there is a list of character codes to be substituted with alternative codes | ||||
} | } | ||||
if (new_c == 0) | if (new_c == 0) | ||||
return (c); // no substitution | |||||
return c; // no substitution | |||||
if (new_c & 0xffe00000) { | if (new_c & 0xffe00000) { | ||||
// there is a second character to be inserted | // there is a second character to be inserted | ||||
new_c = towupper2(new_c); | new_c = towupper2(new_c); | ||||
*wordflags |= FLAG_CHAR_REPLACED; | *wordflags |= FLAG_CHAR_REPLACED; | ||||
return (new_c); | |||||
return new_c; | |||||
} | } | ||||
c = initial + 0x1100; | c = initial + 0x1100; | ||||
*insert = (11*28*21) + (medial*28) + final + 0xac00; | *insert = (11*28*21) + (medial*28) + final + 0xac00; | ||||
} | } | ||||
return (c); | |||||
return c; | |||||
} else if (((code = c - 0x3130) >= 0) && (code < 0x34)) { | } else if (((code = c - 0x3130) >= 0) && (code < 0x34)) { | ||||
// Hangul compatibility jamo | // Hangul compatibility jamo | ||||
return (hangul_compatibility[code] + 0x1100); | |||||
return hangul_compatibility[code] + 0x1100; | |||||
} | } | ||||
switch (tr->translator_name) | switch (tr->translator_name) | ||||
if ((next_in == 'n') && (tr->translator_name == L('a', 'f'))) { | if ((next_in == 'n') && (tr->translator_name == L('a', 'f'))) { | ||||
// n preceded by either apostrophe or U2019 "right single quotation mark" | // n preceded by either apostrophe or U2019 "right single quotation mark" | ||||
ptr[0] = ' '; // delete the n | ptr[0] = ' '; // delete the n | ||||
return (0x0259); // replace ' by unicode schwa character | |||||
return 0x0259; // replace ' by unicode schwa character | |||||
} | } | ||||
if ((next_in == 'n') || (next_in == 't')) { | if ((next_in == 'n') || (next_in == 't')) { | ||||
// Dutch, [@n] and [@t] | // Dutch, [@n] and [@t] | ||||
return (0x0259); // replace ' by unicode schwa character | |||||
return 0x0259; // replace ' by unicode schwa character | |||||
} | } | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
return (SubstituteChar(tr, c, next_in, insert, wordflags)); | |||||
return SubstituteChar(tr, c, next_in, insert, wordflags); | |||||
} | } | ||||
len = strlen(p); | len = strlen(p); | ||||
if ((word[-len] == ' ') && (memcmp(&word[-len+1], p, len-1) == 0)) { | if ((word[-len] == ' ') && (memcmp(&word[-len+1], p, len-1) == 0)) { | ||||
if ((c == p[len-1]) || ((p[len-1] == 'A') && IsVowel(tr, c))) | if ((c == p[len-1]) || ((p[len-1] == 'A') && IsVowel(tr, c))) | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int tone2; | int tone2; | ||||
if (tr == NULL) { | if (tr == NULL) { | ||||
return (NULL); | |||||
return NULL; | |||||
} | } | ||||
p_textinput = (unsigned char *)vp_input; | p_textinput = (unsigned char *)vp_input; | ||||
} | } | ||||
if (Eof() || (vp_input == NULL)) | if (Eof() || (vp_input == NULL)) | ||||
return (NULL); | |||||
return NULL; | |||||
if (option_multibyte == espeakCHARS_WCHAR) | if (option_multibyte == espeakCHARS_WCHAR) | ||||
return ((void *)p_wchar_input); | |||||
return (void *)p_wchar_input; | |||||
else | else | ||||
return ((void *)p_textinput); | |||||
return (void *)p_textinput; | |||||
} | } | ||||
char *p; | char *p; | ||||
if (fgets(buf, size, f_in) == NULL) | if (fgets(buf, size, f_in) == NULL) | ||||
return (NULL); | |||||
return NULL; | |||||
if (buf[0] == '#') { | if (buf[0] == '#') { | ||||
buf[0] = 0; | buf[0] = 0; | ||||
return (buf); | |||||
return buf; | |||||
} | } | ||||
len = strlen(buf); | len = strlen(buf); | ||||
if ((p = strstr(buf, "//")) != NULL) | if ((p = strstr(buf, "//")) != NULL) | ||||
*p = 0; | *p = 0; | ||||
return (buf); | |||||
return buf; | |||||
} | } | ||||
for (ix = 0; ix < n_tunes; ix++) { | for (ix = 0; ix < n_tunes; ix++) { | ||||
if (strcmp(name, tunes[ix].name) == 0) | if (strcmp(name, tunes[ix].name) == 0) | ||||
return (ix); | |||||
return ix; | |||||
} | } | ||||
return (-1); | |||||
return -1; | |||||
} | } | ||||
sprintf(fname_buf, "%s/mbrola/%s", path_home, vname); | sprintf(fname_buf, "%s/mbrola/%s", path_home, vname); | ||||
if (GetFileLength(fname_buf) <= 0) | if (GetFileLength(fname_buf) <= 0) | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
#endif | #endif | ||||
gender = LookupMnem(genders, vgender); | gender = LookupMnem(genders, vgender); | ||||
if (n_languages == 0) { | if (n_languages == 0) { | ||||
return (NULL); // no language lines in the voice file | |||||
return NULL; // no language lines in the voice file | |||||
} | } | ||||
p = (char *)calloc(sizeof(espeak_VOICE) + langix + strlen(fname) + strlen(vname) + 3, 1); | p = (char *)calloc(sizeof(espeak_VOICE) + langix + strlen(fname) + strlen(vname) + 3, 1); | ||||
voice_data->gender = gender; | voice_data->gender = gender; | ||||
voice_data->variant = 0; | voice_data->variant = 0; | ||||
voice_data->xx1 = n_variants; | voice_data->xx1 = n_variants; | ||||
return (voice_data); | |||||
return voice_data; | |||||
} | } | ||||
{ | { | ||||
// Read 8 integer numbers | // Read 8 integer numbers | ||||
memset(data, 0, 8+sizeof(int)); | memset(data, 0, 8+sizeof(int)); | ||||
return (sscanf(data_in, "%d %d %d %d %d %d %d %d", | |||||
&data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7])); | |||||
return sscanf(data_in, "%d %d %d %d %d %d %d %d", | |||||
&data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7]); | |||||
} | } | ||||
for (ix = 0; (ix < 4) && ((c = string[ix]) != 0); ix++) { | for (ix = 0; (ix < 4) && ((c = string[ix]) != 0); ix++) { | ||||
value = (value << 8) | (c & 0xff); | value = (value << 8) | (c & 0xff); | ||||
} | } | ||||
return (value); | |||||
return value; | |||||
} | } | ||||
if (control & 0x10) { | if (control & 0x10) { | ||||
strcpy(buf, vname); | strcpy(buf, vname); | ||||
if (GetFileLength(buf) <= 0) | if (GetFileLength(buf) <= 0) | ||||
return (NULL); | |||||
return NULL; | |||||
} else { | } else { | ||||
if (voicename[0] == 0) | if (voicename[0] == 0) | ||||
strcpy(voicename, "default"); | strcpy(voicename, "default"); | ||||
language_type = "en"; // default | language_type = "en"; // default | ||||
if (f_voice == NULL) { | if (f_voice == NULL) { | ||||
if (control & 3) | if (control & 3) | ||||
return (NULL); // can't open file | |||||
return NULL; // can't open file | |||||
if (SelectPhonemeTableName(voicename) >= 0) | if (SelectPhonemeTableName(voicename) >= 0) | ||||
language_type = voicename; | language_type = voicename; | ||||
LoadDictionary(new_translator, new_dictionary, control & 4); | LoadDictionary(new_translator, new_dictionary, control & 4); | ||||
if (dictionary_name[0] == 0) { | if (dictionary_name[0] == 0) { | ||||
DeleteTranslator(new_translator); | DeleteTranslator(new_translator); | ||||
return (NULL); // no dictionary loaded | |||||
return NULL; // no dictionary loaded | |||||
} | } | ||||
new_translator->dict_condition = conditional_rules; | new_translator->dict_condition = conditional_rules; | ||||
translator->stress_amps_r[ix] = stress_amps[ix] -1; | translator->stress_amps_r[ix] = stress_amps[ix] -1; | ||||
} | } | ||||
return (voice); | |||||
return voice; | |||||
} | } | ||||
sprintf(variant_name, "%sf%d", variant_prefix, variant_num-10); // female | sprintf(variant_name, "%sf%d", variant_prefix, variant_num-10); // female | ||||
} | } | ||||
return (variant_name); | |||||
return variant_name; | |||||
} | } | ||||
variant_name = ExtractVoiceVariantName(buf, variant_num, 1); | variant_name = ExtractVoiceVariantName(buf, variant_num, 1); | ||||
if ((v = LoadVoice(buf, 0)) == NULL) | if ((v = LoadVoice(buf, 0)) == NULL) | ||||
return (NULL); | |||||
return NULL; | |||||
if (variant_name[0] != 0) { | if (variant_name[0] != 0) { | ||||
v = LoadVoice(variant_name, 2); | v = LoadVoice(variant_name, 2); | ||||
} | } | ||||
return (v); | |||||
return v; | |||||
} | } | ||||
if ((ix = strcmp(&v1->languages[1], &v2->languages[1])) != 0) // primary language name | if ((ix = strcmp(&v1->languages[1], &v2->languages[1])) != 0) // primary language name | ||||
return (ix); | |||||
return ix; | |||||
if ((ix = v1->languages[0] - v2->languages[0]) != 0) // priority number | if ((ix = v1->languages[0] - v2->languages[0]) != 0) // priority number | ||||
return (ix); | |||||
return (strcmp(v1->name, v2->name)); | |||||
return ix; | |||||
return strcmp(v1->name, v2->name); | |||||
} | } | ||||
espeak_VOICE *v2 = *(espeak_VOICE **)p2; | espeak_VOICE *v2 = *(espeak_VOICE **)p2; | ||||
if ((ix = v2->score - v1->score) != 0) | if ((ix = v2->score - v1->score) != 0) | ||||
return (ix); | |||||
return (strcmp(v1->name, v2->name)); | |||||
return ix; | |||||
return strcmp(v1->name, v2->name); | |||||
} | } | ||||
if (spec_n_parts < 0) { | if (spec_n_parts < 0) { | ||||
// match on the subdirectory | // match on the subdirectory | ||||
if (memcmp(voice->identifier, spec_language, spec_lang_len) == 0) | if (memcmp(voice->identifier, spec_language, spec_lang_len) == 0) | ||||
return (100); | |||||
return (0); | |||||
return 100; | |||||
return 0; | |||||
} | } | ||||
if (spec_n_parts == 0) { | if (spec_n_parts == 0) { | ||||
} | } | ||||
} | } | ||||
if (score == 0) | if (score == 0) | ||||
return (0); | |||||
return 0; | |||||
if (voice_spec->name != NULL) { | if (voice_spec->name != NULL) { | ||||
if (strcmp(voice_spec->name, voice->name) == 0) { | if (strcmp(voice_spec->name, voice->name) == 0) { | ||||
} | } | ||||
if (score < 1) | if (score < 1) | ||||
score = 1; | score = 1; | ||||
return (score); | |||||
return score; | |||||
} | } | ||||
voices[nv] = NULL; // list terminator | voices[nv] = NULL; // list terminator | ||||
if (nv == 0) | if (nv == 0) | ||||
return (0); | |||||
return 0; | |||||
// sort the selected voices by their score | // sort the selected voices by their score | ||||
qsort(voices, nv, sizeof(espeak_VOICE *), (int(__cdecl *)(const void *, const void *))VoiceScoreSorter); | qsort(voices, nv, sizeof(espeak_VOICE *), (int(__cdecl *)(const void *, const void *))VoiceScoreSorter); | ||||
return (nv); | |||||
return nv; | |||||
} | } | ||||
} | } | ||||
if (match_name < 0) | if (match_name < 0) | ||||
return (NULL); | |||||
return NULL; | |||||
return (voices[match_name]); | |||||
return voices[match_name]; | |||||
} | } | ||||
if ((voice_select2.gender == 0) && (voice_select2.age == 0) && (voice_select2.variant == 0)) { | if ((voice_select2.gender == 0) && (voice_select2.age == 0) && (voice_select2.variant == 0)) { | ||||
if (variant_name[0] != 0) { | if (variant_name[0] != 0) { | ||||
sprintf(voice_id, "%s+%s", vp->identifier, variant_name); | sprintf(voice_id, "%s+%s", vp->identifier, variant_name); | ||||
return (voice_id); | |||||
return voice_id; | |||||
} | } | ||||
return (vp->identifier); | |||||
return vp->identifier; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
// index the sorted list by the required variant number | // index the sorted list by the required variant number | ||||
if (ix2 == 0) | if (ix2 == 0) | ||||
return (NULL); | |||||
return NULL; | |||||
vp = voices2[voice_select2.variant % ix2]; | vp = voices2[voice_select2.variant % ix2]; | ||||
if (vp->variant != 0) { | if (vp->variant != 0) { | ||||
variant_name = ExtractVoiceVariantName(NULL, vp->variant, 0); | variant_name = ExtractVoiceVariantName(NULL, vp->variant, 0); | ||||
sprintf(voice_id, "%s+%s", vp->identifier, variant_name); | sprintf(voice_id, "%s+%s", vp->identifier, variant_name); | ||||
return (voice_id); | |||||
return voice_id; | |||||
} | } | ||||
return (vp->identifier); | |||||
return vp->identifier; | |||||
} | } | ||||
DoVoiceChange(voice); | DoVoiceChange(voice); | ||||
voice_selector.languages = voice->language_name; | voice_selector.languages = voice->language_name; | ||||
SetVoiceStack(&voice_selector, variant_name); | SetVoiceStack(&voice_selector, variant_name); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
if (n_voices_list == 0) | if (n_voices_list == 0) | ||||
DoVoiceChange(voice); | DoVoiceChange(voice); | ||||
voice_selector.languages = voice->language_name; | voice_selector.languages = voice->language_name; | ||||
SetVoiceStack(&voice_selector, variant_name); | SetVoiceStack(&voice_selector, variant_name); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
} | } | ||||
return (EE_INTERNAL_ERROR); // voice name not found | |||||
return EE_INTERNAL_ERROR; // voice name not found | |||||
} | } | ||||
voice_id = SelectVoice(voice_selector, &voice_found); | voice_id = SelectVoice(voice_selector, &voice_found); | ||||
if (voice_found == 0) | if (voice_found == 0) | ||||
return (EE_NOT_FOUND); | |||||
return EE_NOT_FOUND; | |||||
LoadVoiceVariant(voice_id, 0); | LoadVoiceVariant(voice_id, 0); | ||||
DoVoiceChange(voice); | DoVoiceChange(voice); | ||||
SetVoiceStack(voice_selector, ""); | SetVoiceStack(voice_selector, ""); | ||||
return (EE_OK); | |||||
return EE_OK; | |||||
} | } | ||||
GetVoices(path_voices); | GetVoices(path_voices); | ||||
voices_list[n_voices_list] = NULL; // voices list terminator | voices_list[n_voices_list] = NULL; // voices list terminator | ||||
} | } | ||||
return ((const espeak_VOICE **)voices_list); | |||||
return (const espeak_VOICE **)voices_list; | |||||
#else | #else | ||||
int ix; | int ix; | ||||
} | } | ||||
voices[j] = NULL; | voices[j] = NULL; | ||||
} | } | ||||
return ((const espeak_VOICE **)voices); | |||||
return (const espeak_VOICE **)voices; | |||||
#endif | #endif | ||||
} | } | ||||
ESPEAK_API espeak_VOICE *espeak_GetCurrentVoice(void) | ESPEAK_API espeak_VOICE *espeak_GetCurrentVoice(void) | ||||
{ | { | ||||
return (¤t_voice_selected); | |||||
return ¤t_voice_selected; | |||||
} | } | ||||
#pragma GCC visibility pop | #pragma GCC visibility pop |
} | } | ||||
#endif | #endif | ||||
return (aResult); | |||||
return aResult; | |||||
} | } | ||||
if (active == 1) { | if (active == 1) { | ||||
SHOW_TIME("wave_open_sound > already active"); | SHOW_TIME("wave_open_sound > already active"); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (active < 0) { | if (active < 0) { | ||||
out_channels = 1; | out_channels = 1; | ||||
SHOW("wave_open_sound > %s\n", "LEAVE"); | SHOW("wave_open_sound > %s\n", "LEAVE"); | ||||
return (err != paNoError); | |||||
return err != paNoError; | |||||
} | } | ||||
#if (USE_PORTAUDIO == 19) | #if (USE_PORTAUDIO == 19) | ||||
select_device("alsa"); | select_device("alsa"); | ||||
once = 1; | once = 1; | ||||
} | } | ||||
return ((void *)1); | |||||
return (void *)1; | |||||
} | } | ||||
static size_t copyBuffer(char *dest, char *src, const size_t theSizeInBytes) | static size_t copyBuffer(char *dest, char *src, const size_t theSizeInBytes) | ||||
SHOW("wave_is_busy: %d\n", active); | SHOW("wave_is_busy: %d\n", active); | ||||
return (active == 1); | |||||
return active == 1; | |||||
} | } | ||||
void wave_terminate() | void wave_terminate() | ||||
int wave_get_remaining_time(uint32_t sample, uint32_t *time) | int wave_get_remaining_time(uint32_t sample, uint32_t *time) | ||||
{ | { | ||||
if (!time) return (-1); | |||||
if (!time) return -1; | |||||
*time = (uint32_t)0; | *time = (uint32_t)0; | ||||
return 0; | return 0; | ||||
} | } |
void *wave_open(const char *the_api) | void *wave_open(const char *the_api) | ||||
{ | { | ||||
ENTER("wave_open"); | ENTER("wave_open"); | ||||
return ((void *)1); | |||||
return (void *)1; | |||||
} | } | ||||
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) | size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) | ||||
int wave_get_remaining_time(uint32_t sample, uint32_t *time) | int wave_get_remaining_time(uint32_t sample, uint32_t *time) | ||||
{ | { | ||||
if (!time) return (-1); | |||||
if (!time) return -1; | |||||
*time = (uint32_t)0; | *time = (uint32_t)0; | ||||
return 0; | return 0; | ||||
} | } |
SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd); | SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd); | ||||
if (sun_audio_fd < 0) { | if (sun_audio_fd < 0) { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo); | ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo); | ||||
if (ioctl(sun_audio_fd, AUDIO_SETINFO, &ainfo) == -1) { | if (ioctl(sun_audio_fd, AUDIO_SETINFO, &ainfo) == -1) { | ||||
SHOW("wave_init() failed to set audio params: %s\n", strerror(errno)); | SHOW("wave_init() failed to set audio params: %s\n", strerror(errno)); | ||||
close(sun_audio_fd); | close(sun_audio_fd); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
// wave_open | // wave_open | ||||
void *wave_open(const char *the_api) | void *wave_open(const char *the_api) | ||||
{ | { | ||||
ENTER("wave_open"); | ENTER("wave_open"); | ||||
return ((void *)sun_audio_fd); | |||||
return (void *)sun_audio_fd; | |||||
} | } | ||||
// wave_write | // wave_write | ||||
audio_info_t ainfo; | audio_info_t ainfo; | ||||
ENTER("wave_get_remaining_time"); | ENTER("wave_get_remaining_time"); | ||||
if (!time) { | if (!time) { | ||||
return (-1); | |||||
return -1; | |||||
SHOW_TIME("wave_get_remaining_time > LEAVE"); | SHOW_TIME("wave_get_remaining_time > LEAVE"); | ||||
} | } | ||||
int wave_get_remaining_time(uint32_t sample, uint32_t *time) | int wave_get_remaining_time(uint32_t sample, uint32_t *time) | ||||
{ | { | ||||
if (!time) return (-1); | |||||
if (!time) return -1; | |||||
*time = (uint32_t)0; | *time = (uint32_t)0; | ||||
return 0; | return 0; | ||||
} | } |
int i; | int i; | ||||
i = wcmdq_head - wcmdq_tail; | i = wcmdq_head - wcmdq_tail; | ||||
if (i <= 0) i += N_WCMDQ; | if (i <= 0) i += N_WCMDQ; | ||||
return (i); | |||||
return i; | |||||
} | } | ||||
int WcmdqUsed() | int WcmdqUsed() | ||||
{ | { | ||||
return (N_WCMDQ - WcmdqFree()); | |||||
return N_WCMDQ - WcmdqFree(); | |||||
} | } | ||||
#if USE_PORTAUDIO == 18 | #if USE_PORTAUDIO == 18 | ||||
#ifdef PLATFORM_WINDOWS | #ifdef PLATFORM_WINDOWS | ||||
return (result); | |||||
return result; | |||||
#endif | #endif | ||||
if (result != 0) { | if (result != 0) { | ||||
static int end_timer = 0; | static int end_timer = 0; | ||||
if (end_timer > 0) { | if (end_timer > 0) { | ||||
end_timer--; | end_timer--; | ||||
if (end_timer == 0) | if (end_timer == 0) | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
#else | #else | ||||
return (result); | |||||
return result; | |||||
#endif | #endif | ||||
} | } | ||||
result = Pa_OpenStream( | result = Pa_OpenStream( | ||||
stream, NULL, &hostApiOutputParameters, sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData); | stream, NULL, &hostApiOutputParameters, sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData); | ||||
return (result); | |||||
return result; | |||||
} | } | ||||
#endif | #endif | ||||
if (option_waveout || option_quiet) { | if (option_waveout || option_quiet) { | ||||
// writing to WAV file, not to portaudio | // writing to WAV file, not to portaudio | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
#if USE_PORTAUDIO == 18 | #if USE_PORTAUDIO == 18 | ||||
#endif | #endif | ||||
if (active == 1) | if (active == 1) | ||||
return (0); | |||||
return 0; | |||||
if (active < 0) { | if (active < 0) { | ||||
out_channels = 1; | out_channels = 1; | ||||
exit(2); | exit(2); | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (active == 0) { | if (active == 0) { | ||||
Pa_CloseStream(pa_stream); | Pa_CloseStream(pa_stream); | ||||
pa_stream = NULL; | pa_stream = NULL; | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
} else { | } else { | ||||
WavegenOpenSound(); // still items in the queue, shouldn't be closed | WavegenOpenSound(); // still items in the queue, shouldn't be closed | ||||
} | } | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
PaError err; | PaError err; | ||||
if (option_quiet) | if (option_quiet) | ||||
return (0); | |||||
return 0; | |||||
// PortAudio sound output library | // PortAudio sound output library | ||||
err = Pa_Initialize(); | err = Pa_Initialize(); | ||||
pa_init_err = err; | pa_init_err = err; | ||||
if (err != paNoError) { | if (err != paNoError) { | ||||
fprintf(stderr, "Failed to initialise the PortAudio sound\n"); | fprintf(stderr, "Failed to initialise the PortAudio sound\n"); | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
#else | #else | ||||
int WavegenOpenSound() | int WavegenOpenSound() | ||||
{ | { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int WavegenCloseSound() | int WavegenCloseSound() | ||||
{ | { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
int WavegenInitSound() | int WavegenInitSound() | ||||
{ | { | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
#endif | #endif | ||||
amp = (embedded_value[EMBED_A])*55/100; | amp = (embedded_value[EMBED_A])*55/100; | ||||
general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16; | general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16; | ||||
return (general_amplitude); | |||||
return general_amplitude; | |||||
} | } | ||||
#ifdef SPECT_EDITOR | #ifdef SPECT_EDITOR | ||||
if (harm_sqrt_n > 0) | if (harm_sqrt_n > 0) | ||||
return (HarmToHarmspect(pitch, htab)); | |||||
return HarmToHarmspect(pitch, htab); | |||||
#endif | #endif | ||||
// initialise as much of *out as we will need | // initialise as much of *out as we will need | ||||
if (wvoice == NULL) | if (wvoice == NULL) | ||||
return (1); | |||||
return 1; | |||||
hmax = (peaks[wvoice->n_harmonic_peaks].freq + peaks[wvoice->n_harmonic_peaks].right)/pitch; | hmax = (peaks[wvoice->n_harmonic_peaks].freq + peaks[wvoice->n_harmonic_peaks].right)/pitch; | ||||
if (hmax >= MAX_HARMONIC) | if (hmax >= MAX_HARMONIC) | ||||
hmax = MAX_HARMONIC-1; | hmax = MAX_HARMONIC-1; | ||||
} | } | ||||
} | } | ||||
return (hmax); // highest harmonic number | |||||
return hmax; // highest harmonic number | |||||
} | } | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
return (value); | |||||
return value; | |||||
} | } | ||||
for (;;) { | for (;;) { | ||||
if ((end_wave == 0) && (samplecount == nsamples)) | if ((end_wave == 0) && (samplecount == nsamples)) | ||||
return (0); | |||||
return 0; | |||||
if ((samplecount & 0x3f) == 0) { | if ((samplecount & 0x3f) == 0) { | ||||
// every 64 samples, adjust the parameters | // every 64 samples, adjust the parameters | ||||
// sign has changed, reached a quiet point in the waveform | // sign has changed, reached a quiet point in the waveform | ||||
cbytes = wavemult_offset - (cycle_samples)/2; | cbytes = wavemult_offset - (cycle_samples)/2; | ||||
if (samplecount > nsamples) | if (samplecount > nsamples) | ||||
return (0); | |||||
return 0; | |||||
cycle_count++; | cycle_count++; | ||||
echo_head = 0; | echo_head = 0; | ||||
if (out_ptr >= out_end) | if (out_ptr >= out_end) | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
wavephase = 0x7fffffff; | wavephase = 0x7fffffff; | ||||
if (length == 0) | if (length == 0) | ||||
return (0); | |||||
return 0; | |||||
if (resume == 0) | if (resume == 0) | ||||
n_samples = length; | n_samples = length; | ||||
echo_head = 0; | echo_head = 0; | ||||
if (out_ptr >= out_end) | if (out_ptr >= out_end) | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
echo_head = 0; | echo_head = 0; | ||||
if (out_ptr >= out_end) | if (out_ptr >= out_end) | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
static int SetWithRange0(int value, int max) | static int SetWithRange0(int value, int max) | ||||
{ | { | ||||
if (value < 0) | if (value < 0) | ||||
return (0); | |||||
return 0; | |||||
if (value > max) | if (value > max) | ||||
return (max); | |||||
return (value); | |||||
return max; | |||||
return value; | |||||
} | } | ||||
if (resume == 0) | if (resume == 0) | ||||
SetSynth(length, modulation, fr1, fr2, wvoice); | SetSynth(length, modulation, fr1, fr2, wvoice); | ||||
return (Wavegen()); | |||||
return Wavegen(); | |||||
} | } | ||||
void Write4Bytes(FILE *f, int value) | void Write4Bytes(FILE *f, int value) | ||||
// continue to play silence until echo is completed | // continue to play silence until echo is completed | ||||
resume = PlaySilence(echo_complete, resume); | resume = PlaySilence(echo_complete, resume); | ||||
if (resume == 1) | if (resume == 1) | ||||
return (0); // not yet finished | |||||
return 0; // not yet finished | |||||
} | } | ||||
if (fill_zeros) { | if (fill_zeros) { | ||||
while (out_ptr < out_end) | while (out_ptr < out_end) | ||||
*out_ptr++ = 0; | *out_ptr++ = 0; | ||||
} | } | ||||
return (1); // queue empty, close sound channel | |||||
return 1; // queue empty, close sound channel | |||||
} | } | ||||
result = 0; | result = 0; | ||||
} | } | ||||
} | } | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
if (sonicSpeedupStream == NULL) | if (sonicSpeedupStream == NULL) | ||||
return (0); | |||||
return 0; | |||||
if (end_of_text) { | if (end_of_text) { | ||||
sonicFlushStream(sonicSpeedupStream); | sonicFlushStream(sonicSpeedupStream); |
}; | }; | ||||
if (path == NULL) | if (path == NULL) | ||||
return (2); | |||||
return 2; | |||||
while (isspace(*path)) path++; | while (isspace(*path)) path++; | ||||
Write4Bytes(f_wave, rate); | Write4Bytes(f_wave, rate); | ||||
Write4Bytes(f_wave, rate * 2); | Write4Bytes(f_wave, rate * 2); | ||||
fwrite(&wave_hdr[32], 1, 12, f_wave); | fwrite(&wave_hdr[32], 1, 12, f_wave); | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
finished = WavegenFill(0); | finished = WavegenFill(0); | ||||
if (quiet) | if (quiet) | ||||
return (finished); | |||||
return finished; | |||||
if (f_wave == NULL) { | if (f_wave == NULL) { | ||||
sprintf(fname, "%s_%.2d%s", wavefile, ++wavefile_count, filetype); | sprintf(fname, "%s_%.2d%s", wavefile, ++wavefile_count, filetype); | ||||
if (OpenWaveFile(fname, samplerate) != 0) | if (OpenWaveFile(fname, samplerate) != 0) | ||||
return (1); | |||||
return 1; | |||||
} | } | ||||
if (end_of_sentence) { | if (end_of_sentence) { | ||||
samples_total += (out_ptr - wav_outbuf)/2; | samples_total += (out_ptr - wav_outbuf)/2; | ||||
fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave); | fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave); | ||||
} | } | ||||
return (finished); | |||||
return finished; | |||||
} | } | ||||
for (param = 0; param < N_SPEECH_PARAM; param++) | for (param = 0; param < N_SPEECH_PARAM; param++) | ||||
param_stack[0].parameter[param] = param_defaults[param]; | param_stack[0].parameter[param] = param_defaults[param]; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
if (option_quiet) { | if (option_quiet) { | ||||
while (SpeakNextClause(NULL, NULL, 1) != 0) ; | while (SpeakNextClause(NULL, NULL, 1) != 0) ; | ||||
return (0); | |||||
return 0; | |||||
} | } | ||||
speaking = 1; | speaking = 1; | ||||
if ((f_trans != stdout) && (f_trans != stderr)) | if ((f_trans != stdout) && (f_trans != stderr)) | ||||
fclose(f_trans); // needed for WinCe | fclose(f_trans); // needed for WinCe | ||||
return (0); | |||||
return 0; | |||||
} | } |