Browse Source

Merge remote-tracking branch 'jaacoppi/booleans'

master
Reece H. Dunn 7 years ago
parent
commit
7435f1a9d4

+ 32
- 32
src/libespeak-ng/compiledata.c View File

static int resample_count = 0; static int resample_count = 0;
static int resample_fails = 0; static int resample_fails = 0;
static int then_count = 0; static int then_count = 0;
static int after_if = 0;
static bool after_if = false;


static char current_fname[80]; static char current_fname[80];


typedef struct { typedef struct {
USHORT *p_then; USHORT *p_then;
USHORT *p_else; USHORT *p_else;
int returned;
bool returned;
} IF_STACK; } IF_STACK;
IF_STACK if_stack[N_IF_STACK]; IF_STACK if_stack[N_IF_STACK];


int max = 0; int max = 0;
int length; int length;
int sr1, sr2; int sr1, sr2;
int failed;
bool failed;
int len; int len;
int resample_wav = 0;
bool resample_wav = false;
const char *fname2; const char *fname2;
char fname_temp[100]; char fname_temp[100];
char msg[120]; char msg[120];
int fd_temp; int fd_temp;
char command[sizeof(path_home)+250]; char command[sizeof(path_home)+250];


failed = 0;
failed = false;


#ifdef HAVE_MKSTEMP #ifdef HAVE_MKSTEMP
strcpy(fname_temp, "/tmp/espeakXXXXXX"); strcpy(fname_temp, "/tmp/espeakXXXXXX");


sprintf(command, "sox \"%s/%s.wav\" -r %d -c1 -t wav %s\n", phsrc, fname2, samplerate_native, fname_temp); sprintf(command, "sox \"%s/%s.wav\" -r %d -c1 -t wav %s\n", phsrc, fname2, samplerate_native, fname_temp);
if (system(command) != 0) if (system(command) != 0)
failed = 1;
failed = true;


if (failed || (GetFileLength(fname_temp) <= 0)) { if (failed || (GetFileLength(fname_temp) <= 0)) {
if (resample_fails < 2) if (resample_fails < 2)
if (f_report != NULL) if (f_report != NULL)
fprintf(f_report, "resampled %s\n", fname); fprintf(f_report, "resampled %s\n", fname);
resample_count++; resample_count++;
resample_wav = 1;
resample_wav = true;
fseek(f, 40, SEEK_SET); // skip past the WAV header, up to before "data length" fseek(f, 40, SEEK_SET); // skip past the WAV header, up to before "data length"
} }


length++; length++;
} }


if (resample_wav != 0) {
if (resample_wav == true) {
fclose(f); fclose(f);
remove(fname_temp); remove(fname_temp);
} }
static int CompileIf(int elif) static int CompileIf(int elif)
{ {
int key; int key;
int finish = 0;
bool finish = false;
int word = 0; int word = 0;
int word2; int word2;
int data; int data;
int bitmap; int bitmap;
int brackets; int brackets;
int not_flag;
bool not_flag;
USHORT *prog_last_if = NULL; USHORT *prog_last_if = NULL;


then_count = 2; then_count = 2;
after_if = 1;
after_if = true;


while (!finish) { while (!finish) {
not_flag = 0;
not_flag = false;
word2 = 0; word2 = 0;
if (prog_out >= prog_out_max) { if (prog_out >= prog_out_max) {
error("Phoneme program too large"); error("Phoneme program too large");
error("Expected a condition, not '%s'", item_string); error("Expected a condition, not '%s'", item_string);


if ((item_type == 0) && (key == k_NOT)) { if ((item_type == 0) && (key == k_NOT)) {
not_flag = 1;
not_flag = true;
if ((key = NextItem(tCONDITION)) < 0) if ((key = NextItem(tCONDITION)) < 0)
error("Expected a condition, not '%s'", item_string); error("Expected a condition, not '%s'", item_string);
} }
*prog_last_if |= i_OR; *prog_last_if |= i_OR;
break; break;
case k_THEN: case k_THEN:
finish = 1;
finish = true;
break; break;
default: default:
error("Expected AND, OR, THEN"); error("Expected AND, OR, THEN");
if_stack[if_level].p_else = NULL; if_stack[if_level].p_else = NULL;
} }


if_stack[if_level].returned = 0;
if_stack[if_level].returned = false;
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_stack[if_level].returned == 0)
if (if_stack[if_level].returned == false)
FillThen(1); FillThen(1);
else else
FillThen(0); FillThen(0);


if (if_stack[if_level].returned == 0) {
if (if_stack[if_level].returned == false) {
ref = prog_out; ref = prog_out;
*prog_out++ = 0; *prog_out++ = 0;


prog_out = prog_buf; prog_out = prog_buf;
prog_out_max = &prog_buf[MAX_PROG_BUF-1]; prog_out_max = &prog_buf[MAX_PROG_BUF-1];
if_level = 0; if_level = 0;
if_stack[0].returned = 0;
after_if = 0;
if_stack[0].returned = false;
after_if = false;
phoneme_flags = 0; phoneme_flags = 0;


NextItem(tSTRING); NextItem(tSTRING);
if (phoneme_out->type == phVOWEL) if (phoneme_out->type == phVOWEL)
value = (value * vowel_length_factor)/100; value = (value * vowel_length_factor)/100;


if (after_if == 0)
if (after_if == false)
phoneme_out->std_length = value/2; phoneme_out->std_length = value/2;
else { else {
*prog_out++ = (i_SET_LENGTH << 8) + value/2; *prog_out++ = (i_SET_LENGTH << 8) + value/2;
DecThenCount(); DecThenCount();
break; break;
case kFMT: case kFMT:
if_stack[if_level].returned = 1;
if_stack[if_level].returned = true;
DecThenCount(); DecThenCount();
if (phoneme_out->type == phVOWEL) if (phoneme_out->type == phVOWEL)
CompileSound(keyword, 1); CompileSound(keyword, 1);
CompileSound(keyword, 0); CompileSound(keyword, 0);
break; break;
case kWAV: case kWAV:
if_stack[if_level].returned = 1;
if_stack[if_level].returned = true;
// fallthrough: // fallthrough:
case kVOWELSTART: case kVOWELSTART:
case kVOWELENDING: case kVOWELENDING:
endphoneme = 1; endphoneme = 1;
if (if_level > 0) if (if_level > 0)
error("Missing ENDIF"); error("Missing ENDIF");
if ((prog_out > prog_buf) && (if_stack[0].returned == 0))
if ((prog_out > prog_buf) && (if_stack[0].returned == false))
*prog_out++ = INSTN_RETURN; *prog_out++ = INSTN_RETURN;
break; break;
} }
char c; char c;
int keyword; int keyword;
int n_tune_names = 0; int n_tune_names = 0;
int done_split = 0;
int done_onset = 0;
int done_last = 0;
bool done_split = false;
bool done_onset = false;
bool done_last = false;
int n_preset_tunes = 0; int n_preset_tunes = 0;
int found = 0; int found = 0;
int tune_number = 0; int tune_number = 0;
switch (keyword) switch (keyword)
{ {
case kTUNE: case kTUNE:
done_split = 0;
done_split = false;


memcpy(&new_tune, &default_tune, sizeof(TUNE)); memcpy(&new_tune, &default_tune, sizeof(TUNE));
NextItem(tSTRING); NextItem(tSTRING);
break; break;
case kENDTUNE: case kENDTUNE:
if (!found) continue; if (!found) continue;
if (done_onset == 0) {
if (done_onset == false) {
new_tune.unstr_start[0] = new_tune.unstr_start[1]; new_tune.unstr_start[0] = new_tune.unstr_start[1];
new_tune.unstr_end[0] = new_tune.unstr_end[1]; new_tune.unstr_end[0] = new_tune.unstr_end[1];
} }
if (done_last == 0) {
if (done_last == false) {
new_tune.unstr_start[2] = new_tune.unstr_start[1]; new_tune.unstr_start[2] = new_tune.unstr_start[1];
new_tune.unstr_end[2] = new_tune.unstr_end[1]; new_tune.unstr_end[2] = new_tune.unstr_end[1];
} }
new_tune.onset = NextItem(tNUMBER); new_tune.onset = NextItem(tNUMBER);
new_tune.unstr_start[0] = NextItem(tSIGNEDNUMBER); new_tune.unstr_start[0] = NextItem(tSIGNEDNUMBER);
new_tune.unstr_end[0] = NextItem(tSIGNEDNUMBER); new_tune.unstr_end[0] = NextItem(tSIGNEDNUMBER);
done_onset = 1;
done_onset = true;
break; break;
case kTUNE_HEADLAST: case kTUNE_HEADLAST:
new_tune.head_last = NextItem(tNUMBER); new_tune.head_last = NextItem(tNUMBER);
new_tune.unstr_start[2] = NextItem(tSIGNEDNUMBER); new_tune.unstr_start[2] = NextItem(tSIGNEDNUMBER);
new_tune.unstr_end[2] = NextItem(tSIGNEDNUMBER); new_tune.unstr_end[2] = NextItem(tSIGNEDNUMBER);
done_last = 1;
done_last = true;
break; break;
case kTUNE_HEADENV: case kTUNE_HEADENV:
NextItem(tSTRING); NextItem(tSTRING);
error("Bad envelope name: '%s'", item_string); error("Bad envelope name: '%s'", item_string);
break; break;
} }
done_split = 1;
done_split = true;
new_tune.split_nucleus_env = ix; new_tune.split_nucleus_env = ix;
new_tune.split_nucleus_max = NextItem(tNUMBER); new_tune.split_nucleus_max = NextItem(tNUMBER);
new_tune.split_nucleus_min = NextItem(tNUMBER); new_tune.split_nucleus_min = NextItem(tNUMBER);

+ 28
- 29
src/libespeak-ng/compiledict.c View File



static int linenum; static int linenum;
static int error_count; static int error_count;
static int text_mode = 0;
static bool text_mode = false;
static int debug_flag = 0; static int debug_flag = 0;
static int error_need_dictionary = 0; static int error_need_dictionary = 0;


char *p_end; char *p_end;
int ix; int ix;
int match_type; int match_type;
int finished = 0;
bool finished = false;
int value; int value;
int linenum = 0; int linenum = 0;
int flags; int flags;
int suffix_char; int suffix_char;
int condition_num = 0; int condition_num = 0;
int at_start = 0;
bool at_start = false;
const char *name; const char *name;
char buf[200]; char buf[200];
char buf_pre[200]; char buf_pre[200];
{ {
case 0: case 0:
case RULE_PHONEMES: case RULE_PHONEMES:
finished = 1;
finished = true;
break; break;
case RULE_PRE_ATSTART: case RULE_PRE_ATSTART:
at_start = 1;
at_start = true;
// fallthrough: // fallthrough:
case RULE_PRE: case RULE_PRE:
match_type = RULE_PRE; match_type = RULE_PRE;
int flag_offset; int flag_offset;
int length; int length;
int multiple_words = 0; int multiple_words = 0;
int multiple_numeric_hyphen = 0;
bool multiple_numeric_hyphen = false;
char *multiple_string = NULL; char *multiple_string = NULL;
char *multiple_string_end = NULL; char *multiple_string_end = NULL;


int len_word; int len_word;
int len_phonetic; int len_phonetic;
int text_not_phonemes; // this word specifies replacement text, not phonemes
bool text_not_phonemes = false; // this word specifies replacement text, not phonemes
unsigned int wc; unsigned int wc;
int all_upper_case;
bool all_upper_case;


char *mnemptr; char *mnemptr;
unsigned char flag_codes[100]; unsigned char flag_codes[100];
int bad_phoneme; int bad_phoneme;
static char nullstring[] = { 0 }; static char nullstring[] = { 0 };


text_not_phonemes = 0;
phonetic = word = nullstring; phonetic = word = nullstring;


p = linebuf; p = linebuf;
flagnum = LookupMnem(mnem_flags, mnemptr); flagnum = LookupMnem(mnem_flags, mnemptr);
if (flagnum > 0) { if (flagnum > 0) {
if (flagnum == 200) if (flagnum == 200)
text_mode = 1;
text_mode = true;
else if (flagnum == 201) else if (flagnum == 201)
text_mode = 0;
text_mode = false;
else if (flagnum == BITNUM_FLAG_TEXTMODE) else if (flagnum == BITNUM_FLAG_TEXTMODE)
text_not_phonemes = 1;
text_not_phonemes = true;
else else
flag_codes[n_flag_codes++] = flagnum; flag_codes[n_flag_codes++] = flagnum;
} else { } else {
case LINE_PARSER_END_OF_WORD: case LINE_PARSER_END_OF_WORD:
if ((c == '-') && multiple_words) { if ((c == '-') && multiple_words) {
if (IsDigit09(word[0])) if (IsDigit09(word[0]))
multiple_numeric_hyphen = 1;
multiple_numeric_hyphen = true;
flag_codes[n_flag_codes++] = BITNUM_FLAG_HYPHENATED; flag_codes[n_flag_codes++] = BITNUM_FLAG_HYPHENATED;
c = ' '; c = ' ';
} }
return 0; // blank line return 0; // blank line


if (text_mode) if (text_mode)
text_not_phonemes = 1;
text_not_phonemes = true;


if (text_not_phonemes) { if (text_not_phonemes) {
if (word[0] == '_') { if (word[0] == '_') {
// PROBLEM vowel reductions are not applied to the translated phonemes // PROBLEM vowel reductions are not applied to the translated phonemes
// condition rules are not applied // condition rules are not applied
TranslateWord(translator, phonetic, NULL, NULL); TranslateWord(translator, phonetic, NULL, NULL);
text_not_phonemes = 0;
text_not_phonemes = false;
strncpy0(encoded_ph, word_phonemes, N_WORD_BYTES-4); strncpy0(encoded_ph, word_phonemes, N_WORD_BYTES-4);


if ((word_phonemes[0] == 0) && (error_need_dictionary < 3)) { if ((word_phonemes[0] == 0) && (error_need_dictionary < 3)) {
// convert to lower case, and note if the word is all-capitals // convert to lower case, and note if the word is all-capitals
int c2; int c2;


all_upper_case = 1;
all_upper_case = true;
for (p = word;;) { for (p = word;;) {
// this assumes that the lower case char is the same length as the upper case char // this assumes that the lower case char is the same length as the upper case char
// OK, except for Turkish "I", but use towlower() rather than towlower2() // OK, except for Turkish "I", but use towlower() rather than towlower2()
if (iswupper(c2)) if (iswupper(c2))
utf8_out(towlower2(c2), p); utf8_out(towlower2(c2), p);
else else
all_upper_case = 0;
all_upper_case = false;
p += ix; p += ix;
} }
if (all_upper_case) if (all_upper_case)
char fname[sizeof(path_home)+45]; char fname[sizeof(path_home)+45];
char dict_line[256]; // length is uint8_t, so an entry can't take up more than 256 bytes char dict_line[256]; // length is uint8_t, so an entry can't take up more than 256 bytes


text_mode = 0;
text_mode = false;


// try with and without '.txt' extension // try with and without '.txt' extension
sprintf(fname, "%s%s.txt", path, filename); sprintf(fname, "%s%s.txt", path, filename);
int c2, c3; int c2, c3;
int sxflags; int sxflags;
int value; int value;
int literal;
int hexdigit_input = 0;
bool literal;
bool hexdigit_input = false;
int state = *state_out; int state = *state_out;
MNEM_TAB *mr; MNEM_TAB *mr;


sxflags = 0x808000; // to ensure non-zero bytes sxflags = 0x808000; // to ensure non-zero bytes


for (p = string, ix = 0;;) { for (p = string, ix = 0;;) {
literal = 0;
literal = false;
c = *p++; c = *p++;
if ((c == '0') && (p[0] == 'x') && (isHexDigit(p[1]) >= 0) && (isHexDigit(p[2]) >= 0)) { if ((c == '0') && (p[0] == 'x') && (isHexDigit(p[1]) >= 0) && (isHexDigit(p[2]) >= 0)) {
hexdigit_input = 1;
hexdigit_input = true;
c = p[1]; c = p[1];
p += 2; p += 2;
} }
c = (c-'0')*64 + (p[0]-'0')*8 + (p[1]-'0'); c = (c-'0')*64 + (p[0]-'0')*8 + (p[1]-'0');
p += 2; p += 2;
} }
literal = 1;
literal = true;
} }
if (hexdigit_input) { if (hexdigit_input) {
if (((c2 = isHexDigit(c)) >= 0) && ((c3 = isHexDigit(p[0])) >= 0)) { if (((c2 = isHexDigit(c)) >= 0) && ((c3 = isHexDigit(p[0])) >= 0)) {
c = c2 * 16 + c3; c = c2 * 16 + c3;
literal = 1;
literal = true;
p++; p++;
} else } else
hexdigit_input = 0;
hexdigit_input = false;
} }
if ((state == 1) || (state == 3)) { if ((state == 1) || (state == 3)) {
// replace special characters (note: 'E' is reserved for a replaced silent 'e') // replace special characters (note: 'E' is reserved for a replaced silent 'e')
if (literal == 0) {
if (literal == false) {
static const char lettergp_letters[9] = { LETTERGP_A, LETTERGP_B, LETTERGP_C, 0, 0, LETTERGP_F, LETTERGP_G, LETTERGP_H, LETTERGP_Y }; static const char lettergp_letters[9] = { LETTERGP_A, LETTERGP_B, LETTERGP_C, 0, 0, LETTERGP_F, LETTERGP_G, LETTERGP_H, LETTERGP_Y };
switch (c) switch (c)
{ {
int len_name; int len_name;
int start; int start;
int state = 2; int state = 2;
int finish = 0;
bool finish = false;
char buf[80]; char buf[80];
char output[150]; char output[150];
int bad_phoneme; int bad_phoneme;


p = buf; p = buf;


for (ix = 0; finish == 0; ix++) {
for (ix = 0; finish == false; ix++) {
switch (c = input[ix]) switch (c = input[ix])
{ {
case ')': // end of prefix section case ')': // end of prefix section
case 0: // end of line case 0: // end of line
*p = 0; *p = 0;
copy_rule_string(buf, &state); copy_rule_string(buf, &state);
finish = 1;
finish = true;
break; break;
case '\t': // end of section section case '\t': // end of section section
case ' ': case ' ':

+ 13
- 13
src/libespeak-ng/dictionary.c View File

int c; int c;
int mnem; int mnem;
int len; int len;
int first;
bool first;
int ix = 0; int ix = 0;
char *p; char *p;
PHONEME_DATA phdata; PHONEME_DATA phdata;
} }
} }


first = 1;
first = true;
for (mnem = ph->mnemonic; (c = mnem & 0xff) != 0; mnem = mnem >> 8) { for (mnem = ph->mnemonic; (c = mnem & 0xff) != 0; mnem = mnem >> 8) {
if ((c == '/') && (option_phoneme_variants == 0)) if ((c == '/') && (option_phoneme_variants == 0))
break; // discard phoneme variant indicator break; // discard phoneme variant indicator
ix += utf8_out(c, &phon_out[ix]); ix += utf8_out(c, &phon_out[ix]);
} else } else
phon_out[ix++] = c; phon_out[ix++] = c;
first = 0;
first = false;
} }


phon_out = &phon_out[ix]; phon_out = &phon_out[ix];
int n_bytes; int n_bytes;
int add_points; int add_points;
int command; int command;
int check_atstart;
bool check_atstart;
unsigned int *flags; unsigned int *flags;


MatchRecord match; MatchRecord match;
letter_w = 0; letter_w = 0;
distance_right = -6; // used to reduce points for matches further away the current letter distance_right = -6; // used to reduce points for matches further away the current letter
distance_left = -2; distance_left = -2;
check_atstart = 0;
check_atstart = false;


match.points = 1; match.points = 1;
match.end_type = 0; match.end_type = 0;
failed = 2; // matched OK failed = 2; // matched OK
break; break;
case RULE_PRE_ATSTART: // pre rule with implied 'start of word' case RULE_PRE_ATSTART: // pre rule with implied 'start of word'
check_atstart = 1;
check_atstart = true;
unpron_ignore = 0; unpron_ignore = 0;
match_type = RULE_PRE; match_type = RULE_PRE;
break; break;


if ((failed == 2) && (unpron_ignore == 0)) { if ((failed == 2) && (unpron_ignore == 0)) {
// do we also need to check for 'start of word' ? // do we also need to check for 'start of word' ?
if ((check_atstart == 0) || (pre_ptr[-1] == ' ')) {
if ((check_atstart == false) || (pre_ptr[-1] == ' ')) {
if (check_atstart) if (check_atstart)
match.points += 4; match.points += 4;


const char *map; const char *map;
char *p = text; char *p = text;
char *p2; char *p2;
int all_alpha = 1;
bool all_alpha = true;
int bits; int bits;
int acc; int acc;
int pairs_start; int pairs_start;
if (map[c - min] > 0) if (map[c - min] > 0)
buf[bufix++] = map[c - min]; buf[bufix++] = map[c - min];
else { else {
all_alpha = 0;
all_alpha = false;
break; break;
} }
} }
} else { } else {
all_alpha = 0;
all_alpha = false;
break; break;
} }
} }


if (option_phonemes & espeakPHONEMES_TRACE) { if (option_phonemes & espeakPHONEMES_TRACE) {
char ph_decoded[N_WORD_PHONEMES]; char ph_decoded[N_WORD_PHONEMES];
int textmode;
bool textmode;


DecodePhonemes(phonetic, ph_decoded); DecodePhonemes(phonetic, ph_decoded);


if ((dictionary_flags & FLAG_TEXTMODE) == 0) if ((dictionary_flags & FLAG_TEXTMODE) == 0)
textmode = 0;
textmode = false;
else else
textmode = 1;
textmode = true;


if (textmode == translator->langopts.textmode) { if (textmode == translator->langopts.textmode) {
// only show this line if the word translates to phonemes, not replacement text // only show this line if the word translates to phonemes, not replacement text

+ 21
- 21
src/libespeak-ng/intonation.c View File

int increment = 0; int increment = 0;
int n_steps = 0; int n_steps = 0;
int stage; // onset, head, last int stage; // onset, head, last
int initial;
bool initial;
int overflow_ix = 0; int overflow_ix = 0;
int pitch_range; int pitch_range;
int pitch_range_abs; int pitch_range_abs;
int n_unstressed = 0; int n_unstressed = 0;
int unstressed_ix = 0; int unstressed_ix = 0;
int unstressed_inc; int unstressed_inc;
int used_onset = 0;
bool used_onset = false;
int head_final = end_ix; int head_final = end_ix;
int secondary = 2; int secondary = 2;


pitch_range = (tune->head_end - tune->head_start) << 8; pitch_range = (tune->head_end - tune->head_start) << 8;
pitch_range_abs = abs(pitch_range); pitch_range_abs = abs(pitch_range);
drops = drops_0; // this should be controled by tune->head_drops drops = drops_0; // this should be controled by tune->head_drops
initial = 1;
initial = true;


stage = 0; stage = 0;
if (tune->onset == 255) if (tune->onset == 255)
// a primary stress // a primary stress


if ((initial) || (stress == 5)) { if ((initial) || (stress == 5)) {
initial = 0;
initial = false;
overflow_ix = 0; overflow_ix = 0;


if (tune->onset == 255) { if (tune->onset == 255) {
// a pitch has been specified for the onset syllable, don't include it in the pitch incrementing // a pitch has been specified for the onset syllable, don't include it in the pitch incrementing
n_steps = count_increments(syllable_tab, syl_ix+1, head_final, 4); n_steps = count_increments(syllable_tab, syl_ix+1, head_final, 4);
pitch = tune->onset << 8; pitch = tune->onset << 8;
used_onset = 1;
used_onset = true;
} }


if (n_steps > tune->head_max_steps) if (n_steps > tune->head_max_steps)
} else { } else {
if (used_onset) { if (used_onset) {
stage = 1; stage = 1;
used_onset = 0;
used_onset = false;
pitch = tune->head_start << 8; pitch = tune->head_start << 8;
n_steps++; n_steps++;
} else if (n_steps > 0) } else if (n_steps > 0)
/* Calculate pitches until next RESET or tonic syllable, or end. /* Calculate pitches until next RESET or tonic syllable, or end.
Increment pitch if stress is >= min_stress. Increment pitch if stress is >= min_stress.
Used for tonic segment */ Used for tonic segment */
static int calc_pitch_segment(SYLLABLE *syllable_tab, int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *tn, int min_stress, int continuing)
static int calc_pitch_segment(SYLLABLE *syllable_tab, int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *tn, int min_stress, bool continuing)
{ {
int stress; int stress;
int pitch = 0; int pitch = 0;
int increment = 0; int increment = 0;
int n_primary = 0; int n_primary = 0;
int n_steps = 0; int n_steps = 0;
int initial;
bool initial;
int overflow = 0; int overflow = 0;
int n_overflow; int n_overflow;
int pitch_range; int pitch_range;
pitch_range_abs = abs(pitch_range); pitch_range_abs = abs(pitch_range);


if (continuing) { if (continuing) {
initial = 0;
initial = false;
overflow = 0; overflow = 0;
n_overflow = 5; n_overflow = 5;
overflow_tab = continue_tab; overflow_tab = continue_tab;
} else { } else {
n_overflow = th->n_overflow; n_overflow = th->n_overflow;
overflow_tab = th->overflow; overflow_tab = th->overflow;
initial = 1;
initial = true;
} }


while (ix < end_ix) { while (ix < end_ix) {
// a primary stress // a primary stress


if ((initial) || (stress == 5)) { if ((initial) || (stress == 5)) {
initial = 0;
initial = false;
overflow = 0; overflow = 0;
n_steps = n_primary = count_increments(syllable_tab, ix, end_ix, min_stress); n_steps = n_primary = count_increments(syllable_tab, ix, end_ix, min_stress);


TONE_HEAD *th; TONE_HEAD *th;
TONE_NUCLEUS *tn; TONE_NUCLEUS *tn;
int drop; int drop;
int continuing = 0;
bool continuing = false;


if (control == 0) if (control == 0)
return calc_pitches2(syllable_tab, start, end, tune_number); return calc_pitches2(syllable_tab, start, end, tune_number);


if (start > 0) if (start > 0)
continuing = 1;
continuing = true;


th = &tone_head_table[tune_number]; th = &tone_head_table[tune_number];
tn = &tone_nucleus_table[tune_number]; tn = &tone_nucleus_table[tune_number];
int final_stressed = 0; int final_stressed = 0;


int tone_ph; int tone_ph;
int pause;
int tone_promoted;
bool pause;
bool tone_promoted;
PHONEME_TAB *tph; PHONEME_TAB *tph;
PHONEME_TAB *prev_tph; // forget across word boundary PHONEME_TAB *prev_tph; // forget across word boundary
PHONEME_TAB *prevw_tph; // remember across word boundary PHONEME_TAB *prevw_tph; // remember across word boundary
p->tone_ph = PhonemeCode('7'); // change default tone (tone 1) to falling tone at end of clause p->tone_ph = PhonemeCode('7'); // change default tone (tone 1) to falling tone at end of clause
} }


pause = 1;
tone_promoted = 0;
pause = true;
tone_promoted = false;


prev_p = p = &phoneme_list[0]; prev_p = p = &phoneme_list[0];
prev_tph = prevw_tph = phoneme_tab[phonPAUSE]; prev_tph = prevw_tph = phoneme_tab[phonPAUSE];
// perform tone sandhi // perform tone sandhi
for (ix = 0; ix < n_phoneme_list; ix++, p++) { for (ix = 0; ix < n_phoneme_list; ix++, p++) {
if ((p->type == phPAUSE) && (p->ph->std_length > 50)) { if ((p->type == phPAUSE) && (p->ph->std_length > 50)) {
pause = 1; // there is a pause since the previous vowel
pause = true; // there is a pause since the previous vowel
prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone
} }


if (tone_ph == 0) { if (tone_ph == 0) {
if (pause || tone_promoted) { if (pause || tone_promoted) {
tone_ph = PhonemeCode2('5', '5'); // no previous vowel, use tone 1 tone_ph = PhonemeCode2('5', '5'); // no previous vowel, use tone 1
tone_promoted = 1;
tone_promoted = true;
} else } else
tone_ph = PhonemeCode2('1', '1'); // default tone 5 tone_ph = PhonemeCode2('1', '1'); // default tone 5


p->tone_ph = tone_ph; p->tone_ph = tone_ph;
tph = phoneme_tab[tone_ph]; tph = phoneme_tab[tone_ph];
} else } else
tone_promoted = 0;
tone_promoted = false;


if (ix == final_stressed) { if (ix == final_stressed) {
if ((tph->mnemonic == 0x3535 ) || (tph->mnemonic == 0x3135)) { if ((tph->mnemonic == 0x3535 ) || (tph->mnemonic == 0x3135)) {


prev_p = p; prev_p = p;
prevw_tph = prev_tph = tph; prevw_tph = prev_tph = tph;
pause = 0;
pause = false;
} }
} }



+ 25
- 25
src/libespeak-ng/numbers.c View File

{ {
// returns M, or perhaps MA or MB for some cases // returns M, or perhaps MA or MB for some cases


int teens = 0;
bool teens = false;


if (((value % 100) > 10) && ((value % 100) < 20)) if (((value % 100) > 10) && ((value % 100) < 20))
teens = 1;
teens = true;


switch ((translator->langopts.numbers2 >> 6) & 0x7) switch ((translator->langopts.numbers2 >> 6) & 0x7)
{ {
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 == false) && ((value % 10) == 1))
return "1M"; return "1M";
break; break;
case 2: // lang=cs,sk case 2: // lang=cs,sk
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 == false) && (((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 == true) || ((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 == false) {
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 used_and; return used_and;
} }


static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int control)
static int LookupNum3(Translator *tr, int value, char *ph_out, bool suppress_null, int thousandplex, int control)
{ {
// Translate a 3 digit number // Translate a 3 digit number
// control bit 0, previous thousands // control bit 0, previous thousands
int exact; int exact;
int ordinal; int ordinal;
int tplex; int tplex;
int say_zero_hundred = 0;
int say_one_hundred;
bool say_zero_hundred = false;
bool say_one_hundred;
char string[12]; // for looking up entries in **_list char string[12]; // for looking up entries in **_list
char buf1[100]; char buf1[100];
char buf2[100]; char buf2[100];
ph_thousand_and[0] = 0; ph_thousand_and[0] = 0;


if ((tr->langopts.numbers & NUM_ZERO_HUNDRED) && ((control & 1) || (hundreds >= 10))) if ((tr->langopts.numbers & NUM_ZERO_HUNDRED) && ((control & 1) || (hundreds >= 10)))
say_zero_hundred = 1; // lang=vi
say_zero_hundred = true; // lang=vi


if ((hundreds > 0) || say_zero_hundred) { if ((hundreds > 0) || say_zero_hundred) {
found = 0; found = 0;
sprintf(ph_thousands, "%s%c%s%c", ph_digits, phonEND_WORD, ph_10T, phonEND_WORD); sprintf(ph_thousands, "%s%c%s%c", ph_digits, phonEND_WORD, ph_10T, phonEND_WORD);


hundreds %= 10; hundreds %= 10;
if ((hundreds == 0) && (say_zero_hundred == 0))
if ((hundreds == 0) && (say_zero_hundred == false))
ph_100[0] = 0; ph_100[0] = 0;
suppress_null = 1;
suppress_null = true;
control |= 1; control |= 1;
} }


if ((tr->langopts.numbers & NUM_AND_HUNDRED) && ((control & 1) || (ph_thousands[0] != 0))) if ((tr->langopts.numbers & NUM_AND_HUNDRED) && ((control & 1) || (ph_thousands[0] != 0)))
Lookup(tr, "_0and", ph_thousand_and); Lookup(tr, "_0and", ph_thousand_and);


suppress_null = 1;
suppress_null = true;


found = 0; found = 0;
if ((ordinal) if ((ordinal)
if (found) if (found)
ph_100[0] = 0; ph_100[0] = 0;
else { else {
say_one_hundred = 1;
say_one_hundred = true;
if (hundreds == 1) { if (hundreds == 1) {
if ((tr->langopts.numbers & NUM_OMIT_1_HUNDRED) != 0) if ((tr->langopts.numbers & NUM_OMIT_1_HUNDRED) != 0)
say_one_hundred = 0;
say_one_hundred = false;
} }


if (say_one_hundred != 0)
if (say_one_hundred == true)
LookupNum2(tr, hundreds, thousandplex, 0, ph_digits); LookupNum2(tr, hundreds, thousandplex, 0, ph_digits);
} }
} }


buf2[0] = 0; buf2[0] = 0;


if ((tensunits != 0) || (suppress_null == 0)) {
if ((tensunits != 0) || (suppress_null == false)) {
x = 0; x = 0;
if (thousandplex == 0) { if (thousandplex == 0) {
x = 2; // allow "eins" for 1 rather than "ein" x = 2; // allow "eins" for 1 rather than "ein"
int ix; int ix;
int digix; int digix;
unsigned char c; unsigned char c;
int suppress_null = 0;
bool suppress_null = false;
int decimal_point = 0; int decimal_point = 0;
int thousandplex = 0; int thousandplex = 0;
int thousands_exact = 1; int thousands_exact = 1;
} }


if ((value == 0) && prev_thousands) if ((value == 0) && prev_thousands)
suppress_null = 1;
suppress_null = true;


if (tr->translator_name == L('h', 'u')) { if (tr->translator_name == L('h', 'u')) {
// variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt // variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt
// this "word" ends with a decimal point // this "word" ends with a decimal point
Lookup(tr, "_dpt", ph_append); Lookup(tr, "_dpt", ph_append);
decimal_point = 0x100; decimal_point = 0x100;
} else if (suppress_null == 0) {
} else if (suppress_null == false) {
if (thousands_inc > 0) { if (thousands_inc > 0) {
if (thousandplex > 0) { if (thousandplex > 0) {
if ((suppress_null == 0) && (LookupThousands(tr, value, thousandplex, thousands_exact, ph_append))) {
if ((suppress_null == false) && (LookupThousands(tr, value, thousandplex, thousands_exact, ph_append))) {
// found an exact match for N thousand // found an exact match for N thousand
value = 0; value = 0;
suppress_null = 1;
suppress_null = true;
} }
} }
} }
n_digits++; n_digits++;
} }
if ((decimal_count <= max_decimal_count) && IsDigit09(word[n_digits])) { if ((decimal_count <= max_decimal_count) && IsDigit09(word[n_digits])) {
LookupNum3(tr, atoi(&word[n_digits]), buf1, 0, 0, 0);
LookupNum3(tr, atoi(&word[n_digits]), buf1, false, 0, 0);
strcat(ph_out, buf1); strcat(ph_out, buf1);
n_digits += decimal_count; n_digits += decimal_count;
} }
case NUM_DFRACTION_1: // italian, say "hundredths" if leading zero case NUM_DFRACTION_1: // italian, say "hundredths" if leading zero
case NUM_DFRACTION_5: // hungarian, always say "tenths" etc. case NUM_DFRACTION_5: // hungarian, always say "tenths" etc.
case NUM_DFRACTION_6: // kazakh, always say "tenths" etc, before the decimal fraction case NUM_DFRACTION_6: // kazakh, always say "tenths" etc, before the decimal fraction
LookupNum3(tr, atoi(&word[n_digits]), ph_buf, 0, 0, 0);
LookupNum3(tr, atoi(&word[n_digits]), ph_buf, false, 0, 0);
if ((word[n_digits] == '0') || (decimal_mode != NUM_DFRACTION_1)) { if ((word[n_digits] == '0') || (decimal_mode != NUM_DFRACTION_1)) {
// decimal part has leading zeros, so add a "hundredths" or "thousandths" suffix // decimal part has leading zeros, so add a "hundredths" or "thousandths" suffix
sprintf(string, "_0Z%d", decimal_count); sprintf(string, "_0Z%d", decimal_count);
case NUM_DFRACTION_3: case NUM_DFRACTION_3:
// Romanian decimal fractions // Romanian decimal fractions
if ((decimal_count <= 4) && (word[n_digits] != '0')) { if ((decimal_count <= 4) && (word[n_digits] != '0')) {
LookupNum3(tr, atoi(&word[n_digits]), buf1, 0, 0, 0);
LookupNum3(tr, atoi(&word[n_digits]), buf1, false, 0, 0);
strcat(ph_out, buf1); strcat(ph_out, buf1);
n_digits += decimal_count; n_digits += decimal_count;
} }

+ 10
- 10
src/libespeak-ng/phonemelist.c View File

int k; int k;
int replace_flags; int replace_flags;
int n_plist_out = 0; int n_plist_out = 0;
int word_end;
bool word_end;
PHONEME_LIST2 *plist2; PHONEME_LIST2 *plist2;
PHONEME_TAB *next = NULL; PHONEME_TAB *next = NULL;


if (ix < (n_ph_list2 -1)) if (ix < (n_ph_list2 -1))
next = phoneme_tab[ph_list2[ix+1].phcode]; next = phoneme_tab[ph_list2[ix+1].phcode];


word_end = 0;
word_end = false;
if ((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE))) if ((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE)))
word_end = 1; // this phoneme is the end of a word
word_end = true; // this phoneme is the end of a word


// check whether a Voice has specified that we should replace this phoneme // check whether a Voice has specified that we should replace this phoneme
for (k = 0; k < n_replace_phonemes; k++) { for (k = 0; k < n_replace_phonemes; k++) {
if (plist2->phcode == replace_phonemes[k].old_ph) { if (plist2->phcode == replace_phonemes[k].old_ph) {
replace_flags = replace_phonemes[k].type; replace_flags = replace_phonemes[k].type;


if ((replace_flags & 1) && (word_end == 0))
if ((replace_flags & 1) && (word_end == false))
continue; // this replacement only occurs at the end of a word continue; // this replacement only occurs at the end of a word


if ((replace_flags & 2) && ((plist2->stresslevel & 0x7) > 3)) if ((replace_flags & 2) && ((plist2->stresslevel & 0x7) > 3))
return n_plist_out; return n_plist_out;
} }


void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence)
{ {
int ix = 0; int ix = 0;
int j; int j;
// set consonant clusters to all voiced or all unvoiced // set consonant clusters to all voiced or all unvoiced
// Regressive // Regressive
int type; int type;
int stop_propagation = 0;
bool stop_propagation = false;
voicing = 0; voicing = 0;


for (j = n_ph_list2-1; j >= 0; j--) { for (j = n_ph_list2-1; j >= 0; j--) {
continue; continue;


if (plist2[j].synthflags & SFLAG_SWITCHED_LANG) { if (plist2[j].synthflags & SFLAG_SWITCHED_LANG) {
stop_propagation = 0;
stop_propagation = false;
voicing = 0; voicing = 0;
if (regression & 0x100) if (regression & 0x100)
voicing = 1; // word-end devoicing voicing = 1; // word-end devoicing
if (regression & 0x2) { if (regression & 0x2) {
// [v] amd [v;] don't cause regression, or [R^] // [v] amd [v;] don't cause regression, or [R^]
if (((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff) == 'R')) { if (((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff) == 'R')) {
stop_propagation = 1;
stop_propagation = true;
if (regression & 0x10) if (regression & 0x10)
voicing = 0; voicing = 0;
} }
} }
if (stop_propagation) { if (stop_propagation) {
voicing = 0; voicing = 0;
stop_propagation = 0;
stop_propagation = false;
} }


if (plist2[j].sourceix) { if (plist2[j].sourceix) {


if (start_sentence) { if (start_sentence) {
phlist[ix].newword = 5; // start of sentence + start of word phlist[ix].newword = 5; // start of sentence + start of word
start_sentence = 0;
start_sentence = false;
} }
} else } else
phlist[ix].newword = 0; phlist[ix].newword = 0;

+ 37
- 37
src/libespeak-ng/readclause.c View File

static int ungot_char; static int ungot_char;
static const char *ungot_word = NULL; static const char *ungot_word = NULL;


static int ignore_text = 0; // set during <sub> ... </sub> to ignore text which has been replaced by an alias
static int audio_text = 0; // set during <audio> ... </audio>
static int clear_skipping_text = 0; // next clause should clear the skipping_text flag
static bool ignore_text = false; // set during <sub> ... </sub> to ignore text which has been replaced by an alias
static bool audio_text = false; // set during <audio> ... </audio>
static bool clear_skipping_text = false; // next clause should clear the skipping_text flag
int count_characters = 0; int count_characters = 0;
static int sayas_mode; static int sayas_mode;
static int sayas_start; static int sayas_start;
return 0; return 0;
} }


static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, int self_closing)
static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, bool self_closing)
{ {
// xml_buf is the tag and attributes with a zero terminator in place of the original '>' // xml_buf is the tag and attributes with a zero terminator in place of the original '>'
// returns a clause terminator value. // returns a clause terminator value.
case SSML_SUB: case SSML_SUB:
if ((attr1 = GetSsmlAttribute(px, "alias")) != NULL) { if ((attr1 = GetSsmlAttribute(px, "alias")) != NULL) {
// use the alias rather than the text // use the alias rather than the text
ignore_text = 1;
ignore_text = true;
*outix += attrcopy_utf8(&outbuf[*outix], attr1, n_outbuf-*outix); *outix += attrcopy_utf8(&outbuf[*outix], attr1, n_outbuf-*outix);
} }
break; break;
case SSML_IGNORE_TEXT: case SSML_IGNORE_TEXT:
ignore_text = 1;
ignore_text = true;
break; break;
case SSML_SUB + SSML_CLOSE: case SSML_SUB + SSML_CLOSE:
case SSML_IGNORE_TEXT + SSML_CLOSE: case SSML_IGNORE_TEXT + SSML_CLOSE:
ignore_text = 0;
ignore_text = false;
break; break;
case SSML_MARK: case SSML_MARK:
if ((attr1 = GetSsmlAttribute(px, "name")) != NULL) { if ((attr1 = GetSsmlAttribute(px, "name")) != NULL) {


if (strcmp(skip_marker, buf) == 0) { if (strcmp(skip_marker, buf) == 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 = true;
skip_marker[0] = 0; skip_marker[0] = 0;
return CLAUSE_NONE; return CLAUSE_NONE;
} }
if (self_closing) if (self_closing)
PopParamStack(tag_type, outbuf, outix); PopParamStack(tag_type, outbuf, outix);
else else
audio_text = 1;
audio_text = true;
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 = false;
return CLAUSE_NONE; return CLAUSE_NONE;
case SSML_BREAK: case SSML_BREAK:
value = 21; value = 21;
int n_xml_buf; int n_xml_buf;
int terminator; int terminator;
int found; int found;
int any_alnum = 0;
int self_closing;
bool any_alnum = false;
bool self_closing;
int punct_data = 0; int punct_data = 0;
int is_end_clause;
bool is_end_clause;
int announced_punctuation = 0; int announced_punctuation = 0;
int stressed_word = 0;
bool stressed_word = false;
int end_clause_after_tag = 0; int end_clause_after_tag = 0;
int end_clause_index = 0; int end_clause_index = 0;
wchar_t xml_buf[N_XML_BUF+1]; wchar_t xml_buf[N_XML_BUF+1];
static int ungot_string_ix = -1; static int ungot_string_ix = -1;


if (clear_skipping_text) { if (clear_skipping_text) {
skipping_text = 0;
clear_skipping_text = 0;
skipping_text = false;
clear_skipping_text = false;
} }


tr->phonemes_repeat_count = 0; tr->phonemes_repeat_count = 0;
if ((skip_characters > 0) && (count_characters >= skip_characters)) { if ((skip_characters > 0) && (count_characters >= skip_characters)) {
// reached the specified start position // reached the specified start position
// don't break a word // don't break a word
clear_skipping_text = 1;
clear_skipping_text = true;
skip_characters = 0; skip_characters = 0;
UngetC(c2); UngetC(c2);
return CLAUSE_NONE; return CLAUSE_NONE;
xml_buf[n_xml_buf] = 0; xml_buf[n_xml_buf] = 0;
c2 = ' '; c2 = ' ';


self_closing = 0;
self_closing = false;
if (xml_buf[n_xml_buf-1] == '/') { if (xml_buf[n_xml_buf-1] == '/') {
// a self-closing tag // a self-closing tag
xml_buf[n_xml_buf-1] = ' '; xml_buf[n_xml_buf-1] = ' ';
self_closing = 1;
self_closing = true;
} }


terminator = ProcessSsmlTag(xml_buf, buf, &ix, n_buf, self_closing); terminator = ProcessSsmlTag(xml_buf, buf, &ix, n_buf, self_closing);
} }


if (iswalnum(c1)) if (iswalnum(c1))
any_alnum = 1;
any_alnum = true;
else { else {
if (stressed_word) { if (stressed_word) {
stressed_word = 0;
stressed_word = false;
c1 = CHAR_EMPHASIS; // indicate this word is stressed c1 = CHAR_EMPHASIS; // indicate this word is stressed
UngetC(c2); UngetC(c2);
c2 = ' '; c2 = ' ';
announced_punctuation = 0; announced_punctuation = 0;


if ((phoneme_mode == 0) && (sayas_mode == 0)) { if ((phoneme_mode == 0) && (sayas_mode == 0)) {
is_end_clause = 0;
is_end_clause = false;


if (end_clause_after_tag) { if (end_clause_after_tag) {
// Because of an xml tag, we are waiting for the // Because of an xml tag, we are waiting for the
if ((punct_data = clause_type_from_codepoint(c1)) != CLAUSE_NONE) { if ((punct_data = clause_type_from_codepoint(c1)) != CLAUSE_NONE) {
if (punct_data & CLAUSE_PUNCTUATION_IN_WORD) { if (punct_data & CLAUSE_PUNCTUATION_IN_WORD) {
// Armenian punctuation inside a word // Armenian punctuation inside a word
stressed_word = 1;
stressed_word = true;
*tone_type = punct_data >> 12 & 0xf; // override the end-of-sentence type *tone_type = punct_data >> 12 & 0xf; // override the end-of-sentence type
continue; continue;
} }


if ((iswspace(c2) || (punct_data & CLAUSE_OPTIONAL_SPACE_AFTER) || IsBracket(c2) || (c2 == '?') || Eof() || (c2 == ctrl_embedded))) { // don't check for '-' because it prevents recognizing ':-)' if ((iswspace(c2) || (punct_data & CLAUSE_OPTIONAL_SPACE_AFTER) || IsBracket(c2) || (c2 == '?') || Eof() || (c2 == ctrl_embedded))) { // don't check for '-' because it prevents recognizing ':-)'
// note: (c2='?') is for when a smart-quote has been replaced by '?' // note: (c2='?') is for when a smart-quote has been replaced by '?'
is_end_clause = 1;
is_end_clause = true;
} }
} }


// don't announce punctuation for the alternative text inside inside <audio> ... </audio> // don't announce punctuation for the alternative text inside inside <audio> ... </audio>
if (c1 == 0xe000+'<') c1 = '<'; if (c1 == 0xe000+'<') c1 = '<';
if (option_punctuation && iswpunct(c1) && (audio_text == 0)) {
if (option_punctuation && iswpunct(c1) && (audio_text == false)) {
// option is set to explicitly speak punctuation characters // option is set to explicitly speak punctuation characters
// if a list of allowed punctuation has been set up, check whether the character is in it // if a list of allowed punctuation has been set up, check whether the character is in it
if ((option_punctuation == 1) || (wcschr(option_punctlist, c1) != NULL)) { if ((option_punctuation == 1) || (wcschr(option_punctlist, c1) != NULL)) {
if ((c1 == ',') && (cprev == '.') && (tr->translator_name == L('h', 'u')) && iswdigit(cprev2) && (iswdigit(c_next) || (iswlower(c_next)))) { if ((c1 == ',') && (cprev == '.') && (tr->translator_name == L('h', 'u')) && iswdigit(cprev2) && (iswdigit(c_next) || (iswlower(c_next)))) {
// lang=hu, fix for ordinal numbers, eg: "december 2., szerda", ignore ',' after ordinal number // lang=hu, fix for ordinal numbers, eg: "december 2., szerda", ignore ',' after ordinal number
c1 = CHAR_COMMA_BREAK; c1 = CHAR_COMMA_BREAK;
is_end_clause = 0;
is_end_clause = false;
} }


if (c1 == '.') { if (c1 == '.') {
(iswdigit(cprev) || (IsRomanU(cprev) && (IsRomanU(cprev2) || iswspace(cprev2))))) { // lang=hu (iswdigit(cprev) || (IsRomanU(cprev) && (IsRomanU(cprev2) || iswspace(cprev2))))) { // lang=hu
// dot after a number indicates an ordinal number // dot after a number indicates an ordinal number
if (!iswdigit(cprev)) if (!iswdigit(cprev))
is_end_clause = 0; // Roman number followed by dot
is_end_clause = false; // Roman number followed by dot
else if (iswlower(c_next) || (c_next == '-')) // hyphen is needed for lang-hu (eg. 2.-kal) else if (iswlower(c_next) || (c_next == '-')) // hyphen is needed for lang-hu (eg. 2.-kal)
is_end_clause = 0; // only if followed by lower-case, (or if there is a XML tag)
is_end_clause = false; // only if followed by lower-case, (or if there is a XML tag)
} else if (c_next == '\'') } else if (c_next == '\'')
is_end_clause = 0; // eg. u.s.a.'s
is_end_clause = false; // eg. u.s.a.'s
if (iswlower(c_next)) { if (iswlower(c_next)) {
// next word has no capital letter, this dot is probably from an abbreviation // next word has no capital letter, this dot is probably from an abbreviation
is_end_clause = 0; is_end_clause = 0;
} }
if (any_alnum == 0) {
if (any_alnum == false) {
// no letters or digits yet, so probably not a sentence terminator // no letters or digits yet, so probably not a sentence terminator
// Here, dot is followed by space or bracket // Here, dot is followed by space or bracket
c1 = ' '; c1 = ' ';
is_end_clause = 0;
is_end_clause = false;
} }
} else { } else {
if (any_alnum == 0) {
if (any_alnum == false) {
// no letters or digits yet, so probably not a sentence terminator // no letters or digits yet, so probably not a sentence terminator
is_end_clause = 0;
is_end_clause = false;
} }
} }


if (is_end_clause && (c1 == '.') && (c_next == '<') && option_ssml) { if (is_end_clause && (c1 == '.') && (c_next == '<') && option_ssml) {
// wait until after the end of the xml tag, then look for upper-case letter // wait until after the end of the xml tag, then look for upper-case letter
is_end_clause = 0;
is_end_clause = false;
end_clause_index = ix; end_clause_index = ix;
end_clause_after_tag = punct_data; end_clause_after_tag = punct_data;
} }


current_voice_id[0] = 0; current_voice_id[0] = 0;


ignore_text = 0;
audio_text = 0;
clear_skipping_text = 0;
ignore_text = false;
audio_text = false;
clear_skipping_text = false;
count_characters = -1; count_characters = -1;
sayas_mode = 0; sayas_mode = 0;



+ 8
- 8
src/libespeak-ng/setlengths.c View File

int stress; int stress;
int type; int type;
static int more_syllables = 0; static int more_syllables = 0;
int pre_sonorant = 0;
int pre_voiced = 0;
bool pre_sonorant = false;
bool pre_voiced = false;
int last_pitch = 0; int last_pitch = 0;
int pitch_start; int pitch_start;
int length_mod; int length_mod;


if (type == phVFRICATIVE) { if (type == phVFRICATIVE) {
if (next->type == phVOWEL) if (next->type == phVOWEL)
pre_voiced = 1;
pre_voiced = true;
if ((prev->type == phVOWEL) || (prev->type == phLIQUID)) if ((prev->type == phVOWEL) || (prev->type == phLIQUID))
p->length = (255 + prev->length)/2; p->length = (255 + prev->length)/2;
} }


if (next->type == phVOWEL || next->type == phLIQUID) { if (next->type == phVOWEL || next->type == phLIQUID) {
if ((next->type == phVOWEL) || !next->newword) if ((next->type == phVOWEL) || !next->newword)
pre_voiced = 1;
pre_voiced = true;


p->prepause = 40; p->prepause = 40;


} }


if (next->type == phVOWEL) if (next->type == phVOWEL)
pre_sonorant = 1;
pre_sonorant = true;
else { else {
p->pitch2 = last_pitch; p->pitch2 = last_pitch;


if (p->pitch2 < 16) if (p->pitch2 < 16)
p->pitch1 = 0; p->pitch1 = 0;
p->env = PITCHfall; p->env = PITCHfall;
pre_voiced = 0;
pre_voiced = false;
} }
break; break;
case phVOWEL: case phVOWEL:
} }


last_pitch = p->pitch1 + ((p->pitch2-p->pitch1)*envelope_data[p->env][127])/256; last_pitch = p->pitch1 + ((p->pitch2-p->pitch1)*envelope_data[p->env][127])/256;
pre_sonorant = 0;
pre_voiced = 0;
pre_sonorant = false;
pre_voiced = false;
break; break;
} }
} }

+ 2
- 2
src/libespeak-ng/speech.c View File



} }
if (skip_characters || skip_words || skip_sentences) if (skip_characters || skip_words || skip_sentences)
skipping_text = 1;
skipping_text = true;


end_character_position = end_position; end_character_position = end_position;




if (index_mark != NULL) { if (index_mark != NULL) {
strncpy0(skip_marker, index_mark, sizeof(skip_marker)); strncpy0(skip_marker, index_mark, sizeof(skip_marker));
skipping_text = 1;
skipping_text = true;
} }


end_character_position = end_position; end_character_position = end_position;

+ 10
- 10
src/libespeak-ng/synth_mbrola.c View File



MBROLA_TAB *pr; MBROLA_TAB *pr;
PHONEME_TAB *other_ph; PHONEME_TAB *other_ph;
int found = 0;
bool found = false;
static int mnem; static int mnem;


// control // control
while (pr->name != 0) { while (pr->name != 0) {
if (mnem == pr->name) { if (mnem == pr->name) {
if (pr->next_phoneme == 0) if (pr->next_phoneme == 0)
found = 1;
found = true;
else if ((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN)) else if ((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN))
found = 1;
found = true;
else { else {
if (pr->control & 2) if (pr->control & 2)
other_ph = ph_prev; other_ph = ph_prev;
if ((pr->next_phoneme == other_ph->mnemonic) || if ((pr->next_phoneme == other_ph->mnemonic) ||
((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) || ((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) ||
((pr->next_phoneme == '_') && (other_ph->type == phPAUSE))) ((pr->next_phoneme == '_') && (other_ph->type == phPAUSE)))
found = 1;
found = true;
} }


if ((pr->control & 4) && (plist->newword == 0)) // only at start of word if ((pr->control & 4) && (plist->newword == 0)) // only at start of word
found = 0;
found = false;


if ((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word if ((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word
found = 0;
found = false;


if ((pr->control & 0x20) && (plist->stresslevel < plist->wordstress)) if ((pr->control & 0x20) && (plist->stresslevel < plist->wordstress))
found = 0; // only in stressed syllables
found = false; // only in stressed syllables


if (found) { if (found) {
*name2 = pr->mbr_name2; *name2 = pr->mbr_name2;
bool released; bool released;
int name2; int name2;
int control; int control;
int done;
bool done;
int len_percent; int len_percent;
const char *final_pitch; const char *final_pitch;
char *ptr; char *ptr;
name2 = 0; name2 = 0;
} }


done = 0;
done = false;
final_pitch = ""; final_pitch = "";


switch (ph->type) switch (ph->type)
pitch = WritePitch(p->env, p->pitch1, p->pitch2, -len_percent, 0); pitch = WritePitch(p->env, p->pitch1, p->pitch2, -len_percent, 0);
ptr += sprintf(ptr, "%s\t%d\t%s", WordToString(name2), len-len1, pitch); ptr += sprintf(ptr, "%s\t%d\t%s", WordToString(name2), len-len1, pitch);
} }
done = 1;
done = true;
break; break;
case phSTOP: case phSTOP:
released = false; released = false;

+ 4
- 4
src/libespeak-ng/synthdata.c View File

unsigned int data; unsigned int data;
int instn; int instn;
int instn2; int instn2;
int check_endtype = 0;
bool check_endtype = false;
PHONEME_TAB *ph; PHONEME_TAB *ph;
PHONEME_LIST *plist_this; PHONEME_LIST *plist_this;


case 0: // prevPh case 0: // prevPh
case 5: // prevPhW case 5: // prevPhW
plist--; plist--;
check_endtype = 1;
check_endtype = true;
break; break;
case 1: // thisPh case 1: // thisPh
break; break;
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 = true;
break; break;
case 9: // next3PhW case 9: // next3PhW
for (ix = 1; ix <= 3; ix++) { for (ix = 1; ix <= 3; ix++) {
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 = true;
break; break;
} }



+ 16
- 16
src/libespeak-ng/synthesize.c View File

int ix; int ix;
int len; int len;
int pk; int pk;
int modified;
bool modified;
int allowed; int allowed;
int diff; int diff;


break; // doesn't follow on from previous frame break; // doesn't follow on from previous frame


frame = frame2 = (frame_t *)q[2]; frame = frame2 = (frame_t *)q[2];
modified = 0;
modified = false;


if (frame->frflags & FRFLAG_BREAK) if (frame->frflags & FRFLAG_BREAK)
break; break;
allowed = (allowed * len)/256; allowed = (allowed * len)/256;


if (diff > allowed) { if (diff > allowed) {
if (modified == 0) {
if (modified == false) {
frame2 = CopyFrame(frame, 0); frame2 = CopyFrame(frame, 0);
modified = 1;
modified = true;
} }
frame2->ffreq[pk] = frame1->ffreq[pk] + allowed; frame2->ffreq[pk] = frame1->ffreq[pk] + allowed;
q[2] = (intptr_t)frame2; q[2] = (intptr_t)frame2;
} else if (diff < -allowed) { } else if (diff < -allowed) {
if (modified == 0) {
if (modified == false) {
frame2 = CopyFrame(frame, 0); frame2 = CopyFrame(frame, 0);
modified = 1;
modified = true;
} }
frame2->ffreq[pk] = frame1->ffreq[pk] - allowed; frame2->ffreq[pk] = frame1->ffreq[pk] - allowed;
q[2] = (intptr_t)frame2; q[2] = (intptr_t)frame2;
} }


frame = frame2 = (frame_t *)q[3]; frame = frame2 = (frame_t *)q[3];
modified = 0;
modified = false;


if (frame1->frflags & FRFLAG_BREAK) if (frame1->frflags & FRFLAG_BREAK)
break; break;
allowed = (allowed * len)/256; allowed = (allowed * len)/256;


if (diff > allowed) { if (diff > allowed) {
if (modified == 0) {
if (modified == false) {
frame2 = CopyFrame(frame, 0); frame2 = CopyFrame(frame, 0);
modified = 1;
modified = true;
} }
frame2->ffreq[pk] = frame1->ffreq[pk] + allowed; frame2->ffreq[pk] = frame1->ffreq[pk] + allowed;
q[3] = (intptr_t)frame2; q[3] = (intptr_t)frame2;
} else if (diff < -allowed) { } else if (diff < -allowed) {
if (modified == 0) {
if (modified == false) {
frame2 = CopyFrame(frame, 0); frame2 = CopyFrame(frame, 0);
modified = 1;
modified = true;
} }
frame2->ffreq[pk] = frame1->ffreq[pk] - allowed; frame2->ffreq[pk] = frame1->ffreq[pk] - allowed;
q[3] = (intptr_t)frame2; q[3] = (intptr_t)frame2;
unsigned char *amp_env; unsigned char *amp_env;
PHONEME_TAB *ph; PHONEME_TAB *ph;
int use_ipa = 0; int use_ipa = 0;
int done_phoneme_marker;
bool done_phoneme_marker;
int vowelstart_prev; int vowelstart_prev;
char phoneme_name[16]; char phoneme_name[16];
static int sourceix = 0; static int sourceix = 0;
if ((p->prepause > 0) && !(p->ph->phflags & phPREVOICE)) if ((p->prepause > 0) && !(p->ph->phflags & phPREVOICE))
DoPause(p->prepause, 1); DoPause(p->prepause, 1);


done_phoneme_marker = 0;
done_phoneme_marker = false;
if (option_phoneme_events && (p->ph->code != phonEND_WORD)) { if (option_phoneme_events && (p->ph->code != phonEND_WORD)) {
if ((p->type == phVOWEL) && (prev->type == phLIQUID || prev->type == phNASAL)) { if ((p->type == phVOWEL) && (prev->type == phLIQUID || prev->type == phNASAL)) {
// For vowels following a liquid or nasal, do the phoneme event after the vowel-start // For vowels following a liquid or nasal, do the phoneme event after the vowel-start
} else { } else {
WritePhMnemonic(phoneme_name, p->ph, p, use_ipa, NULL); WritePhMnemonic(phoneme_name, p->ph, p, use_ipa, NULL);
DoPhonemeMarker(espeakEVENT_PHONEME, sourceix, 0, phoneme_name); DoPhonemeMarker(espeakEVENT_PHONEME, sourceix, 0, phoneme_name);
done_phoneme_marker = 1;
done_phoneme_marker = true;
} }
} }


DoSpect2(ph, 1, &fmtp, p, modulation); DoSpect2(ph, 1, &fmtp, p, modulation);
} }


if ((option_phoneme_events) && (done_phoneme_marker == 0)) {
if ((option_phoneme_events) && (done_phoneme_marker == false)) {
WritePhMnemonic(phoneme_name, p->ph, p, use_ipa, NULL); WritePhMnemonic(phoneme_name, p->ph, p, use_ipa, NULL);
DoPhonemeMarker(espeakEVENT_PHONEME, sourceix, 0, phoneme_name); DoPhonemeMarker(espeakEVENT_PHONEME, sourceix, 0, phoneme_name);
} }
} }


if (text_decoder_eof(p_decoder)) { if (text_decoder_eof(p_decoder)) {
skipping_text = 0;
skipping_text = false;
return 0; return 0;
} }



+ 1
- 1
src/libespeak-ng/tr_languages.c View File

tr->langopts.our_alphabet = 0x3100; tr->langopts.our_alphabet = 0x3100;
tr->langopts.word_gap = 0x21; // length of a final vowel is less dependent on the next consonant, don't merge consonant with next word tr->langopts.word_gap = 0x21; // length of a final vowel is less dependent on the next consonant, don't merge consonant with next word
if (name2 == L3('z', 'h', 'y')) { if (name2 == L3('z', 'h', 'y')) {
tr->langopts.textmode = 1;
tr->langopts.textmode = true;
tr->langopts.listx = 1; // compile zh_listx after zh_list tr->langopts.listx = 1; // compile zh_listx after zh_list
tr->langopts.numbers = 1; tr->langopts.numbers = 1;
tr->langopts.numbers2 = NUM2_ZERO_TENS; tr->langopts.numbers2 = NUM2_ZERO_TENS;

+ 73
- 76
src/libespeak-ng/translate.c View File

int skip_words; int skip_words;
int skip_characters; int skip_characters;
char skip_marker[N_MARKER_LENGTH]; char skip_marker[N_MARKER_LENGTH];
int skipping_text; // waiting until word count, sentence count, or named marker is reached
bool skipping_text; // waiting until word count, sentence count, or named marker is reached
int end_character_position; int end_character_position;
int count_sentences; int count_sentences;
int count_words; int count_words;
int clause_start_char; int clause_start_char;
int clause_start_word; int clause_start_word;
int new_sentence;
bool new_sentence;
static int word_emphasis = 0; // set if emphasis level 3 or 4 static int word_emphasis = 0; // set if emphasis level 3 or 4
static int embedded_flag = 0; // there are embedded commands to be applied to the next phoneme, used in TranslateWord2() static int embedded_flag = 0; // there are embedded commands to be applied to the next phoneme, used in TranslateWord2()


static int prev_clause_pause = 0; static int prev_clause_pause = 0;
static int max_clause_pause = 0; static int max_clause_pause = 0;
static int any_stressed_words;
static bool any_stressed_words;
int pre_pause; int pre_pause;
ALPHABET *current_alphabet; ALPHABET *current_alphabet;


{ {
int posn = 0; int posn = 0;
int capitals = 0; int capitals = 0;
int non_initial = 0;
bool non_initial = false;


if (spell_word > 2) if (spell_word > 2)
capitals = 2; // speak 'capital' capitals = 2; // speak 'capital'
while ((*word != ' ') && (*word != 0)) { while ((*word != ' ') && (*word != 0)) {
word += TranslateLetter(tr, word, phonemes, capitals | non_initial); word += TranslateLetter(tr, word, phonemes, capitals | non_initial);
posn++; posn++;
non_initial = 1;
non_initial = true;
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);
int first_char; int first_char;
int last_char = 0; int last_char = 0;
int prefix_flags = 0; int prefix_flags = 0;
int more_suffixes;
int confirm_prefix;
bool more_suffixes;
bool confirm_prefix;
int spell_word; int spell_word;
int emphasize_allcaps = 0; int emphasize_allcaps = 0;
int wflags; int wflags;
// dictionary_flags may have ben set there // dictionary_flags may have ben set there


int posn; int posn;
int non_initial;
bool non_initial = false;
int length; int length;


posn = 0; posn = 0;
non_initial = 0;
length = 999; length = 999;
wordx = word1; wordx = word1;


break; break;


if (posn > 0) if (posn > 0)
non_initial = 1;
non_initial = true;


wordx += TranslateLetter(tr, wordx, unpron_phonemes, non_initial); wordx += TranslateLetter(tr, wordx, unpron_phonemes, non_initial);
posn++; posn++;
c_temp = wordx[-1]; c_temp = wordx[-1];


found = false; found = false;
confirm_prefix = 1;
confirm_prefix = true;
for (loopcount = 0; (loopcount < 50) && (end_type & SUFX_P); loopcount++) { for (loopcount = 0; (loopcount < 50) && (end_type & SUFX_P); loopcount++) {
// Found a standard prefix, remove it and retranslate // Found a standard prefix, remove it and retranslate
// loopcount guards against an endless loop // loopcount guards against an endless loop
fprintf(f_trans, " suffix [%s]\n\n", end_phonemes2); fprintf(f_trans, " suffix [%s]\n\n", end_phonemes2);
} }
} }
confirm_prefix = 0;
confirm_prefix = false;
continue; continue;
} }
} }
} }
c_temp = wordx[-1]; c_temp = wordx[-1];
wordx[-1] = ' '; wordx[-1] = ' ';
confirm_prefix = 1;
confirm_prefix = true;
wflags |= FLAG_PREFIX_REMOVED; wflags |= FLAG_PREFIX_REMOVED;


if (prefix_type & SUFX_B) { if (prefix_type & SUFX_B) {


// The word has a standard ending, re-translate without this ending // The word has a standard ending, re-translate without this ending
end_flags = RemoveEnding(tr, wordx, end_type, word_copy); end_flags = RemoveEnding(tr, wordx, end_type, word_copy);
more_suffixes = 1;
more_suffixes = true;


while (more_suffixes) { while (more_suffixes) {
more_suffixes = 0;
more_suffixes = false;
phonemes[0] = 0; phonemes[0] = 0;


if (prefix_phonemes[0] != 0) { if (prefix_phonemes[0] != 0) {
if ((end_type != 0) && !(end_type & SUFX_P)) { if ((end_type != 0) && !(end_type & SUFX_P)) {
// there is another suffix // there is another suffix
end_flags = RemoveEnding(tr, wordx, end_type, NULL); end_flags = RemoveEnding(tr, wordx, end_type, NULL);
more_suffixes = 1;
more_suffixes = true;
} }
} else { } else {
// don't remove any previous suffix // don't remove any previous suffix
char words_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes char words_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes
char *phonemes = words_phonemes; char *phonemes = words_phonemes;
int available = N_WORD_PHONEMES; int available = N_WORD_PHONEMES;
int first_word = 1;
bool first_word = true;


int flags = TranslateWord3(tr, word_start, wtab, word_out); int flags = TranslateWord3(tr, word_start, wtab, word_out);
if (flags & FLAG_TEXTMODE && word_out) { if (flags & FLAG_TEXTMODE && word_out) {
int n; int n;
if (first_word) { if (first_word) {
n = snprintf(phonemes, available, "%s", word_phonemes); n = snprintf(phonemes, available, "%s", word_phonemes);
first_word = 0;
first_word = false;
} else { } else {
n = snprintf(phonemes, available, "%c%s", phonEND_WORD, word_phonemes); n = snprintf(phonemes, available, "%c%s", phonEND_WORD, word_phonemes);
} }
int prev_vowel = -1; int prev_vowel = -1;
int pitch_raised = 0; int pitch_raised = 0;
int switch_phonemes = -1; int switch_phonemes = -1;
int first_phoneme = 1;
bool first_phoneme = true;
int source_ix; int source_ix;
int len; int len;
int ix; int ix;


if ((flags & FLAG_COMBINE) && !(wtab[1].flags & FLAG_PHONEMES)) { if ((flags & FLAG_COMBINE) && !(wtab[1].flags & FLAG_PHONEMES)) {
char *p2; char *p2;
int ok = 1;
bool ok = true;
unsigned int flags2[2]; unsigned int flags2[2];
int c_word2; int c_word2;
char ph_buf[N_WORD_PHONEMES]; char ph_buf[N_WORD_PHONEMES];


utf8_in(&c_word2, p2+1); // first character of the next word; utf8_in(&c_word2, p2+1); // first character of the next word;
if (!iswalpha(c_word2)) if (!iswalpha(c_word2))
ok = 0;
ok = false;


if (ok != 0) {
if (ok == true) {
strcpy(ph_buf, word_phonemes); strcpy(ph_buf, word_phonemes);


flags2[0] = TranslateWord(translator, p2+1, wtab+1, NULL); flags2[0] = TranslateWord(translator, p2+1, wtab+1, NULL);
if ((flags2[0] & FLAG_WAS_UNPRONOUNCABLE) || (word_phonemes[0] == phonSWITCH)) if ((flags2[0] & FLAG_WAS_UNPRONOUNCABLE) || (word_phonemes[0] == phonSWITCH))
ok = 0;
ok = false;


if (sylimit & 0x100) { if (sylimit & 0x100) {
// only if the second word has $alt attribute // only if the second word has $alt attribute
if ((flags2[0] & FLAG_ALT_TRANS) == 0) if ((flags2[0] & FLAG_ALT_TRANS) == 0)
ok = 0;
ok = false;
} }


if ((sylimit & 0x200) && ((wtab+1)->flags & FLAG_LAST_WORD)) { if ((sylimit & 0x200) && ((wtab+1)->flags & FLAG_LAST_WORD)) {
// not if the next word is end-of-sentence // not if the next word is end-of-sentence
ok = 0;
ok = false;
} }


if (ok == 0)
if (ok == false)
strcpy(word_phonemes, ph_buf); strcpy(word_phonemes, ph_buf);
} }


next_stress = 1; // default is 'unstressed' next_stress = 1; // default is 'unstressed'


if (stress >= 4) if (stress >= 4)
any_stressed_words = 1;
any_stressed_words = true;


if ((prev_vowel >= 0) && (n_ph_list2-1) != prev_vowel) if ((prev_vowel >= 0) && (n_ph_list2-1) != prev_vowel)
ph_list2[n_ph_list2-1].stresslevel = stress; // set stress for previous consonant ph_list2[n_ph_list2-1].stresslevel = stress; // set stress for previous consonant


ph_list2[n_ph_list2].stresslevel = stress; ph_list2[n_ph_list2].stresslevel = stress;
n_ph_list2++; n_ph_list2++;
first_phoneme = 0;
first_phoneme = false;
} }
} }


unsigned int word; unsigned int word;
unsigned int new_c, c2, c_lower; unsigned int new_c, c2, c_lower;
int upper_case = 0; int upper_case = 0;
static int ignore_next = 0;
static bool ignore_next = false;
const unsigned int *replace_chars; const unsigned int *replace_chars;


if (ignore_next) { if (ignore_next) {
ignore_next = 0;
ignore_next = false;
return 8; return 8;
} }
if (c == 0) return 0; if (c == 0) return 0;
} }
if ((word >> 16) == (unsigned int)towlower2(next_in)) { if ((word >> 16) == (unsigned int)towlower2(next_in)) {
new_c = replace_chars[ix+1]; new_c = replace_chars[ix+1];
ignore_next = 1;
ignore_next = true;
break; break;
} }
} }
int pre_pause_add = 0; int pre_pause_add = 0;
int word_mark = 0; int word_mark = 0;
int all_upper_case = FLAG_ALL_UPPER; int all_upper_case = FLAG_ALL_UPPER;
int finished;
int single_quoted;
int phoneme_mode = 0;
bool finished = false;
bool single_quoted = false;
bool phoneme_mode = false;
int dict_flags = 0; // returned from dictionary lookup int dict_flags = 0; // returned from dictionary lookup
int word_flags; // set here int word_flags; // set here
int next_word_flags; int next_word_flags;
int new_sentence2;
bool new_sentence2;
int embedded_count = 0; int embedded_count = 0;
int letter_count = 0; int letter_count = 0;
int space_inserted = 0;
int syllable_marked = 0;
int decimal_sep_count = 0;
bool space_inserted = false;
bool syllable_marked = false;
bool decimal_sep_count = false;
char *word; char *word;
char *p; char *p;
int j, k; int j, k;
embedded_ix = 0; embedded_ix = 0;
embedded_read = 0; embedded_read = 0;
pre_pause = 0; pre_pause = 0;
any_stressed_words = 0;
any_stressed_words = false;


if ((clause_start_char = count_characters) < 0) if ((clause_start_char = count_characters) < 0)
clause_start_char = 0; clause_start_char = 0;
if (new_sentence) if (new_sentence)
terminator |= CLAUSE_TYPE_SENTENCE; // carry forward an end-of-sentence indicator terminator |= CLAUSE_TYPE_SENTENCE; // carry forward an end-of-sentence indicator
max_clause_pause += clause_pause; max_clause_pause += clause_pause;
new_sentence2 = 0;
new_sentence2 = false;
} else { } else {
max_clause_pause = clause_pause; max_clause_pause = clause_pause;
new_sentence2 = new_sentence; new_sentence2 = new_sentence;
if (skip_sentences > 0) { if (skip_sentences > 0) {
skip_sentences--; skip_sentences--;
if (skip_sentences == 0) if (skip_sentences == 0)
skipping_text = 0;
skipping_text = false;
} }
} }


tr->prev_dict_flags[1] = 0; tr->prev_dict_flags[1] = 0;


word_count = 0; word_count = 0;
single_quoted = 0;
word_flags = 0; word_flags = 0;
next_word_flags = 0; next_word_flags = 0;




words[0].start = ix; words[0].start = ix;
words[0].flags = 0; words[0].flags = 0;
finished = 0;


for (j = 0; charix[j] <= 0; j++) ; for (j = 0; charix[j] <= 0; j++) ;
words[0].sourceix = charix[j]; words[0].sourceix = charix[j];
next_in_nbytes = utf8_in(&next_in, &source[source_index]); next_in_nbytes = utf8_in(&next_in, &source[source_index]);


if (c == 0) { if (c == 0) {
finished = 1;
finished = true;
c = ' '; c = ' ';
} }


all_upper_case = FLAG_PHONEMES; all_upper_case = FLAG_PHONEMES;


if ((c == ']') && (next_in == ']')) { if ((c == ']') && (next_in == ']')) {
phoneme_mode = 0;
phoneme_mode = false;
source_index++; source_index++;
c = ' '; c = ' ';
} }
if (count_sayas_digits > (option_sayas2 & 0xf)) { if (count_sayas_digits > (option_sayas2 & 0xf)) {
// break after the specified number of digits // break after the specified number of digits
c = ' '; c = ' ';
space_inserted = 1;
space_inserted = true;
count_sayas_digits = 0; count_sayas_digits = 0;
} }
} else { } else {
count_sayas_digits = 0; count_sayas_digits = 0;
if (iswdigit(prev_out)) { if (iswdigit(prev_out)) {
c = ' '; c = ' ';
space_inserted = 1;
space_inserted = true;
} }
} }
} else if ((option_sayas2 & 0x10) == 0) { } else if ((option_sayas2 & 0x10) == 0) {
// allow a tone number as part of the word // allow a tone number as part of the word
} else { } else {
c = ' '; // ensure we have an end-of-word terminator c = ' '; // ensure we have an end-of-word terminator
space_inserted = 1;
space_inserted = true;
} }
} }
} }
if (iswdigit(prev_out)) { if (iswdigit(prev_out)) {
if (!iswdigit(c) && (c != '.') && (c != ',') && (c != ' ')) { if (!iswdigit(c) && (c != '.') && (c != ',') && (c != ' ')) {
c = ' '; // terminate digit string with a space c = ' '; // terminate digit string with a space
space_inserted = 1;
space_inserted = true;
} }
} else { // Prev output is not digit } else { // Prev output is not digit
if (prev_in == ',') { if (prev_in == ',') {
if (c == ',') if (c == ',')
c = ' '; c = ' ';
} else { } else {
decimal_sep_count = 0;
decimal_sep_count = false;
} }
} }


if (c == '[') { if (c == '[') {
if ((next_in == '\002') || ((next_in == '[') && option_phoneme_input)) { if ((next_in == '\002') || ((next_in == '[') && option_phoneme_input)) {
// "[\002" is used internally to start phoneme mode // "[\002" is used internally to start phoneme mode
phoneme_mode = FLAG_PHONEMES;
phoneme_mode = true;
source_index++; source_index++;
continue; continue;
} }
if ((prev_out != ' ') && (wcschr(tr->punct_within_word, prev_out) == 0)) { if ((prev_out != ' ') && (wcschr(tr->punct_within_word, prev_out) == 0)) {
// start of word, insert space if not one there already // start of word, insert space if not one there already
c = ' '; c = ' ';
space_inserted = 1;
space_inserted = true;


if (!IsBracket(prev_out)) // ?? perhaps only set FLAG_NOSPACE for . - / (hyphenated words, URLs, etc) if (!IsBracket(prev_out)) // ?? perhaps only set FLAG_NOSPACE for . - / (hyphenated words, URLs, etc)
next_word_flags |= FLAG_NOSPACE; next_word_flags |= FLAG_NOSPACE;
// Break into separate words // Break into separate words
if (IsAlpha(prev_out)) { if (IsAlpha(prev_out)) {
c = ' '; c = ' ';
space_inserted = 1;
space_inserted = true;
word_flags |= FLAG_HYPHEN_AFTER; word_flags |= FLAG_HYPHEN_AFTER;
next_word_flags |= FLAG_HYPHEN; next_word_flags |= FLAG_HYPHEN;
} }
c = towlower2(c); c = towlower2(c);


if ((j = tr->langopts.param[LOPT_CAPS_IN_WORD]) > 0) { if ((j = tr->langopts.param[LOPT_CAPS_IN_WORD]) > 0) {
if ((j == 2) && (syllable_marked == 0)) {
if ((j == 2) && (syllable_marked == false)) {
char_inserted = c; char_inserted = c;
c = 0x2c8; // stress marker c = 0x2c8; // stress marker
syllable_marked = 1;
syllable_marked = true;
} }
} else { } else {
if (iswlower(prev_in)) { if (iswlower(prev_in)) {
c = towlower2(c); c = towlower2(c);
} else { } else {
c = ' '; // lower case followed by upper case, treat as new word c = ' '; // lower case followed by upper case, treat as new word
space_inserted = 1;
space_inserted = true;
prev_in_save = c; prev_in_save = c;
} }
} else if ((c != ' ') && iswupper(prev_in) && iswlower(next_in)) { } else if ((c != ' ') && iswupper(prev_in) && iswlower(next_in)) {
} else if (IsAlpha(next2_in)) { } else if (IsAlpha(next2_in)) {
// changing from upper to lower case, start new word at the last uppercase, if 3 or more letters // changing from upper to lower case, start new word at the last uppercase, if 3 or more letters
c = ' '; c = ' ';
space_inserted = 1;
space_inserted = true;
prev_in_save = c; prev_in_save = c;
next_word_flags |= FLAG_NOSPACE; next_word_flags |= FLAG_NOSPACE;
} }
if (prev_out != ' ') { if (prev_out != ' ') {
// previous 'word' not yet ended (not alpha or numeric), start new word now. // previous 'word' not yet ended (not alpha or numeric), start new word now.
c = ' '; c = ' ';
space_inserted = 1;
space_inserted = true;
} else { } else {
// '-' between two letters is a hyphen, treat as a space // '-' between two letters is a hyphen, treat as a space
word_flags |= FLAG_HYPHEN; word_flags |= FLAG_HYPHEN;
if (prev_out == '.') { if (prev_out == '.') {
// multiple dots, separate by spaces. Note >3 dots has been replaced by elipsis // multiple dots, separate by spaces. Note >3 dots has been replaced by elipsis
c = ' '; c = ' ';
space_inserted = 1;
space_inserted = true;
} else if ((word_count > 0) && !(words[word_count-1].flags & FLAG_NOSPACE) && IsAlpha(prev_in)) { } else if ((word_count > 0) && !(words[word_count-1].flags & FLAG_NOSPACE) && IsAlpha(prev_in)) {
// dot after a word, with space following, probably an abbreviation // dot after a word, with space following, probably an abbreviation
words[word_count-1].flags |= FLAG_HAS_DOT; words[word_count-1].flags |= FLAG_HAS_DOT;
} else if (c == '\'') { } else if (c == '\'') {
if (((prev_in == '.') || iswalnum(prev_in)) && IsAlpha(next_in)) { if (((prev_in == '.') || iswalnum(prev_in)) && IsAlpha(next_in)) {
// between two letters, or in an abbreviation (eg. u.s.a.'s). Consider the apostrophe as part of the word // between two letters, or in an abbreviation (eg. u.s.a.'s). Consider the apostrophe as part of the word
single_quoted = 0;
single_quoted = false;
} else if ((tr->langopts.param[LOPT_APOSTROPHE] & 1) && IsAlpha(next_in)) } else if ((tr->langopts.param[LOPT_APOSTROPHE] & 1) && IsAlpha(next_in))
single_quoted = 0; // apostrophe at start of word is part of the word
single_quoted = false; // apostrophe at start of word is part of the word
else if ((tr->langopts.param[LOPT_APOSTROPHE] & 2) && IsAlpha(prev_in)) else if ((tr->langopts.param[LOPT_APOSTROPHE] & 2) && IsAlpha(prev_in))
single_quoted = 0; // apostrophe at end of word is part of the word
single_quoted = false; // apostrophe at end of word is part of the word
else if ((wcschr(tr->char_plus_apostrophe, prev_in) != 0) && (prev_out2 == ' ')) { else if ((wcschr(tr->char_plus_apostrophe, prev_in) != 0) && (prev_out2 == ' ')) {
// consider single character plus apostrophe as a word // consider single character plus apostrophe as a word
single_quoted = 0;
single_quoted = false;
if (next_in == ' ') if (next_in == ' ')
source_index++; // skip following space source_index++; // skip following space
} else { } else {
if ((prev_out == 's') && (single_quoted == 0)) {
if ((prev_out == 's') && (single_quoted == false)) {
// looks like apostrophe after an 's' // looks like apostrophe after an 's'
c = ' '; c = ' ';
} else { } else {
if (IsSpace(prev_out)) if (IsSpace(prev_out))
single_quoted = 1;
single_quoted = true;
else else
single_quoted = 0;
single_quoted = false;


pre_pause_add = 4; // single quote pre_pause_add = 4; // single quote
c = ' '; c = ' ';
else if (iswdigit(c)) { else if (iswdigit(c)) {
if (tr->langopts.tone_numbers && IsAlpha(prev_out) && !IsDigit(next_in)) { if (tr->langopts.tone_numbers && IsAlpha(prev_out) && !IsDigit(next_in)) {
} else if ((prev_out != ' ') && !iswdigit(prev_out)) { } else if ((prev_out != ' ') && !iswdigit(prev_out)) {
if ((prev_out != tr->langopts.decimal_sep) || ((decimal_sep_count > 0) && (tr->langopts.decimal_sep == ','))) {
if ((prev_out != tr->langopts.decimal_sep) || ((decimal_sep_count == true) && (tr->langopts.decimal_sep == ','))) {
c = ' '; c = ' ';
space_inserted = 1;
space_inserted = true;
} else } else
decimal_sep_count = 1;
decimal_sep_count = true;
} else if ((prev_out == ' ') && IsAlpha(prev_out2) && !IsAlpha(prev_in)) { } else if ((prev_out == ' ') && IsAlpha(prev_out2) && !IsAlpha(prev_in)) {
// insert extra space between a word and a number, to distinguish 'a 2' from 'a2' // insert extra space between a word and a number, to distinguish 'a 2' from 'a2'
sbuf[ix++] = ' '; sbuf[ix++] = ' ';
pre_pause = 0; pre_pause = 0;
word_mark = 0; word_mark = 0;
all_upper_case = FLAG_ALL_UPPER; all_upper_case = FLAG_ALL_UPPER;
syllable_marked = 0;
syllable_marked = false;
} }


if (space_inserted) { if (space_inserted) {
source_index = prev_source_index; // rewind to the previous character source_index = prev_source_index; // rewind to the previous character
char_inserted = 0; char_inserted = 0;
space_inserted = 0;
space_inserted = false;
} }
} else { } else {
if ((ix < (N_TR_SOURCE - 4))) if ((ix < (N_TR_SOURCE - 4)))
if (skip_words > 0) { if (skip_words > 0) {
skip_words--; skip_words--;
if (skip_words == 0) if (skip_words == 0)
skipping_text = 0;
skipping_text = false;
} }
if (skipping_text) if (skipping_text)
continue; continue;
if (tone_out != NULL) if (tone_out != NULL)
*tone_out = tone; *tone_out = tone;


new_sentence = 0;
new_sentence = false;
if (terminator & CLAUSE_TYPE_SENTENCE) if (terminator & CLAUSE_TYPE_SENTENCE)
new_sentence = 1; // next clause is a new sentence
new_sentence = true; // next clause is a new sentence


if (voice_change != NULL) { if (voice_change != NULL) {
// return new voice name if an embedded voice change command terminated the clause // return new voice name if an embedded voice change command terminated the clause
skip_marker[0] = 0; skip_marker[0] = 0;
skip_words = 0; skip_words = 0;
skip_characters = 0; skip_characters = 0;
skipping_text = 0;
new_sentence = 1;
skipping_text = false;
new_sentence = true;


prev_clause_pause = 0; prev_clause_pause = 0;



+ 3
- 3
src/libespeak-ng/translate.h View File

char spelling_stress; // 0=default, 1=stress first letter char spelling_stress; // 0=default, 1=stress first letter
char tone_numbers; char tone_numbers;
char ideographs; // treat as separate words char ideographs; // treat as separate words
char textmode; // the meaning of FLAG_TEXTMODE is reversed (to save data when *_list file is compiled)
bool textmode; // the meaning of FLAG_TEXTMODE is reversed (to save data when *_list file is compiled)
char dotless_i; // uses letter U+0131 char dotless_i; // uses letter U+0131
int testing; // testing options: bit 1= specify stressed syllable in the form: "outdoor/2" int testing; // testing options: bit 1= specify stressed syllable in the form: "outdoor/2"
int listx; // compile *_listx after *list int listx; // compile *_listx after *list
extern int skip_characters; extern int skip_characters;
extern int skip_words; extern int skip_words;
extern int skip_sentences; extern int skip_sentences;
extern int skipping_text;
extern bool skipping_text;
extern int end_character_position; extern int end_character_position;
extern int clause_start_char; extern int clause_start_char;
extern int clause_start_word; extern int clause_start_word;
void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len); void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len);
char *DecodeRule(const char *group_chars, int group_length, char *rule, int control); char *DecodeRule(const char *group_chars, int group_length, char *rule, int control);


void MakePhonemeList(Translator *tr, int post_pause, int new_sentence);
void MakePhonemeList(Translator *tr, int post_pause, bool new_sentence);
int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch); int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch);
void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags); void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags);
void AppendPhonemes(Translator *tr, char *string, int size, const char *ph); void AppendPhonemes(Translator *tr, char *string, int size, const char *ph);

+ 6
- 6
src/libespeak-ng/voices.c View File

int value2; int value2;
int langix = 0; int langix = 0;
int tone_only = control & 2; int tone_only = control & 2;
int language_set = 0;
int phonemes_set = 0;
bool language_set = false;
bool phonemes_set = false;
int stress_amps_set = 0; int stress_amps_set = 0;
int stress_lengths_set = 0; int stress_lengths_set = 0;
int stress_add_set = 0; int stress_add_set = 0;
} }


// only act on the first language line // only act on the first language line
if (language_set == 0) {
if (language_set == false) {
language_type = strtok(language_name, "-"); language_type = strtok(language_name, "-");
language_set = 1;
language_set = true;
strcpy(translator_name, language_type); strcpy(translator_name, language_type);
strcpy(new_dictionary, language_type); strcpy(new_dictionary, language_type);
strcpy(phonemes_name, language_type); strcpy(phonemes_name, language_type);
fprintf(stderr, "Cannot set stressopt: language not set, or is invalid.\n"); fprintf(stderr, "Cannot set stressopt: language not set, or is invalid.\n");
break; break;
case V_REPLACE: case V_REPLACE:
if (phonemes_set == 0) {
if (phonemes_set == false) {
// must set up a phoneme table before we can lookup phoneme mnemonics // must set up a phoneme table before we can lookup phoneme mnemonics
SelectPhonemeTableName(phonemes_name); SelectPhonemeTableName(phonemes_name);
phonemes_set = 1;
phonemes_set = true;
} }
PhonemeReplacement(p); PhonemeReplacement(p);
break; break;

Loading…
Cancel
Save