@@ -173,7 +173,7 @@ void DisplayVoices(FILE *f_out, char *language) | |||
static void Write4Bytes(FILE *f, int value) | |||
{ | |||
// Write 4 bytes to a file, least significant first | |||
// Write 4 bytes to a file, least significant first | |||
int ix; | |||
for (ix = 0; ix < 4; ix++) { | |||
@@ -233,14 +233,13 @@ static void CloseWavFile() | |||
fclose(f_wavfile); | |||
f_wavfile = NULL; | |||
} | |||
static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) | |||
{ | |||
char fname[210]; | |||
if (quiet) return 0; // -q quiet mode | |||
if (quiet) return 0; // -q quiet mode | |||
if (wav == NULL) { | |||
CloseWavFile(); | |||
@@ -267,10 +266,8 @@ static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) | |||
sprintf(fname, "%s_%.2d%s", wavefile, wavefile_count+1, filetype); | |||
if (OpenWavFile(fname, samplerate) != 0) | |||
return 1; | |||
} else { | |||
if (OpenWavFile(wavefile, samplerate) != 0) | |||
return 1; | |||
} | |||
} else if (OpenWavFile(wavefile, samplerate) != 0) | |||
return 1; | |||
} | |||
if (numsamples > 0) { | |||
@@ -298,7 +295,7 @@ struct option { | |||
}; | |||
int optind; | |||
static int optional_argument; | |||
static const char *arg_opts = "abfgklpsvw"; // which options have arguments | |||
static const char *arg_opts = "abfgklpsvw"; // which options have arguments | |||
static char *opt_string = ""; | |||
#define no_argument 0 | |||
#define required_argument 1 | |||
@@ -334,7 +331,7 @@ int main(int argc, char **argv) | |||
FILE *f_text = NULL; | |||
char *p_text = NULL; | |||
FILE *f_phonemes_out = stdout; | |||
char *data_path = NULL; // use default path for espeak-data | |||
char *data_path = NULL; // use default path for espeak-data | |||
int option_index = 0; | |||
int c; | |||
@@ -360,7 +357,7 @@ int main(int argc, char **argv) | |||
espeak_VOICE voice_select; | |||
char filename[200]; | |||
char voicename[40]; | |||
#define N_PUNCTLIST 100 | |||
#define N_PUNCTLIST 100 | |||
wchar_t option_punctlist[N_PUNCTLIST]; | |||
voicename[0] = 0; | |||
@@ -389,7 +386,7 @@ int main(int argc, char **argv) | |||
if (c == '-') { | |||
if (p[0] == 0) | |||
break; // -- means don't interpret further - as commands | |||
break; // -- means don't interpret further - as commands | |||
opt_string = ""; | |||
for (ix = 0;; ix++) { | |||
@@ -417,7 +414,7 @@ int main(int argc, char **argv) | |||
c = getopt_long(argc, argv, "a:b:f:g:hk:l:mp:qs:v:w:xXz", | |||
long_options, &option_index); | |||
/* Detect the end of the options. */ | |||
// Detect the end of the options. | |||
if (c == -1) | |||
break; | |||
optarg2 = optarg; | |||
@@ -478,23 +475,23 @@ int main(int argc, char **argv) | |||
option_waveout = 1; | |||
strncpy0(wavefile, optarg2, sizeof(filename)); | |||
break; | |||
case 'z': // remove pause from the end of a sentence | |||
case 'z': // remove pause from the end of a sentence | |||
synth_flags &= ~espeakENDPAUSE; | |||
break; | |||
case 0x100: // --stdin | |||
case 0x100: // --stdin | |||
flag_stdin = 1; | |||
break; | |||
case 0x105: // --stdout | |||
case 0x105: // --stdout | |||
option_waveout = 1; | |||
strcpy(wavefile, "stdout"); | |||
break; | |||
case 0x101: // --compile-debug | |||
case 0x102: // --compile | |||
case 0x101: // --compile-debug | |||
case 0x102: // --compile | |||
strncpy0(voicename, optarg2, sizeof(voicename)); | |||
flag_compile = c; | |||
quiet = 1; | |||
break; | |||
case 0x103: // --punct | |||
case 0x103: // --punct | |||
option_punctuation = 1; | |||
if (optarg2 != NULL) { | |||
ix = 0; | |||
@@ -503,27 +500,27 @@ int main(int argc, char **argv) | |||
option_punctuation = 2; | |||
} | |||
break; | |||
case 0x104: // --voices | |||
case 0x104: // --voices | |||
espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0); | |||
DisplayVoices(stdout, optarg2); | |||
exit(0); | |||
case 0x106: // -- split | |||
case 0x106: // -- split | |||
if (optarg2 == NULL) | |||
samples_split_seconds = 30 * 60; // default 30 minutes | |||
samples_split_seconds = 30 * 60; // default 30 minutes | |||
else | |||
samples_split_seconds = atoi(optarg2) * 60; | |||
break; | |||
case 0x107: // --path | |||
case 0x107: // --path | |||
data_path = optarg2; | |||
break; | |||
case 0x108: // --phonout | |||
case 0x108: // --phonout | |||
if ((f_phonemes_out = fopen(optarg2, "w")) == NULL) | |||
fprintf(stderr, "Can't write to: %s\n", optarg2); | |||
break; | |||
case 0x109: // --pho | |||
case 0x109: // --pho | |||
phoneme_options |= espeakPHONEMES_MBROLA; | |||
break; | |||
case 0x10a: // --ipa | |||
case 0x10a: // --ipa | |||
phoneme_options |= espeakPHONEMES_IPA; | |||
if (optarg2 != NULL) { | |||
// deprecated and obsolete | |||
@@ -537,43 +534,43 @@ int main(int argc, char **argv) | |||
phoneme_options |= espeakPHONEMES_TIE; | |||
break; | |||
case 3: | |||
phonemes_separator = 0x200d; // ZWJ | |||
phonemes_separator = 0x200d; // ZWJ | |||
phoneme_options |= espeakPHONEMES_TIE; | |||
break; | |||
} | |||
} | |||
break; | |||
case 0x10b: // --version | |||
case 0x10b: // --version | |||
PrintVersion(); | |||
exit(0); | |||
case 0x10c: // --sep | |||
case 0x10c: // --sep | |||
phoneme_options |= espeakPHONEMES_SHOW; | |||
if (optarg2 == 0) | |||
phonemes_separator = ' '; | |||
else | |||
utf8_in(&phonemes_separator, optarg2); | |||
if (phonemes_separator == 'z') | |||
phonemes_separator = 0x200c; // ZWNJ | |||
phonemes_separator = 0x200c; // ZWNJ | |||
break; | |||
case 0x10d: // --tie | |||
case 0x10d: // --tie | |||
phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); | |||
if (optarg2 == 0) | |||
phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
else | |||
utf8_in(&phonemes_separator, optarg2); | |||
if (phonemes_separator == 'z') | |||
phonemes_separator = 0x200d; // ZWJ | |||
phonemes_separator = 0x200d; // ZWJ | |||
break; | |||
case 0x10e: // --compile-mbrola | |||
case 0x10e: // --compile-mbrola | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0); | |||
espeak_ng_CompileMbrolaVoice(optarg2, stdout); | |||
exit(0); | |||
case 0x10f: // --compile-intonations | |||
case 0x10f: // --compile-intonations | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY); | |||
espeak_ng_CompileIntonation(stdout); | |||
exit(0); | |||
case 0x110: // --compile-phonemes | |||
case 0x110: // --compile-phonemes | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY); | |||
espeak_ng_CompilePhonemeData(22050, stdout); | |||
exit(0); | |||
@@ -707,6 +704,6 @@ int main(int argc, char **argv) | |||
} | |||
if (f_phonemes_out != stdout) | |||
fclose(f_phonemes_out); // needed for WinCE | |||
fclose(f_phonemes_out); | |||
return 0; | |||
} |
@@ -54,9 +54,9 @@ static char *hash_chains[N_HASH_DICT]; | |||
static char letterGroupsDefined[N_LETTER_GROUPS]; | |||
MNEM_TAB mnem_rules[] = { | |||
{ "unpr", DOLLAR_UNPR }, | |||
{ "unpr", DOLLAR_UNPR }, | |||
{ "noprefix", DOLLAR_NOPREFIX }, // rule fails if a prefix has been removed | |||
{ "list", DOLLAR_LIST }, // a pronunciation is given in the *_list file | |||
{ "list", DOLLAR_LIST }, // a pronunciation is given in the *_list file | |||
{ "w_alt1", 0x11 }, | |||
{ "w_alt2", 0x12 }, | |||
@@ -64,7 +64,7 @@ MNEM_TAB mnem_rules[] = { | |||
{ "w_alt4", 0x14 }, | |||
{ "w_alt5", 0x15 }, | |||
{ "w_alt6", 0x16 }, | |||
{ "w_alt", 0x11 }, // note: put longer names before their sub-strings | |||
{ "w_alt", 0x11 }, // note: put longer names before their sub-strings | |||
{ "p_alt1", 0x21 }, | |||
{ "p_alt2", 0x22 }, | |||
@@ -72,82 +72,84 @@ MNEM_TAB mnem_rules[] = { | |||
{ "p_alt4", 0x24 }, | |||
{ "p_alt5", 0x25 }, | |||
{ "p_alt6", 0x26 }, | |||
{ "p_alt", 0x21 }, | |||
{ "p_alt", 0x21 }, | |||
{ NULL, -1 } | |||
}; | |||
MNEM_TAB mnem_flags[] = { | |||
// these in the first group put a value in bits0-3 of dictionary_flags | |||
{ "$1", 0x41 }, // stress on 1st syllable | |||
{ "$2", 0x42 }, // stress on 2nd syllable | |||
{ "$3", 0x43 }, | |||
{ "$4", 0x44 }, | |||
{ "$5", 0x45 }, | |||
{ "$6", 0x46 }, | |||
{ "$7", 0x47 }, | |||
{ "$u", 0x48 }, // reduce to unstressed | |||
{ "$u1", 0x49 }, | |||
{ "$u2", 0x4a }, | |||
{ "$u3", 0x4b }, | |||
{ "$u+", 0x4c }, // reduce to unstressed, but stress at end of clause | |||
{ "$1", 0x41 }, // stress on 1st syllable | |||
{ "$2", 0x42 }, // stress on 2nd syllable | |||
{ "$3", 0x43 }, | |||
{ "$4", 0x44 }, | |||
{ "$5", 0x45 }, | |||
{ "$6", 0x46 }, | |||
{ "$7", 0x47 }, | |||
{ "$u", 0x48 }, // reduce to unstressed | |||
{ "$u1", 0x49 }, | |||
{ "$u2", 0x4a }, | |||
{ "$u3", 0x4b }, | |||
{ "$u+", 0x4c }, // reduce to unstressed, but stress at end of clause | |||
{ "$u1+", 0x4d }, | |||
{ "$u2+", 0x4e }, | |||
{ "$u3+", 0x4f }, | |||
// these set the corresponding numbered bit if dictionary_flags | |||
{ "$pause", 8 }, // ensure pause before this word | |||
{ "$strend", 9 }, // full stress if at end of clause | |||
{ "$strend2", 10 }, // full stress if at end of clause, or only followed by unstressed | |||
{ "$unstressend", 11 }, // reduce stress at end of clause | |||
{ "$pause", 8 }, // ensure pause before this word | |||
{ "$strend", 9 }, // full stress if at end of clause | |||
{ "$strend2", 10 }, // full stress if at end of clause, or only followed by unstressed | |||
{ "$unstressend", 11 }, // reduce stress at end of clause | |||
{ "$accent_before", 12 }, // used with accent names, say this accent name before the letter name | |||
{ "$abbrev", 13 }, // use this pronuciation rather than split into letters | |||
// language specific | |||
{ "$double", 14 }, // IT double the initial consonant of next word | |||
{ "$alt", 15 }, // use alternative pronunciation | |||
{ "$alt1", 15 }, // synonym for $alt | |||
{ "$alt2", 16 }, | |||
{ "$alt3", 17 }, | |||
{ "$alt4", 18 }, | |||
{ "$alt5", 19 }, | |||
{ "$alt6", 20 }, | |||
{ "$alt7", 21 }, | |||
{ "$combine", 23 }, // Combine with the next word | |||
{ "$dot", 24 }, // ignore '.' after this word (abbreviation) | |||
{ "$hasdot", 25 }, // use this pronunciation if there is a dot after the word | |||
{ "$max3", 27 }, // limit to 3 repetitions | |||
{ "$brk", 28 }, // a shorter $pause | |||
{ "$text", 29 }, // word translates to replcement text, not phonemes | |||
// flags in dictionary word 2 | |||
{ "$verbf", 0x20 }, // verb follows | |||
{ "$verbsf", 0x21 }, // verb follows, allow -s suffix | |||
{ "$nounf", 0x22 }, // noun follows | |||
{ "$pastf", 0x23 }, // past tense follows | |||
{ "$verb", 0x24 }, // use this pronunciation when its a verb | |||
{ "$noun", 0x25 }, // use this pronunciation when its a noun | |||
{ "$past", 0x26 }, // use this pronunciation when its past tense | |||
{ "$abbrev", 13 }, // use this pronuciation rather than split into letters | |||
// language specific | |||
{ "$double", 14 }, // IT double the initial consonant of next word | |||
{ "$alt", 15 }, // use alternative pronunciation | |||
{ "$alt1", 15 }, // synonym for $alt | |||
{ "$alt2", 16 }, | |||
{ "$alt3", 17 }, | |||
{ "$alt4", 18 }, | |||
{ "$alt5", 19 }, | |||
{ "$alt6", 20 }, | |||
{ "$alt7", 21 }, | |||
{ "$combine", 23 }, // Combine with the next word | |||
{ "$dot", 24 }, // ignore '.' after this word (abbreviation) | |||
{ "$hasdot", 25 }, // use this pronunciation if there is a dot after the word | |||
{ "$max3", 27 }, // limit to 3 repetitions | |||
{ "$brk", 28 }, // a shorter $pause | |||
{ "$text", 29 }, // word translates to replcement text, not phonemes | |||
// flags in dictionary word 2 | |||
{ "$verbf", 0x20 }, // verb follows | |||
{ "$verbsf", 0x21 }, // verb follows, allow -s suffix | |||
{ "$nounf", 0x22 }, // noun follows | |||
{ "$pastf", 0x23 }, // past tense follows | |||
{ "$verb", 0x24 }, // use this pronunciation when its a verb | |||
{ "$noun", 0x25 }, // use this pronunciation when its a noun | |||
{ "$past", 0x26 }, // use this pronunciation when its past tense | |||
{ "$verbextend", 0x28 }, // extend influence of 'verb follows' | |||
{ "$capital", 0x29 }, // use this pronunciation if initial letter is upper case | |||
{ "$allcaps", 0x2a }, // use this pronunciation if initial letter is upper case | |||
{ "$accent", 0x2b }, // character name is base-character name + accent name | |||
{ "$sentence", 0x2d }, // only if this clause is a sentence (i.e. terminator is {. ? !} not {, ; :} | |||
{ "$only", 0x2e }, // only match on this word without suffix | |||
{ "$onlys", 0x2f }, // only match with none, or with 's' suffix | |||
{ "$stem", 0x30 }, // must have a suffix | |||
{ "$atend", 0x31 }, // use this pronunciation if at end of clause | |||
{ "$atstart", 0x32 }, // use this pronunciation at start of clause | |||
{ "$native", 0x33 }, // not if we've switched translators | |||
{ "$capital", 0x29 }, // use this pronunciation if initial letter is upper case | |||
{ "$allcaps", 0x2a }, // use this pronunciation if initial letter is upper case | |||
{ "$accent", 0x2b }, // character name is base-character name + accent name | |||
{ "$sentence", 0x2d }, // only if this clause is a sentence (i.e. terminator is {. ? !} not {, ; :} | |||
{ "$only", 0x2e }, // only match on this word without suffix | |||
{ "$onlys", 0x2f }, // only match with none, or with 's' suffix | |||
{ "$stem", 0x30 }, // must have a suffix | |||
{ "$atend", 0x31 }, // use this pronunciation if at end of clause | |||
{ "$atstart", 0x32 }, // use this pronunciation at start of clause | |||
{ "$native", 0x33 }, // not if we've switched translators | |||
// doesn't set dictionary_flags | |||
{ "$?", 100 }, // conditional rule, followed by byte giving the condition number | |||
{ "$?", 100 }, // conditional rule, followed by byte giving the condition number | |||
{ "$textmode", 200 }, | |||
{ "$textmode", 200 }, | |||
{ "$phonememode", 201 }, | |||
{ NULL, -1 } | |||
{ NULL, -1 } | |||
}; | |||
#define LEN_GROUP_NAME 12 | |||
@@ -161,7 +163,7 @@ typedef struct { | |||
int isspace2(unsigned int c) | |||
{ | |||
// can't use isspace() because on Windows, isspace(0xe1) gives TRUE ! | |||
// can't use isspace() because on Windows, isspace(0xe1) gives TRUE ! | |||
int c2; | |||
if (((c2 = (c & 0xff)) == 0) || (c > ' ')) | |||
@@ -171,7 +173,7 @@ int isspace2(unsigned int c) | |||
static FILE *fopen_log(const char *fname, const char *access) | |||
{ | |||
// performs fopen, but produces error message to f_log if it fails | |||
// performs fopen, but produces error message to f_log if it fails | |||
FILE *f; | |||
if ((f = fopen(fname, access)) == NULL) { | |||
@@ -181,7 +183,7 @@ static FILE *fopen_log(const char *fname, const char *access) | |||
return f; | |||
} | |||
/* Lookup a mnemonic string in a table, return its name */ | |||
// Lookup a mnemonic string in a table, return its name | |||
const char *LookupMnemName(MNEM_TAB *table, const int value) | |||
{ | |||
while (table->mnem != NULL) { | |||
@@ -189,7 +191,7 @@ const char *LookupMnemName(MNEM_TAB *table, const int value) | |||
return table->mnem; | |||
table++; | |||
} | |||
return ""; /* not found */ | |||
return ""; // not found | |||
} | |||
void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len) | |||
@@ -222,7 +224,7 @@ 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) | |||
{ | |||
/* Convert compiled match template to ascii */ | |||
// Convert compiled match template to ascii | |||
unsigned char rb; | |||
unsigned char c; | |||
@@ -243,9 +245,12 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
char suffix[20]; | |||
static char output[80]; | |||
static char symbols[] = | |||
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', | |||
'&', '%', '+', '#', 'S', 'D', 'Z', 'A', 'L', '!', ' ', '@', '?', 'J', 'N', 'K', 'V', '?', 'T', 'X', '?', 'W' }; | |||
static char symbols[] = { | |||
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', | |||
'&', '%', '+', '#', 'S', 'D', 'Z', 'A', 'L', '!', | |||
' ', '@', '?', 'J', 'N', 'K', 'V', '?', 'T', 'X', | |||
'?', 'W' | |||
}; | |||
static char symbols_lg[] = { 'A', 'B', 'C', 'H', 'F', 'G', 'Y' }; | |||
@@ -268,7 +273,8 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
finished = 1; | |||
break; | |||
case RULE_PRE_ATSTART: | |||
at_start = 1; // drop through to next case | |||
at_start = 1; | |||
// fallthrough: | |||
case RULE_PRE: | |||
match_type = RULE_PRE; | |||
*p = 0; | |||
@@ -283,7 +289,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
case RULE_PH_COMMON: | |||
break; | |||
case RULE_CONDITION: | |||
/* conditional rule, next byte gives condition number */ | |||
// conditional rule, next byte gives condition number | |||
condition_num = *rule++; | |||
break; | |||
case RULE_LINENUM: | |||
@@ -365,7 +371,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
} | |||
*p = 0; | |||
buf[p_end - p] = 0; // prevent overflow in output[] | |||
buf[p_end - p] = 0; // prevent overflow in output[] | |||
strcat(p, buf); | |||
ix = strlen(output); | |||
while (ix < 8) | |||
@@ -376,7 +382,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
{ | |||
// Compile a line in the language_list file | |||
// Compile a line in the language_list file | |||
unsigned char c; | |||
char *p; | |||
char *word; | |||
@@ -394,7 +400,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
int len_word; | |||
int len_phonetic; | |||
int text_not_phonemes; // this word specifies replacement text, not phonemes | |||
int text_not_phonemes; // this word specifies replacement text, not phonemes | |||
unsigned int wc; | |||
int all_upper_case; | |||
@@ -441,7 +447,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
} | |||
if ((c == '$') && isalnum(p[1])) { | |||
/* read keyword parameter */ | |||
// read keyword parameter | |||
mnemptr = p; | |||
while (!isspace2(c = *p)) p++; | |||
*p = 0; | |||
@@ -462,9 +468,8 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
} | |||
} | |||
if ((c == '/') && (p[1] == '/') && (multiple_words == 0)) { | |||
c = '\n'; /* "//" treat comment as end of line */ | |||
} | |||
if ((c == '/') && (p[1] == '/') && (multiple_words == 0)) | |||
c = '\n'; // "//" treat comment as end of line | |||
switch (step) | |||
{ | |||
@@ -486,7 +491,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
c = ' '; | |||
} | |||
if (isspace2(c)) { | |||
p[0] = 0; /* terminate english word */ | |||
p[0] = 0; // terminate english word | |||
if (multiple_words) { | |||
multiple_string = multiple_string_end = p+1; | |||
@@ -509,7 +514,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
if (isspace2(c)) | |||
multiple_words++; | |||
else if (c == ')') { | |||
p[0] = ' '; // terminate extra string | |||
p[0] = ' '; // terminate extra string | |||
multiple_string_end = p+1; | |||
step = 3; | |||
} | |||
@@ -522,7 +527,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
break; | |||
case 4: | |||
if (isspace2(c)) { | |||
p[0] = 0; /* terminate phonetic */ | |||
p[0] = 0; // terminate phonetic | |||
step = 5; | |||
} | |||
break; | |||
@@ -533,7 +538,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
} | |||
if (word[0] == 0) | |||
return 0; /* blank line */ | |||
return 0; // blank line | |||
if (text_mode) | |||
text_not_phonemes = 1; | |||
@@ -541,7 +546,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
if (text_not_phonemes) { | |||
if (word[0] == '_') { | |||
// This is a special word, used by eSpeak. Translate this into phonemes now | |||
strcat(phonetic, " "); // need a space to indicate word-boundary | |||
strcat(phonetic, " "); // need a space to indicate word-boundary | |||
// PROBLEM vowel reductions are not applied to the translated phonemes | |||
// condition rules are not applied | |||
@@ -574,7 +579,6 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
if (text_not_phonemes != translator->langopts.textmode) | |||
flag_codes[n_flag_codes++] = BITNUM_FLAG_TEXTMODE; | |||
if (sscanf(word, "U+%x", &wc) == 1) { | |||
// Character code | |||
ix = utf8_out(wc, word); | |||
@@ -609,7 +613,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
*hash = HashDictionary(word); | |||
len_phonetic = strlen(encoded_ph); | |||
dict_line[1] = len_word; // bit 6 indicates whether the word has been compressed | |||
dict_line[1] = len_word; // bit 6 indicates whether the word has been compressed | |||
len_word &= 0x3f; | |||
memcpy(&dict_line[2], word, len_word); | |||
@@ -647,7 +651,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
static void compile_dictlist_start(void) | |||
{ | |||
// initialise dictionary list | |||
// initialise dictionary list | |||
int ix; | |||
char *p; | |||
char *p2; | |||
@@ -666,7 +670,7 @@ static void compile_dictlist_start(void) | |||
static void compile_dictlist_end(FILE *f_out) | |||
{ | |||
// Write out the compiled dictionary list | |||
// Write out the compiled dictionary list | |||
int hash; | |||
int length; | |||
char *p; | |||
@@ -725,7 +729,7 @@ static int compile_dictlist_file(const char *path, const char *filename) | |||
linenum++; | |||
length = compile_line(buf, dict_line, &hash); | |||
if (length == 0) continue; /* blank line */ | |||
if (length == 0) continue; // blank line | |||
hash_counts[hash]++; | |||
@@ -758,7 +762,7 @@ static char rule_phonemes[80]; | |||
static char group_name[LEN_GROUP_NAME+1]; | |||
static int group3_ix; | |||
#define N_RULES 3000 // max rules for each group | |||
#define N_RULES 3000 // max rules for each group | |||
int isHexDigit(int c) | |||
{ | |||
@@ -773,7 +777,7 @@ int isHexDigit(int c) | |||
static void copy_rule_string(char *string, int *state_out) | |||
{ | |||
// state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes | |||
// state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes | |||
static char *outbuf[5] = { rule_cond, rule_pre, rule_match, rule_post, rule_phonemes }; | |||
static int next_state[5] = { 2, 2, 4, 4, 4 }; | |||
char *output; | |||
@@ -799,7 +803,7 @@ static void copy_rule_string(char *string, int *state_out) | |||
rule_phonemes[len++] = ' '; | |||
output = &rule_phonemes[len]; | |||
} | |||
sxflags = 0x808000; // to ensure non-zero bytes | |||
sxflags = 0x808000; // to ensure non-zero bytes | |||
for (p = string, ix = 0;;) { | |||
literal = 0; | |||
@@ -810,7 +814,7 @@ static void copy_rule_string(char *string, int *state_out) | |||
p += 2; | |||
} | |||
if (c == '\\') { | |||
c = *p++; // treat next character literally | |||
c = *p++; // treat next character literally | |||
if ((c >= '0') && (c <= '3') && (p[0] >= '0') && (p[0] <= '7') && (p[1] >= '0') && (p[1] <= '7')) { | |||
// character code given by 3 digit octal value; | |||
c = (c-'0')*64 + (p[0]-'0')*8 + (p[1]-'0'); | |||
@@ -837,8 +841,9 @@ static void copy_rule_string(char *string, int *state_out) | |||
break; | |||
case 'Y': | |||
c = 'I'; // drop through to next case | |||
case 'A': // vowel | |||
c = 'I'; | |||
// fallthrough: | |||
case 'A': // vowel | |||
case 'B': | |||
case 'C': | |||
case 'H': | |||
@@ -947,10 +952,10 @@ static void copy_rule_string(char *string, int *state_out) | |||
error_count++; | |||
} | |||
break; | |||
case 'P': | |||
sxflags |= SUFX_P; // Prefix, now drop through to Suffix | |||
case 'P': // Prefix | |||
sxflags |= SUFX_P; | |||
// fallthrough | |||
case 'S': | |||
case 'S': // Suffix | |||
output[ix++] = RULE_ENDING; | |||
value = 0; | |||
while (!isspace2(c = *p++) && (c != 0)) { | |||
@@ -962,7 +967,7 @@ static void copy_rule_string(char *string, int *state_out) | |||
case 'i': | |||
sxflags |= SUFX_I; | |||
break; | |||
case 'p': // obsolete, replaced by 'P' above | |||
case 'p': // obsolete, replaced by 'P' above | |||
sxflags |= SUFX_P; | |||
break; | |||
case 'v': | |||
@@ -1041,13 +1046,13 @@ static char *compile_rule(char *input) | |||
switch (c = input[ix]) | |||
{ | |||
case ')': // end of prefix section | |||
case ')': // end of prefix section | |||
*p = 0; | |||
state = 1; | |||
copy_rule_string(buf, &state); | |||
p = buf; | |||
break; | |||
case '(': // start of suffix section | |||
case '(': // start of suffix section | |||
*p = 0; | |||
state = 2; | |||
copy_rule_string(buf, &state); | |||
@@ -1058,14 +1063,14 @@ static char *compile_rule(char *input) | |||
error_count++; | |||
} | |||
break; | |||
case '\n': // end of line | |||
case '\n': // end of line | |||
case '\r': | |||
case 0: // end of line | |||
case 0: // end of line | |||
*p = 0; | |||
copy_rule_string(buf, &state); | |||
finish = 1; | |||
break; | |||
case '\t': // end of section section | |||
case '\t': // end of section section | |||
case ' ': | |||
*p = 0; | |||
copy_rule_string(buf, &state); | |||
@@ -1180,7 +1185,7 @@ int __cdecl string_sorter(char **a, char **b) | |||
static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b) | |||
{ | |||
// Sort long names before short names | |||
// Sort long names before short names | |||
int ix; | |||
ix = strlen(b->name) - strlen(a->name); | |||
if (ix != 0) return ix; | |||
@@ -1314,23 +1319,23 @@ static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name | |||
qsort((void *)rules, n_rules, sizeof(char *), (int(__cdecl *)(const void *, const void *))string_sorter); | |||
if (strcmp(name, "9") == 0) | |||
len_name = 0; // don't remove characters from numeric match strings | |||
len_name = 0; // don't remove characters from numeric match strings | |||
for (ix = 0; ix < n_rules; ix++) { | |||
p = rules[ix]; | |||
len1 = strlen(p) + 1; // phoneme string | |||
len1 = strlen(p) + 1; // phoneme string | |||
p3 = &p[len1]; | |||
p2 = p3 + len_name; // remove group name from start of match string | |||
p2 = p3 + len_name; // remove group name from start of match string | |||
len2 = strlen(p2); | |||
nextchar_count[(unsigned char)(p2[0])]++; // the next byte after the group name | |||
nextchar_count[(unsigned char)(p2[0])]++; // the next byte after the group name | |||
if ((common[0] != 0) && (strcmp(p, common) == 0)) { | |||
fwrite(p2, len2, 1, f_out); | |||
fputc(0, f_out); // no phoneme string, it's the same as previous rule | |||
fputc(0, f_out); // no phoneme string, it's the same as previous rule | |||
} else { | |||
if ((ix < n_rules-1) && (strcmp(p, rules[ix+1]) == 0)) { | |||
common = rules[ix]; // phoneme string is same as next, set as common | |||
common = rules[ix]; // phoneme string is same as next, set as common | |||
fputc(RULE_PH_COMMON, f_out); | |||
} | |||
@@ -1358,7 +1363,7 @@ static int compile_lettergroup(char *input, FILE *f_out) | |||
int length; | |||
int max_length = 0; | |||
#define N_LETTERGP_ITEMS 200 | |||
#define N_LETTERGP_ITEMS 200 | |||
char *items[N_LETTERGP_ITEMS]; | |||
char item_length[N_LETTERGP_ITEMS]; | |||
@@ -1395,7 +1400,7 @@ static int compile_lettergroup(char *input, FILE *f_out) | |||
items[n_items] = p_start = p; | |||
while ((*p & 0xff) > ' ') { | |||
if (*p == '_') *p = ' '; // allow '_' for word break | |||
if (*p == '_') *p = ' '; // allow '_' for word break | |||
p++; | |||
} | |||
*p++ = 0; | |||
@@ -1408,9 +1413,8 @@ static int compile_lettergroup(char *input, FILE *f_out) | |||
// write out the items, longest first | |||
while (max_length > 1) { | |||
for (ix = 0; ix < n_items; ix++) { | |||
if (item_length[ix] == max_length) { | |||
if (item_length[ix] == max_length) | |||
fwrite(items[ix], 1, max_length, f_out); | |||
} | |||
} | |||
max_length--; | |||
} | |||
@@ -1457,7 +1461,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
if ((p = (unsigned char *)strstr(buf, "//")) != NULL) | |||
*p = 0; | |||
if (buf[0] == '\r') buf++; // ignore extra \r in \r\n | |||
if (buf[0] == '\r') buf++; // ignore extra \r in \r\n | |||
} | |||
if ((buf == NULL) || (buf[0] == '.')) { | |||
@@ -1478,11 +1482,11 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
if (compile_mode == 2) { | |||
// end of the character replacements section | |||
fwrite(&n_rules, 1, 4, f_out); // write a zero word to terminate the replacemenmt list | |||
fwrite(&n_rules, 1, 4, f_out); // write a zero word to terminate the replacemenmt list | |||
compile_mode = 0; | |||
} | |||
if (buf == NULL) break; // end of file | |||
if (buf == NULL) break; // end of file | |||
if (memcmp(buf, ".L", 2) == 0) { | |||
compile_lettergroup(&buf[2], f_out); | |||
@@ -1503,7 +1507,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
compile_mode = 1; | |||
p = (unsigned char *)&buf[6]; | |||
while ((p[0] == ' ') || (p[0] == '\t')) p++; // Note: Windows isspace(0xe1) gives TRUE ! | |||
while ((p[0] == ' ') || (p[0] == '\t')) p++; // Note: Windows isspace(0xe1) gives TRUE ! | |||
ix = 0; | |||
while ((*p > ' ') && (ix < LEN_GROUP_NAME)) | |||
group_name[ix++] = *p++; | |||
@@ -1522,7 +1526,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
if (translator->letter_bits_offset > 0) { | |||
utf8_in(&wc, group_name); | |||
if (((ix = (wc - translator->letter_bits_offset)) >= 0) && (ix < 128)) | |||
group3_ix = ix+1; // not zero | |||
group3_ix = ix+1; // not zero | |||
} | |||
} | |||
@@ -1541,7 +1545,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
switch (compile_mode) | |||
{ | |||
case 1: // .group | |||
case 1: // .group | |||
prule = compile_rule(buf); | |||
if (prule != NULL) { | |||
if (n_rules < N_RULES) | |||
@@ -1556,7 +1560,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
} | |||
break; | |||
case 2: // .replace | |||
case 2: // .replace | |||
{ | |||
int replace1; | |||
int replace2; | |||
@@ -1580,11 +1584,11 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
ix += 16; | |||
} | |||
if (replace1 != 0) { | |||
Write4Bytes(f_out, replace1); // write as little-endian | |||
Write4Bytes(f_out, replace2); // if big-endian, reverse the bytes in LoadDictionary() | |||
Write4Bytes(f_out, replace1); // write as little-endian | |||
Write4Bytes(f_out, replace2); // if big-endian, reverse the bytes in LoadDictionary() | |||
} | |||
} | |||
break; | |||
break; | |||
} | |||
} | |||
fclose(f_temp); | |||
@@ -1631,8 +1635,8 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err, int flags) | |||
{ | |||
// fname: space to write the filename in case of error | |||
// flags: bit 0: include source line number information, for debug purposes. | |||
// fname: space to write the filename in case of error | |||
// flags: bit 0: include source line number information, for debug purposes. | |||
FILE *f_in; | |||
FILE *f_out; |
@@ -78,7 +78,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
char name2[40]; | |||
char mbrola_voice[40]; | |||
char buf[sizeof(path_home)+30]; | |||
int mbrola_ctrl = 20; // volume in 1/16 ths | |||
int mbrola_ctrl = 20; // volume in 1/16 ths | |||
MBROLA_TAB data[N_PHONEME_TAB]; | |||
strcpy(buf, filepath); | |||
@@ -91,7 +91,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
buf[sizeof(phoneme)-1] = 0; | |||
if ((p = strstr(buf, "//")) != NULL) | |||
*p = 0; // truncate line at comment | |||
*p = 0; // truncate line at comment | |||
if (memcmp(buf, "volume", 6) == 0) { | |||
mbrola_ctrl = atoi(&buf[6]); | |||
@@ -128,7 +128,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
return ENE_WRITE_ERROR; | |||
} | |||
data[count].name = 0; // list terminator | |||
data[count].name = 0; // list terminator | |||
Write4Bytes(f_out, mbrola_ctrl); | |||
pw_end = (int *)(&data[count+1]); |
@@ -89,8 +89,8 @@ typedef struct { | |||
typedef enum { | |||
CS_UNDEFINED, // The command has just been created | |||
CS_PENDING, // stored in the fifo | |||
CS_PROCESSED // processed | |||
CS_PENDING, // stored in the fifo | |||
CS_PROCESSED // processed | |||
} t_command_state; | |||
typedef struct { |
@@ -50,9 +50,11 @@ static bool thread_inited; | |||
static t_espeak_callback *my_callback = NULL; | |||
static int my_event_is_running = 0; | |||
enum { MIN_TIMEOUT_IN_MS = 10, | |||
ACTIVITY_TIMEOUT = 50, // in ms, check that the stream is active | |||
MAX_ACTIVITY_CHECK = 6 }; | |||
enum { | |||
MIN_TIMEOUT_IN_MS = 10, | |||
ACTIVITY_TIMEOUT = 50, // in ms, check that the stream is active | |||
MAX_ACTIVITY_CHECK = 6 | |||
}; | |||
typedef struct t_node { | |||
void *data; | |||
@@ -359,9 +361,9 @@ static int get_remaining_time(uint32_t sample, uint32_t *time_in_ms, int *stop_i | |||
for (i = 0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++) { | |||
err = wave_get_remaining_time(sample, time_in_ms); | |||
if (err || wave_is_busy(NULL) || (*time_in_ms == 0)) { // if err, stream not available: quit | |||
// if wave is busy, time_in_ms is known: quit | |||
// if wave is not busy but remaining time == 0, event is reached: quit | |||
if (err || // if err, stream not available: quit | |||
wave_is_busy(NULL) || // if wave is busy, time_in_ms is known: quit | |||
(*time_in_ms == 0)) { // if wave is not busy but remaining time == 0, event is reached: quit | |||
break; | |||
} | |||
@@ -412,20 +414,19 @@ static void *polling_thread(void *p) | |||
SHOW_TIME("polling_thread > unlocked\n"); | |||
a_stop_is_required = 0; | |||
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); // NOTE: may set a_stop_is_required to -1 | |||
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); // NOTE: may set a_stop_is_required to -1 | |||
if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
} | |||
; | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) | |||
; | |||
} else | |||
a_stop_is_required = 0; | |||
// In this loop, my_event_is_running = 1 | |||
while (head && (a_stop_is_required <= 0)) { | |||
SHOW_TIME("polling_thread > check head\n"); | |||
while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
} | |||
while (0 == sem_trywait(&my_sem_start_is_required)) | |||
; | |||
espeak_EVENT *event = (espeak_EVENT *)(head->data); | |||
assert(event); | |||
@@ -465,8 +466,8 @@ static void *polling_thread(void *p) | |||
if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
} | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) | |||
; | |||
} else | |||
a_stop_is_required = 0; | |||
} else // The event will be notified soon: sleep until timeout or stop request | |||
@@ -483,8 +484,8 @@ static void *polling_thread(void *p) | |||
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); | |||
if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
} | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) | |||
; | |||
} else | |||
a_stop_is_required = 0; | |||
} | |||
@@ -573,8 +574,8 @@ static void init() | |||
{ | |||
ENTER("event > init"); | |||
while (event_delete((espeak_EVENT *)pop())) { | |||
} | |||
while (event_delete((espeak_EVENT *)pop())) | |||
; | |||
node_counter = 0; | |||
} |
@@ -43,8 +43,6 @@ | |||
static pthread_mutex_t my_mutex; | |||
static int my_command_is_running = 0; | |||
static int my_stop_is_required = 0; | |||
// + fifo | |||
// | |||
// my_thread: reads commands from the fifo, and runs them. | |||
static pthread_t my_thread; | |||
@@ -57,9 +55,12 @@ static espeak_ERROR push(t_espeak_command *the_command); | |||
static t_espeak_command *pop(); | |||
static void init(int process_parameters); | |||
static int node_counter = 0; | |||
enum { MAX_NODE_COUNTER = 400, | |||
INACTIVITY_TIMEOUT = 50, // in ms, check that the stream is inactive | |||
MAX_INACTIVITY_CHECK = 2 }; | |||
enum { | |||
MAX_NODE_COUNTER = 400, | |||
INACTIVITY_TIMEOUT = 50, // in ms, check that the stream is inactive | |||
MAX_INACTIVITY_CHECK = 2 | |||
}; | |||
void fifo_init() | |||
{ | |||
@@ -338,8 +339,8 @@ static void *say_thread(void *p) | |||
display_espeak_command(a_command); | |||
// purge start semaphore | |||
SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); | |||
while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
} | |||
while (0 == sem_trywait(&my_sem_start_is_required)) | |||
; | |||
if (my_stop_is_required) { | |||
SHOW_TIME("say_thread > my_command_is_running = 0\n"); | |||
@@ -361,8 +362,8 @@ static void *say_thread(void *p) | |||
// purge start semaphore | |||
SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); | |||
while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
} | |||
while (0 == sem_trywait(&my_sem_start_is_required)) | |||
; | |||
// acknowledge the stop request | |||
SHOW_TIME("say_thread > post my_sem_stop_is_acknowledged\n"); |
@@ -46,7 +46,7 @@ | |||
typedef struct { | |||
char stress; | |||
char env; | |||
char flags; // bit 0=pitch rising, bit1=emnphasized, bit2=end of clause | |||
char flags; // bit 0=pitch rising, bit1=emnphasized, bit2=end of clause | |||
char nextph_type; | |||
unsigned char pitch1; | |||
unsigned char pitch2; | |||
@@ -54,18 +54,17 @@ typedef struct { | |||
static SYLLABLE *syllable_tab; | |||
static int tone_pitch_env; /* used to return pitch envelope */ | |||
static int tone_pitch_env; // used to return pitch envelope | |||
/* Pitch data for tone types */ | |||
/*****************************/ | |||
#define PITCHfall 0 | |||
#define PITCHrise 2 | |||
#define PITCHfrise 4 // and 3 must be for the variant preceded by 'r' | |||
#define PITCHfrise2 6 // and 5 must be the 'r' variant | |||
#define PITCHrisefall 8 | |||
#define PITCHfall 0 | |||
#define PITCHrise 2 | |||
#define PITCHfrise 4 // and 3 must be for the variant preceded by 'r' | |||
#define PITCHfrise2 6 // and 5 must be the 'r' variant | |||
#define PITCHrisefall 8 | |||
/* 0 fall */ | |||
unsigned char env_fall[128] = { | |||
0xff, 0xfd, 0xfa, 0xf8, 0xf6, 0xf4, 0xf2, 0xf0, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, | |||
0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xd0, 0xce, 0xcc, 0xca, 0xc8, 0xc6, 0xc4, 0xc2, 0xc0, | |||
@@ -77,7 +76,6 @@ unsigned char env_fall[128] = { | |||
0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0e, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x00 | |||
}; | |||
/* 1 rise */ | |||
unsigned char env_rise[128] = { | |||
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, | |||
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, | |||
@@ -213,7 +211,7 @@ unsigned char *envelope_data[N_ENVELOPE_DATA] = { | |||
env_risefallrise, env_risefallrise | |||
}; | |||
/* indexed by stress */ | |||
// indexed by stress | |||
static int min_drop[] = { 6, 7, 9, 9, 20, 20, 20, 25 }; | |||
// pitch change during the main part of the clause | |||
@@ -224,8 +222,8 @@ static signed char oflow[] = { 0, 40, 24, 8, 0 }; | |||
static signed char oflow_emf[] = { 10, 52, 32, 20, 10 }; | |||
static signed char oflow_less[] = { 6, 38, 24, 14, 4 }; | |||
#define N_TONE_HEAD_TABLE 13 | |||
#define N_TONE_NUCLEUS_TABLE 13 | |||
#define N_TONE_HEAD_TABLE 13 | |||
#define N_TONE_NUCLEUS_TABLE 13 | |||
typedef struct { | |||
unsigned char pre_start; | |||
@@ -243,11 +241,11 @@ typedef struct { | |||
} TONE_HEAD; | |||
typedef struct { | |||
unsigned char pitch_env0; /* pitch envelope, tonic syllable at end */ | |||
unsigned char pitch_env0; // pitch envelope, tonic syllable at end | |||
unsigned char tonic_max0; | |||
unsigned char tonic_min0; | |||
unsigned char pitch_env1; /* followed by unstressed */ | |||
unsigned char pitch_env1; // followed by unstressed | |||
unsigned char tonic_max1; | |||
unsigned char tonic_min1; | |||
@@ -261,57 +259,56 @@ typedef struct { | |||
#define T_EMPH 1 | |||
static TONE_HEAD tone_head_table[N_TONE_HEAD_TABLE] = { | |||
{ 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 0 statement | |||
{ 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 1 comma | |||
{ 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 2 question | |||
{ 46, 57, 90, 50, drops_0, 3, 9, 5, oflow_emf }, // 3 exclamation | |||
{ 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 4 statement, emphatic | |||
{ 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less },// 5 statement, less intonation | |||
{ 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less },// 6 comma, less intonation | |||
{ 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less },// 7 comma, less intonation, less rise | |||
{ 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 8 pitch raises at end of sentence | |||
{ 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 9 comma | |||
{ 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 10 question | |||
{ 34, 41, 41, 32, drops_0, 3, 7, 5, oflow_less }, // 11 test | |||
{ 46, 57, 55, 50, drops_0, 3, 7, 5, oflow_less }, // 12 test | |||
{ 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 0 statement | |||
{ 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 1 comma | |||
{ 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 2 question | |||
{ 46, 57, 90, 50, drops_0, 3, 9, 5, oflow_emf }, // 3 exclamation | |||
{ 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 4 statement, emphatic | |||
{ 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less }, // 5 statement, less intonation | |||
{ 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less }, // 6 comma, less intonation | |||
{ 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less }, // 7 comma, less intonation, less rise | |||
{ 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 8 pitch raises at end of sentence | |||
{ 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 9 comma | |||
{ 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 10 question | |||
{ 34, 41, 41, 32, drops_0, 3, 7, 5, oflow_less }, // 11 test | |||
{ 46, 57, 55, 50, drops_0, 3, 7, 5, oflow_less }, // 12 test | |||
}; | |||
static TONE_NUCLEUS tone_nucleus_table[N_TONE_NUCLEUS_TABLE] = { | |||
{ PITCHfall, 64, 8, PITCHfall, 70, 18, NULL, 24, 12, 0 }, // 0 statement | |||
{ PITCHfrise, 80, 18, PITCHfrise2, 78, 22, NULL, 34, 52, 0 }, // 1 comma | |||
{ PITCHfrise, 88, 22, PITCHfrise2, 82, 22, NULL, 34, 64, 0 }, // 2 question | |||
{ PITCHfall, 92, 8, PITCHfall, 92, 80, NULL, 76, 8, T_EMPH }, // 3 exclamation | |||
{ PITCHfall, 86, 4, PITCHfall, 94, 66, NULL, 34, 10, 0 }, // 4 statement, emphatic | |||
{ PITCHfall, 62, 10, PITCHfall, 62, 20, NULL, 28, 16, 0 }, // 5 statement, less intonation | |||
{ PITCHfrise, 68, 18, PITCHfrise2, 68, 22, NULL, 30, 44, 0 }, // 6 comma, less intonation | |||
{ PITCHfrise2, 64, 16, PITCHfall, 66, 32, NULL, 32, 18, 0 }, // 7 comma, less intonation, less rise | |||
{ PITCHrise, 68, 46, PITCHfall, 42, 32, NULL, 46, 58, 0 }, // 8 pitch raises at end of sentence | |||
{ PITCHfrise, 78, 24, PITCHfrise2, 72, 22, NULL, 42, 52, 0 }, // 9 comma | |||
{ PITCHfrise, 88, 34, PITCHfall, 64, 32, NULL, 46, 82, 0 }, // 10 question | |||
{ PITCHfall, 56, 12, PITCHfall, 56, 20, NULL, 24, 12, 0 }, // 11 test | |||
{ PITCHfall, 70, 18, PITCHfall, 70, 24, NULL, 32, 20, 0 }, // 12 test | |||
{ PITCHfall, 64, 8, PITCHfall, 70, 18, NULL, 24, 12, 0 }, // 0 statement | |||
{ PITCHfrise, 80, 18, PITCHfrise2, 78, 22, NULL, 34, 52, 0 }, // 1 comma | |||
{ PITCHfrise, 88, 22, PITCHfrise2, 82, 22, NULL, 34, 64, 0 }, // 2 question | |||
{ PITCHfall, 92, 8, PITCHfall, 92, 80, NULL, 76, 8, T_EMPH }, // 3 exclamation | |||
{ PITCHfall, 86, 4, PITCHfall, 94, 66, NULL, 34, 10, 0 }, // 4 statement, emphatic | |||
{ PITCHfall, 62, 10, PITCHfall, 62, 20, NULL, 28, 16, 0 }, // 5 statement, less intonation | |||
{ PITCHfrise, 68, 18, PITCHfrise2, 68, 22, NULL, 30, 44, 0 }, // 6 comma, less intonation | |||
{ PITCHfrise2, 64, 16, PITCHfall, 66, 32, NULL, 32, 18, 0 }, // 7 comma, less intonation, less rise | |||
{ PITCHrise, 68, 46, PITCHfall, 42, 32, NULL, 46, 58, 0 }, // 8 pitch raises at end of sentence | |||
{ PITCHfrise, 78, 24, PITCHfrise2, 72, 22, NULL, 42, 52, 0 }, // 9 comma | |||
{ PITCHfrise, 88, 34, PITCHfall, 64, 32, NULL, 46, 82, 0 }, // 10 question | |||
{ PITCHfall, 56, 12, PITCHfall, 56, 20, NULL, 24, 12, 0 }, // 11 test | |||
{ PITCHfall, 70, 18, PITCHfall, 70, 24, NULL, 32, 20, 0 }, // 12 test | |||
}; | |||
/* index by 0=. 1=, 2=?, 3=! 4=none, 5=emphasized */ | |||
// index by 0=. 1=, 2=?, 3=! 4=none, 5=emphasized | |||
unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS] = { | |||
{ 0, 1, 2, 3, 0, 4 }, | |||
{ 0, 1, 2, 3, 0, 4 }, | |||
{ 5, 6, 2, 3, 0, 4 }, | |||
{ 5, 7, 1, 3, 0, 4 }, | |||
{ 8, 9, 10, 3, 0, 0 }, | |||
{ 8, 8, 10, 3, 0, 0 }, | |||
{ 11, 11, 11, 11, 0, 0 }, // 6 test | |||
{ 0, 1, 2, 3, 0, 4 }, | |||
{ 0, 1, 2, 3, 0, 4 }, | |||
{ 5, 6, 2, 3, 0, 4 }, | |||
{ 5, 7, 1, 3, 0, 4 }, | |||
{ 8, 9, 10, 3, 0, 0 }, | |||
{ 8, 8, 10, 3, 0, 0 }, | |||
{ 11, 11, 11, 11, 0, 0 }, // 6 test | |||
{ 12, 12, 12, 12, 0, 0 } | |||
}; | |||
int n_tunes = 0; | |||
TUNE *tunes = NULL; | |||
#define SECONDARY 3 | |||
#define PRIMARY 4 | |||
#define SECONDARY 3 | |||
#define PRIMARY 4 | |||
#define PRIMARY_STRESSED 6 | |||
#define PRIMARY_LAST 7 | |||
#define PRIMARY_LAST 7 | |||
static int number_pre; | |||
static int number_body; | |||
@@ -326,16 +323,16 @@ static void count_pitch_vowels(int start, int end, int clause_end) | |||
int ix; | |||
int stress; | |||
int max_stress = 0; | |||
int max_stress_posn = 0; // last syllable ot the highest stress | |||
int max_stress_posn2 = 0; // penuntimate syllable of the highest stress | |||
int max_stress_posn = 0; // last syllable ot the highest stress | |||
int max_stress_posn2 = 0; // penuntimate syllable of the highest stress | |||
number_pre = -1; /* number of vowels before 1st primary stress */ | |||
number_pre = -1; // number of vowels before 1st primary stress | |||
number_body = 0; | |||
number_tail = 0; /* number between tonic syllable and next primary */ | |||
number_tail = 0; // number between tonic syllable and next primary | |||
last_primary = -1; | |||
for (ix = start; ix < end; ix++) { | |||
stress = syllable_tab[ix].stress; /* marked stress level */ | |||
stress = syllable_tab[ix].stress; // marked stress level | |||
if (stress >= max_stress) { | |||
if (stress > max_stress) | |||
@@ -360,9 +357,9 @@ static void count_pitch_vowels(int start, int end, int clause_end) | |||
tone_posn = max_stress_posn; | |||
tone_posn2 = max_stress_posn2; | |||
if (no_tonic) { | |||
tone_posn = tone_posn2 = end; // next position after the end of the truncated clause | |||
} else if (last_primary >= 0) { | |||
if (no_tonic) | |||
tone_posn = tone_posn2 = end; // next position after the end of the truncated clause | |||
else if (last_primary >= 0) { | |||
if (end == clause_end) | |||
syllable_tab[last_primary].stress = PRIMARY_LAST; | |||
} else { | |||
@@ -371,7 +368,7 @@ static void count_pitch_vowels(int start, int end, int clause_end) | |||
} | |||
} | |||
/* Count number of primary stresses up to tonic syllable or body_reset */ | |||
// Count number of primary stresses up to tonic syllable or body_reset | |||
static int count_increments(int ix, int end_ix, int min_stress) | |||
{ | |||
int count = 0; | |||
@@ -434,7 +431,7 @@ static int SetHeadIntonation(TUNE *tune, int syl_ix, int end_ix, int control) | |||
int pitch = 0; | |||
int increment = 0; | |||
int n_steps = 0; | |||
int stage; // onset, head, last | |||
int stage; // onset, head, last | |||
int initial; | |||
int overflow_ix = 0; | |||
int pitch_range; | |||
@@ -445,16 +442,16 @@ static int SetHeadIntonation(TUNE *tune, int syl_ix, int end_ix, int control) | |||
int unstressed_inc; | |||
int used_onset = 0; | |||
int head_final = end_ix; | |||
int secondary = 2; // 2 | |||
int secondary = 2; | |||
pitch_range = (tune->head_end - tune->head_start) << 8; | |||
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; | |||
stage = 0; | |||
if (tune->onset == 255) | |||
stage = 1; // no onset specified | |||
stage = 1; // no onset specified | |||
if (tune->head_last != 255) { | |||
// find the last primary stress in the body | |||
@@ -624,7 +621,7 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t | |||
} else if (stress >= SECONDARY) | |||
set_pitch(syl, (pitch >> 8), drops[stress]); | |||
else { | |||
/* unstressed, drop pitch if preceded by PRIMARY */ | |||
// unstressed, drop pitch if preceded by PRIMARY | |||
if ((syllable_tab[ix-1].stress & 0x3f) >= SECONDARY) | |||
set_pitch(syl, (pitch >> 8) - th->body_lower_u, drops[stress]); | |||
else | |||
@@ -638,8 +635,8 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t | |||
static void SetPitchGradient(int start_ix, int end_ix, int start_pitch, int end_pitch) | |||
{ | |||
// Set a linear pitch change over a number of syllables. | |||
// Used for pre-head, unstressed syllables in the body, and the tail | |||
// Set a linear pitch change over a number of syllables. | |||
// Used for pre-head, unstressed syllables in the body, and the tail | |||
int ix; | |||
int stress; | |||
@@ -691,24 +688,21 @@ static int calc_pitches2(int start, int end, int tune_number) | |||
tune = &tunes[tune_number]; | |||
ix = start; | |||
/* vowels before the first primary stress */ | |||
/******************************************/ | |||
// vowels before the first primary stress | |||
SetPitchGradient(ix, ix+number_pre, tune->prehead_start, tune->prehead_end); | |||
ix += number_pre; | |||
/* body of tonic segment */ | |||
/*************************/ | |||
// body of tonic segment | |||
if (option_tone_flags & OPTION_EMPHASIZE_PENULTIMATE) | |||
tone_posn = tone_posn2; // put tone on the penultimate stressed word | |||
tone_posn = tone_posn2; // put tone on the penultimate stressed word | |||
ix = SetHeadIntonation(tune, ix, tone_posn, 0); | |||
if (no_tonic) | |||
return 0; | |||
/* tonic syllable */ | |||
/******************/ | |||
// tonic syllable | |||
if (number_tail == 0) { | |||
tone_pitch_env = tune->nucleus0_env; | |||
@@ -724,8 +718,7 @@ static int calc_pitches2(int start, int end, int tune_number) | |||
if (syllable_tab[tone_posn].stress == PRIMARY) | |||
syllable_tab[tone_posn].stress = PRIMARY_STRESSED; | |||
/* tail, after the tonic syllable */ | |||
/**********************************/ | |||
// tail, after the tonic syllable | |||
SetPitchGradient(ix, end, tune->tail_start, tune->tail_end); | |||
@@ -751,28 +744,24 @@ static int calc_pitches(int control, int start, int end, int tune_number) | |||
tn = &tone_nucleus_table[tune_number]; | |||
ix = start; | |||
/* vowels before the first primary stress */ | |||
/******************************************/ | |||
// vowels before the first primary stress | |||
SetPitchGradient(ix, ix+number_pre, th->pre_start, th->pre_end); | |||
ix += number_pre; | |||
/* body of tonic segment */ | |||
/*************************/ | |||
// body of tonic segment | |||
if (option_tone_flags & OPTION_EMPHASIZE_PENULTIMATE) | |||
tone_posn = tone_posn2; // put tone on the penultimate stressed word | |||
tone_posn = tone_posn2; // put tone on the penultimate stressed word | |||
ix = calc_pitch_segment(ix, tone_posn, th, tn, PRIMARY, continuing); | |||
if (no_tonic) | |||
return 0; | |||
/* tonic syllable */ | |||
/******************/ | |||
// tonic syllable | |||
if (tn->flags & T_EMPH) { | |||
if (tn->flags & T_EMPH) | |||
syllable_tab[ix].flags |= SYL_EMPHASIS; | |||
} | |||
if (number_tail == 0) { | |||
tone_pitch_env = tn->pitch_env0; | |||
@@ -788,8 +777,7 @@ static int calc_pitches(int control, int start, int end, int tune_number) | |||
if (syllable_tab[tone_posn].stress == PRIMARY) | |||
syllable_tab[tone_posn].stress = PRIMARY_STRESSED; | |||
/* tail, after the tonic syllable */ | |||
/**********************************/ | |||
// tail, after the tonic syllable | |||
SetPitchGradient(ix, end, tn->tail_start, tn->tail_end); | |||
@@ -798,7 +786,8 @@ static int calc_pitches(int control, int start, int end, int tune_number) | |||
static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
{ | |||
// clause_tone: 0=. 1=, 2=?, 3=! 4=none | |||
// clause_tone: 0=. 1=, 2=?, 3=! 4=none | |||
PHONEME_LIST *p; | |||
int ix; | |||
int count_stressed = 0; | |||
@@ -808,14 +797,14 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
int pause; | |||
int tone_promoted; | |||
PHONEME_TAB *tph; | |||
PHONEME_TAB *prev_tph; // forget across word boundary | |||
PHONEME_TAB *prevw_tph; // remember across word boundary | |||
PHONEME_TAB *prev_tph; // forget across word boundary | |||
PHONEME_TAB *prevw_tph; // remember across word boundary | |||
PHONEME_LIST *prev_p; | |||
int pitch_adjust = 0; // pitch gradient through the clause - inital value | |||
int pitch_decrement = 0; // decrease by this for each stressed syllable | |||
int pitch_low = 0; // until it drops to this | |||
int pitch_high = 0; // then reset to this | |||
int pitch_adjust = 0; // pitch gradient through the clause - inital value | |||
int pitch_decrement = 0; // decrease by this for each stressed syllable | |||
int pitch_low = 0; // until it drops to this | |||
int pitch_high = 0; // then reset to this | |||
// count number of stressed syllables | |||
p = &phoneme_list[0]; | |||
@@ -838,7 +827,7 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
// LANG=vi | |||
p = &phoneme_list[final_stressed]; | |||
if (p->tone_ph == 0) | |||
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; | |||
@@ -850,12 +839,12 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
// perform tone sandhi | |||
for (ix = 0; ix < n_phoneme_list; ix++, p++) { | |||
if ((p->type == phPAUSE) && (p->ph->std_length > 50)) { | |||
pause = 1; // there is a pause since the previous vowel | |||
prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone | |||
pause = 1; // there is a pause since the previous vowel | |||
prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone | |||
} | |||
if (p->newword) | |||
prev_tph = phoneme_tab[phonPAUSE]; // forget across word boundaries | |||
prev_tph = phoneme_tab[phonPAUSE]; // forget across word boundaries | |||
if (p->synthflags & SFLAG_SYLLABLE) { | |||
tone_ph = p->tone_ph; | |||
@@ -865,10 +854,10 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
if (tr->translator_name == L('z', 'h')) { | |||
if (tone_ph == 0) { | |||
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; | |||
} else | |||
tone_ph = PhonemeCode2('1', '1'); // default tone 5 | |||
tone_ph = PhonemeCode2('1', '1'); // default tone 5 | |||
p->tone_ph = tone_ph; | |||
tph = phoneme_tab[tone_ph]; | |||
@@ -883,12 +872,12 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
} | |||
if (prevw_tph->mnemonic == 0x343132) { // [214] | |||
if (tph->mnemonic == 0x343132) // [214] | |||
if (tph->mnemonic == 0x343132) // [214] | |||
prev_p->tone_ph = PhonemeCode2('3', '5'); | |||
else | |||
prev_p->tone_ph = PhonemeCode2('2', '1'); | |||
} | |||
if ((prev_tph->mnemonic == 0x3135) && (tph->mnemonic == 0x3135)) // [51] + [51] | |||
if ((prev_tph->mnemonic == 0x3135) && (tph->mnemonic == 0x3135)) // [51] + [51] | |||
prev_p->tone_ph = PhonemeCode2('5', '3'); | |||
if (tph->mnemonic == 0x3131) { // [11] Tone 5 | |||
@@ -901,7 +890,7 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
p->tone_ph = PhonemeCode2('4', '4'); | |||
// tone 5 is unstressed (shorter) | |||
p->stresslevel = 0; // diminished stress | |||
p->stresslevel = 0; // diminished stress | |||
} | |||
} | |||
@@ -929,7 +918,7 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
} | |||
if (tone_ph == 0) { | |||
tone_ph = phonDEFAULTTONE; // no tone specified, use default tone 1 | |||
tone_ph = phonDEFAULTTONE; // no tone specified, use default tone 1 | |||
p->tone_ph = tone_ph; | |||
} | |||
p->pitch1 = pitch_adjust + phoneme_tab[tone_ph]->start_type; | |||
@@ -940,7 +929,8 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
void CalcPitches(Translator *tr, int clause_type) | |||
{ | |||
// clause_type: 0=. 1=, 2=?, 3=! 4=none | |||
// clause_type: 0=. 1=, 2=?, 3=! 4=none | |||
PHONEME_LIST *p; | |||
SYLLABLE *syl; | |||
int ix; | |||
@@ -961,7 +951,7 @@ void CalcPitches(Translator *tr, int clause_type) | |||
SYLLABLE syllable_tab2[N_PHONEME_LIST]; | |||
syllable_tab = syllable_tab2; // don't use permanent storage. it's only needed during the call of CalcPitches() | |||
syllable_tab = syllable_tab2; // don't use permanent storage. it's only needed during the call of CalcPitches() | |||
n_st = 0; | |||
n_primary = 0; | |||
for (ix = 0; ix < (n_phoneme_list-1); ix++) { | |||
@@ -977,10 +967,10 @@ void CalcPitches(Translator *tr, int clause_type) | |||
} else if ((p->ph->code == phonPAUSE_CLAUSE) && (n_st > 0)) | |||
syllable_tab[n_st-1].flags |= SYL_END_CLAUSE; | |||
} | |||
syllable_tab[n_st].stress = 0; // extra 0 entry at the end | |||
syllable_tab[n_st].stress = 0; // extra 0 entry at the end | |||
if (n_st == 0) | |||
return; // nothing to do | |||
return; // nothing to do | |||
if (tr->langopts.tone_language == 1) { | |||
CalcPitches_Tone(tr, clause_type); | |||
@@ -996,11 +986,11 @@ void CalcPitches(Translator *tr, int clause_type) | |||
group_tone_comma = tr->langopts.tunes[1]; | |||
} else { | |||
group_tone = tr->punct_to_tone[option][clause_type]; | |||
group_tone_comma = tr->punct_to_tone[option][1]; // emphatic form of statement | |||
group_tone_comma = tr->punct_to_tone[option][1]; // emphatic form of statement | |||
} | |||
if (clause_type == 4) | |||
no_tonic = 1; /* incomplete clause, used for abbreviations such as Mr. Dr. Mrs. */ | |||
no_tonic = 1; // incomplete clause, used for abbreviations such as Mr. Dr. Mrs. | |||
else | |||
no_tonic = 0; | |||
@@ -1056,12 +1046,12 @@ void CalcPitches(Translator *tr, int clause_type) | |||
count_pitch_vowels(st_start, ix, n_st); | |||
if ((ix < n_st) || (clause_type == 0)) { | |||
calc_pitches(option, st_start, ix, group_tone); // split into > 1 tone groups | |||
calc_pitches(option, st_start, ix, group_tone); // split into > 1 tone groups | |||
if ((clause_type == 1) || (clause_type == 2)) | |||
group_tone = tr->langopts.tunes[1]; // , or ? remainder has comma-tone | |||
group_tone = tr->langopts.tunes[1]; // , or ? remainder has comma-tone | |||
else | |||
group_tone = tr->langopts.tunes[0]; // . or ! remainder has statement tone | |||
group_tone = tr->langopts.tunes[0]; // . or ! remainder has statement tone | |||
} else | |||
calc_pitches(option, st_start, ix, group_tone); | |||
@@ -1114,7 +1104,7 @@ void CalcPitches(Translator *tr, int clause_type) | |||
} | |||
if (syl->flags & SYL_EMPHASIS) | |||
p->stresslevel |= 8; // emphasized | |||
p->stresslevel |= 8; // emphasized | |||
st_ix++; | |||
} |
@@ -53,7 +53,7 @@ static int sample_count; | |||
#define getrandom(min, max) ((rand()%(long)(((max)+1)-(min)))+(min)) | |||
#endif | |||
/* function prototypes for functions private to this file */ | |||
// function prototypes for functions private to this file | |||
static void flutter(klatt_frame_ptr); | |||
static double sampled_source(int); | |||
@@ -71,50 +71,50 @@ static klatt_global_t kt_globals; | |||
#define NUMBER_OF_SAMPLES 100 | |||
static int scale_wav_tab[] = { 45, 38, 45, 45, 55 }; // scale output from different voicing sources | |||
static int scale_wav_tab[] = { 45, 38, 45, 45, 55 }; // scale output from different voicing sources | |||
// For testing, this can be overwritten in KlattInit() | |||
static short natural_samples2[256] = { | |||
2583, 2516, 2450, 2384, 2319, 2254, 2191, 2127, | |||
2067, 2005, 1946, 1890, 1832, 1779, 1726, 1675, | |||
1626, 1579, 1533, 1491, 1449, 1409, 1372, 1336, | |||
1302, 1271, 1239, 1211, 1184, 1158, 1134, 1111, | |||
1089, 1069, 1049, 1031, 1013, 996, 980, 965, | |||
950, 936, 921, 909, 895, 881, 869, 855, | |||
843, 830, 818, 804, 792, 779, 766, 754, | |||
740, 728, 715, 702, 689, 676, 663, 651, | |||
637, 626, 612, 601, 588, 576, 564, 552, | |||
540, 530, 517, 507, 496, 485, 475, 464, | |||
454, 443, 434, 424, 414, 404, 394, 385, | |||
375, 366, 355, 347, 336, 328, 317, 308, | |||
299, 288, 280, 269, 260, 250, 240, 231, | |||
220, 212, 200, 192, 181, 172, 161, 152, | |||
142, 133, 123, 113, 105, 94, 86, 76, | |||
67, 57, 49, 39, 30, 22, 11, 4, | |||
-5, -14, -23, -32, -41, -50, -60, -69, | |||
-78, -87, -96, -107, -115, -126, -134, -144, | |||
-154, -164, -174, -183, -193, -203, -213, -222, | |||
-233, -242, -252, -262, -271, -281, -291, -301, | |||
-310, -320, -330, -339, -349, -357, -368, -377, | |||
-387, -397, -406, -417, -426, -436, -446, -456, | |||
-467, -477, -487, -499, -509, -521, -532, -543, | |||
-555, -567, -579, -591, -603, -616, -628, -641, | |||
-653, -666, -679, -692, -705, -717, -732, -743, | |||
-758, -769, -783, -795, -808, -820, -834, -845, | |||
-860, -872, -885, -898, -911, -926, -939, -955, | |||
-968, -986, -999, -1018, -1034, -1054, -1072, -1094, | |||
2583, 2516, 2450, 2384, 2319, 2254, 2191, 2127, | |||
2067, 2005, 1946, 1890, 1832, 1779, 1726, 1675, | |||
1626, 1579, 1533, 1491, 1449, 1409, 1372, 1336, | |||
1302, 1271, 1239, 1211, 1184, 1158, 1134, 1111, | |||
1089, 1069, 1049, 1031, 1013, 996, 980, 965, | |||
950, 936, 921, 909, 895, 881, 869, 855, | |||
843, 830, 818, 804, 792, 779, 766, 754, | |||
740, 728, 715, 702, 689, 676, 663, 651, | |||
637, 626, 612, 601, 588, 576, 564, 552, | |||
540, 530, 517, 507, 496, 485, 475, 464, | |||
454, 443, 434, 424, 414, 404, 394, 385, | |||
375, 366, 355, 347, 336, 328, 317, 308, | |||
299, 288, 280, 269, 260, 250, 240, 231, | |||
220, 212, 200, 192, 181, 172, 161, 152, | |||
142, 133, 123, 113, 105, 94, 86, 76, | |||
67, 57, 49, 39, 30, 22, 11, 4, | |||
-5, -14, -23, -32, -41, -50, -60, -69, | |||
-78, -87, -96, -107, -115, -126, -134, -144, | |||
-154, -164, -174, -183, -193, -203, -213, -222, | |||
-233, -242, -252, -262, -271, -281, -291, -301, | |||
-310, -320, -330, -339, -349, -357, -368, -377, | |||
-387, -397, -406, -417, -426, -436, -446, -456, | |||
-467, -477, -487, -499, -509, -521, -532, -543, | |||
-555, -567, -579, -591, -603, -616, -628, -641, | |||
-653, -666, -679, -692, -705, -717, -732, -743, | |||
-758, -769, -783, -795, -808, -820, -834, -845, | |||
-860, -872, -885, -898, -911, -926, -939, -955, | |||
-968, -986, -999, -1018, -1034, -1054, -1072, -1094, | |||
-1115, -1138, -1162, -1188, -1215, -1244, -1274, -1307, | |||
-1340, -1377, -1415, -1453, -1496, -1538, -1584, -1631, | |||
-1680, -1732, -1783, -1839, -1894, -1952, -2010, -2072, | |||
-2133, -2196, -2260, -2325, -2390, -2456, -2522, -2589, | |||
}; | |||
static short natural_samples[100] = { | |||
-310, -400, 530, 356, 224, 89, 23, -10, -58, -16, 461, 599, 536, 701, 770, | |||
605, 497, 461, 560, 404, 110, 224, 131, 104, -97, 155, 278, -154, -1165, | |||
-598, 737, 125, -592, 41, 11, -247, -10, 65, 92, 80, -304, 71, 167, -1, 122, | |||
233, 161, -43, 278, 479, 485, 407, 266, 650, 134, 80, 236, 68, 260, 269, 179, | |||
53, 140, 275, 293, 296, 104, 257, 152, 311, 182, 263, 245, 125, 314, 140, 44, | |||
203, 230, -235, -286, 23, 107, 92, -91, 38, 464, 443, 176, 98, -784, -2449, | |||
-310, -400, 530, 356, 224, 89, 23, -10, -58, -16, 461, 599, 536, 701, 770, | |||
605, 497, 461, 560, 404, 110, 224, 131, 104, -97, 155, 278, -154, -1165, | |||
-598, 737, 125, -592, 41, 11, -247, -10, 65, 92, 80, -304, 71, 167, -1, 122, | |||
233, 161, -43, 278, 479, 485, 407, 266, 650, 134, 80, 236, 68, 260, 269, 179, | |||
53, 140, 275, 293, 296, 104, 257, 152, 311, 182, 263, 245, 125, 314, 140, 44, | |||
203, 230, -235, -286, 23, 107, 92, -91, 38, 464, 443, 176, 98, -784, -2449, | |||
-1891, -1045, -1600, -1462, -1384, -1261, -949, -730 | |||
}; | |||
@@ -182,7 +182,7 @@ static void flutter(klatt_frame_ptr frame) | |||
fla = (double)kt_globals.f0_flutter / 50; | |||
flb = (double)kt_globals.original_f0 / 100; | |||
flc = sin(PI*12.7*time_count); // because we are calling flutter() more frequently, every 2.9mS | |||
flc = sin(PI*12.7*time_count); // because we are calling flutter() more frequently, every 2.9mS | |||
fld = sin(PI*7.1*time_count); | |||
fle = sin(PI*4.7*time_count); | |||
delta_f0 = fla * flb * (flc + fld + fle) * 10; | |||
@@ -262,30 +262,26 @@ static int parwave(klatt_frame_ptr frame) | |||
static double sourc; | |||
int ix; | |||
flutter(frame); /* add f0 flutter */ | |||
flutter(frame); // add f0 flutter | |||
/* MAIN LOOP, for each output sample of current frame: */ | |||
// MAIN LOOP, for each output sample of current frame: | |||
for (kt_globals.ns = 0; kt_globals.ns < kt_globals.nspfr; kt_globals.ns++) { | |||
/* Get low-passed random number for aspiration and frication noise */ | |||
// Get low-passed random number for aspiration and frication noise | |||
noise = gen_noise(noise); | |||
/* | |||
Amplitude modulate noise (reduce noise amplitude during | |||
second half of glottal period) if voicing simultaneously present. | |||
*/ | |||
// Amplitude modulate noise (reduce noise amplitude during | |||
// second half of glottal period) if voicing simultaneously present. | |||
if (kt_globals.nper > kt_globals.nmod) | |||
noise *= (double)0.5; | |||
/* Compute frication noise */ | |||
// Compute frication noise | |||
frics = kt_globals.amp_frica * noise; | |||
/* | |||
Compute voicing waveform. Run glottal source simulation at 4 | |||
times normal sample rate to minimize quantization noise in | |||
period of female voice. | |||
*/ | |||
// Compute voicing waveform. Run glottal source simulation at 4 | |||
// times normal sample rate to minimize quantization noise in | |||
// period of female voice. | |||
for (n4 = 0; n4 < 4; n4++) { | |||
switch (kt_globals.glsource) | |||
@@ -304,55 +300,46 @@ static int parwave(klatt_frame_ptr frame) | |||
break; | |||
} | |||
/* Reset period when counter 'nper' reaches T0 */ | |||
// Reset period when counter 'nper' reaches T0 | |||
if (kt_globals.nper >= kt_globals.T0) { | |||
kt_globals.nper = 0; | |||
pitch_synch_par_reset(frame); | |||
} | |||
/* | |||
Low-pass filter voicing waveform before downsampling from 4*samrate | |||
to samrate samples/sec. Resonator f=.09*samrate, bw=.06*samrate | |||
*/ | |||
// Low-pass filter voicing waveform before downsampling from 4*samrate | |||
// to samrate samples/sec. Resonator f=.09*samrate, bw=.06*samrate | |||
voice = resonator(&(kt_globals.rsn[RLP]), voice); | |||
/* Increment counter that keeps track of 4*samrate samples per sec */ | |||
// Increment counter that keeps track of 4*samrate samples per sec | |||
kt_globals.nper++; | |||
} | |||
/* | |||
Tilt spectrum of voicing source down by soft low-pass filtering, amount | |||
of tilt determined by TLTdb | |||
*/ | |||
// Tilt spectrum of voicing source down by soft low-pass filtering, amount | |||
// of tilt determined by TLTdb | |||
voice = (voice * kt_globals.onemd) + (vlast * kt_globals.decay); | |||
vlast = voice; | |||
/* | |||
Add breathiness during glottal open phase. Amount of breathiness | |||
determined by parameter Aturb Use nrand rather than noise because | |||
noise is low-passed. | |||
*/ | |||
// Add breathiness during glottal open phase. Amount of breathiness | |||
// determined by parameter Aturb Use nrand rather than noise because | |||
// noise is low-passed. | |||
if (kt_globals.nper < kt_globals.nopen) | |||
voice += kt_globals.amp_breth * kt_globals.nrand; | |||
/* Set amplitude of voicing */ | |||
// Set amplitude of voicing | |||
glotout = kt_globals.amp_voice * voice; | |||
par_glotout = kt_globals.par_amp_voice * voice; | |||
/* Compute aspiration amplitude and add to voicing source */ | |||
// Compute aspiration amplitude and add to voicing source | |||
aspiration = kt_globals.amp_aspir * noise; | |||
glotout += aspiration; | |||
par_glotout += aspiration; | |||
/* | |||
Cascade vocal tract, excited by laryngeal sources. | |||
Nasal antiresonator, then formants FNP, F5, F4, F3, F2, F1 | |||
*/ | |||
// Cascade vocal tract, excited by laryngeal sources. | |||
// Nasal antiresonator, then formants FNP, F5, F4, F3, F2, F1 | |||
out = 0; | |||
if (kt_globals.synthesis_model != ALL_PARALLEL) { | |||
@@ -368,15 +355,13 @@ static int parwave(klatt_frame_ptr frame) | |||
out = resonator2(&(kt_globals.rsn[R1c]), casc_next_in); | |||
} | |||
/* Excite parallel F1 and FNP by voicing waveform */ | |||
sourc = par_glotout; /* Source is voicing plus aspiration */ | |||
// Excite parallel F1 and FNP by voicing waveform | |||
sourc = par_glotout; // Source is voicing plus aspiration | |||
/* | |||
Standard parallel vocal tract Formants F6,F5,F4,F3,F2, | |||
outputs added with alternating sign. Sound source for other | |||
parallel resonators is frication plus first difference of | |||
voicing waveform. | |||
*/ | |||
// Standard parallel vocal tract Formants F6,F5,F4,F3,F2, | |||
// outputs added with alternating sign. Sound source for other | |||
// parallel resonators is frication plus first difference of | |||
// voicing waveform. | |||
out += resonator(&(kt_globals.rsn[R1p]), sourc); | |||
out += resonator(&(kt_globals.rsn[Rnpp]), sourc); | |||
@@ -392,30 +377,27 @@ static int parwave(klatt_frame_ptr frame) | |||
out = outbypas - out; | |||
out = resonator(&(kt_globals.rsn[Rout]), out); | |||
temp = (int)(out * wdata.amplitude * kt_globals.amp_gain0); /* Convert back to integer */ | |||
temp = (int)(out * wdata.amplitude * kt_globals.amp_gain0); // Convert back to integer | |||
// mix with a recorded WAV if required for this phoneme | |||
{ | |||
int z2; | |||
signed char c; | |||
int sample; | |||
z2 = 0; | |||
if (wdata.mix_wavefile_ix < wdata.n_mix_wavefile) { | |||
if (wdata.mix_wave_scale == 0) { | |||
// a 16 bit sample | |||
c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1]; | |||
sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256); | |||
wdata.mix_wavefile_ix += 2; | |||
} else { | |||
// a 8 bit sample, scaled | |||
sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale; | |||
} | |||
z2 = sample * wdata.amplitude_v / 1024; | |||
z2 = (z2 * wdata.mix_wave_amp)/40; | |||
temp += z2; | |||
int z2; | |||
signed char c; | |||
int sample; | |||
z2 = 0; | |||
if (wdata.mix_wavefile_ix < wdata.n_mix_wavefile) { | |||
if (wdata.mix_wave_scale == 0) { | |||
// a 16 bit sample | |||
c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1]; | |||
sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256); | |||
wdata.mix_wavefile_ix += 2; | |||
} else { | |||
// a 8 bit sample, scaled | |||
sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale; | |||
} | |||
z2 = sample * wdata.amplitude_v / 1024; | |||
z2 = (z2 * wdata.mix_wave_amp)/40; | |||
temp += z2; | |||
} | |||
// if fadeout is set, fade to zero over 64 samples, to avoid clicks at end of synthesis | |||
@@ -459,7 +441,6 @@ void KlattReset(int control) | |||
kt_globals.minus_pi_t = -PI / kt_globals.samrate; | |||
kt_globals.two_pi_t = -2.0 * kt_globals.minus_pi_t; | |||
setabc(kt_globals.FLPhz, kt_globals.BLPhz, &(kt_globals.rsn[RLP])); | |||
} | |||
if (control > 0) { | |||
@@ -514,7 +495,7 @@ static void frame_init(klatt_frame_ptr frame) | |||
Gain0_tmp = 57; | |||
kt_globals.amp_gain0 = DBtoLIN(Gain0_tmp) / kt_globals.scale_wav; | |||
/* Set coefficients of variable cascade resonators */ | |||
// Set coefficients of variable cascade resonators | |||
for (ix = 1; ix <= 9; ix++) { | |||
// formants 1 to 8, plus nasal pole | |||
setabc(frame->Fhz[ix], frame->Bhz[ix], &(kt_globals.rsn[ix])); | |||
@@ -535,14 +516,14 @@ static void frame_init(klatt_frame_ptr frame) | |||
kt_globals.rsn[F_NZ].b_inc = (kt_globals.rsn_next[F_NZ].b - kt_globals.rsn[F_NZ].b) / 64.0; | |||
kt_globals.rsn[F_NZ].c_inc = (kt_globals.rsn_next[F_NZ].c - kt_globals.rsn[F_NZ].c) / 64.0; | |||
/* Set coefficients of parallel resonators, and amplitude of outputs */ | |||
// Set coefficients of parallel resonators, and amplitude of outputs | |||
for (ix = 0; ix <= 6; ix++) { | |||
setabc(frame->Fhz[ix], frame->Bphz[ix], &(kt_globals.rsn[Rparallel+ix])); | |||
kt_globals.rsn[Rparallel+ix].a *= amp_par[ix]; | |||
} | |||
/* output low-pass filter */ | |||
// output low-pass filter | |||
setabc((long)0.0, (long)(kt_globals.samrate/2), &(kt_globals.rsn[Rout])); | |||
} | |||
@@ -631,40 +612,39 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) | |||
static long skew; | |||
static short B0[224] = { | |||
1200, 1142, 1088, 1038, 991, 948, 907, 869, 833, 799, 768, 738, 710, 683, 658, | |||
634, 612, 590, 570, 551, 533, 515, 499, 483, 468, 454, 440, 427, 415, 403, | |||
391, 380, 370, 360, 350, 341, 332, 323, 315, 307, 300, 292, 285, 278, 272, | |||
265, 259, 253, 247, 242, 237, 231, 226, 221, 217, 212, 208, 204, 199, 195, | |||
192, 188, 184, 180, 177, 174, 170, 167, 164, 161, 158, 155, 153, 150, 147, | |||
145, 142, 140, 137, 135, 133, 131, 128, 126, 124, 122, 120, 119, 117, 115, | |||
113, 111, 110, 108, 106, 105, 103, 102, 100, 99, 97, 96, 95, 93, 92, 91, 90, | |||
88, 87, 86, 85, 84, 83, 82, 80, 79, 78, 77, 76, 75, 75, 74, 73, 72, 71, | |||
70, 69, 68, 68, 67, 66, 65, 64, 64, 63, 62, 61, 61, 60, 59, 59, 58, 57, | |||
57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, | |||
47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 41, 41, 40, 40, | |||
39, 39, 38, 38, 38, 38, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 33, | |||
33, 33, 33, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, | |||
28, 28, 28, 28, 27, 27 | |||
634, 612, 590, 570, 551, 533, 515, 499, 483, 468, 454, 440, 427, 415, 403, | |||
391, 380, 370, 360, 350, 341, 332, 323, 315, 307, 300, 292, 285, 278, 272, | |||
265, 259, 253, 247, 242, 237, 231, 226, 221, 217, 212, 208, 204, 199, 195, | |||
192, 188, 184, 180, 177, 174, 170, 167, 164, 161, 158, 155, 153, 150, 147, | |||
145, 142, 140, 137, 135, 133, 131, 128, 126, 124, 122, 120, 119, 117, 115, | |||
113, 111, 110, 108, 106, 105, 103, 102, 100, 99, 97, 96, 95, 93, 92, 91, 90, | |||
88, 87, 86, 85, 84, 83, 82, 80, 79, 78, 77, 76, 75, 75, 74, 73, 72, 71, | |||
70, 69, 68, 68, 67, 66, 65, 64, 64, 63, 62, 61, 61, 60, 59, 59, 58, 57, | |||
57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, | |||
47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 41, 41, 40, 40, | |||
39, 39, 38, 38, 38, 38, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 33, | |||
33, 33, 33, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, | |||
28, 28, 28, 28, 27, 27 | |||
}; | |||
if (frame->F0hz10 > 0) { | |||
/* T0 is 4* the number of samples in one pitch period */ | |||
// T0 is 4* the number of samples in one pitch period | |||
kt_globals.T0 = (40 * kt_globals.samrate) / frame->F0hz10; | |||
kt_globals.amp_voice = DBtoLIN(frame->AVdb_tmp); | |||
/* Duration of period before amplitude modulation */ | |||
// Duration of period before amplitude modulation | |||
kt_globals.nmod = kt_globals.T0; | |||
if (frame->AVdb_tmp > 0) | |||
kt_globals.nmod >>= 1; | |||
/* Breathiness of voicing waveform */ | |||
// Breathiness of voicing waveform | |||
kt_globals.amp_breth = DBtoLIN(frame->Aturb) * 0.1; | |||
/* Set open phase of glottal period where 40 <= open phase <= 263 */ | |||
// Set open phase of glottal period where 40 <= open phase <= 263 | |||
kt_globals.nopen = 4 * frame->Kopen; | |||
@@ -675,31 +655,28 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) | |||
kt_globals.nopen = kt_globals.T0 - 2; | |||
if (kt_globals.nopen < 40) { | |||
/* F0 max = 1000 Hz */ | |||
// F0 max = 1000 Hz | |||
kt_globals.nopen = 40; | |||
} | |||
/* Reset a & b, which determine shape of "natural" glottal waveform */ | |||
// Reset a & b, which determine shape of "natural" glottal waveform | |||
kt_globals.pulse_shape_b = B0[kt_globals.nopen-40]; | |||
kt_globals.pulse_shape_a = (kt_globals.pulse_shape_b * kt_globals.nopen) * 0.333; | |||
/* Reset width of "impulsive" glottal pulse */ | |||
// Reset width of "impulsive" glottal pulse | |||
temp = kt_globals.samrate / kt_globals.nopen; | |||
setabc((long)0, temp, &(kt_globals.rsn[RGL])); | |||
/* Make gain at F1 about constant */ | |||
// Make gain at F1 about constant | |||
temp1 = kt_globals.nopen *.00833; | |||
kt_globals.rsn[RGL].a *= temp1 * temp1; | |||
/* | |||
Truncate skewness so as not to exceed duration of closed phase | |||
of glottal period. | |||
*/ | |||
// Truncate skewness so as not to exceed duration of closed phase | |||
// of glottal period. | |||
temp = kt_globals.T0 - kt_globals.nopen; | |||
if (frame->Kskew > temp) | |||
@@ -709,11 +686,11 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) | |||
else | |||
skew = -frame->Kskew; | |||
/* Add skewness to closed portion of voicing period */ | |||
// Add skewness to closed portion of voicing period | |||
kt_globals.T0 = kt_globals.T0 + skew; | |||
skew = -skew; | |||
} else { | |||
kt_globals.T0 = 4; /* Default for f0 undefined */ | |||
kt_globals.T0 = 4; // Default for f0 undefined | |||
kt_globals.amp_voice = 0.0; | |||
kt_globals.nmod = kt_globals.T0; | |||
kt_globals.amp_breth = 0.0; | |||
@@ -721,10 +698,10 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) | |||
kt_globals.pulse_shape_b = 0.0; | |||
} | |||
/* Reset these pars pitch synchronously or at update rate if f0=0 */ | |||
// Reset these pars pitch synchronously or at update rate if f0=0 | |||
if ((kt_globals.T0 != 4) || (kt_globals.ns == 0)) { | |||
/* Set one-pole low-pass filter that tilts glottal source */ | |||
// Set one-pole low-pass filter that tilts glottal source | |||
kt_globals.decay = (0.033 * frame->TLTdb); | |||
@@ -747,18 +724,18 @@ static void setabc(long int f, long int bw, resonator_ptr rp) | |||
double r; | |||
double arg; | |||
/* Let r = exp(-pi bw t) */ | |||
// Let r = exp(-pi bw t) | |||
arg = kt_globals.minus_pi_t * bw; | |||
r = exp(arg); | |||
/* Let c = -r**2 */ | |||
// Let c = -r**2 | |||
rp->c = -(r * r); | |||
/* Let b = r * 2*cos(2 pi f t) */ | |||
// Let b = r * 2*cos(2 pi f t) | |||
arg = kt_globals.two_pi_t * f; | |||
rp->b = r * cos(arg) * 2.0; | |||
/* Let a = 1.0 - b - c */ | |||
// Let a = 1.0 - b - c | |||
rp->a = 1.0 - rp->b - rp->c; | |||
} | |||
@@ -776,28 +753,28 @@ static void setzeroabc(long int f, long int bw, resonator_ptr rp) | |||
f = -f; | |||
/* First compute ordinary resonator coefficients */ | |||
/* Let r = exp(-pi bw t) */ | |||
// First compute ordinary resonator coefficients | |||
// Let r = exp(-pi bw t) | |||
arg = kt_globals.minus_pi_t * bw; | |||
r = exp(arg); | |||
/* Let c = -r**2 */ | |||
// Let c = -r**2 | |||
rp->c = -(r * r); | |||
/* Let b = r * 2*cos(2 pi f t) */ | |||
// Let b = r * 2*cos(2 pi f t) | |||
arg = kt_globals.two_pi_t * f; | |||
rp->b = r * cos(arg) * 2.; | |||
/* Let a = 1.0 - b - c */ | |||
// Let a = 1.0 - b - c | |||
rp->a = 1.0 - rp->b - rp->c; | |||
/* Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) */ | |||
/* If f == 0 then rp->a gets set to 0 which makes a'=1/a set a', b' and c' to | |||
* INF, causing an audible sound spike when triggered (e.g. apiration with the | |||
* nasal register set to f=0, bw=0). | |||
*/ | |||
// Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) | |||
// If f == 0 then rp->a gets set to 0 which makes a'=1/a set a', b' and c' to | |||
// INF, causing an audible sound spike when triggered (e.g. apiration with the | |||
// nasal register set to f=0, bw=0). | |||
if (rp->a != 0) { | |||
/* Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) */ | |||
// Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) | |||
rp->a = 1.0 / rp->a; | |||
rp->c *= -rp->a; | |||
rp->b *= -rp->a; | |||
@@ -847,15 +824,15 @@ static double gen_noise(double noise) | |||
static double DBtoLIN(long dB) | |||
{ | |||
static short amptable[88] = { | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, | |||
8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, 32, | |||
35, 40, 45, 51, 57, 64, 71, 80, 90, 101, 114, 128, | |||
142, 159, 179, 202, 227, 256, 284, 318, 359, 405, | |||
455, 512, 568, 638, 719, 881, 911, 1024, 1137, 1276, | |||
1438, 1622, 1823, 2048, 2273, 2552, 2875, 3244, 3645, | |||
4096, 4547, 5104, 5751, 6488, 7291, 8192, 9093, 10207, | |||
11502, 12976, 14582, 16384, 18350, 20644, 23429, | |||
26214, 29491, 32767 | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, | |||
8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, 32, | |||
35, 40, 45, 51, 57, 64, 71, 80, 90, 101, 114, 128, | |||
142, 159, 179, 202, 227, 256, 284, 318, 359, 405, | |||
455, 512, 568, 638, 719, 881, 911, 1024, 1137, 1276, | |||
1438, 1622, 1823, 2048, 2273, 2552, 2875, 3244, 3645, | |||
4096, 4547, 5104, 5751, 6488, 7291, 8192, 9093, 10207, | |||
11502, 12976, 14582, 16384, 18350, 20644, 23429, | |||
26214, 29491, 32767 | |||
}; | |||
if ((dB < 0) || (dB > 87)) | |||
@@ -939,14 +916,14 @@ int Wavegen_Klatt(int resume) | |||
if (kt_globals.nspfr > STEPSIZE) | |||
kt_globals.nspfr = STEPSIZE; | |||
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) | |||
return 1; // output buffer is full | |||
return 1; // output buffer is full | |||
} | |||
if (end_wave > 0) { | |||
fade = 64; // not followd by formant synthesis | |||
fade = 64; // not followed by formant synthesis | |||
// fade out to avoid a click | |||
kt_globals.fadeout = fade; | |||
@@ -954,7 +931,7 @@ int Wavegen_Klatt(int resume) | |||
sample_count -= fade; | |||
kt_globals.nspfr = fade; | |||
if (parwave(&kt_frame) == 1) | |||
return 1; // output buffer is full | |||
return 1; // output buffer is full | |||
} | |||
return 0; | |||
@@ -979,7 +956,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
end_wave = 0; | |||
if (control & 2) | |||
end_wave = 1; // fadeout at the end | |||
end_wave = 1; // fadeout at the end | |||
if (control & 1) { | |||
end_wave = 1; | |||
for (qix = wcmdq_head+1;; qix++) { | |||
@@ -988,7 +965,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
cmd = wcmdq[qix][0]; | |||
if (cmd == WCMD_KLATT) { | |||
end_wave = 0; // next wave generation is from another spectrum | |||
end_wave = 0; // next wave generation is from another spectrum | |||
fr3 = (frame_t *)wcmdq[qix][2]; | |||
for (ix = 1; ix < 6; ix++) { | |||
@@ -1001,7 +978,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
break; | |||
} | |||
if ((cmd == WCMD_WAVE) || (cmd == WCMD_PAUSE)) | |||
break; // next is not from spectrum, so continue until end of wave cycle | |||
break; // next is not from spectrum, so continue until end of wave cycle | |||
} | |||
} | |||
@@ -1047,7 +1024,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
// nasal zero frequency | |||
peaks[0].freq1 = fr1->klattp[KLATT_FNZ] * 2; | |||
if (peaks[0].freq1 == 0) | |||
peaks[0].freq1 = kt_frame.Fhz[F_NP]; // if no nasal zero, set it to same freq as nasal pole | |||
peaks[0].freq1 = kt_frame.Fhz[F_NP]; // if no nasal zero, set it to same freq as nasal pole | |||
peaks[0].freq = (int)peaks[0].freq1; | |||
next = fr2->klattp[KLATT_FNZ] * 2; | |||
@@ -1063,12 +1040,12 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
if (fr1->frflags & FRFLAG_KLATT) { | |||
// the frame contains additional parameters for parallel resonators | |||
for (ix = 1; ix < 7; ix++) { | |||
peaks[ix].bp1 = fr1->klatt_bp[ix] * 4; // parallel bandwidth | |||
peaks[ix].bp1 = fr1->klatt_bp[ix] * 4; // parallel bandwidth | |||
peaks[ix].bp = (int)peaks[ix].bp1; | |||
next = fr2->klatt_bp[ix] * 4; | |||
peaks[ix].bp_inc = ((next - peaks[ix].bp1) * STEPSIZE) / length; | |||
peaks[ix].ap1 = fr1->klatt_ap[ix]; // parallal amplitude | |||
peaks[ix].ap1 = fr1->klatt_ap[ix]; // parallal amplitude | |||
peaks[ix].ap = (int)peaks[ix].ap1; | |||
next = fr2->klatt_ap[ix]; | |||
peaks[ix].ap_inc = ((next - peaks[ix].ap1) * STEPSIZE) / length; | |||
@@ -1099,7 +1076,7 @@ void KlattInit() | |||
kt_globals.synthesis_model = CASCADE_PARALLEL; | |||
kt_globals.samrate = 22050; | |||
kt_globals.glsource = IMPULSIVE; // IMPULSIVE, NATURAL, SAMPLED | |||
kt_globals.glsource = IMPULSIVE; | |||
kt_globals.scale_wav = scale_wav_tab[kt_globals.glsource]; | |||
kt_globals.natural_samples = natural_samples; | |||
kt_globals.num_samples = NUMBER_OF_SAMPLES; | |||
@@ -1120,14 +1097,14 @@ void KlattInit() | |||
kt_frame.Bhz_next[F_NZ] = bandwidth[F_NZ]; | |||
kt_frame.F0hz10 = 1000; | |||
kt_frame.AVdb = 59; // 59 | |||
kt_frame.AVdb = 59; | |||
kt_frame.ASP = 0; | |||
kt_frame.Kopen = 40; // 40 | |||
kt_frame.Kopen = 40; | |||
kt_frame.Aturb = 0; | |||
kt_frame.TLTdb = 0; | |||
kt_frame.AF = 50; | |||
kt_frame.Kskew = 0; | |||
kt_frame.AB = 0; | |||
kt_frame.AVpdb = 0; | |||
kt_frame.Gain0 = 62; // 60 | |||
kt_frame.Gain0 = 62; | |||
} |
@@ -59,7 +59,7 @@ struct datablock { | |||
struct datablock *next; | |||
int done; | |||
int size; | |||
char buffer[1]; /* 1 or more, dynamically allocated */ | |||
char buffer[1]; // 1 or more, dynamically allocated | |||
}; | |||
static struct datablock *mbr_pending_data_head, *mbr_pending_data_tail; | |||
@@ -296,24 +296,24 @@ static int mbrola_has_errors(void) | |||
} | |||
if (result == 0) { | |||
/* EOF on stderr, assume mbrola died. */ | |||
// EOF on stderr, assume mbrola died. | |||
return mbrola_died(); | |||
} | |||
buf_ptr[result] = 0; | |||
for (; (lf = strchr(buf_ptr, '\n')); buf_ptr = lf + 1) { | |||
/* inhibit the reset signal messages */ | |||
// inhibit the reset signal messages | |||
if (strncmp(buf_ptr, "Got a reset signal", 18) == 0 || | |||
strncmp(buf_ptr, "Input Flush Signal", 18) == 0) | |||
continue; | |||
*lf = 0; | |||
log("mbrola: %s", buf_ptr); | |||
/* is this the last line? */ | |||
// is this the last line? | |||
if (lf == &buf_ptr[result - 1]) { | |||
snprintf(mbr_errorbuf, sizeof(mbr_errorbuf), | |||
"%s", buf_ptr); | |||
/* don't consider this fatal at this point */ | |||
// don't consider this fatal at this point | |||
return 0; | |||
} | |||
} | |||
@@ -369,9 +369,9 @@ static int send_to_mbrola(const char *cmd) | |||
static int mbrola_is_idle(void) | |||
{ | |||
char *p; | |||
char buffer[20]; /* looking for "12345 (mbrola) S" so 20 is plenty*/ | |||
char buffer[20]; // looking for "12345 (mbrola) S" so 20 is plenty | |||
/* look in /proc to determine if mbrola is still running or sleeping */ | |||
// look in /proc to determine if mbrola is still running or sleeping | |||
if (lseek(mbr_proc_stat, 0, SEEK_SET) != 0) | |||
return 0; | |||
if (read(mbr_proc_stat, buffer, sizeof(buffer)) != sizeof(buffer)) | |||
@@ -494,7 +494,7 @@ int init_MBR(const char *voice_path) | |||
return -1; | |||
} | |||
/* we should actually be getting only 44 bytes */ | |||
// we should actually be getting only 44 bytes | |||
result = receive_from_mbrola(wavhdr, 45); | |||
if (result != 44) { | |||
if (result >= 0) | |||
@@ -503,7 +503,7 @@ int init_MBR(const char *voice_path) | |||
return -1; | |||
} | |||
/* parse wavhdr to get mbrola voice samplerate */ | |||
// parse wavhdr to get mbrola voice samplerate | |||
if (memcmp(wavhdr, "RIFF", 4) != 0 || | |||
memcmp(wavhdr+8, "WAVEfmt ", 8) != 0) { | |||
err("mbrola did not return a .wav header"); | |||
@@ -512,9 +512,8 @@ int init_MBR(const char *voice_path) | |||
} | |||
mbr_samplerate = wavhdr[24] + (wavhdr[25]<<8) + | |||
(wavhdr[26]<<16) + (wavhdr[27]<<24); | |||
// log("mbrowrap: voice samplerate = %d", mbr_samplerate); | |||
/* remember the voice path for setVolumeRatio_MBR() */ | |||
// remember the voice path for setVolumeRatio_MBR() | |||
if (mbr_voice_path != voice_path) { | |||
free(mbr_voice_path); | |||
mbr_voice_path = strdup(voice_path); |
@@ -64,7 +64,7 @@ | |||
#define M_RETROFLEX 20 | |||
#define M_HOOK 21 | |||
#define M_MIDDLE_DOT M_DOT_ABOVE // duplicate of M_DOT_ABOVE | |||
#define M_MIDDLE_DOT M_DOT_ABOVE // duplicate of M_DOT_ABOVE | |||
#define M_IMPLOSIVE M_HOOK | |||
static int n_digit_lookup; | |||
@@ -109,17 +109,16 @@ static ACCENTS accents_tab[] = { | |||
#define LETTER(ch, mod1, mod2) (ch-59)+(mod1 << 6)+(mod2 << 11) | |||
#define LIGATURE(ch1, ch2, mod1) (ch1-59)+((ch2-59) << 6)+(mod1 << 12)+M_LIGATURE | |||
#define L_ALPHA 60 // U+3B1 | |||
#define L_SCHWA 61 // U+259 | |||
#define L_OPEN_E 62 // U+25B | |||
#define L_GAMMA 63 // U+3B3 | |||
#define L_IOTA 64 // U+3B9 | |||
#define L_OE 65 // U+153 | |||
#define L_OMEGA 66 // U+3C9 | |||
#define L_ALPHA 60 // U+3B1 | |||
#define L_SCHWA 61 // U+259 | |||
#define L_OPEN_E 62 // U+25B | |||
#define L_GAMMA 63 // U+3B3 | |||
#define L_IOTA 64 // U+3B9 | |||
#define L_OE 65 // U+153 | |||
#define L_OMEGA 66 // U+3C9 | |||
#define L_PHI 67 // U+3C6 | |||
#define L_ESH 68 // U+283 | |||
#define L_PHI 67 // U+3C6 | |||
#define L_ESH 68 // U+283 | |||
#define L_UPSILON 69 // U+3C5 | |||
#define L_EZH 70 // U+292 | |||
#define L_GLOTTAL 71 // U+294 | |||
@@ -127,13 +126,14 @@ static ACCENTS accents_tab[] = { | |||
#define L_RLONG 73 // U+27C | |||
static const short non_ascii_tab[] = { | |||
0, 0x3b1, 0x259, 0x25b, 0x3b3, 0x3b9, 0x153, 0x3c9, | |||
0, | |||
0x3b1, 0x259, 0x25b, 0x3b3, 0x3b9, 0x153, 0x3c9, | |||
0x3c6, 0x283, 0x3c5, 0x292, 0x294, 0x27e, 0x27c | |||
}; | |||
// characters U+00e0 to U+017f | |||
static const unsigned short letter_accents_0e0[] = { | |||
LETTER('a', M_GRAVE, 0), // U+00e0 | |||
LETTER('a', M_GRAVE, 0), // U+00e0 | |||
LETTER('a', M_ACUTE, 0), | |||
LETTER('a', M_CIRCUMFLEX, 0), | |||
LETTER('a', M_TILDE, 0), | |||
@@ -149,23 +149,23 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('i', M_ACUTE, 0), | |||
LETTER('i', M_CIRCUMFLEX, 0), | |||
LETTER('i', M_DIAERESIS, 0), | |||
LETTER('d', M_NAME, 0), // eth // U+00f0 | |||
LETTER('d', M_NAME, 0), // eth U+00f0 | |||
LETTER('n', M_TILDE, 0), | |||
LETTER('o', M_GRAVE, 0), | |||
LETTER('o', M_ACUTE, 0), | |||
LETTER('o', M_CIRCUMFLEX, 0), | |||
LETTER('o', M_TILDE, 0), | |||
LETTER('o', M_DIAERESIS, 0), | |||
0, // division sign | |||
0, // division sign | |||
LETTER('o', M_STROKE, 0), | |||
LETTER('u', M_GRAVE, 0), | |||
LETTER('u', M_ACUTE, 0), | |||
LETTER('u', M_CIRCUMFLEX, 0), | |||
LETTER('u', M_DIAERESIS, 0), | |||
LETTER('y', M_ACUTE, 0), | |||
LETTER('t', M_NAME, 0), // thorn | |||
LETTER('t', M_NAME, 0), // thorn | |||
LETTER('y', M_DIAERESIS, 0), | |||
CAPITAL, // U+0100 | |||
CAPITAL, // U+0100 | |||
LETTER('a', M_MACRON, 0), | |||
CAPITAL, | |||
LETTER('a', M_BREVE, 0), | |||
@@ -181,7 +181,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('c', M_CARON, 0), | |||
CAPITAL, | |||
LETTER('d', M_CARON, 0), | |||
CAPITAL, // U+0110 | |||
CAPITAL, // U+0110 | |||
LETTER('d', M_STROKE, 0), | |||
CAPITAL, | |||
LETTER('e', M_MACRON, 0), | |||
@@ -197,7 +197,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('g', M_CIRCUMFLEX, 0), | |||
CAPITAL, | |||
LETTER('g', M_BREVE, 0), | |||
CAPITAL, // U+0120 | |||
CAPITAL, // U+0120 | |||
LETTER('g', M_DOT_ABOVE, 0), | |||
CAPITAL, | |||
LETTER('g', M_CEDILLA, 0), | |||
@@ -213,7 +213,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('i', M_BREVE, 0), | |||
CAPITAL, | |||
LETTER('i', M_OGONEK, 0), | |||
CAPITAL, // U+0130 | |||
CAPITAL, // U+0130 | |||
LETTER('i', M_NAME, 0), // dotless i | |||
CAPITAL, | |||
LIGATURE('i', 'j', 0), | |||
@@ -221,7 +221,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('j', M_CIRCUMFLEX, 0), | |||
CAPITAL, | |||
LETTER('k', M_CEDILLA, 0), | |||
LETTER('k', M_NAME, 0), // kra | |||
LETTER('k', M_NAME, 0), // kra | |||
CAPITAL, | |||
LETTER('l', M_ACUTE, 0), | |||
CAPITAL, | |||
@@ -229,7 +229,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
CAPITAL, | |||
LETTER('l', M_CARON, 0), | |||
CAPITAL, | |||
LETTER('l', M_MIDDLE_DOT, 0), // U+0140 | |||
LETTER('l', M_MIDDLE_DOT, 0), // U+0140 | |||
CAPITAL, | |||
LETTER('l', M_STROKE, 0), | |||
CAPITAL, | |||
@@ -238,14 +238,14 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('n', M_CEDILLA, 0), | |||
CAPITAL, | |||
LETTER('n', M_CARON, 0), | |||
LETTER('n', M_NAME, 0), // apostrophe n | |||
LETTER('n', M_NAME, 0), // apostrophe n | |||
CAPITAL, | |||
LETTER('n', M_NAME, 0), // eng | |||
LETTER('n', M_NAME, 0), // eng | |||
CAPITAL, | |||
LETTER('o', M_MACRON, 0), | |||
CAPITAL, | |||
LETTER('o', M_BREVE, 0), | |||
CAPITAL, // U+0150 | |||
CAPITAL, // U+0150 | |||
LETTER('o', M_DOUBLE_ACUTE, 0), | |||
CAPITAL, | |||
LIGATURE('o', 'e', 0), | |||
@@ -261,7 +261,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('s', M_CIRCUMFLEX, 0), | |||
CAPITAL, | |||
LETTER('s', M_CEDILLA, 0), | |||
CAPITAL, // U+0160 | |||
CAPITAL, // U+0160 | |||
LETTER('s', M_CARON, 0), | |||
CAPITAL, | |||
LETTER('t', M_CEDILLA, 0), | |||
@@ -277,7 +277,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('u', M_BREVE, 0), | |||
CAPITAL, | |||
LETTER('u', M_RING, 0), | |||
CAPITAL, // U+0170 | |||
CAPITAL, // U+0170 | |||
LETTER('u', M_DOUBLE_ACUTE, 0), | |||
CAPITAL, | |||
LETTER('u', M_OGONEK, 0), | |||
@@ -285,43 +285,43 @@ static const unsigned short letter_accents_0e0[] = { | |||
LETTER('w', M_CIRCUMFLEX, 0), | |||
CAPITAL, | |||
LETTER('y', M_CIRCUMFLEX, 0), | |||
CAPITAL, // Y-DIAERESIS | |||
CAPITAL, // Y-DIAERESIS | |||
CAPITAL, | |||
LETTER('z', M_ACUTE, 0), | |||
CAPITAL, | |||
LETTER('z', M_DOT_ABOVE, 0), | |||
CAPITAL, | |||
LETTER('z', M_CARON, 0), | |||
LETTER('s', M_NAME, 0), // long-s // U+17f | |||
LETTER('s', M_NAME, 0), // long-s U+17f | |||
}; | |||
// characters U+0250 to U+029F | |||
static const unsigned short letter_accents_250[] = { | |||
LETTER('a', M_TURNED, 0), // U+250 | |||
LETTER('a', M_TURNED, 0), // U+250 | |||
LETTER(L_ALPHA, 0, 0), | |||
LETTER(L_ALPHA, M_TURNED, 0), | |||
LETTER('b', M_IMPLOSIVE, 0), | |||
0, // open-o | |||
0, // open-o | |||
LETTER('c', M_CURL, 0), | |||
LETTER('d', M_RETROFLEX, 0), | |||
LETTER('d', M_IMPLOSIVE, 0), | |||
LETTER('e', M_REVERSED, 0), // U+258 | |||
0, // schwa | |||
LETTER('e', M_REVERSED, 0), // U+258 | |||
0, // schwa | |||
LETTER(L_SCHWA, M_HOOK, 0), | |||
0, // open-e | |||
0, // open-e | |||
LETTER(L_OPEN_E, M_REVERSED, 0), | |||
LETTER(L_OPEN_E, M_HOOK, M_REVERSED), | |||
0, | |||
LETTER('j', M_BAR, 0), | |||
LETTER('g', M_IMPLOSIVE, 0), // U+260 | |||
LETTER('g', M_IMPLOSIVE, 0), // U+260 | |||
LETTER('g', 0, 0), | |||
LETTER('g', M_SMALLCAP, 0), | |||
LETTER(L_GAMMA, 0, 0), | |||
0, // ramshorn | |||
0, // ramshorn | |||
LETTER('h', M_TURNED, 0), | |||
LETTER('h', M_HOOK, 0), | |||
0, | |||
LETTER('i', M_BAR, 0), // U+268 | |||
LETTER('i', M_BAR, 0), // U+268 | |||
LETTER(L_IOTA, 0, 0), | |||
LETTER('i', M_SMALLCAP, 0), | |||
LETTER('l', M_TILDE, 0), | |||
@@ -337,23 +337,23 @@ static const unsigned short letter_accents_250[] = { | |||
LETTER('o', M_BAR, 0), | |||
LIGATURE('o', 'e', M_SMALLCAP), | |||
0, | |||
LETTER(L_PHI, 0, 0), // U+278 | |||
LETTER(L_PHI, 0, 0), // U+278 | |||
LETTER('r', M_TURNED, 0), | |||
LETTER(L_RLONG, M_TURNED, 0), | |||
LETTER('r', M_RETROFLEX, M_TURNED), | |||
0, | |||
LETTER('r', M_RETROFLEX, 0), | |||
0, // r-tap | |||
0, // r-tap | |||
LETTER(L_RTAP, M_REVERSED, 0), | |||
LETTER('r', M_SMALLCAP, 0), // U+280 | |||
LETTER('r', M_SMALLCAP, 0), // U+280 | |||
LETTER('r', M_TURNED, M_SMALLCAP), | |||
LETTER('s', M_RETROFLEX, 0), | |||
0, // esh | |||
0, // esh | |||
LETTER('j', M_HOOK, 0), | |||
LETTER(L_ESH, M_REVERSED, 0), | |||
LETTER(L_ESH, M_CURL, 0), | |||
LETTER('t', M_TURNED, 0), | |||
LETTER('t', M_RETROFLEX, 0), // U+288 | |||
LETTER('t', M_RETROFLEX, 0), // U+288 | |||
LETTER('u', M_BAR, 0), | |||
LETTER(L_UPSILON, 0, 0), | |||
LETTER('v', M_HOOK, 0), | |||
@@ -361,15 +361,15 @@ static const unsigned short letter_accents_250[] = { | |||
LETTER('w', M_TURNED, 0), | |||
LETTER('y', M_TURNED, 0), | |||
LETTER('y', M_SMALLCAP, 0), | |||
LETTER('z', M_RETROFLEX, 0), // U+290 | |||
LETTER('z', M_RETROFLEX, 0), // U+290 | |||
LETTER('z', M_CURL, 0), | |||
0, // ezh | |||
0, // ezh | |||
LETTER(L_EZH, M_CURL, 0), | |||
0, // glottal stop | |||
0, // glottal stop | |||
LETTER(L_GLOTTAL, M_REVERSED, 0), | |||
LETTER(L_GLOTTAL, M_TURNED, 0), | |||
0, | |||
0, // bilabial click // U+298 | |||
0, // bilabial click U+298 | |||
LETTER('b', M_SMALLCAP, 0), | |||
0, | |||
LETTER('g', M_IMPLOSIVE, M_SMALLCAP), | |||
@@ -377,14 +377,14 @@ static const unsigned short letter_accents_250[] = { | |||
LETTER('j', M_CURL, 0), | |||
LETTER('k', M_TURNED, 0), | |||
LETTER('l', M_SMALLCAP, 0), | |||
LETTER('q', M_HOOK, 0), // U+2a0 | |||
LETTER('q', M_HOOK, 0), // U+2a0 | |||
LETTER(L_GLOTTAL, M_STROKE, 0), | |||
LETTER(L_GLOTTAL, M_STROKE, M_REVERSED), | |||
LIGATURE('d', 'z', 0), | |||
0, // dezh | |||
0, // dezh | |||
LIGATURE('d', 'z', M_CURL), | |||
LIGATURE('t', 's', 0), | |||
0, // tesh | |||
0, // tesh | |||
LIGATURE('t', 's', M_CURL), | |||
}; | |||
@@ -476,7 +476,7 @@ void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf) | |||
void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1, int control) | |||
{ | |||
// control, bit 0: not the first letter of a word | |||
// control, bit 0: not the first letter of a word | |||
int len; | |||
static char single_letter[10] = { 0, 0 }; | |||
@@ -494,18 +494,18 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b | |||
single_letter[1] = '_'; | |||
if (Lookup(tr, &single_letter[1], ph_buf3) != 0) | |||
return; // the character is specified as _* so ignore it when speaking normal text | |||
return; // the character is specified as _* so ignore it when speaking normal text | |||
// check whether this character is specified for English | |||
if (tr->translator_name == L('e', 'n')) | |||
return; // we are already using English | |||
return; // we are already using English | |||
SetTranslator2("en"); | |||
if (Lookup(translator2, &single_letter[2], ph_buf3) != 0) { | |||
// yes, switch to English and re-translate the word | |||
sprintf(ph_buf1, "%c", phonSWITCH); | |||
} | |||
SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table | |||
SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table | |||
return; | |||
} | |||
@@ -518,7 +518,7 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b | |||
if (next_byte != ' ') | |||
next_byte = RULE_SPELLING; | |||
single_letter[3+len] = next_byte; // follow by space-space if the end of the word, or space-31 | |||
single_letter[3+len] = next_byte; // follow by space-space if the end of the word, or space-31 | |||
single_letter[1] = '_'; | |||
@@ -543,31 +543,31 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b | |||
SetWordStress(tr, ph_buf1, dict_flags, -1, control & 1); | |||
} | |||
// unicode ranges for non-ascii digits 0-9 | |||
// unicode ranges for non-ascii digits 0-9 (these must be in ascending order) | |||
static const int number_ranges[] = { | |||
0x660, 0x6f0, // arabic | |||
0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6, 0xc66, 0xce6, 0xd66, // indic | |||
0x660, 0x6f0, // arabic | |||
0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6, 0xc66, 0xce6, 0xd66, // indic | |||
0xe50, 0xed0, 0xf20, 0x1040, 0x1090, | |||
0 | |||
}; // these must be in ascending order | |||
}; | |||
int NonAsciiNumber(int letter) | |||
{ | |||
// Change non-ascii digit into ascii digit '0' to '9', (or -1 if not) | |||
// Change non-ascii digit into ascii digit '0' to '9', (or -1 if not) | |||
const int *p; | |||
int base; | |||
for (p = number_ranges; (base = *p) != 0; p++) { | |||
if (letter < base) | |||
break; // not found | |||
break; // not found | |||
if (letter < (base+10)) | |||
return letter-base+'0'; | |||
} | |||
return -1; | |||
} | |||
#define L_SUB 0x4000 // subscript | |||
#define L_SUP 0x8000 // superscript | |||
#define L_SUB 0x4000 // subscript | |||
#define L_SUP 0x8000 // superscript | |||
static const char *modifiers[] = { NULL, "_sub", "_sup", NULL }; | |||
@@ -638,11 +638,19 @@ static unsigned short derived_letters[] = { | |||
0, 0 | |||
}; | |||
static const char *hex_letters[] = { "'e:j", "b'i:", "s'i:", "d'i:", "'i:", "'ef" }; // names, using phonemes available to all languages | |||
// names, using phonemes available to all languages | |||
static const char *hex_letters[] = { | |||
"'e:j", | |||
"b'i:", | |||
"s'i:", | |||
"d'i:", | |||
"'i:", | |||
"'ef" | |||
}; | |||
int IsSuperscript(int letter) | |||
{ | |||
// is this a subscript or superscript letter ? | |||
// is this a subscript or superscript letter ? | |||
int ix; | |||
int c; | |||
@@ -657,11 +665,11 @@ int IsSuperscript(int letter) | |||
int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
{ | |||
// get pronunciation for an isolated letter | |||
// return number of bytes used by the letter | |||
// control bit 0: a non-initial letter in a word | |||
// bit 1: say 'capital' | |||
// bit 2: say character code for unknown letters | |||
// get pronunciation for an isolated letter | |||
// return number of bytes used by the letter | |||
// control bit 0: a non-initial letter in a word | |||
// bit 1: say 'capital' | |||
// bit 2: say character code for unknown letters | |||
int n_bytes; | |||
int letter; | |||
@@ -693,7 +701,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
n_bytes = utf8_in(&letter, word); | |||
if ((letter & 0xfff00) == 0x0e000) | |||
letter &= 0xff; // uncode private usage area | |||
letter &= 0xff; // uncode private usage area | |||
if (control & 2) { | |||
// include CAPITAL information | |||
@@ -711,7 +719,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
// don't say "superscript" during normal text reading | |||
Lookup(tr, modifier, capital); | |||
if (capital[0] == 0) { | |||
capital[2] = SetTranslator2("en"); // overwrites previous contents of translator2 | |||
capital[2] = SetTranslator2("en"); // overwrites previous contents of translator2 | |||
Lookup(translator2, modifier, &capital[3]); | |||
if (capital[3] != 0) { | |||
capital[0] = phonPAUSE; | |||
@@ -755,7 +763,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
ph_buf2[0] = 0; | |||
if (Lookup(translator, alphabet->name, ph_alphabet) == 0) { // the original language for the current voice | |||
// Can't find the local name for this alphabet, use the English name | |||
ph_alphabet[2] = SetTranslator2("en"); // overwrites previous contents of translator2 | |||
ph_alphabet[2] = SetTranslator2("en"); // overwrites previous contents of translator2 | |||
Lookup(translator2, alphabet->name, ph_buf2); | |||
} else if (translator != tr) { | |||
phontab_1 = tr->phoneme_tab_ix; | |||
@@ -777,7 +785,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
} | |||
} | |||
// caution: SetWordStress() etc don't expect phonSWITCH + phoneme table number | |||
// caution: SetWordStress() etc don't expect phonSWITCH + phoneme table number | |||
if (ph_buf[0] == 0) { | |||
if ((al_offset != 0) && (al_offset == translator->langopts.alt_alphabet)) | |||
@@ -805,8 +813,8 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
if ((initial = (code/28)/21) != 11) { | |||
p3 += utf8_out(initial + 0x1100, p3); | |||
} | |||
utf8_out(((code/28) % 21) + 0x1161, p3); // medial | |||
utf8_out((code % 28) + 0x11a7, &p3[3]); // final | |||
utf8_out(((code/28) % 21) + 0x1161, p3); // medial | |||
utf8_out((code % 28) + 0x11a7, &p3[3]); // final | |||
p3[6] = ' '; | |||
p3[7] = 0; | |||
ph_buf[3] = 0; | |||
@@ -821,13 +829,13 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
LookupLetter(translator2, letter, word[n_bytes], &ph_buf[3], control & 1); | |||
} | |||
SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table | |||
SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table | |||
if (ph_buf[3] != 0) { | |||
ph_buf[0] = phonPAUSE; | |||
ph_buf[1] = phonSWITCH; | |||
len = strlen(&ph_buf[3]) + 3; | |||
ph_buf[len] = phonSWITCH; // switch back | |||
ph_buf[len] = phonSWITCH; // switch back | |||
ph_buf[len+1] = tr->phoneme_tab_ix; | |||
ph_buf[len+2] = 0; | |||
} | |||
@@ -890,16 +898,15 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
if (tr->langopts.accents & 2) // 'capital' before or after the word ? | |||
sprintf(ph_buf2, "%c%s%s%s", 0xff, ph_alphabet, ph_buf, capital); | |||
else | |||
sprintf(ph_buf2, "%c%s%s%s", 0xff, ph_alphabet, capital, ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress() | |||
if ((len + strlen(ph_buf2)) < N_WORD_PHONEMES) { | |||
sprintf(ph_buf2, "%c%s%s%s", 0xff, ph_alphabet, capital, ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress() | |||
if ((len + strlen(ph_buf2)) < N_WORD_PHONEMES) | |||
strcpy(&phonemes[len], ph_buf2); | |||
} | |||
return n_bytes; | |||
} | |||
void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) | |||
{ | |||
// Individual letter names, reduce the stress of some. | |||
// Individual letter names, reduce the stress of some. | |||
int ix; | |||
unsigned int c; | |||
int n_stress = 0; | |||
@@ -927,17 +934,17 @@ void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) | |||
} else { | |||
if (count != n_stress) { | |||
if (((count % 3) != 0) || (count == n_stress-1)) | |||
c = phonSTRESS_3; // reduce to secondary stress | |||
c = phonSTRESS_3; // reduce to secondary stress | |||
} | |||
} | |||
} else if (c == 0xff) { | |||
if ((control < 2) || (ix == 0)) | |||
continue; // don't insert pauses | |||
continue; // don't insert pauses | |||
if (control == 4) | |||
c = phonPAUSE; // pause after each character | |||
c = phonPAUSE; // pause after each character | |||
if (((count % 3) == 0) || (control > 2)) | |||
c = phonPAUSE_NOLINK; // pause following a primary stress | |||
c = phonPAUSE_NOLINK; // pause following a primary stress | |||
else | |||
c = phonPAUSE_VSHORT; | |||
} | |||
@@ -981,14 +988,14 @@ static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB | |||
nextflags = TranslateWord(tr, &word_end[2], 0, NULL, NULL); | |||
if ((tr->prev_dict_flags[0] & FLAG_ALT_TRANS) && ((c2 == 0) || (wtab[0].flags & FLAG_COMMA_AFTER) || iswdigit(c2))) | |||
ordinal = 0; // TEST 09.02.10 | |||
ordinal = 0; // TEST 09.02.10 | |||
if (nextflags & FLAG_ALT_TRANS) | |||
ordinal = 0; | |||
if (nextflags & FLAG_ALT3_TRANS) { | |||
if (word[-2] == '-') | |||
ordinal = 0; // eg. december 2-5. között | |||
ordinal = 0; // e.g. december 2-5. között | |||
if (tr->prev_dict_flags[0] & (FLAG_ALT_TRANS | FLAG_ALT3_TRANS)) | |||
ordinal = 0x22; | |||
@@ -1002,14 +1009,14 @@ static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB | |||
static int hu_number_e(const char *word, int thousandplex, int value) | |||
{ | |||
// lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett | |||
// lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett | |||
if ((word[0] == 'a') || (word[0] == 'e')) { | |||
if ((word[1] == ' ') || (word[1] == 'z') || ((word[1] == 't') && (word[2] == 't'))) | |||
return 0; | |||
if (((thousandplex == 1) || ((value % 1000) == 0)) && (word[1] == 'l')) | |||
return 0; // 1000-el | |||
return 0; // 1000-el | |||
return 1; | |||
} | |||
@@ -1044,13 +1051,13 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) | |||
flags[1] = 0; | |||
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 ((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. | |||
} 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; | |||
@@ -1084,7 +1091,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) | |||
} | |||
if (IsDigit09(word[0])) | |||
return 0; // eg. 'xx2' | |||
return 0; // e.g. 'xx2' | |||
acc += prev; | |||
if (acc < tr->langopts.min_roman) | |||
@@ -1093,7 +1100,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) | |||
if (acc > tr->langopts.max_roman) | |||
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 | |||
p = &ph_out[0]; | |||
if ((tr->langopts.numbers & NUM_ROMAN_AFTER) == 0) { | |||
@@ -1145,25 +1152,25 @@ static const char *M_Variant(int value) | |||
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)) | |||
return "1M"; | |||
break; | |||
case 2: // lang=cs,sk | |||
case 2: // lang=cs,sk | |||
if ((value >= 2) && (value <= 4)) | |||
return "0MA"; | |||
break; | |||
case 3: // lang=pl | |||
case 3: // lang=pl | |||
if ((teens == 0) && (((value % 10) >= 2) && ((value % 10) <= 4))) | |||
return "0MA"; | |||
break; | |||
case 4: // lang=lt | |||
case 4: // lang=lt | |||
if ((teens == 1) || ((value % 10) == 0)) | |||
return "0MB"; | |||
if ((value % 10) == 1) | |||
return "0MA"; | |||
break; | |||
case 5: // lang=bs,hr,sr | |||
case 5: // lang=bs,hr,sr | |||
if (teens == 0) { | |||
if ((value % 10) == 1) | |||
return "1M"; | |||
@@ -1177,7 +1184,7 @@ static const char *M_Variant(int value) | |||
static int LookupThousands(Translator *tr, int value, int thousandplex, int thousands_exact, char *ph_out) | |||
{ | |||
// thousands_exact: bit 0 no hundreds,tens,or units, bit 1 ordinal numberr | |||
// thousands_exact: bit 0 no hundreds,tens,or units, bit 1 ordinal numberr | |||
int found; | |||
int found_value = 0; | |||
char string[12]; | |||
@@ -1266,15 +1273,15 @@ static int LookupThousands(Translator *tr, int value, int thousandplex, int thou | |||
static int LookupNum2(Translator *tr, int value, int thousandplex, const int control, char *ph_out) | |||
{ | |||
// Lookup a 2 digit number | |||
// control bit 0: ordinal number | |||
// control bit 1: final tens and units (not number of thousands) (use special form of '1', LANG=de "eins") | |||
// control bit 2: tens and units only, no higher digits | |||
// control bit 3: use feminine form of '2' (for thousands | |||
// control bit 4: speak zero tens | |||
// control bit 5: variant of ordinal number (lang=hu) | |||
// bit 8 followed by decimal fraction | |||
// bit 9: use #f form for both tens and units (lang=ml) | |||
// Lookup a 2 digit number | |||
// control bit 0: ordinal number | |||
// control bit 1: final tens and units (not number of thousands) (use special form of '1', LANG=de "eins") | |||
// control bit 2: tens and units only, no higher digits | |||
// control bit 3: use feminine form of '2' (for thousands | |||
// control bit 4: speak zero tens | |||
// control bit 5: variant of ordinal number (lang=hu) | |||
// bit 8 followed by decimal fraction | |||
// bit 9: use #f form for both tens and units (lang=ml) | |||
int found; | |||
int ix; | |||
@@ -1285,7 +1292,7 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
int found_ordinal = 0; | |||
int next_phtype; | |||
int ord_type = 'o'; | |||
char string[12]; // for looking up entries in *_list | |||
char string[12]; // for looking up entries in *_list | |||
char ph_ordinal[20]; | |||
char ph_tens[50]; | |||
char ph_digits[50]; | |||
@@ -1322,10 +1329,10 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
strcpy(ph_ordinal, ph_ordinal2); | |||
if (control & 4) { | |||
sprintf(string, "_%d%cx", value, ord_type); // LANG=hu, special word for 1. 2. when there are no higher digits | |||
sprintf(string, "_%d%cx", value, ord_type); // LANG=hu, special word for 1. 2. when there are no higher digits | |||
if ((found = Lookup(tr, string, ph_digits)) != 0) { | |||
if (ph_ordinal2x[0] != 0) | |||
strcpy(ph_ordinal, ph_ordinal2x); // alternate pronunciation (lang=an) | |||
strcpy(ph_ordinal, ph_ordinal2x); // alternate pronunciation (lang=an) | |||
} | |||
} | |||
if (found == 0) { | |||
@@ -1346,7 +1353,7 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
} else { | |||
// followed by hundreds or thousands etc | |||
if ((tr->langopts.numbers2 & NUM2_ORDINAL_AND_THOUSANDS) && (thousandplex <= 1)) | |||
sprintf(string, "_%do", value); // LANG=TA | |||
sprintf(string, "_%do", value); // LANG=TA | |||
else | |||
sprintf(string, "_%da", value); | |||
found = Lookup(tr, string, ph_digits); | |||
@@ -1369,9 +1376,9 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
// speak leading zero | |||
Lookup(tr, "_0", ph_tens); | |||
} else { | |||
if (found) { | |||
if (found) | |||
ph_tens[0] = 0; | |||
} else { | |||
else { | |||
if (is_ordinal) { | |||
sprintf(string, "_%dX%c", tens, ord_type); | |||
if (Lookup(tr, string, ph_tens) != 0) { | |||
@@ -1416,9 +1423,8 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
if ((is_ordinal) && ((tr->langopts.numbers & NUM_SWAP_TENS) == 0)) { | |||
// ordinal | |||
sprintf(string, "_%d%c", units, ord_type); | |||
if ((found = Lookup(tr, string, ph_digits)) != 0) { | |||
if ((found = Lookup(tr, string, ph_digits)) != 0) | |||
found_ordinal = 1; | |||
} | |||
} | |||
if (found == 0) { | |||
if ((number_control & 1) && (control & 2)) { | |||
@@ -1511,11 +1517,12 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int control) | |||
{ | |||
// Translate a 3 digit number | |||
// control bit 0, previous thousands | |||
// bit 1, ordinal number | |||
// bit 5 variant form of ordinal number | |||
// bit 8 followed by decimal fraction | |||
// Translate a 3 digit number | |||
// control bit 0, previous thousands | |||
// bit 1, ordinal number | |||
// bit 5 variant form of ordinal number | |||
// bit 8 followed by decimal fraction | |||
int found; | |||
int hundreds; | |||
int tensunits; | |||
@@ -1526,7 +1533,7 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
int tplex; | |||
int say_zero_hundred = 0; | |||
int 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 buf2[100]; | |||
char ph_100[20]; | |||
@@ -1544,9 +1551,8 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
ph_thousands[0] = 0; | |||
ph_thousand_and[0] = 0; | |||
if ((tr->langopts.numbers & NUM_ZERO_HUNDRED) && ((control & 1) || (hundreds >= 10))) { | |||
say_zero_hundred = 1; // lang=vi | |||
} | |||
if ((tr->langopts.numbers & NUM_ZERO_HUNDRED) && ((control & 1) || (hundreds >= 10))) | |||
say_zero_hundred = 1; // lang=vi | |||
if ((hundreds > 0) || say_zero_hundred) { | |||
found = 0; | |||
@@ -1579,14 +1585,14 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
if (LookupThousands(tr, hundreds / 10, tplex, exact | ordinal, ph_10T) == 0) { | |||
x = 0; | |||
if (tr->langopts.numbers2 & (1 << tplex)) | |||
x = 8; // use variant (feminine) for before thousands and millions | |||
x = 8; // use variant (feminine) for before thousands and millions | |||
if (tr->translator_name == L('m', 'l')) | |||
x = 0x208; | |||
LookupNum2(tr, hundreds/10, thousandplex, x, ph_digits); | |||
} | |||
if (tr->langopts.numbers2 & 0x200) | |||
sprintf(ph_thousands, "%s%c%s%c", ph_10T, phonEND_WORD, ph_digits, phonEND_WORD); // say "thousands" before its number, not after | |||
sprintf(ph_thousands, "%s%c%s%c", ph_10T, phonEND_WORD, ph_digits, phonEND_WORD); // say "thousands" before its number, not after | |||
else | |||
sprintf(ph_thousands, "%s%c%s%c", ph_digits, phonEND_WORD, ph_10T, phonEND_WORD); | |||
@@ -1674,18 +1680,18 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
if ((tensunits != 0) || (suppress_null == 0)) { | |||
x = 0; | |||
if (thousandplex == 0) { | |||
x = 2; // allow "eins" for 1 rather than "ein" | |||
x = 2; // allow "eins" for 1 rather than "ein" | |||
if (ordinal) | |||
x = 3; // ordinal number | |||
x = 3; // ordinal number | |||
if ((value < 100) && !(control & 1)) | |||
x |= 4; // tens and units only, no higher digits | |||
x |= 4; // tens and units only, no higher digits | |||
if (ordinal & 0x20) | |||
x |= 0x20; // variant form of ordinal number | |||
x |= 0x20; // variant form of ordinal number | |||
} else if (tr->langopts.numbers2 & (1 << thousandplex)) | |||
x = 8; // use variant (feminine) for before thousands and millions | |||
x = 8; // use variant (feminine) for before thousands and millions | |||
if ((tr->translator_name == L('m', 'l')) && (thousandplex == 1)) | |||
x |= 0x208; // use #f form for both tens and units | |||
x |= 0x208; // use #f form for both tens and units | |||
if ((tr->langopts.numbers2 & NUM2_ZERO_TENS) && ((control & 1) || (hundreds > 0))) { | |||
// LANG=zh, | |||
@@ -1694,13 +1700,13 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
if (LookupNum2(tr, tensunits, thousandplex, x | (control & 0x100), buf2) != 0) { | |||
if (tr->langopts.numbers & NUM_SINGLE_AND) | |||
ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units | |||
ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units | |||
} | |||
} else { | |||
if (ph_ordinal2[0] != 0) { | |||
ix = strlen(buf1); | |||
if ((ix > 0) && (buf1[ix-1] == phonPAUSE_SHORT)) | |||
buf1[ix-1] = 0; // remove pause before addding ordinal suffix | |||
buf1[ix-1] = 0; // remove pause before addding ordinal suffix | |||
strcpy(buf2, ph_ordinal2); | |||
} | |||
} | |||
@@ -1712,7 +1718,7 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
bool CheckThousandsGroup(char *word, int group_len) | |||
{ | |||
// Is this a group of 3 digits which looks like a thousands group? | |||
// Is this a group of 3 digits which looks like a thousands group? | |||
int ix; | |||
if (IsDigit09(word[group_len]) || IsDigit09(-1)) | |||
@@ -1727,9 +1733,9 @@ bool CheckThousandsGroup(char *word, int group_len) | |||
static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | |||
{ | |||
// Number translation with various options | |||
// the "word" may be up to 4 digits | |||
// "words" of 3 digits may be preceded by another number "word" for thousands or millions | |||
// Number translation with various options | |||
// the "word" may be up to 4 digits | |||
// "words" of 3 digits may be preceded by another number "word" for thousands or millions | |||
int n_digits; | |||
int value; | |||
@@ -1752,13 +1758,13 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
int group_len; | |||
int len; | |||
char *p; | |||
char string[32]; // for looking up entries in **_list | |||
char string[32]; // for looking up entries in **_list | |||
char buf1[100]; | |||
char ph_append[50]; | |||
char ph_buf[200]; | |||
char ph_buf2[50]; | |||
char ph_zeros[50]; | |||
char suffix[30]; // string[] must be long enough for sizeof(suffix)+2 | |||
char suffix[30]; // string[] must be long enough for sizeof(suffix)+2 | |||
char buf_digit_lookup[50]; | |||
static const char str_pause[2] = { phonPAUSE_NOLINK, 0 }; | |||
@@ -1778,9 +1784,9 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
group_len = 4; | |||
// is there a previous thousands part (as a previous "word") ? | |||
if ((n_digits == group_len) && (word[-2] == tr->langopts.thousands_sep) && IsDigit09(word[-3])) { | |||
if ((n_digits == group_len) && (word[-2] == tr->langopts.thousands_sep) && IsDigit09(word[-3])) | |||
prev_thousands = 1; | |||
} else if ((tr->langopts.thousands_sep == ' ') || (tr->langopts.numbers & NUM_ALLOW_SPACE)) { | |||
else if ((tr->langopts.thousands_sep == ' ') || (tr->langopts.numbers & NUM_ALLOW_SPACE)) { | |||
// thousands groups can be separated by spaces | |||
if ((n_digits == 3) && !(wtab->flags & FLAG_MULTIPLE_SPACES) && IsDigit09(word[-2])) | |||
prev_thousands = 1; | |||
@@ -1802,7 +1808,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
} | |||
if ((ordinal == 0) || (tr->translator_name == L('h', 'u'))) { | |||
// NOTE lang=hu, allow both dot and ordinal suffix, eg. "december 21.-én" | |||
// NOTE lang=hu, allow both dot and ordinal suffix, eg. "december 21.-én" | |||
// look for an ordinal number suffix after the number | |||
ix++; | |||
p = suffix; | |||
@@ -1817,7 +1823,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
if (suffix[0] != 0) { | |||
if ((tr->langopts.ordinal_indicator != NULL) && (strcmp(suffix, tr->langopts.ordinal_indicator) == 0)) | |||
ordinal = 2; | |||
else if (!IsDigit09(suffix[0])) { // not _#9 (tab) | |||
else if (!IsDigit09(suffix[0])) { // not _#9 (tab) | |||
sprintf(string, "_#%s", suffix); | |||
if (Lookup(tr, string, ph_ordinal2)) { | |||
// this is an ordinal suffix | |||
@@ -1825,7 +1831,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
flags[0] |= FLAG_SKIPWORDS; | |||
skipwords = 1; | |||
sprintf(string, "_x#%s", suffix); | |||
Lookup(tr, string, ph_ordinal2x); // is there an alternate pronunciation? | |||
Lookup(tr, string, ph_ordinal2x); // is there an alternate pronunciation? | |||
} | |||
} | |||
} | |||
@@ -1843,7 +1849,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
} else { | |||
if (n_digits > 3) { | |||
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 | |||
@@ -1887,7 +1893,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
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 | |||
if ((wtab[thousandplex].flags & FLAG_HYPHEN_AFTER) && (thousands_exact == 1) && hu_number_e(&word[suffix_ix], thousandplex, value)) | |||
number_control |= 1; // use _1e variant of number | |||
number_control |= 1; // use _1e variant of number | |||
} | |||
if ((word[n_digits] == tr->langopts.decimal_sep) && IsDigit09(word[n_digits+1])) { | |||
@@ -1920,7 +1926,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
char *p2; | |||
// look for combinations of the number with the next word | |||
p = word; | |||
while (IsDigit09(p[1])) p++; // just use the last digit | |||
while (IsDigit09(p[1])) p++; // just use the last digit | |||
if (IsDigit09(p[-1])) { | |||
p2 = p - 1; | |||
if (LookupDictList(tr, &p2, buf_digit_lookup, flags, FLAG_SUFX, wtab)) // lookup 2 digits | |||
@@ -1959,7 +1965,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
LookupNum3(tr, value, ph_buf, suppress_null, thousandplex, prev_thousands | ordinal | decimal_point); | |||
if ((thousandplex > 0) && (tr->langopts.numbers2 & 0x200)) | |||
sprintf(ph_out, "%s%s%c%s%s", ph_zeros, ph_append, phonEND_WORD, ph_buf2, ph_buf); // say "thousands" before its number | |||
sprintf(ph_out, "%s%s%c%s%s", ph_zeros, ph_append, phonEND_WORD, ph_buf2, ph_buf); // say "thousands" before its number | |||
else | |||
sprintf(ph_out, "%s%s%s%c%s", ph_zeros, ph_buf2, ph_buf, phonEND_WORD, ph_append); | |||
@@ -1976,7 +1982,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
{ | |||
case NUM_DFRACTION_4: | |||
max_decimal_count = 5; | |||
// fallthrough | |||
// fallthrough: | |||
case NUM_DFRACTION_2: | |||
// French/Polish decimal fraction | |||
while (word[n_digits] == '0') { | |||
@@ -1991,15 +1997,15 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
n_digits += decimal_count; | |||
} | |||
break; | |||
case NUM_DFRACTION_1: // italian, say "hundredths" if leading zero | |||
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_1: // italian, say "hundredths" if leading zero | |||
case NUM_DFRACTION_5: // hungarian, always say "tenths" etc. | |||
case NUM_DFRACTION_6: // kazakh, always say "tenths" etc, before the decimal fraction | |||
LookupNum3(tr, atoi(&word[n_digits]), ph_buf, 0, 0, 0); | |||
if ((word[n_digits] == '0') || (decimal_mode != NUM_DFRACTION_1)) { | |||
// decimal part has leading zeros, so add a "hundredths" or "thousandths" suffix | |||
sprintf(string, "_0Z%d", decimal_count); | |||
if (Lookup(tr, string, buf1) == 0) | |||
break; // revert to speaking single digits | |||
break; // revert to speaking single digits | |||
if (decimal_mode == NUM_DFRACTION_6) | |||
strcat(ph_out, buf1); | |||
@@ -2056,7 +2062,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
utf8_in(&next_char, p); | |||
if (!iswalpha2(next_char) && (thousands_exact == 0)) | |||
strcat(ph_out, str_pause); // don't add pause for 100s, 6th, etc. | |||
strcat(ph_out, str_pause); // don't add pause for 100s, 6th, etc. | |||
} | |||
*flags |= FLAG_FOUND; | |||
@@ -2070,7 +2076,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
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)) | |||
return 0; // speak digits individually | |||
return 0; // speak digits individually | |||
if (tr->langopts.numbers != 0) | |||
return TranslateNumber_1(tr, word1, ph_out, flags, wtab, control); |
@@ -22,7 +22,6 @@ extern "C" | |||
{ | |||
#endif | |||
// phoneme types | |||
#define phPAUSE 0 | |||
#define phSTRESS 1 | |||
@@ -37,7 +36,6 @@ extern "C" | |||
#define phDELETED 14 | |||
#define phINVALID 15 | |||
// phoneme properties | |||
// bits 16-19 give place of articulation | |||
#define phARTICULATION 0xf0000 | |||
@@ -118,11 +116,8 @@ typedef struct { | |||
unsigned char end_type; | |||
unsigned char std_length; // for vowels, in mS/2; for phSTRESS phonemes, this is the stress/tone type | |||
unsigned char length_mod; // a length_mod group number, used to access length_mod_tab | |||
} PHONEME_TAB; | |||
// Several phoneme tables may be loaded into memory. phoneme_tab points to | |||
// one for the current voice | |||
extern int n_phoneme_tab; | |||
@@ -138,8 +133,6 @@ typedef struct { | |||
int equivalence_tables; // lists of equivalent phonemes to match other languages, byte index into phondata | |||
} PHONEME_TAB_LIST; | |||
// table of phonemes to be replaced with different phonemes, for the current voice | |||
#define N_REPLACE_PHONEMES 60 | |||
typedef struct { | |||
@@ -151,15 +144,12 @@ typedef struct { | |||
extern int n_replace_phonemes; | |||
extern REPLACE_PHONEMES replace_phonemes[N_REPLACE_PHONEMES]; | |||
// Table of phoneme programs and lengths. Used by MakeVowelLists | |||
typedef struct { | |||
unsigned int addr; | |||
unsigned int length; | |||
} PHONEME_PROG_LOG; | |||
#define PH(c1, c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name | |||
#define PH3(c1, c2, c3) (c3<<16)+(c2<<8)+c1 | |||
#define PhonemeCode2(c1, c2) PhonemeCode((c2<<8)+c1) |
@@ -32,15 +32,17 @@ | |||
#include "synthesize.h" | |||
#include "translate.h" | |||
const unsigned char pause_phonemes[8] = { 0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG }; | |||
const unsigned char pause_phonemes[8] = { | |||
0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG | |||
}; | |||
extern int n_ph_list2; | |||
extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes | |||
extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes | |||
static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) | |||
{ | |||
// Copy the phonemes list and perform any substitutions that are required for the | |||
// current voice | |||
// Copy the phonemes list and perform any substitutions that are required for the | |||
// current voice | |||
int ix; | |||
int k; | |||
int replace_flags; | |||
@@ -67,24 +69,24 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) | |||
replace_flags = replace_phonemes[k].type; | |||
if ((replace_flags & 1) && (word_end == 0)) | |||
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)) | |||
continue; // this replacement doesn't occur in stressed syllables | |||
continue; // this replacement doesn't occur in stressed syllables | |||
if ((replace_flags & 4) && (plist2->sourceix == 0)) | |||
continue; // this replacement only occurs at the start of a word | |||
continue; // this replacement only occurs at the start of a word | |||
// substitute the replacement phoneme | |||
plist2->phcode = replace_phonemes[k].new_ph; | |||
if ((plist2->stresslevel > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED)) | |||
plist2->stresslevel = 0; // the replacement must be unstressed | |||
plist2->stresslevel = 0; // the replacement must be unstressed | |||
break; | |||
} | |||
} | |||
if (plist2->phcode == 0) | |||
continue; // phoneme has been replaced by NULL, so don't copy it | |||
continue; // phoneme has been replaced by NULL, so don't copy it | |||
} | |||
// copy phoneme into the output list | |||
@@ -144,7 +146,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
// the last word is unstressed, look for a previous word that can be stressed | |||
while (--j >= 0) { | |||
if (plist2[j].synthflags & SFLAG_PROMOTE_STRESS) { // dictionary flags indicated that this stress can be promoted | |||
plist2[j].stresslevel = 4; // promote to stressed | |||
plist2[j].stresslevel = 4; // promote to stressed | |||
break; | |||
} | |||
if (plist2[j].stresslevel >= 4) { | |||
@@ -196,7 +198,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
stop_propagation = 0; | |||
voicing = 0; | |||
if (regression & 0x100) | |||
voicing = 1; // word-end devoicing | |||
voicing = 1; // word-end devoicing | |||
continue; | |||
} | |||
@@ -215,12 +217,12 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
if ((voicing == 0) && (regression & 0xf)) | |||
voicing = 1; | |||
else if ((voicing == 2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants | |||
plist2[j].phcode = ph->end_type; // change to voiced equivalent | |||
plist2[j].phcode = ph->end_type; // change to voiced equivalent | |||
} else if ((type == phVSTOP) || type == (phVFRICATIVE)) { | |||
if ((voicing == 0) && (regression & 0xf)) | |||
voicing = 2; | |||
else if ((voicing == 1) && (ph->end_type != 0)) | |||
plist2[j].phcode = ph->end_type; // change to unvoiced equivalent | |||
plist2[j].phcode = ph->end_type; // change to unvoiced equivalent | |||
} else { | |||
if (regression & 0x8) { | |||
// LANG=Polish, propagate through liquids and nasals | |||
@@ -264,7 +266,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
nextw++; | |||
if (ph_list3[nextw].sourceix) | |||
break; // start of the next word | |||
break; // start of the next word | |||
} | |||
for (k = j; k < nextw; k++) | |||
ph_list3[k].wordstress = word_stress; | |||
@@ -307,7 +309,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
ph = phoneme_tab[insert_ph]; | |||
plist3->ph = ph; | |||
insert_ph = 0; | |||
inserted = 1; // don't insert the same phoneme repeatedly | |||
inserted = 1; // don't insert the same phoneme repeatedly | |||
} else { | |||
// otherwise get the next phoneme from the list | |||
if (plist3->sourceix != 0) | |||
@@ -320,7 +322,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
// change phoneme table | |||
SelectPhonemeTable(plist3->tone_ph); | |||
} | |||
next = phoneme_tab[plist3[1].phcode]; // the phoneme after this one | |||
next = phoneme_tab[plist3[1].phcode]; // the phoneme after this one | |||
plist3[1].ph = next; | |||
} | |||
@@ -348,7 +350,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
if (ph->type == phVOWEL) { | |||
plist3->synthflags |= SFLAG_SYLLABLE; | |||
if (ph2->type != phVOWEL) | |||
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
} else | |||
plist3->synthflags &= ~SFLAG_SYLLABLE; | |||
@@ -365,12 +367,12 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
plist3->phcode = alternative; | |||
if (alternative == 1) | |||
deleted = 1; // NULL phoneme, discard | |||
deleted = 1; // NULL phoneme, discard | |||
else { | |||
if (ph->type == phVOWEL) { | |||
plist3->synthflags |= SFLAG_SYLLABLE; | |||
if (ph2->type != phVOWEL) | |||
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
} else | |||
plist3->synthflags &= ~SFLAG_SYLLABLE; | |||
@@ -408,14 +410,13 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
// stress. But not for the last phoneme of a stressed word | |||
if ((tr->langopts.stress_flags & S_NO_DIM) || ((word_stress > 3) && ((plist3+1)->sourceix != 0))) { | |||
// An unstressed final vowel of a stressed word | |||
unstress_count = 1; // try again for next syllable | |||
unstress_count = 1; // try again for next syllable | |||
} else | |||
plist3->stresslevel = 0; // change stress to 'diminished' | |||
plist3->stresslevel = 0; // change stress to 'diminished' | |||
} | |||
} | |||
} else { | |||
} else | |||
unstress_count = 0; | |||
} | |||
} | |||
if ((plist3+1)->synthflags & SFLAG_LENGTHEN) { | |||
@@ -483,7 +484,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
if (deleted == 0) { | |||
phlist[ix].ph = ph; | |||
phlist[ix].type = ph->type; | |||
phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module | |||
phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module | |||
phlist[ix].synthflags = plist3->synthflags; | |||
phlist[ix].stresslevel = plist3->stresslevel & 0xf; | |||
phlist[ix].wordstress = plist3->wordstress; | |||
@@ -493,10 +494,10 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
if (plist3->sourceix != 0) { | |||
phlist[ix].sourceix = plist3->sourceix; | |||
phlist[ix].newword = 1; // this phoneme is the start of a word | |||
phlist[ix].newword = 1; // this phoneme is the start of a word | |||
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; | |||
} | |||
} else | |||
@@ -505,26 +506,26 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
phlist[ix].length = phdata.pd_param[i_SET_LENGTH]*2; | |||
if ((ph->code == phonPAUSE_LONG) && (option_wordgap > 0) && (plist3[1].sourceix != 0)) { | |||
phlist[ix].ph = phoneme_tab[phonPAUSE_SHORT]; | |||
phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed | |||
phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed | |||
} | |||
if (ph->type == phVOWEL || ph->type == phLIQUID || ph->type == phNASAL || ph->type == phVSTOP || ph->type == phVFRICATIVE || (ph->phflags & phPREVOICE)) { | |||
phlist[ix].length = 128; // length_mod | |||
phlist[ix].length = 128; // length_mod | |||
phlist[ix].env = PITCHfall; | |||
} | |||
phlist[ix].prepause = 0; | |||
phlist[ix].amp = 20; // default, will be changed later | |||
phlist[ix].amp = 20; // default, will be changed later | |||
phlist[ix].pitch1 = 255; | |||
phlist[ix].pitch2 = 255; | |||
ix++; | |||
} | |||
} | |||
phlist[ix].newword = 2; // end of clause | |||
phlist[ix].newword = 2; // end of clause | |||
phlist[ix].phcode = phonPAUSE; | |||
phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes | |||
phlist[ix].length = post_pause; // length of the pause, depends on the punctuation | |||
phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes | |||
phlist[ix].length = post_pause; // length of the pause, depends on the punctuation | |||
phlist[ix].sourceix = end_sourceix; | |||
phlist[ix].synthflags = 0; | |||
phlist[ix++].ph = phoneme_tab[phonPAUSE]; |
@@ -40,10 +40,10 @@ extern int saved_parameters[]; | |||
// convert from words-per-minute to internal speed factor | |||
// Use this to calibrate speed for wpm 80-350 | |||
static unsigned char speed_lookup[] = { | |||
255, 255, 255, 255, 255, // 80 | |||
253, 249, 245, 242, 238, // 85 | |||
235, 232, 228, 225, 222, // 90 | |||
218, 216, 213, 210, 207, // 95 | |||
255, 255, 255, 255, 255, // 80 | |||
253, 249, 245, 242, 238, // 85 | |||
235, 232, 228, 225, 222, // 90 | |||
218, 216, 213, 210, 207, // 95 | |||
204, 201, 198, 196, 193, // 100 | |||
191, 188, 186, 183, 181, // 105 | |||
179, 176, 174, 172, 169, // 110 | |||
@@ -56,54 +56,54 @@ static unsigned char speed_lookup[] = { | |||
118, 117, 115, 114, 113, // 145 | |||
112, 111, 110, 109, 107, // 150 | |||
106, 105, 104, 103, 102, // 155 | |||
101, 100, 99, 98, 97,// 160 | |||
96, 95, 94, 93, 92, // 165 | |||
91, 90, 89, 89, 88, // 170 | |||
87, 86, 85, 84, 83, // 175 | |||
82, 82, 81, 80, 80, // 180 | |||
79, 78, 77, 76, 76, // 185 | |||
75, 75, 74, 73, 72, // 190 | |||
71, 71, 70, 69, 69, // 195 | |||
68, 67, 67, 66, 66, // 200 | |||
65, 64, 64, 63, 62, // 205 | |||
62, 61, 61, 60, 59, // 210 | |||
59, 58, 58, 57, 57, // 215 | |||
56, 56, 55, 54, 54, // 220 | |||
53, 53, 52, 52, 52, // 225 | |||
51, 50, 50, 49, 49, // 230 | |||
48, 48, 47, 47, 46, // 235 | |||
46, 46, 45, 45, 44, // 240 | |||
44, 44, 43, 43, 42, // 245 | |||
41, 40, 40, 40, 39, // 250 | |||
39, 39, 38, 38, 38, // 255 | |||
37, 37, 37, 36, 36, // 260 | |||
35, 35, 35, 35, 34, // 265 | |||
34, 34, 33, 33, 33, // 270 | |||
32, 32, 31, 31, 31, // 275 | |||
30, 30, 30, 29, 29, // 280 | |||
29, 29, 28, 28, 27, // 285 | |||
27, 27, 27, 26, 26, // 290 | |||
26, 26, 25, 25, 25, // 295 | |||
24, 24, 24, 24, 23, // 300 | |||
23, 23, 23, 22, 22, // 305 | |||
22, 21, 21, 21, 21, // 310 | |||
20, 20, 20, 20, 19, // 315 | |||
19, 19, 18, 18, 17, // 320 | |||
17, 17, 16, 16, 16, // 325 | |||
16, 16, 16, 15, 15, // 330 | |||
15, 15, 14, 14, 14, // 335 | |||
13, 13, 13, 12, 12, // 340 | |||
12, 12, 11, 11, 11, // 345 | |||
11, 10, 10, 10, 9, // 350 | |||
9, 9, 8, 8, 8, // 355 | |||
101, 100, 99, 98, 97, // 160 | |||
96, 95, 94, 93, 92, // 165 | |||
91, 90, 89, 89, 88, // 170 | |||
87, 86, 85, 84, 83, // 175 | |||
82, 82, 81, 80, 80, // 180 | |||
79, 78, 77, 76, 76, // 185 | |||
75, 75, 74, 73, 72, // 190 | |||
71, 71, 70, 69, 69, // 195 | |||
68, 67, 67, 66, 66, // 200 | |||
65, 64, 64, 63, 62, // 205 | |||
62, 61, 61, 60, 59, // 210 | |||
59, 58, 58, 57, 57, // 215 | |||
56, 56, 55, 54, 54, // 220 | |||
53, 53, 52, 52, 52, // 225 | |||
51, 50, 50, 49, 49, // 230 | |||
48, 48, 47, 47, 46, // 235 | |||
46, 46, 45, 45, 44, // 240 | |||
44, 44, 43, 43, 42, // 245 | |||
41, 40, 40, 40, 39, // 250 | |||
39, 39, 38, 38, 38, // 255 | |||
37, 37, 37, 36, 36, // 260 | |||
35, 35, 35, 35, 34, // 265 | |||
34, 34, 33, 33, 33, // 270 | |||
32, 32, 31, 31, 31, // 275 | |||
30, 30, 30, 29, 29, // 280 | |||
29, 29, 28, 28, 27, // 285 | |||
27, 27, 27, 26, 26, // 290 | |||
26, 26, 25, 25, 25, // 295 | |||
24, 24, 24, 24, 23, // 300 | |||
23, 23, 23, 22, 22, // 305 | |||
22, 21, 21, 21, 21, // 310 | |||
20, 20, 20, 20, 19, // 315 | |||
19, 19, 18, 18, 17, // 320 | |||
17, 17, 16, 16, 16, // 325 | |||
16, 16, 16, 15, 15, // 330 | |||
15, 15, 14, 14, 14, // 335 | |||
13, 13, 13, 12, 12, // 340 | |||
12, 12, 11, 11, 11, // 345 | |||
11, 10, 10, 10, 9, // 350 | |||
9, 9, 8, 8, 8, // 355 | |||
}; | |||
// speed_factor1 adjustments for speeds 350 to 374: pauses | |||
static unsigned char pause_factor_350[] = { | |||
22, 22, 22, 22, 22, 22, 22, 21, 21, 21, // 350 | |||
21, 20, 20, 19, 19, 18, 17, 16, 15, 15, // 360 | |||
15, 15, 15, 15, 15 | |||
}; // 370 | |||
15, 15, 15, 15, 15 // 370 | |||
}; | |||
// wav_factor adjustments for speeds 350 to 450 | |||
// Use this to calibrate speed for wpm 350-450 | |||
@@ -114,22 +114,22 @@ static unsigned char wav_factor_350[] = { | |||
111, 111, 110, 109, 108, // 365 | |||
107, 106, 106, 104, 103, // 370 | |||
103, 102, 102, 102, 101, // 375 | |||
101, 99, 98, 98, 97,// 380 | |||
96, 96, 95, 94, 93, // 385 | |||
91, 90, 91, 90, 89, // 390 | |||
88, 86, 85, 86, 85, // 395 | |||
85, 84, 82, 81, 80, // 400 | |||
79, 77, 78, 78, 76, // 405 | |||
77, 75, 75, 74, 73, // 410 | |||
71, 72, 70, 69, 69, // 415 | |||
69, 67, 65, 64, 63, // 420 | |||
63, 63, 61, 61, 59, // 425 | |||
59, 59, 58, 56, 57, // 430 | |||
58, 56, 54, 53, 52, // 435 | |||
52, 53, 52, 52, 50, // 440 | |||
48, 47, 47, 45, 46, // 445 | |||
45 | |||
}; // 450 | |||
101, 99, 98, 98, 97, // 380 | |||
96, 96, 95, 94, 93, // 385 | |||
91, 90, 91, 90, 89, // 390 | |||
88, 86, 85, 86, 85, // 395 | |||
85, 84, 82, 81, 80, // 400 | |||
79, 77, 78, 78, 76, // 405 | |||
77, 75, 75, 74, 73, // 410 | |||
71, 72, 70, 69, 69, // 415 | |||
69, 67, 65, 64, 63, // 420 | |||
63, 63, 61, 61, 59, // 425 | |||
59, 59, 58, 56, 57, // 430 | |||
58, 56, 54, 53, 52, // 435 | |||
52, 53, 52, 52, 50, // 440 | |||
48, 47, 47, 45, 46, // 445 | |||
45 // 450 | |||
}; | |||
static int speed1 = 130; | |||
static int speed2 = 121; | |||
@@ -148,7 +148,7 @@ void SetSpeed(int control) | |||
speed.loud_consonants = 0; | |||
speed.min_sample_len = 450; | |||
speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change | |||
speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change | |||
speed.lenmod2_factor = 100; | |||
speed.min_pause = 5; | |||
@@ -232,9 +232,9 @@ void SetSpeed(int control) | |||
s1 = (x * voice->speedf1)/256; | |||
if (wpm >= 170) | |||
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
else | |||
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
if (wpm >= 350) | |||
speed.wav_factor = wav_factor_350[wpm-350]; | |||
@@ -245,10 +245,10 @@ void SetSpeed(int control) | |||
speed.min_sample_len = 420 - (wpm - 440); | |||
} | |||
// adjust for different sample rates | |||
// adjust for different sample rates | |||
speed.min_sample_len = (speed.min_sample_len * samplerate_native) / 22050; | |||
speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
speed.clause_pause_factor = 0; | |||
if (wpm > 430) | |||
@@ -268,11 +268,11 @@ void SetSpeed(int control) | |||
} | |||
} | |||
#else // not using sonic speed-up | |||
#else | |||
void SetSpeed(int control) | |||
{ | |||
// This is the earlier version of SetSpeed() before sonic speed-up was added | |||
// This is the earlier version of SetSpeed() before sonic speed-up was added | |||
int x; | |||
int s1; | |||
int wpm; | |||
@@ -280,7 +280,7 @@ void SetSpeed(int control) | |||
speed.loud_consonants = 0; | |||
speed.min_sample_len = 450; | |||
speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change | |||
speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change | |||
speed.lenmod2_factor = 100; | |||
wpm = embedded_value[EMBED_S]; | |||
@@ -332,9 +332,9 @@ void SetSpeed(int control) | |||
s1 = (x * voice->speedf1)/256; | |||
if (wpm >= 170) | |||
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
else | |||
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
if (wpm >= 350) | |||
speed.wav_factor = wav_factor_350[wpm-350]; | |||
@@ -345,7 +345,7 @@ void SetSpeed(int control) | |||
speed.min_sample_len = 420 - (wpm - 440); | |||
} | |||
speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
speed.clause_pause_factor = 0; | |||
if (wpm > 430) | |||
@@ -367,11 +367,10 @@ void SetSpeed(int control) | |||
#endif | |||
void SetParameter(int parameter, int value, int relative) | |||
{ | |||
// parameter: reset-all, amp, pitch, speed, linelength, expression, capitals, number grouping | |||
// relative 0=absolute 1=relative | |||
// parameter: reset-all, amp, pitch, speed, linelength, expression, capitals, number grouping | |||
// relative 0=absolute 1=relative | |||
int new_value = value; | |||
int default_value; | |||
@@ -432,7 +431,7 @@ static void DoEmbedded2(int *embix) | |||
if ((word & 0x1f) == EMBED_S) { | |||
// speed | |||
SetEmbedded(word & 0x7f, word >> 8); // adjusts embedded_value[EMBED_S] | |||
SetEmbedded(word & 0x7f, word >> 8); // adjusts embedded_value[EMBED_S] | |||
SetSpeed(1); | |||
} | |||
} while ((word & 0x80) == 0); | |||
@@ -529,7 +528,7 @@ void CalcLengths(Translator *tr) | |||
if ((p->ph->phflags & phSIBILANT) && next->type == phSTOP && !next->newword) { | |||
if (prev->type == phVOWEL) | |||
p->length = 200; // ?? should do this if it's from a prefix | |||
p->length = 200; // ?? should do this if it's from a prefix | |||
else | |||
p->length = 150; | |||
} else | |||
@@ -553,7 +552,7 @@ void CalcLengths(Translator *tr) | |||
p->prepause = 40; | |||
if (prev->type == phVOWEL) { | |||
p->prepause = 0; // use murmur instead to link from the preceding vowel | |||
p->prepause = 0; // use murmur instead to link from the preceding vowel | |||
} else if (prev->type == phPAUSE) { | |||
// reduce by the length of the preceding pause | |||
if (prev->length < p->prepause) | |||
@@ -575,8 +574,8 @@ void CalcLengths(Translator *tr) | |||
break; | |||
case phLIQUID: | |||
case phNASAL: | |||
p->amp = tr->stress_amps[0]; // unless changed later | |||
p->length = 256; // TEMPORARY | |||
p->amp = tr->stress_amps[0]; // unless changed later | |||
p->length = 256; // TEMPORARY | |||
min_drop = 0; | |||
if (p->newword) { | |||
@@ -698,7 +697,7 @@ void CalcLengths(Translator *tr) | |||
length_mod = length_mod / 128; | |||
if (length_mod < 8) | |||
length_mod = 8; // restrict how much lengths can be reduced | |||
length_mod = 8; // restrict how much lengths can be reduced | |||
if (stress >= 7) { | |||
// tonic syllable, include a constant component so it doesn't decrease directly with speed | |||
@@ -724,7 +723,7 @@ void CalcLengths(Translator *tr) | |||
// this is the last syllable in the clause, lengthen it - more for short vowels | |||
len = (p->ph->std_length * 2); | |||
if (tr->langopts.stress_flags & S_EO_CLAUSE1) | |||
len = 200; // don't lengthen short vowels more than long vowels at end-of-clause | |||
len = 200; // don't lengthen short vowels more than long vowels at end-of-clause | |||
length_mod = length_mod * (256 + (280 - len)/3)/256; | |||
} | |||
@@ -748,7 +747,7 @@ void CalcLengths(Translator *tr) | |||
// pre-vocalic part | |||
// set last-pitch | |||
env2 = p->env + 1; // version for use with preceding semi-vowel | |||
env2 = p->env + 1; // version for use with preceding semi-vowel | |||
if (p->tone_ph != 0) { | |||
InterpretPhoneme2(p->tone_ph, &phdata_tone); | |||
@@ -761,7 +760,7 @@ void CalcLengths(Translator *tr) | |||
if (pre_sonorant || pre_voiced) { | |||
// set pitch for pre-vocalic part | |||
if (pitch_start == 255) | |||
last_pitch = pitch_start; // pitch is not set | |||
last_pitch = pitch_start; // pitch is not set | |||
if (pitch_start - last_pitch > 16) | |||
last_pitch = pitch_start - 16; |
@@ -76,12 +76,12 @@ t_espeak_callback *synth_callback = NULL; | |||
int (*uri_callback)(int, const char *, const char *) = NULL; | |||
int (*phoneme_callback)(const char *) = NULL; | |||
char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
extern int saved_parameters[N_SPEECH_PARAM]; // Parameters saved on synthesis start | |||
void WVoiceChanged(voice_t *wvoice) | |||
{ | |||
// Voice change in wavegen | |||
// Voice change in wavegen | |||
voice_samplerate = wvoice->samplerate; | |||
} | |||
@@ -235,7 +235,7 @@ static void select_output(espeak_AUDIO_OUTPUT output_type) | |||
my_mode = output_type; | |||
my_audio = NULL; | |||
synchronous_mode = 1; | |||
option_waveout = 1; // inhibit portaudio callback from wavegen.cpp | |||
option_waveout = 1; // inhibit portaudio callback from wavegen.cpp | |||
out_samplerate = 0; | |||
switch (my_mode) | |||
@@ -265,7 +265,7 @@ int GetFileLength(const char *filename) | |||
return 0; | |||
if (S_ISDIR(statbuf.st_mode)) | |||
return -2; // a directory | |||
return -2; // a directory | |||
return statbuf.st_size; | |||
} | |||
@@ -275,7 +275,7 @@ char *Alloc(int size) | |||
{ | |||
char *p; | |||
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; | |||
} | |||
@@ -302,7 +302,7 @@ static void init_path(const char *path) | |||
if ((env = getenv("ESPEAK_DATA_PATH")) != NULL) { | |||
sprintf(path_home, "%s/espeak-data", env); | |||
if (GetFileLength(path_home) == -2) | |||
return; // an espeak-data directory exists | |||
return; // an espeak-data directory exists | |||
} | |||
buf[0] = 0; | |||
@@ -324,7 +324,7 @@ static void init_path(const char *path) | |||
if ((env = getenv("ESPEAK_DATA_PATH")) != NULL) { | |||
snprintf(path_home, sizeof(path_home), "%s/espeak-data", env); | |||
if (GetFileLength(path_home) == -2) | |||
return; // an espeak-data directory exists | |||
return; // an espeak-data directory exists | |||
} | |||
snprintf(path_home, sizeof(path_home), "%s/espeak-data", getenv("HOME")); | |||
@@ -337,7 +337,7 @@ static int initialise(int control) | |||
{ | |||
int param; | |||
int result; | |||
int srate = 22050; // default sample rate 22050 Hz | |||
int srate = 22050; // default sample rate 22050 Hz | |||
err = EE_OK; | |||
LoadConfig(); | |||
@@ -380,7 +380,7 @@ static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, | |||
#endif | |||
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_ssml = flags & espeakSSML; | |||
@@ -402,13 +402,13 @@ static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, | |||
if (my_mode == AUDIO_OUTPUT_SYNCH_PLAYBACK) { | |||
for (;;) { | |||
#ifdef PLATFORM_WINDOWS | |||
Sleep(300); // 0.3s | |||
Sleep(300); // 0.3s | |||
#else | |||
#ifdef USE_NANOSLEEP | |||
struct timespec period; | |||
struct timespec remaining; | |||
period.tv_sec = 0; | |||
period.tv_nsec = 300000000; // 0.3 sec | |||
period.tv_nsec = 300000000; // 0.3 sec | |||
nanosleep(&period, &remaining); | |||
#else | |||
sleep(1); | |||
@@ -446,7 +446,7 @@ static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, | |||
} else | |||
finished = synth_callback((short *)outbuf, length, event_list); | |||
if (finished) { | |||
SpeakNextClause(NULL, 0, 2); // stop | |||
SpeakNextClause(NULL, 0, 2); // stop | |||
break; | |||
} | |||
@@ -465,9 +465,9 @@ static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, | |||
if (dispatch_audio(NULL, 0, NULL) < 0) // TBD: test case | |||
return err = EE_INTERNAL_ERROR; | |||
} else | |||
synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data | |||
synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data | |||
#else | |||
synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data | |||
synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data | |||
#endif | |||
break; | |||
} | |||
@@ -615,7 +615,7 @@ void sync_espeak_Key(const char *key) | |||
my_unique_identifier = 0; | |||
my_user_data = NULL; | |||
Synthesize(0, key, 0); // speak key as a text string | |||
Synthesize(0, key, 0); // speak key as a text string | |||
} | |||
void sync_espeak_Char(wchar_t character) | |||
@@ -959,18 +959,19 @@ ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist) | |||
ESPEAK_API void espeak_SetPhonemeTrace(int phonememode, FILE *stream) | |||
{ | |||
ENTER("espeak_SetPhonemes"); | |||
/* phonememode: Controls the output of phoneme symbols for the text | |||
bits 0-2: | |||
value=0 No phoneme output (default) | |||
value=1 Output the translated phoneme symbols for the text | |||
value=2 as (1), but produces IPA phoneme names rather than ascii | |||
bit 3: output a trace of how the translation was done (showing the matching rules and list entries) | |||
bit 4: produce pho data for mbrola | |||
bit 7: use (bits 8-23) as a tie within multi-letter phonemes names | |||
bits 8-23: separator character, between phoneme names | |||
stream output stream for the phoneme symbols (and trace). If stream=NULL then it uses stdout. | |||
*/ | |||
/* phonememode: Controls the output of phoneme symbols for the text | |||
bits 0-2: | |||
value=0 No phoneme output (default) | |||
value=1 Output the translated phoneme symbols for the text | |||
value=2 as (1), but produces IPA phoneme names rather than ascii | |||
bit 3: output a trace of how the translation was done (showing the matching rules and list entries) | |||
bit 4: produce pho data for mbrola | |||
bit 7: use (bits 8-23) as a tie within multi-letter phonemes names | |||
bits 8-23: separator character, between phoneme names | |||
stream output stream for the phoneme symbols (and trace). If stream=NULL then it uses stdout. | |||
*/ | |||
option_phonemes = phonememode; | |||
f_trans = stream; | |||
if (stream == NULL) | |||
@@ -1007,7 +1008,7 @@ ESPEAK_API espeak_ERROR espeak_Cancel(void) | |||
wave_close(my_audio); | |||
SHOW_TIME("espeak_Cancel > LEAVE"); | |||
#endif | |||
embedded_value[EMBED_T] = 0; // reset echo for pronunciation announcements | |||
embedded_value[EMBED_T] = 0; // reset echo for pronunciation announcements | |||
for (int i = 0; i < N_SPEECH_PARAM; i++) | |||
SetParameter(i, saved_parameters[i], 0); |
@@ -63,10 +63,10 @@ static double read_double(FILE *stream) | |||
float polint(float xa[], float ya[], int n, float x) | |||
{ | |||
// General polinomial interpolation routine, xa[1...n] ya[1...n] | |||
// General polinomial interpolation routine, xa[1...n] ya[1...n] | |||
int i, m, ns = 1; | |||
float den, dif, dift, ho, hp, w; | |||
float y; // result | |||
float y; // result | |||
float c[9], d[9]; | |||
dif = fabs(x-xa[1]); | |||
@@ -86,7 +86,7 @@ float polint(float xa[], float ya[], int n, float x) | |||
hp = xa[i+m]-x; | |||
w = c[i+1]-d[i]; | |||
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; | |||
d[i] = hp*den; | |||
c[i] = ho*den; | |||
@@ -265,7 +265,8 @@ static float GetFrameLength(SpectSeq *spect, int frame) | |||
if (frame >= spect->numframes-1) return 0; | |||
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; | |||
} | |||
return (spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust; | |||
@@ -289,11 +290,11 @@ int LoadSpectSeq(SpectSeq *spect, const char *filename) | |||
fread(&id2, sizeof(uint32_t), 1, stream); | |||
if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEQ)) | |||
spect->file_format = 0; // eSpeak formants | |||
spect->file_format = 0; // eSpeak formants | |||
else if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEK)) | |||
spect->file_format = 1; // formants for Klatt synthesizer | |||
spect->file_format = 1; // formants for Klatt synthesizer | |||
else if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSQ2)) | |||
spect->file_format = 2; // formants for Klatt synthesizer | |||
spect->file_format = 2; // formants for Klatt synthesizer | |||
else { | |||
fprintf(stderr, "Unsupported spectral file format.\n"); | |||
fclose(stream); |
@@ -26,7 +26,6 @@ extern "C" | |||
#define MAX_DISPLAY_FREQ 9500 | |||
#define FRAME_HEIGHT 240 | |||
#define T_ZOOMOUT 301 | |||
#define T_ZOOMIN 302 | |||
#define T_USEPITCHENV 303 | |||
@@ -50,7 +49,6 @@ extern "C" | |||
#define T_KOPEN 320 | |||
#define T_FNZ 321 | |||
#define FILEID1_SPECTSEQ 0x43455053 | |||
#define FILEID2_SPECTSEQ 0x51455354 // for eSpeak sequence | |||
#define FILEID2_SPECTSEK 0x4b455354 // for Klatt sequence | |||
@@ -64,7 +62,6 @@ extern "C" | |||
#define FILEID1_PRAATSEQ 0x41415250 | |||
#define FILEID2_PRAATSEQ 0x51455354 | |||
typedef struct { | |||
unsigned short pitch1; | |||
unsigned short pitch2; | |||
@@ -74,7 +71,7 @@ typedef struct { | |||
typedef struct { | |||
short freq; | |||
short bandw; | |||
} formant_t; | |||
} formant_t; | |||
typedef struct { | |||
short pkfreq; | |||
@@ -84,8 +81,7 @@ typedef struct { | |||
short klt_bw; | |||
short klt_ap; | |||
short klt_bp; | |||
} peak_t; | |||
} peak_t; | |||
typedef struct { | |||
int keyframe; | |||
@@ -100,11 +96,11 @@ typedef struct { | |||
unsigned short nx; | |||
short markers; | |||
int max_y; | |||
USHORT *spect; // sqrt of harmonic amplitudes, 1-nx at 'pitch' | |||
USHORT *spect; // sqrt of harmonic amplitudes, 1-nx at 'pitch' | |||
short klatt_param[N_KLATTP2]; | |||
formant_t formants[N_PEAKS]; // this is just the estimate given by Praat | |||
formant_t formants[N_PEAKS]; // this is just the estimate given by Praat | |||
peak_t peaks[N_PEAKS]; | |||
} SpectFrame; | |||
@@ -69,8 +69,6 @@ typedef signed __int32 intptr_t; | |||
#endif | |||
#endif | |||
typedef struct { | |||
const char *mnem; | |||
int value; |
@@ -106,7 +106,7 @@ static int mbr_name_prefix = 0; | |||
espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate) | |||
{ | |||
// Load a phoneme name translation table from espeak-data/mbrola | |||
// Load a phoneme name translation table from espeak-data/mbrola | |||
int size; | |||
int ix; | |||
@@ -141,16 +141,16 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int | |||
close_MBR(); | |||
#endif | |||
#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"); | |||
return EE_INTERNAL_ERROR; | |||
} | |||
#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; | |||
setNoError_MBR(1); // don't stop on phoneme errors | |||
setNoError_MBR(1); // don't stop on phoneme errors | |||
// read eSpeak's mbrola phoneme translation data, eg. en1_phtrans | |||
sprintf(path, "%s/mbrola_ph/%s", path_home, phtrans); | |||
@@ -180,14 +180,15 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int | |||
else | |||
SetParameter(espeakVOICETYPE, 1, 0); | |||
strcpy(mbrola_name, mbrola_voice); | |||
mbrola_delay = 1000; // improve synchronization of events | |||
mbrola_delay = 1000; // improve synchronization of events | |||
return EE_OK; | |||
} | |||
static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev, PHONEME_TAB *ph_next, int *name2, int *split, int *control) | |||
{ | |||
// Look up a phoneme in the mbrola phoneme name translation table | |||
// It may give none, 1, or 2 mbrola phonemes | |||
// Look up a phoneme in the mbrola phoneme name translation table | |||
// It may give none, 1, or 2 mbrola phonemes | |||
MBROLA_TAB *pr; | |||
PHONEME_TAB *other_ph; | |||
int found = 0; | |||
@@ -218,7 +219,7 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev | |||
if (pr->control & 2) | |||
other_ph = ph_prev; | |||
else if ((pr->control & 8) && ((plist+1)->newword)) | |||
other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary | |||
other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary | |||
else | |||
other_ph = ph_next; | |||
@@ -228,14 +229,14 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev | |||
found = 1; | |||
} | |||
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; | |||
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; | |||
if ((pr->control & 0x20) && (plist->stresslevel < plist->wordstress)) | |||
found = 0; // only in stressed syllables | |||
found = 0; // only in stressed syllables | |||
if (found) { | |||
*name2 = pr->mbr_name2; | |||
@@ -262,7 +263,7 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev | |||
static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
{ | |||
// final=1: only give the final pitch value. | |||
// final=1: only give the final pitch value. | |||
int x; | |||
int ix; | |||
int pitch_base; | |||
@@ -273,7 +274,7 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
int min = 999; | |||
int y_max = 0; | |||
int y_min = 0; | |||
int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s) | |||
int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s) | |||
int y2; | |||
int y[4]; | |||
int env_split; | |||
@@ -311,7 +312,7 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
y[3] = y[2] + (127 - y[2])/2; | |||
// set initial pitch | |||
p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12 | |||
p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12 | |||
p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base; | |||
if (split >= 0) { | |||
@@ -355,7 +356,7 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbrola) | |||
{ | |||
// Generate a mbrola pho file | |||
// Generate a mbrola pho file | |||
unsigned int name; | |||
int len; | |||
int len1; | |||
@@ -412,7 +413,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
if (name == 0) { | |||
phix++; | |||
continue; // ignore this phoneme | |||
continue; // ignore this phoneme | |||
} | |||
if ((ph->type == phPAUSE) && (name == ph->mnemonic)) { | |||
@@ -446,10 +447,10 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
case phVOWEL: | |||
len = ph->std_length; | |||
if (p->synthflags & SFLAG_LENGTHEN) | |||
len += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol | |||
len += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol | |||
if (ph_next->type == phPAUSE) | |||
len += 50; // lengthen vowels before a pause | |||
len += 50; // lengthen vowels before a pause | |||
len = (len * p->length)/256; | |||
if (name2 == 0) { | |||
@@ -477,7 +478,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
InterpretPhoneme(NULL, 0, p, &phdata, NULL); | |||
len = DoSample3(&phdata, 0, -1); | |||
len = (len * 1000)/samplerate; // convert to mS | |||
len = (len * 1000)/samplerate; // convert to mS | |||
len += PauseLength(p->prepause, 1); | |||
break; | |||
case phVSTOP: | |||
@@ -487,10 +488,10 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
len = 0; | |||
InterpretPhoneme(NULL, 0, p, &phdata, NULL); | |||
if (p->synthflags & SFLAG_LENGTHEN) | |||
len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc. | |||
len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc. | |||
len += DoSample3(&phdata, p->length, -1); | |||
len = (len * 1000)/samplerate; // convert to mS | |||
len = (len * 1000)/samplerate; // convert to mS | |||
break; | |||
case phNASAL: | |||
if (next->type != phVOWEL) { | |||
@@ -528,11 +529,11 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
} | |||
if (f_mbrola) | |||
fwrite(mbr_buf, 1, (ptr-mbr_buf), f_mbrola); // write .pho to a file | |||
fwrite(mbr_buf, 1, (ptr-mbr_buf), f_mbrola); // write .pho to a file | |||
else { | |||
int res = write_MBR(mbr_buf); | |||
if (res < 0) | |||
return 0; /* don't get stuck on error */ | |||
return 0; // don't get stuck on error | |||
if (res == 0) | |||
return 1; | |||
wcmdq[wcmdq_tail][0] = WCMD_MBROLA_DATA; | |||
@@ -575,7 +576,7 @@ int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
int MbrolaFill(int length, int resume, int amplitude) | |||
{ | |||
// Read audio data from Mbrola (length is in millisecs) | |||
// Read audio data from Mbrola (length is in millisecs) | |||
static int n_samples; | |||
int req_samples, result; | |||
@@ -596,7 +597,7 @@ int MbrolaFill(int length, int resume, int amplitude) | |||
for (ix = 0; ix < result; ix++) { | |||
value16 = out_ptr[0] + (out_ptr[1] << 8); | |||
value = value16 * amplitude; | |||
value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices | |||
value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices | |||
if (value > 0x7fff) | |||
value = 0x7fff; | |||
if (value < -0x8000) | |||
@@ -611,12 +612,12 @@ int MbrolaFill(int length, int resume, int amplitude) | |||
void MbrolaReset(void) | |||
{ | |||
// Reset the Mbrola engine and flush the pending audio | |||
// Reset the Mbrola engine and flush the pending audio | |||
reset_MBR(); | |||
} | |||
#else // INCLUDE_MBROLA | |||
#else | |||
// mbrola interface is not compiled, provide dummy functions. | |||
@@ -639,4 +640,4 @@ void MbrolaReset(void) | |||
{ | |||
} | |||
#endif // INCLUDE_MBROLA | |||
#endif |
@@ -59,7 +59,7 @@ int n_phoneme_tables; | |||
PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; | |||
int phoneme_tab_number = 0; | |||
int wavefile_ix; // a wavefile to play along with the synthesis | |||
int wavefile_ix; // a wavefile to play along with the synthesis | |||
int wavefile_amp; | |||
int wavefile_ix2; | |||
int wavefile_amp2; | |||
@@ -128,8 +128,8 @@ int LoadPhData(int *srate) | |||
n_tunes = length / sizeof(TUNE); | |||
// read the version number and sample rate from the first 8 bytes of phondata | |||
version = 0; // bytes 0-3, version number | |||
rate = 0; // bytes 4-7, sample rate | |||
version = 0; // bytes 0-3, version number | |||
rate = 0; // bytes 4-7, sample rate | |||
for (ix = 0; ix < 4; ix++) { | |||
version += (wavefile_data[ix] << (ix*8)); | |||
rate += (wavefile_data[ix+4] << (ix*8)); | |||
@@ -248,7 +248,7 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, | |||
if (which == 1) | |||
nf = seq_break + 1; | |||
else { | |||
frames = &frames_buf[seq_break]; // body of vowel, skip past initial frames | |||
frames = &frames_buf[seq_break]; // body of vowel, skip past initial frames | |||
nf -= seq_break; | |||
} | |||
} | |||
@@ -289,16 +289,15 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, | |||
if (length1 > 0) { | |||
if (which == 2) { | |||
// adjust the length of the main part to match the standard length specified for the vowel | |||
// less the front part of the vowel and any added suffix | |||
// less the front part of the vowel and any added suffix | |||
length_std = fmt_params->std_length + seq_len_adjust - 45; | |||
if (length_std < 10) | |||
length_std = 10; | |||
if (plist->synthflags & SFLAG_LENGTHEN) | |||
length_std += (phoneme_tab[phonLENGTHEN]->std_length * 2); // phoneme was followed by an extra : symbol | |||
// can adjust vowel length for stressed syllables here | |||
length_std += (phoneme_tab[phonLENGTHEN]->std_length * 2); // phoneme was followed by an extra : symbol | |||
// can adjust vowel length for stressed syllables here | |||
length_factor = (length_std * 256)/ length1; | |||
@@ -335,7 +334,7 @@ unsigned char *GetEnvelope(int index) | |||
{ | |||
if (index == 0) { | |||
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]; | |||
} | |||
@@ -364,14 +363,14 @@ static void SetUpPhonemeTable(int number, int recursing) | |||
n_phoneme_tab = ph_code; | |||
if (recursing == 0) | |||
phoneme_tab_flags[ph_code] |= 1; // not inherited | |||
phoneme_tab_flags[ph_code] |= 1; // not inherited | |||
} | |||
} | |||
void SelectPhonemeTable(int number) | |||
{ | |||
n_phoneme_tab = 0; | |||
SetUpPhonemeTable(number, 0); // recursively for included phoneme tables | |||
SetUpPhonemeTable(number, 0); // recursively for included phoneme tables | |||
n_phoneme_tab++; | |||
current_phoneme_table = number; | |||
} | |||
@@ -394,8 +393,8 @@ int LookupPhonemeTable(const char *name) | |||
int SelectPhonemeTableName(const char *name) | |||
{ | |||
// Look up a phoneme set by name, and select it if it exists | |||
// Returns the phoneme table number | |||
// Look up a phoneme set by name, and select it if it exists | |||
// Returns the phoneme table number | |||
int ix; | |||
if ((ix = LookupPhonemeTable(name)) == -1) | |||
@@ -407,7 +406,7 @@ int SelectPhonemeTableName(const char *name) | |||
void LoadConfig(void) | |||
{ | |||
// Load configuration file, if one exists | |||
// Load configuration file, if one exists | |||
char buf[sizeof(path_home)+10]; | |||
FILE *f; | |||
int ix; | |||
@@ -462,8 +461,8 @@ static void InvalidInstn(PHONEME_TAB *ph, int instn) | |||
static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, int control) | |||
{ | |||
// condition: | |||
// 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress | |||
// condition: | |||
// 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress | |||
int stress_level; | |||
PHONEME_LIST *pl; | |||
@@ -476,7 +475,7 @@ static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, | |||
if (phoneme_tab[plist[1].phcode]->type == phVOWEL) | |||
pl = &plist[1]; | |||
else | |||
return false; // no stress elevel for this consonant | |||
return false; // no stress elevel for this consonant | |||
} | |||
stress_level = pl->stresslevel & 0xf; | |||
@@ -574,19 +573,19 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
switch (which) | |||
{ | |||
case 0: // prevPh | |||
case 5: // prevPhW | |||
case 0: // prevPh | |||
case 5: // prevPhW | |||
plist--; | |||
check_endtype = 1; | |||
break; | |||
case 1: // thisPh | |||
case 1: // thisPh | |||
break; | |||
case 2: // nextPh | |||
case 4: // nextPhW | |||
case 2: // nextPh | |||
case 4: // nextPhW | |||
plist++; | |||
break; | |||
case 3: // next2Ph | |||
case 6: // next2PhW | |||
case 3: // next2Ph | |||
case 6: // next2PhW | |||
plist += 2; | |||
break; | |||
case 7: | |||
@@ -600,13 +599,13 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
} | |||
} | |||
break; | |||
case 8: // prevVowel in this word | |||
case 8: // prevVowel in this word | |||
if ((worddata == NULL) || (worddata->prev_vowel.ph == NULL)) | |||
return false; // no previous vowel | |||
return false; // no previous vowel | |||
plist = &(worddata->prev_vowel); | |||
check_endtype = 1; | |||
break; | |||
case 9: // next3PhW | |||
case 9: // next3PhW | |||
for (ix = 1; ix <= 3; ix++) { | |||
if (plist[ix].sourceix) | |||
return false; | |||
@@ -641,8 +640,8 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
// not an exact match, check for a vowel type (eg. #i ) | |||
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; | |||
@@ -670,16 +669,16 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
case 3: | |||
case 4: | |||
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); | |||
case 6: // isWordStart | |||
case 6: // isWordStart | |||
return plist->sourceix != 0; | |||
case 7: // notWordStart | |||
case 7: // notWordStart | |||
return plist->sourceix == 0; | |||
case 8: // isWordEnd | |||
case 8: // isWordEnd | |||
return plist[1].sourceix || (plist[1].ph->type == phPAUSE); | |||
break; | |||
case 9: // isAfterStress | |||
case 9: // isAfterStress | |||
if (plist->sourceix != 0) | |||
return false; | |||
do { | |||
@@ -689,28 +688,27 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
} while (plist->sourceix == 0); | |||
break; | |||
case 10: // isNotVowel | |||
case 10: // isNotVowel | |||
return ph->type != phVOWEL; | |||
case 11: // isFinalVowel | |||
case 11: // isFinalVowel | |||
for (;;) { | |||
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 | |||
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) | |||
return false; | |||
} | |||
break; | |||
case 12: // isVoiced | |||
case 12: // isVoiced | |||
return (ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED); | |||
case 13: // isFirstVowel | |||
case 13: // isFirstVowel | |||
return CountVowelPosition(plist) == 1; | |||
case 14: // isSecondVowel | |||
case 14: // isSecondVowel | |||
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) | |||
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; | |||
for (;;) { | |||
@@ -719,13 +717,13 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
if (plist->ph->phflags & phFLAG1) | |||
count++; | |||
else | |||
break; // stop when we find a vowel without flag1 | |||
break; // stop when we find a vowel without flag1 | |||
} | |||
if (plist->sourceix != 0) | |||
break; | |||
} | |||
return count > 0; | |||
case 0x10: // isTranslationGiven | |||
case 0x10: // isTranslationGiven | |||
return (plist->synthflags & SFLAG_DICTIONARY) != 0; | |||
} | |||
break; | |||
@@ -736,11 +734,11 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
// Other conditions | |||
switch (data) | |||
{ | |||
case 1: // PreVoicing | |||
case 1: // PreVoicing | |||
return control & 1; | |||
case 2: // KlattSynth | |||
case 2: // KlattSynth | |||
return voice->klattv[0] != 0; | |||
case 3: // MbrolaSynth | |||
case 3: // MbrolaSynth | |||
return mbrola_name[0] != 0; | |||
} | |||
} | |||
@@ -755,16 +753,16 @@ static void SwitchOnVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT | |||
if (instn_type == 2) { | |||
phdata->pd_control |= pd_FORNEXTPH; | |||
voweltype = plist[1].ph->start_type; // SwitchNextVowelType | |||
voweltype = plist[1].ph->start_type; // SwitchNextVowelType | |||
} else | |||
voweltype = plist[-1].ph->end_type; // SwitchPrevVowelType | |||
voweltype = plist[-1].ph->end_type; // SwitchPrevVowelType | |||
voweltype -= phonVOWELTYPES; | |||
if ((voweltype >= 0) && (voweltype < 6)) { | |||
prog = *p_prog + voweltype*2; | |||
phdata->sound_addr[instn_type] = (((prog[1] & 0xf) << 16) + prog[2]) * 4; | |||
x = (prog[1] >> 4) & 0xff; | |||
phdata->sound_param[instn_type] = x; // sign extend | |||
phdata->sound_param[instn_type] = x; // sign extend | |||
} | |||
*p_prog += 12; | |||
@@ -795,7 +793,7 @@ int NumInstnWords(USHORT *prog) | |||
case 6: | |||
type2 = (instn & 0xf00) >> 9; | |||
if ((type2 == 5) || (type2 == 6)) | |||
return 12; // switch on vowel type | |||
return 12; // switch on vowel type | |||
return 1; | |||
case 2: | |||
case 3: | |||
@@ -818,9 +816,10 @@ int NumInstnWords(USHORT *prog) | |||
void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata) | |||
{ | |||
// control: | |||
// bit 0: PreVoicing | |||
// bit 8: change phonemes | |||
// control: | |||
// bit 0: PreVoicing | |||
// bit 8: change phonemes | |||
PHONEME_TAB *ph; | |||
USHORT *prog; | |||
USHORT instn; | |||
@@ -835,7 +834,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
#define N_RETURN 10 | |||
int n_return = 0; | |||
USHORT *return_addr[N_RETURN]; // return address stack | |||
USHORT *return_addr[N_RETURN]; // return address stack | |||
ph = plist->ph; | |||
@@ -860,7 +859,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
switch (instn >> 12) | |||
{ | |||
case 0: // 0xxx | |||
case 0: // 0xxx | |||
data = instn & 0xff; | |||
if (instn2 == 0) { | |||
@@ -870,10 +869,8 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
case i_RETURN: | |||
end_flag = 1; | |||
break; | |||
case i_CONTINUE: | |||
break; | |||
default: | |||
InvalidInstn(ph, instn); | |||
break; | |||
@@ -897,7 +894,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
phdata->ipa_string[ix] = 0; | |||
} else if (instn2 < N_PHONEME_DATA_PARAM) { | |||
if (instn2 == i_CHANGE_PHONEME2) | |||
phdata->pd_param[i_CHANGE_PHONEME] = data; // also set ChangePhoneme | |||
phdata->pd_param[i_CHANGE_PHONEME] = data; // also set ChangePhoneme | |||
phdata->pd_param[instn2] = data; | |||
if ((instn2 == i_CHANGE_PHONEME) && (control & 0x100)) { | |||
// found ChangePhoneme() in PhonemeList mode, exit | |||
@@ -908,13 +905,13 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
break; | |||
case 1: | |||
if (tr == NULL) | |||
break; // ignore if in synthesis stage | |||
break; // ignore if in synthesis stage | |||
if (instn2 < 8) { | |||
// ChangeIf | |||
if (StressCondition(tr, plist, instn2 & 7, 1) == true) { | |||
phdata->pd_param[i_CHANGE_PHONEME] = instn & 0xff; | |||
end_flag = 1; // change phoneme, exit | |||
end_flag = 1; // change phoneme, exit | |||
} | |||
} | |||
break; | |||
@@ -947,7 +944,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
// instruction after a condition is not JUMP_FALSE, so skip the instruction. | |||
prog += NumInstnWords(prog); | |||
if ((prog[0] & 0xfe00) == 0x6000) | |||
prog++; // and skip ELSE jump | |||
prog++; // and skip ELSE jump | |||
} | |||
} | |||
prog--; | |||
@@ -959,16 +956,13 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
case 0: | |||
prog += (instn & 0xff) - 1; | |||
break; | |||
case 4: | |||
// conditional jumps should have been processed in the Condition section | |||
break; | |||
case 5: // NexttVowelStarts | |||
case 5: // NexttVowelStarts | |||
SwitchOnVowelType(plist, phdata, &prog, 2); | |||
break; | |||
case 6: // PrevVowelTypeEndings | |||
case 6: // PrevVowelTypeEndings | |||
SwitchOnVowelType(plist, phdata, &prog, 3); | |||
break; | |||
} | |||
@@ -995,7 +989,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
break; | |||
} | |||
break; | |||
case 10: // Vowelin, Vowelout | |||
case 10: // Vowelin, Vowelout | |||
if (instn2 == 1) | |||
ix = 0; | |||
else | |||
@@ -1005,11 +999,11 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
phdata->vowel_transition[ix+1] = (prog[2] << 16) + prog[3]; | |||
prog += 3; | |||
break; | |||
case 11: // FMT | |||
case 12: // WAV | |||
case 13: // VowelStart | |||
case 14: // VowelEnd | |||
case 15: // addWav | |||
case 11: // FMT | |||
case 12: // WAV | |||
case 13: // VowelStart | |||
case 14: // VowelEnd | |||
case 15: // addWav | |||
instn2 = (instn >> 12) - 11; | |||
phdata->sound_addr[instn2] = ((instn & 0xf) << 18) + (prog[1] << 2); | |||
param_sc = phdata->sound_param[instn2] = (instn >> 4) & 0xff; | |||
@@ -1054,17 +1048,17 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
plist->std_length = phdata->pd_param[i_SET_LENGTH]; | |||
if (phdata->sound_addr[0] != 0) { | |||
plist->phontab_addr = phdata->sound_addr[0]; // FMT address | |||
plist->phontab_addr = phdata->sound_addr[0]; // FMT address | |||
plist->sound_param = phdata->sound_param[0]; | |||
} else { | |||
plist->phontab_addr = phdata->sound_addr[1]; // WAV address | |||
plist->phontab_addr = phdata->sound_addr[1]; // WAV address | |||
plist->sound_param = phdata->sound_param[1]; | |||
} | |||
} | |||
void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata) | |||
{ | |||
// Examine the program of a single isolated phoneme | |||
// Examine the program of a single isolated phoneme | |||
int ix; | |||
PHONEME_LIST plist[4]; | |||
memset(plist, 0, sizeof(plist)); |
@@ -76,7 +76,7 @@ static PHONEME_LIST next_pause; | |||
const char *WordToString(unsigned int word) | |||
{ | |||
// Convert a phoneme mnemonic word into a string | |||
// Convert a phoneme mnemonic word into a string | |||
int ix; | |||
static char buf[5]; | |||
@@ -131,11 +131,11 @@ static void DoAmplitude(int amp, unsigned char *amp_env) | |||
intptr_t *q; | |||
last_amp_cmd = wcmdq_tail; | |||
amp_length = 0; // total length of vowel with this amplitude envelope | |||
amp_length = 0; // total length of vowel with this amplitude envelope | |||
q = wcmdq[wcmdq_tail]; | |||
q[0] = WCMD_AMPLITUDE; | |||
q[1] = 0; // fill in later from amp_length | |||
q[1] = 0; // fill in later from amp_length | |||
q[2] = (intptr_t)amp_env; | |||
q[3] = amp; | |||
WcmdqInc(); | |||
@@ -154,14 +154,14 @@ static void DoPitch(unsigned char *env, int pitch1, int pitch2) | |||
env = envelope_data[PITCHfall]; | |||
} | |||
last_pitch_cmd = wcmdq_tail; | |||
pitch_length = 0; // total length of spect with this pitch envelope | |||
pitch_length = 0; // total length of spect with this pitch envelope | |||
if (pitch2 < 0) | |||
pitch2 = 0; | |||
q = wcmdq[wcmdq_tail]; | |||
q[0] = WCMD_PITCH; | |||
q[1] = 0; // length, fill in later from pitch_length | |||
q[1] = 0; // length, fill in later from pitch_length | |||
q[2] = (intptr_t)env; | |||
q[3] = (pitch1 << 16) + pitch2; | |||
WcmdqInc(); | |||
@@ -179,16 +179,16 @@ int PauseLength(int pause, int control) | |||
} else | |||
len = (pause * speed.wav_factor)/256; | |||
if (len < speed.min_pause) { | |||
len = speed.min_pause; // mS, limit the amount to which pauses can be shortened | |||
} | |||
if (len < speed.min_pause) | |||
len = speed.min_pause; // mS, limit the amount to which pauses can be shortened | |||
return len; | |||
} | |||
static void DoPause(int length, int control) | |||
{ | |||
// length in nominal mS | |||
// control = 1, less shortening at fast speeds | |||
// length in nominal mS | |||
// control = 1, less shortening at fast speeds | |||
unsigned int len; | |||
int srate2; | |||
@@ -198,9 +198,9 @@ static void DoPause(int length, int control) | |||
len = PauseLength(length, control); | |||
if (len < 90000) | |||
len = (len * samplerate) / 1000; // convert from mS to number of samples | |||
len = (len * samplerate) / 1000; // convert from mS to number of samples | |||
else { | |||
srate2 = samplerate / 25; // avoid overflow | |||
srate2 = samplerate / 25; // avoid overflow | |||
len = (len * srate2) / 40; | |||
} | |||
} | |||
@@ -218,7 +218,7 @@ static void DoPause(int length, int control) | |||
} | |||
} | |||
extern int seq_len_adjust; // temporary fix to advance the start point for playing the wav sample | |||
extern int seq_len_adjust; // temporary fix to advance the start point for playing the wav sample | |||
static int DoSample2(int index, int which, int std_length, int control, int length_mod, int amp) | |||
{ | |||
@@ -235,7 +235,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
p = &wavefile_data[index]; | |||
wav_scale = p[2]; | |||
wav_length = (p[1] * 256); | |||
wav_length += p[0]; // length in bytes | |||
wav_length += p[0]; // length in bytes | |||
if (wav_length == 0) | |||
return 0; | |||
@@ -243,7 +243,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
min_length = speed.min_sample_len; | |||
if (wav_scale == 0) | |||
min_length *= 2; // 16 bit samples | |||
min_length *= 2; // 16 bit samples | |||
if (std_length > 0) { | |||
std_length = (std_length * samplerate)/1000; | |||
@@ -294,7 +294,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
last_wcmdq = wcmdq_tail; | |||
q = wcmdq[wcmdq_tail]; | |||
q[0] = WCMD_WAVE2; | |||
q[1] = length | (wav_length << 16); // length in samples | |||
q[1] = length | (wav_length << 16); // length in samples | |||
q[2] = (intptr_t)(&wavefile_data[index]); | |||
q[3] = wav_scale + (amp << 8); | |||
WcmdqInc(); | |||
@@ -312,7 +312,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
last_wcmdq = wcmdq_tail; | |||
q = wcmdq[wcmdq_tail]; | |||
q[0] = WCMD_WAVE; | |||
q[1] = x; // length in samples | |||
q[1] = x; // length in samples | |||
q[2] = (intptr_t)(&wavefile_data[index]); | |||
q[3] = wav_scale + (amp << 8); | |||
WcmdqInc(); | |||
@@ -325,7 +325,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
last_wcmdq = wcmdq_tail; | |||
q = wcmdq[wcmdq_tail]; | |||
q[0] = WCMD_WAVE; | |||
q[1] = len4*2; // length in samples | |||
q[1] = len4*2; // length in samples | |||
q[2] = (intptr_t)(&wavefile_data[index+x]); | |||
q[3] = wav_scale + (amp << 8); | |||
WcmdqInc(); | |||
@@ -340,7 +340,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
last_wcmdq = wcmdq_tail; | |||
q = wcmdq[wcmdq_tail]; | |||
q[0] = WCMD_WAVE; | |||
q[1] = length; // length in samples | |||
q[1] = length; // length in samples | |||
q[2] = (intptr_t)(&wavefile_data[index+x]); | |||
q[3] = wav_scale + (amp << 8); | |||
WcmdqInc(); | |||
@@ -381,7 +381,7 @@ static frame_t *AllocFrame() | |||
// enough to use a round-robin without checks. | |||
// Only needed for modifying spectra for blending to consonants | |||
#define N_FRAME_POOL N_WCMDQ | |||
#define N_FRAME_POOL N_WCMDQ | |||
static int ix = 0; | |||
static frame_t frame_pool[N_FRAME_POOL]; | |||
@@ -393,15 +393,15 @@ static frame_t *AllocFrame() | |||
static void set_frame_rms(frame_t *fr, int new_rms) | |||
{ | |||
// Each frame includes its RMS amplitude value, so to set a new | |||
// RMS just adjust the formant amplitudes by the appropriate ratio | |||
// Each frame includes its RMS amplitude value, so to set a new | |||
// RMS just adjust the formant amplitudes by the appropriate ratio | |||
int x; | |||
int h; | |||
int ix; | |||
static const short sqrt_tab[200] = { | |||
0, 64, 90, 110, 128, 143, 156, 169, 181, 192, 202, 212, 221, 230, 239, 247, | |||
0, 64, 90, 110, 128, 143, 156, 169, 181, 192, 202, 212, 221, 230, 239, 247, | |||
256, 263, 271, 278, 286, 293, 300, 306, 313, 320, 326, 332, 338, 344, 350, 356, | |||
362, 367, 373, 378, 384, 389, 394, 399, 404, 409, 414, 419, 424, 429, 434, 438, | |||
443, 448, 452, 457, 461, 465, 470, 474, 478, 483, 487, 491, 495, 499, 503, 507, | |||
@@ -422,11 +422,11 @@ static void set_frame_rms(frame_t *fr, int new_rms) | |||
return; | |||
} | |||
if (fr->rms == 0) return; // check for divide by zero | |||
if (fr->rms == 0) return; // check for divide by zero | |||
x = (new_rms * 64)/fr->rms; | |||
if (x >= 200) x = 199; | |||
x = sqrt_tab[x]; // sqrt(new_rms/fr->rms)*0x200; | |||
x = sqrt_tab[x]; // sqrt(new_rms/fr->rms)*0x200; | |||
for (ix = 0; ix < 8; ix++) { | |||
h = fr->fheight[ix] * x; | |||
@@ -436,7 +436,7 @@ static void set_frame_rms(frame_t *fr, int new_rms) | |||
static void formants_reduce_hf(frame_t *fr, int level) | |||
{ | |||
// change height of peaks 2 to 8, percentage | |||
// change height of peaks 2 to 8, percentage | |||
int ix; | |||
int x; | |||
@@ -451,7 +451,8 @@ static void formants_reduce_hf(frame_t *fr, int level) | |||
static frame_t *CopyFrame(frame_t *frame1, int copy) | |||
{ | |||
// create a copy of the specified frame in temporary buffer | |||
// create a copy of the specified frame in temporary buffer | |||
frame_t *frame2; | |||
if ((copy == 0) && (frame1->frflags & FRFLAG_COPIED)) { | |||
@@ -492,7 +493,7 @@ static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj | |||
fr->ffreq[3] += f3_adj; | |||
if (flags & 0x20) | |||
f3_adj = -f3_adj; // . reverse direction for f4,f5 change | |||
f3_adj = -f3_adj; // reverse direction for f4,f5 change | |||
fr->ffreq[4] += f3_adj; | |||
fr->ffreq[5] += f3_adj; | |||
@@ -521,7 +522,7 @@ static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj | |||
static int VowelCloseness(frame_t *fr) | |||
{ | |||
// return a value 0-3 depending on the vowel's f1 | |||
// return a value 0-3 depending on the vowel's f1 | |||
int f1; | |||
if ((f1 = fr->ffreq[1]) < 300) | |||
@@ -550,11 +551,11 @@ int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsig | |||
int flags; | |||
int vcolour; | |||
#define N_VCOLOUR 2 | |||
// percentage change for each formant in 256ths | |||
#define N_VCOLOUR 2 | |||
// percentage change for each formant in 256ths | |||
static short vcolouring[N_VCOLOUR][5] = { | |||
{ 243, 272, 256, 256, 256 }, // palatal consonant follows | |||
{ 256, 256, 240, 240, 240 }, // retroflex | |||
{ 243, 272, 256, 256, 256 }, // palatal consonant follows | |||
{ 256, 256, 240, 240, 240 }, // retroflex | |||
}; | |||
frame_t *fr = NULL; | |||
@@ -578,13 +579,13 @@ int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsig | |||
flags |= 8; | |||
if (which == 1) { | |||
/* entry to vowel */ | |||
// entry to vowel | |||
fr = CopyFrame(seq[0].frame, 0); | |||
seq[0].frame = fr; | |||
seq[0].length = VOWEL_FRONT_LENGTH; | |||
if (len > 0) | |||
seq[0].length = len; | |||
seq[0].frflags |= FRFLAG_LEN_MOD2; // reduce length modification | |||
seq[0].frflags |= FRFLAG_LEN_MOD2; // reduce length modification | |||
fr->frflags |= FRFLAG_LEN_MOD2; | |||
next_rms = seq[1].frame->rms; | |||
@@ -649,11 +650,11 @@ int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsig | |||
if (flags & 4) | |||
fr->frflags |= FRFLAG_FORMANT_RATE; | |||
if (flags & 2) | |||
fr->frflags |= FRFLAG_BREAK; // don't merge with next frame | |||
fr->frflags |= FRFLAG_BREAK; // don't merge with next frame | |||
} | |||
if (flags & 0x40) | |||
DoPause(20, 0); // add a short pause after the consonant | |||
DoPause(20, 0); // add a short pause after the consonant | |||
if (flags & 16) | |||
return len; | |||
@@ -705,7 +706,7 @@ static void SmoothSpect(void) | |||
q[3] = (intptr_t)frame2; | |||
frame1 = frame2; | |||
} else | |||
break; // doesn't follow on from previous frame | |||
break; // doesn't follow on from previous frame | |||
frame = frame2 = (frame_t *)q[2]; | |||
modified = 0; | |||
@@ -714,7 +715,7 @@ static void SmoothSpect(void) | |||
break; | |||
if (frame->frflags & FRFLAG_FORMANT_RATE) | |||
len = (len * 12)/10; // allow slightly greater rate of change for this frame (was 12/10) | |||
len = (len * 12)/10; // allow slightly greater rate of change for this frame (was 12/10) | |||
for (pk = 0; pk < 6; pk++) { | |||
int f1, f2; | |||
@@ -778,7 +779,7 @@ static void SmoothSpect(void) | |||
q[2] = (intptr_t)frame2; | |||
frame1 = frame2; | |||
} else | |||
break; // doesn't follow on from previous frame | |||
break; // doesn't follow on from previous frame | |||
} | |||
frame = frame2 = (frame_t *)q[3]; | |||
@@ -788,7 +789,7 @@ static void SmoothSpect(void) | |||
break; | |||
if (frame1->frflags & FRFLAG_FORMANT_RATE) | |||
len = (len *6)/5; // allow slightly greater rate of change for this frame | |||
len = (len *6)/5; // allow slightly greater rate of change for this frame | |||
for (pk = 0; pk < 6; pk++) { | |||
int f1, f2; | |||
@@ -868,10 +869,10 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
length_mod = plist->length; | |||
if (length_mod == 0) length_mod = 256; | |||
length_min = (samplerate/70); // greater than one cycle at low pitch (Hz) | |||
length_min = (samplerate/70); // greater than one cycle at low pitch (Hz) | |||
if (which == 2) { | |||
if ((translator->langopts.param[LOPT_LONG_VOWEL_THRESHOLD] > 0) && ((this_ph->std_length >= translator->langopts.param[LOPT_LONG_VOWEL_THRESHOLD]) || (plist->synthflags & SFLAG_LENGTHEN) || (this_ph->phflags & phLONG))) | |||
length_min *= 2; // ensure long vowels are longer | |||
length_min *= 2; // ensure long vowels are longer | |||
} | |||
if (which == 1) { | |||
@@ -885,7 +886,7 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
modn_flags = 0; | |||
frames = LookupSpect(this_ph, which, fmt_params, &n_frames, plist); | |||
if (frames == NULL) | |||
return 0; // not found | |||
return 0; // not found | |||
if (fmt_params->fmt_amp != fmt_amplitude) { | |||
// an amplitude adjustment is specified for this sequence | |||
@@ -940,7 +941,7 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
} | |||
if ((this_ph->type == phVOWEL) && (which == 2)) { | |||
SmoothSpect(); // process previous syllable | |||
SmoothSpect(); // process previous syllable | |||
// remember the point in the output queue of the centre of the vowel | |||
syllable_centre = wcmdq_tail; | |||
@@ -949,11 +950,10 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
length_sum = 0; | |||
for (frameix = 1; frameix < n_frames; frameix++) { | |||
length_factor = length_mod; | |||
if (frames[frameix-1].frflags & FRFLAG_LEN_MOD) { // reduce effect of length mod | |||
if (frames[frameix-1].frflags & FRFLAG_LEN_MOD) // reduce effect of length mod | |||
length_factor = (length_mod*(256-speed.lenmod_factor) + 256*speed.lenmod_factor)/256; | |||
} else if (frames[frameix-1].frflags & FRFLAG_LEN_MOD2) { // reduce effect of length mod, used for the start of a vowel | |||
else if (frames[frameix-1].frflags & FRFLAG_LEN_MOD2) // reduce effect of length mod, used for the start of a vowel | |||
length_factor = (length_mod*(256-speed.lenmod2_factor) + 256*speed.lenmod2_factor)/256; | |||
} | |||
frame_length = frames[frameix-1].length; | |||
len = (frame_length * samplerate)/1000; | |||
@@ -984,7 +984,7 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
if (frame1->frflags & FRFLAG_MODULATE) | |||
modulation = 6; | |||
if ((frameix == n_frames-1) && (modn_flags & 0xf00)) | |||
modulation |= modn_flags; // before or after a glottal stop | |||
modulation |= modn_flags; // before or after a glottal stop | |||
} | |||
len = frame_lengths[frameix]; | |||
@@ -1023,8 +1023,9 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
void DoMarker(int type, int char_posn, int length, int value) | |||
{ | |||
// This could be used to return an index to the word currently being spoken | |||
// Type 1=word, 2=sentence, 3=named marker, 4=play audio, 5=end | |||
// This could be used to return an index to the word currently being spoken | |||
// Type 1=word, 2=sentence, 3=named marker, 4=play audio, 5=end | |||
if (WcmdqFree() > 5) { | |||
wcmdq[wcmdq_tail][0] = WCMD_MARKER + (type << 8); | |||
wcmdq[wcmdq_tail][1] = (char_posn & 0xffffff) | (length << 24); | |||
@@ -1035,15 +1036,16 @@ void DoMarker(int type, int char_posn, int length, int value) | |||
void DoPhonemeMarker(int type, int char_posn, int length, char *name) | |||
{ | |||
// This could be used to return an index to the word currently being spoken | |||
// Type 7=phoneme | |||
// This could be used to return an index to the word currently being spoken | |||
// Type 7=phoneme | |||
int *p; | |||
if (WcmdqFree() > 5) { | |||
wcmdq[wcmdq_tail][0] = WCMD_MARKER + (type << 8); | |||
wcmdq[wcmdq_tail][1] = (char_posn & 0xffffff) | (length << 24); | |||
p = (int *)name; | |||
wcmdq[wcmdq_tail][2] = p[0]; // up to 8 bytes of UTF8 characters | |||
wcmdq[wcmdq_tail][2] = p[0]; // up to 8 bytes of UTF8 characters | |||
wcmdq[wcmdq_tail][3] = p[1]; | |||
WcmdqInc(); | |||
} | |||
@@ -1052,7 +1054,7 @@ void DoPhonemeMarker(int type, int char_posn, int length, char *name) | |||
#if HAVE_SONIC_H | |||
void DoSonicSpeed(int value) | |||
{ | |||
// value, multiplier * 1024 | |||
// value, multiplier * 1024 | |||
wcmdq[wcmdq_tail][0] = WCMD_SONIC_SPEED; | |||
wcmdq[wcmdq_tail][1] = value; | |||
WcmdqInc(); | |||
@@ -1061,7 +1063,7 @@ void DoSonicSpeed(int value) | |||
void DoVoiceChange(voice_t *v) | |||
{ | |||
// allocate memory for a copy of the voice data, and free it in wavegenfill() | |||
// allocate memory for a copy of the voice data, and free it in wavegenfill() | |||
voice_t *v2; | |||
v2 = (voice_t *)malloc(sizeof(voice_t)); | |||
@@ -1074,7 +1076,7 @@ void DoVoiceChange(voice_t *v) | |||
void DoEmbedded(int *embix, int sourceix) | |||
{ | |||
// There were embedded commands in the text at this point | |||
unsigned int word; // bit 7=last command for this word, bits 5,6 sign, bits 0-4 command | |||
unsigned int word; // bit 7=last command for this word, bits 5,6 sign, bits 0-4 command | |||
unsigned int value; | |||
int command; | |||
@@ -1084,36 +1086,36 @@ void DoEmbedded(int *embix, int sourceix) | |||
command = word & 0x7f; | |||
if (command == 0) | |||
return; // error | |||
return; // error | |||
(*embix)++; | |||
switch (command & 0x1f) | |||
{ | |||
case EMBED_S: // speed | |||
SetEmbedded((command & 0x60) + EMBED_S2, value); // adjusts embedded_value[EMBED_S2] | |||
case EMBED_S: // speed | |||
SetEmbedded((command & 0x60) + EMBED_S2, value); // adjusts embedded_value[EMBED_S2] | |||
SetSpeed(2); | |||
break; | |||
case EMBED_I: // play dynamically loaded wav data (sound icon) | |||
case EMBED_I: // play dynamically loaded wav data (sound icon) | |||
if ((int)value < n_soundicon_tab) { | |||
if (soundicon_tab[value].length != 0) { | |||
DoPause(10, 0); // ensure a break in the speech | |||
DoPause(10, 0); // ensure a break in the speech | |||
wcmdq[wcmdq_tail][0] = WCMD_WAVE; | |||
wcmdq[wcmdq_tail][1] = soundicon_tab[value].length; | |||
wcmdq[wcmdq_tail][2] = (intptr_t)soundicon_tab[value].data + 44; // skip WAV header | |||
wcmdq[wcmdq_tail][3] = 0x1500; // 16 bit data, amp=21 | |||
wcmdq[wcmdq_tail][2] = (intptr_t)soundicon_tab[value].data + 44; // skip WAV header | |||
wcmdq[wcmdq_tail][3] = 0x1500; // 16 bit data, amp=21 | |||
WcmdqInc(); | |||
} | |||
} | |||
break; | |||
case EMBED_M: // named marker | |||
case EMBED_M: // named marker | |||
DoMarker(espeakEVENT_MARK, (sourceix & 0x7ff) + clause_start_char, 0, value); | |||
break; | |||
case EMBED_U: // play sound | |||
DoMarker(espeakEVENT_PLAY, count_characters+1, 0, value); // always occurs at end of clause | |||
case EMBED_U: // play sound | |||
DoMarker(espeakEVENT_PLAY, count_characters+1, 0, value); // always occurs at end of clause | |||
break; | |||
default: | |||
DoPause(10, 0); // ensure a break in the speech | |||
DoPause(10, 0); // ensure a break in the speech | |||
wcmdq[wcmdq_tail][0] = WCMD_EMBEDDED; | |||
wcmdq[wcmdq_tail][1] = command; | |||
wcmdq[wcmdq_tail][2] = value; | |||
@@ -1177,7 +1179,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
last_pitch_cmd = -1; | |||
memset(vowel_transition, 0, sizeof(vowel_transition)); | |||
memset(&worddata, 0, sizeof(worddata)); | |||
DoPause(0, 0); // isolate from the previous clause | |||
DoPause(0, 0); // isolate from the previous clause | |||
} | |||
while ((ix < (*n_ph)) && (ix < N_PHONEME_LIST-2)) { | |||
@@ -1186,12 +1188,12 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
if (p->type == phPAUSE) | |||
free_min = 10; | |||
else if (p->type != phVOWEL) | |||
free_min = 15; // we need less Q space for non-vowels, and we need to generate phonemes after a vowel so that the pitch_length is filled in | |||
free_min = 15; // we need less Q space for non-vowels, and we need to generate phonemes after a vowel so that the pitch_length is filled in | |||
else | |||
free_min = MIN_WCMDQ; // 25 | |||
free_min = MIN_WCMDQ; | |||
if (WcmdqFree() <= free_min) | |||
return 1; // wait | |||
return 1; // wait | |||
prev = &phoneme_list[ix-1]; | |||
next = &phoneme_list[ix+1]; | |||
@@ -1209,10 +1211,10 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
sourceix = (p->sourceix & 0x7ff) + clause_start_char; | |||
if (p->newword & 4) | |||
DoMarker(espeakEVENT_SENTENCE, sourceix, 0, count_sentences); // start of sentence | |||
DoMarker(espeakEVENT_SENTENCE, sourceix, 0, count_sentences); // start of sentence | |||
if (p->newword & 1) | |||
DoMarker(espeakEVENT_WORD, sourceix, p->sourceix >> 11, clause_start_word + word_count++); // NOTE, this count doesn't include multiple-word pronunciations in *_list. eg (of a) | |||
DoMarker(espeakEVENT_WORD, sourceix, p->sourceix >> 11, clause_start_word + word_count++); // NOTE, this count doesn't include multiple-word pronunciations in *_list. eg (of a) | |||
} | |||
EndAmplitude(); | |||
@@ -1271,7 +1273,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
InterpretPhoneme(NULL, 0, p, &phdata, &worddata); | |||
if (p->synthflags & SFLAG_LENGTHEN) | |||
DoSample3(&phdata, p->length, 0); // play it twice for [s:] etc. | |||
DoSample3(&phdata, p->length, 0); // play it twice for [s:] etc. | |||
DoSample3(&phdata, p->length, 0); | |||
break; | |||
case phVSTOP: | |||
@@ -1381,7 +1383,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
} else if (prev->type == phVOWEL && (p->synthflags & SFLAG_SEQCONTINUE)) | |||
DoSpect2(p->ph, 0, &fmtp, p, 0); | |||
else { | |||
last_frame = NULL; // only for nasal ? | |||
last_frame = NULL; // only for nasal ? | |||
DoSpect2(p->ph, 0, &fmtp, p, 0); | |||
last_frame = NULL; | |||
} | |||
@@ -1461,23 +1463,23 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
modulation = 2; | |||
if (stress <= 1) | |||
modulation = 1; // 16ths | |||
modulation = 1; // 16ths | |||
else if (stress >= 7) | |||
modulation = 3; | |||
if (prev->type == phVSTOP || prev->type == phVFRICATIVE) { | |||
DoAmplitude(p->amp, amp_env); | |||
DoPitch(pitch_env, p->pitch1, p->pitch2); // don't use prevocalic rising tone | |||
DoPitch(pitch_env, p->pitch1, p->pitch2); // don't use prevocalic rising tone | |||
DoSpect2(ph, 1, &fmtp, p, modulation); | |||
} else if (prev->type == phLIQUID || prev->type == phNASAL) { | |||
DoAmplitude(p->amp, amp_env); | |||
DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone | |||
DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone | |||
DoPitch(pitch_env, p->pitch1, p->pitch2); | |||
} else if (vowelstart_prev) { | |||
// VowelStart from the previous phoneme, but not phLIQUID or phNASAL | |||
DoPitch(envelope_data[PITCHrise], p->pitch2 - 15, p->pitch2); | |||
DoAmplitude(p->amp-1, amp_env); | |||
DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone | |||
DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone | |||
DoPitch(pitch_env, p->pitch1, p->pitch2); | |||
} else { | |||
if (!(p->synthflags & SFLAG_SEQCONTINUE)) { | |||
@@ -1505,12 +1507,11 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
InterpretPhoneme(NULL, 0, next, &phdata_next, NULL); | |||
fmtp.use_vowelin = 1; | |||
fmtp.transition0 = phdata_next.vowel_transition[2]; // always do vowel_transition, even if ph_VWLEND ?? consider [N] | |||
fmtp.transition0 = phdata_next.vowel_transition[2]; // always do vowel_transition, even if ph_VWLEND ?? consider [N] | |||
fmtp.transition1 = phdata_next.vowel_transition[3]; | |||
if ((fmtp.fmt2_addr = phdata_next.sound_addr[pd_VWLEND]) != 0) { | |||
if ((fmtp.fmt2_addr = phdata_next.sound_addr[pd_VWLEND]) != 0) | |||
fmtp.fmt2_lenadj = phdata_next.sound_param[pd_VWLEND]; | |||
} | |||
} | |||
DoSpect2(ph, 2, &fmtp, p, modulation); | |||
@@ -1520,11 +1521,11 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
} | |||
EndPitch(1); | |||
if (*n_ph > 0) { | |||
DoMarker(espeakEVENT_END, count_characters, 0, count_sentences); // end of clause | |||
DoMarker(espeakEVENT_END, count_characters, 0, count_sentences); // end of clause | |||
*n_ph = 0; | |||
} | |||
return 0; // finished the phoneme list | |||
return 0; // finished the phoneme list | |||
} | |||
static int timer_on = 0; | |||
@@ -1553,16 +1554,16 @@ int SynthStatus() | |||
int SpeakNextClause(FILE *f_in, const void *text_in, int control) | |||
{ | |||
// Speak text from file (f_in) or memory (text_in) | |||
// control 0: start | |||
// either f_in or text_in is set, the other must be NULL | |||
// Speak text from file (f_in) or memory (text_in) | |||
// control 0: start | |||
// either f_in or text_in is set, the other must be NULL | |||
// The other calls have f_in and text_in = NULL | |||
// control 1: speak next text | |||
// 2: stop | |||
// 3: pause (toggle) | |||
// 4: is file being read (0=no, 1=yes) | |||
// 5: interrupt and flush current text. | |||
// The other calls have f_in and text_in = NULL | |||
// control 1: speak next text | |||
// 2: stop | |||
// 3: pause (toggle) | |||
// 4: is file being read (0=no, 1=yes) | |||
// 5: interrupt and flush current text. | |||
int clause_tone; | |||
char *voice_change; | |||
@@ -1600,7 +1601,7 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control) | |||
WavegenOpenSound(); | |||
timer_on = 1; | |||
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; | |||
} | |||
@@ -1650,7 +1651,6 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control) | |||
phoneme_callback(phon_out); | |||
} | |||
if (skipping_text) { | |||
n_phoneme_list = 0; | |||
return 1; |
@@ -22,69 +22,67 @@ extern "C" | |||
{ | |||
#endif | |||
#define espeakINITIALIZE_PHONEME_IPA 0x0002 // move this to speak_lib.h, after eSpeak version 1.46.02 | |||
#define espeakINITIALIZE_PHONEME_IPA 0x0002 // move this to speak_lib.h, after eSpeak version 1.46.02 | |||
#define N_PHONEME_LIST 1000 // enough for source[N_TR_SOURCE] full of text, else it will truncate | |||
#define N_PHONEME_LIST 1000 // enough for source[N_TR_SOURCE] full of text, else it will truncate | |||
#define MAX_HARMONIC 400 // 400 * 50Hz = 20 kHz, more than enough | |||
#define N_SEQ_FRAMES 25 // max frames in a spectrum sequence (real max is ablut 8) | |||
#define STEPSIZE 64 // 2.9mS at 22 kHz sample rate | |||
#define MAX_HARMONIC 400 // 400 * 50Hz = 20 kHz, more than enough | |||
#define N_SEQ_FRAMES 25 // max frames in a spectrum sequence (real max is ablut 8) | |||
#define STEPSIZE 64 // 2.9mS at 22 kHz sample rate | |||
// flags set for frames within a spectrum sequence | |||
#define FRFLAG_KLATT 0x01 // this frame includes extra data for Klatt synthesizer | |||
#define FRFLAG_VOWEL_CENTRE 0x02 // centre point of vowel | |||
#define FRFLAG_LEN_MOD 0x04 // reduce effect of length adjustment | |||
#define FRFLAG_BREAK_LF 0x08 // but keep f3 upwards | |||
#define FRFLAG_BREAK 0x10 // don't merge with next frame | |||
#define FRFLAG_BREAK_2 0x18 // FRFLAG_BREAK_LF or FRFLAG_BREAK | |||
#define FRFLAG_FORMANT_RATE 0x20 // Flag5 allow increased rate of change of formant freq | |||
#define FRFLAG_MODULATE 0x40 // Flag6 modulate amplitude of some cycles to give trill | |||
#define FRFLAG_DEFER_WAV 0x80 // Flag7 defer mixing WAV until the next frame | |||
#define FRFLAG_LEN_MOD2 0x4000 // reduce effect of length adjustment, used for the start of a vowel | |||
#define FRFLAG_COPIED 0x8000 // This frame has been copied into temporary rw memory | |||
#define SFLAG_SEQCONTINUE 0x01 // a liquid or nasal after a vowel, but not followed by a vowel | |||
#define SFLAG_EMBEDDED 0x02 // there are embedded commands before this phoneme | |||
#define SFLAG_SYLLABLE 0x04 // vowel or syllabic consonant | |||
#define SFLAG_LENGTHEN 0x08 // lengthen symbol : included after this phoneme | |||
#define SFLAG_DICTIONARY 0x10 // the pronunciation of this word was listed in the xx_list dictionary | |||
#define SFLAG_SWITCHED_LANG 0x20 // this word uses phonemes from a different language | |||
#define SFLAG_PROMOTE_STRESS 0x40 // this unstressed word can be promoted to stressed | |||
#define SFLAG_PREV_PAUSE 0x1000 // consider previous phoneme as pause | |||
#define SFLAG_NEXT_PAUSE 0x2000 // consider next phoneme as pause | |||
#define FRFLAG_KLATT 0x01 // this frame includes extra data for Klatt synthesizer | |||
#define FRFLAG_VOWEL_CENTRE 0x02 // centre point of vowel | |||
#define FRFLAG_LEN_MOD 0x04 // reduce effect of length adjustment | |||
#define FRFLAG_BREAK_LF 0x08 // but keep f3 upwards | |||
#define FRFLAG_BREAK 0x10 // don't merge with next frame | |||
#define FRFLAG_BREAK_2 0x18 // FRFLAG_BREAK_LF or FRFLAG_BREAK | |||
#define FRFLAG_FORMANT_RATE 0x20 // Flag5 allow increased rate of change of formant freq | |||
#define FRFLAG_MODULATE 0x40 // Flag6 modulate amplitude of some cycles to give trill | |||
#define FRFLAG_DEFER_WAV 0x80 // Flag7 defer mixing WAV until the next frame | |||
#define FRFLAG_LEN_MOD2 0x4000 // reduce effect of length adjustment, used for the start of a vowel | |||
#define FRFLAG_COPIED 0x8000 // This frame has been copied into temporary rw memory | |||
#define SFLAG_SEQCONTINUE 0x01 // a liquid or nasal after a vowel, but not followed by a vowel | |||
#define SFLAG_EMBEDDED 0x02 // there are embedded commands before this phoneme | |||
#define SFLAG_SYLLABLE 0x04 // vowel or syllabic consonant | |||
#define SFLAG_LENGTHEN 0x08 // lengthen symbol : included after this phoneme | |||
#define SFLAG_DICTIONARY 0x10 // the pronunciation of this word was listed in the xx_list dictionary | |||
#define SFLAG_SWITCHED_LANG 0x20 // this word uses phonemes from a different language | |||
#define SFLAG_PROMOTE_STRESS 0x40 // this unstressed word can be promoted to stressed | |||
#define SFLAG_PREV_PAUSE 0x1000 // consider previous phoneme as pause | |||
#define SFLAG_NEXT_PAUSE 0x2000 // consider next phoneme as pause | |||
// embedded command numbers | |||
#define EMBED_P 1 // pitch | |||
#define EMBED_S 2 // speed (used in setlengths) | |||
#define EMBED_A 3 // amplitude/volume | |||
#define EMBED_R 4 // pitch range/expression | |||
#define EMBED_H 5 // echo/reverberation | |||
#define EMBED_T 6 // different tone for announcing punctuation (not used) | |||
#define EMBED_I 7 // sound icon | |||
#define EMBED_S2 8 // speed (used in synthesize) | |||
#define EMBED_Y 9 // say-as commands | |||
#define EMBED_M 10 // mark name | |||
#define EMBED_U 11 // audio uri | |||
#define EMBED_B 12 // break | |||
#define EMBED_F 13 // emphasis | |||
#define EMBED_C 14 // capital letter indication | |||
#define EMBED_P 1 // pitch | |||
#define EMBED_S 2 // speed (used in setlengths) | |||
#define EMBED_A 3 // amplitude/volume | |||
#define EMBED_R 4 // pitch range/expression | |||
#define EMBED_H 5 // echo/reverberation | |||
#define EMBED_T 6 // different tone for announcing punctuation (not used) | |||
#define EMBED_I 7 // sound icon | |||
#define EMBED_S2 8 // speed (used in synthesize) | |||
#define EMBED_Y 9 // say-as commands | |||
#define EMBED_M 10 // mark name | |||
#define EMBED_U 11 // audio uri | |||
#define EMBED_B 12 // break | |||
#define EMBED_F 13 // emphasis | |||
#define EMBED_C 14 // capital letter indication | |||
#define N_EMBEDDED_VALUES 15 | |||
extern int embedded_value[N_EMBEDDED_VALUES]; | |||
extern int embedded_default[N_EMBEDDED_VALUES]; | |||
#define N_PEAKS 9 | |||
#define N_PEAKS2 9 // plus Notch and Fill (not yet implemented) | |||
#define N_PEAKS2 9 // plus Notch and Fill (not yet implemented) | |||
#define N_MARKERS 8 | |||
#define N_KLATTP 10 // this affects the phoneme data file format | |||
#define N_KLATTP2 14 // used in vowel files, with extra parameters for future extensions | |||
#define N_KLATTP 10 // this affects the phoneme data file format | |||
#define N_KLATTP2 14 // used in vowel files, with extra parameters for future extensions | |||
#define KLATT_AV 0 | |||
#define KLATT_FNZ 1 // nasal zero freq | |||
#define KLATT_FNZ 1 // nasal zero freq | |||
#define KLATT_Tilt 2 | |||
#define KLATT_Aspr 3 | |||
#define KLATT_Skew 4 | |||
@@ -95,38 +93,33 @@ extern int embedded_default[N_EMBEDDED_VALUES]; | |||
#define KLATT_FricBP 8 | |||
#define KLATT_Turb 9 | |||
typedef struct { // 64 bytes | |||
typedef struct { // 64 bytes | |||
short frflags; | |||
short ffreq[7]; | |||
unsigned char length; | |||
unsigned char rms; | |||
unsigned char fheight[8]; | |||
unsigned char fwidth[6]; // width/4 f0-5 | |||
unsigned char fright[3]; // width/4 f0-2 | |||
unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 | |||
unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew | |||
unsigned char klattp2[5]; // continuation of klattp[], Avp, Fric, FricBP, Turb | |||
unsigned char klatt_ap[7]; // Klatt parallel amplitude | |||
unsigned char klatt_bp[7]; // Klatt parallel bandwidth /2 | |||
unsigned char spare; // pad to multiple of 4 bytes | |||
} frame_t; // with extra Klatt parameters for parallel resonators | |||
typedef struct { // 44 bytes | |||
unsigned char fwidth[6]; // width/4 f0-5 | |||
unsigned char fright[3]; // width/4 f0-2 | |||
unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 | |||
unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew | |||
unsigned char klattp2[5]; // continuation of klattp[], Avp, Fric, FricBP, Turb | |||
unsigned char klatt_ap[7]; // Klatt parallel amplitude | |||
unsigned char klatt_bp[7]; // Klatt parallel bandwidth /2 | |||
unsigned char spare; // pad to multiple of 4 bytes | |||
} frame_t; // with extra Klatt parameters for parallel resonators | |||
typedef struct { // 44 bytes | |||
short frflags; | |||
short ffreq[7]; | |||
unsigned char length; | |||
unsigned char rms; | |||
unsigned char fheight[8]; | |||
unsigned char fwidth[6]; // width/4 f0-5 | |||
unsigned char fright[3]; // width/4 f0-2 | |||
unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 | |||
unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew | |||
} frame_t2; // without the extra Klatt parameters | |||
unsigned char fwidth[6]; // width/4 f0-5 | |||
unsigned char fright[3]; // width/4 f0-2 | |||
unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 | |||
unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew | |||
} frame_t2; // without the extra Klatt parameters | |||
// formant data used by wavegen | |||
typedef struct { | |||
@@ -138,11 +131,11 @@ typedef struct { | |||
DOUBLEX height1; | |||
DOUBLEX left1; | |||
DOUBLEX right1; | |||
DOUBLEX freq_inc; // increment by this every 64 samples | |||
DOUBLEX freq_inc; // increment by this every 64 samples | |||
DOUBLEX height_inc; | |||
DOUBLEX left_inc; | |||
DOUBLEX right_inc; | |||
} wavegen_peaks_t; | |||
} wavegen_peaks_t; | |||
typedef struct { | |||
unsigned char *pitch_env; | |||
@@ -153,8 +146,8 @@ typedef struct { | |||
int pitch_range; // Hz*256 range of envelope | |||
unsigned char *mix_wavefile; // wave file to be added to synthesis | |||
int n_mix_wavefile; // length in bytes | |||
int mix_wave_scale; // 0=2 byte samples | |||
int n_mix_wavefile; // length in bytes | |||
int mix_wave_scale; // 0=2 byte samples | |||
int mix_wave_amp; | |||
int mix_wavefile_ix; | |||
int mix_wavefile_max; // length of available WAV data (in bytes) | |||
@@ -165,30 +158,27 @@ typedef struct { | |||
int amplitude_fmt; // percentage amplitude adjustment for formant synthesis | |||
} WGEN_DATA; | |||
typedef struct { | |||
double a; | |||
double b; | |||
double c; | |||
double x1; | |||
double x2; | |||
} RESONATOR; | |||
} RESONATOR; | |||
typedef struct { | |||
short length_total; // not used | |||
unsigned char n_frames; | |||
unsigned char sqflags; | |||
frame_t2 frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence | |||
} SPECT_SEQ; // sequence of espeak formant frames | |||
frame_t2 frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence | |||
} SPECT_SEQ; // sequence of espeak formant frames | |||
typedef struct { | |||
short length_total; // not used | |||
unsigned char n_frames; | |||
unsigned char sqflags; | |||
frame_t frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence | |||
} SPECT_SEQK; // sequence of klatt formants frames | |||
frame_t frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence | |||
} SPECT_SEQK; // sequence of klatt formants frames | |||
typedef struct { | |||
short length; | |||
@@ -198,22 +188,21 @@ typedef struct { | |||
// a clause translated into phoneme codes (first stage) | |||
typedef struct { | |||
unsigned short synthflags; // NOTE Put shorts on 32bit boundaries, because of RISC OS compiler bug? | |||
unsigned short synthflags; // NOTE Put shorts on 32bit boundaries, because of RISC OS compiler bug? | |||
unsigned char phcode; | |||
unsigned char stresslevel; | |||
unsigned short sourceix; // ix into the original source text string, only set at the start of a word | |||
unsigned char wordstress; // the highest level stress in this word | |||
unsigned char wordstress; // the highest level stress in this word | |||
unsigned char tone_ph; // tone phoneme to use with this vowel | |||
} PHONEME_LIST2; | |||
typedef struct { | |||
// The first section is a copy of PHONEME_LIST2 | |||
// The first section is a copy of PHONEME_LIST2 | |||
unsigned short synthflags; | |||
unsigned char phcode; | |||
unsigned char stresslevel; | |||
unsigned short sourceix; // ix into the original source text string, only set at the start of a word | |||
unsigned char wordstress; // the highest level stress in this word | |||
unsigned char wordstress; // the highest level stress in this word | |||
unsigned char tone_ph; // tone phoneme to use with this vowel | |||
PHONEME_TAB *ph; | |||
@@ -231,7 +220,6 @@ typedef struct { | |||
int sound_param; | |||
} PHONEME_LIST; | |||
#define pd_FMT 0 | |||
#define pd_WAV 1 | |||
#define pd_VWLSTART 2 | |||
@@ -259,7 +247,6 @@ typedef struct { | |||
char ipa_string[18]; | |||
} PHONEME_DATA; | |||
typedef struct { | |||
int fmt_control; | |||
int use_vowelin; | |||
@@ -304,7 +291,6 @@ typedef struct { | |||
#define i_ADD_LENGTH 0x0c | |||
// conditions and jumps | |||
#define i_CONDITION 0x2000 | |||
#define i_OR 0x1000 // added to i_CONDITION | |||
@@ -347,23 +333,20 @@ typedef struct { | |||
#define i_isSeqFlag1 0x8f | |||
#define i_IsTranslationGiven 0x90 | |||
// place of articulation | |||
#define i_isVel 0x28 | |||
// phflags | |||
#define i_isSibilant 0x45 // bit 5 in phflags | |||
#define i_isPalatal 0x49 // bit 9 in phflags | |||
#define i_isLong 0x55 // bit 21 in phflags | |||
#define i_isRhotic 0x57 // bit 23 in phflags | |||
#define i_isSibilant 0x45 // bit 5 in phflags | |||
#define i_isPalatal 0x49 // bit 9 in phflags | |||
#define i_isLong 0x55 // bit 21 in phflags | |||
#define i_isRhotic 0x57 // bit 23 in phflags | |||
#define i_isFlag1 0x5c | |||
#define i_isFlag2 0x5d | |||
#define i_isFlag3 0x5e | |||
#define i_StressLevel 0x800 | |||
typedef struct { | |||
int name; | |||
int length; | |||
@@ -376,7 +359,7 @@ typedef struct { | |||
unsigned int next_phoneme; | |||
int mbr_name; | |||
int mbr_name2; | |||
int percent; // percentage length of first component | |||
int percent; // percentage length of first component | |||
int control; | |||
} MBROLA_TAB; | |||
@@ -392,7 +375,6 @@ typedef struct { | |||
int fast_settings[8]; | |||
} SPEED_FACTORS; | |||
typedef struct { | |||
char name[12]; | |||
unsigned char flags[4]; | |||
@@ -413,14 +395,14 @@ typedef struct { | |||
unsigned char head_max_steps; | |||
unsigned char n_head_extend; | |||
signed char unstr_start[3]; // for: onset, head, last | |||
signed char unstr_start[3]; // for: onset, head, last | |||
signed char unstr_end[3]; | |||
unsigned char nucleus0_env; // pitch envelope, tonic syllable is at end, no tail | |||
unsigned char nucleus0_env; // pitch envelope, tonic syllable is at end, no tail | |||
unsigned char nucleus0_max; | |||
unsigned char nucleus0_min; | |||
unsigned char nucleus1_env; // when followed by a tail | |||
unsigned char nucleus1_env; // when followed by a tail | |||
unsigned char nucleus1_max; | |||
unsigned char nucleus1_min; | |||
unsigned char tail_start; | |||
@@ -434,7 +416,7 @@ typedef struct { | |||
unsigned char split_tune; | |||
unsigned char spare[8]; | |||
int spare2; // the struct length should be a multiple of 4 bytes | |||
int spare2; // the struct length should be a multiple of 4 bytes | |||
} TUNE; | |||
extern int n_tunes; | |||
@@ -472,8 +454,6 @@ extern unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1]; | |||
#define WCMD_FMT_AMPLITUDE 14 | |||
#define WCMD_SONIC_SPEED 15 | |||
#define N_WCMDQ 170 | |||
#define MIN_WCMDQ 25 // need this many free entries before adding new phoneme | |||
@@ -494,7 +474,6 @@ float polint(float xa[], float ya[], int n, float x); | |||
int WavegenFill(int fill_zeros); | |||
void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr); | |||
extern unsigned char *wavefile_data; | |||
extern int samplerate; | |||
extern int samplerate_native; | |||
@@ -538,10 +517,9 @@ int Read4Bytes(FILE *f); | |||
int Reverse4Bytes(int word); | |||
int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name, int flags); | |||
#define ENV_LEN 128 // length of pitch envelopes | |||
#define PITCHfall 0 // standard pitch envelopes | |||
#define PITCHrise 2 | |||
#define PITCHfall 0 // standard pitch envelopes | |||
#define PITCHrise 2 | |||
#define N_ENVELOPE_DATA 20 | |||
extern unsigned char *envelope_data[N_ENVELOPE_DATA]; | |||
@@ -22,99 +22,96 @@ extern "C" | |||
{ | |||
#endif | |||
#define L(c1, c2) (c1<<8)+c2 // combine two characters into an integer for translator name | |||
#define L(c1, c2) (c1<<8)+c2 // combine two characters into an integer for translator name | |||
#define CTRL_EMBEDDED 0x01 // control character at the start of an embedded command | |||
#define REPLACED_E 'E' // 'e' replaced by silent e | |||
#define CTRL_EMBEDDED 0x01 // control character at the start of an embedded command | |||
#define REPLACED_E 'E' // 'e' replaced by silent e | |||
#define N_WORD_PHONEMES 200 // max phonemes in a word | |||
#define N_WORD_BYTES 160 // max bytes for the UTF8 characters in a word | |||
#define N_CLAUSE_WORDS 300 // max words in a clause | |||
#define N_TR_SOURCE 800 // the source text of a single clause (UTF8 bytes) | |||
#define N_WORD_PHONEMES 200 // max phonemes in a word | |||
#define N_WORD_BYTES 160 // max bytes for the UTF8 characters in a word | |||
#define N_CLAUSE_WORDS 300 // max words in a clause | |||
#define N_TR_SOURCE 800 // the source text of a single clause (UTF8 bytes) | |||
#define N_RULE_GROUP2 120 // max num of two-letter rule chains | |||
#define N_RULE_GROUP2 120 // max num of two-letter rule chains | |||
#define N_HASH_DICT 1024 | |||
#define N_CHARSETS 20 | |||
#define N_LETTER_GROUPS 95 // maximum is 127-32 | |||
#define N_LETTER_GROUPS 95 // maximum is 127-32 | |||
/* dictionary flags, word 1 */ | |||
// dictionary flags, word 1 | |||
// bits 0-3 stressed syllable, bit 6=unstressed | |||
#define FLAG_SKIPWORDS 0x80 | |||
#define FLAG_PREPAUSE 0x100 | |||
#define FLAG_STRESS_END 0x200 // full stress if at end of clause | |||
#define FLAG_STRESS_END2 0x400 // full stress if at end of clause, or only followed by unstressed | |||
#define FLAG_UNSTRESS_END 0x800 // reduce stress at end of clause | |||
#define FLAG_SPELLWORD 0x1000 // re-translate the word as individual letters, separated by spaces | |||
#define FLAG_ACCENT_BEFORE 0x1000 // say this accent name before the letter name | |||
#define FLAG_ABBREV 0x2000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters | |||
#define FLAG_DOUBLING 0x4000 // doubles the following consonant | |||
#define BITNUM_FLAG_ALT 14 // bit number of FLAG_ALT_TRANS - 1 | |||
#define FLAG_ALT_TRANS 0x8000 // language specific | |||
#define FLAG_ALT2_TRANS 0x10000 // language specific | |||
#define FLAG_ALT3_TRANS 0x20000 // language specific | |||
#define FLAG_ALT4_TRANS 0x40000 // language specific | |||
#define FLAG_ALT5_TRANS 0x80000 // language specific | |||
#define FLAG_ALT6_TRANS 0x100000 // language specific | |||
#define FLAG_ALT7_TRANS 0x200000 // language specific | |||
#define FLAG_COMBINE 0x800000 // combine with the next word | |||
#define FLAG_ALLOW_DOT 0x01000000 // ignore '.' after word (abbreviation) | |||
#define FLAG_NEEDS_DOT 0x02000000 // only if the word is followed by a dot | |||
#define FLAG_STRESS_END 0x200 // full stress if at end of clause | |||
#define FLAG_STRESS_END2 0x400 // full stress if at end of clause, or only followed by unstressed | |||
#define FLAG_UNSTRESS_END 0x800 // reduce stress at end of clause | |||
#define FLAG_SPELLWORD 0x1000 // re-translate the word as individual letters, separated by spaces | |||
#define FLAG_ACCENT_BEFORE 0x1000 // say this accent name before the letter name | |||
#define FLAG_ABBREV 0x2000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters | |||
#define FLAG_DOUBLING 0x4000 // doubles the following consonant | |||
#define BITNUM_FLAG_ALT 14 // bit number of FLAG_ALT_TRANS - 1 | |||
#define FLAG_ALT_TRANS 0x8000 // language specific | |||
#define FLAG_ALT2_TRANS 0x10000 // language specific | |||
#define FLAG_ALT3_TRANS 0x20000 // language specific | |||
#define FLAG_ALT4_TRANS 0x40000 // language specific | |||
#define FLAG_ALT5_TRANS 0x80000 // language specific | |||
#define FLAG_ALT6_TRANS 0x100000 // language specific | |||
#define FLAG_ALT7_TRANS 0x200000 // language specific | |||
#define FLAG_COMBINE 0x800000 // combine with the next word | |||
#define FLAG_ALLOW_DOT 0x01000000 // ignore '.' after word (abbreviation) | |||
#define FLAG_NEEDS_DOT 0x02000000 // only if the word is followed by a dot | |||
#define FLAG_WAS_UNPRONOUNCABLE 0x04000000 // the unpronounceable routine was used | |||
#define FLAG_MAX3 0x08000000 // limit to 3 repeats | |||
#define FLAG_PAUSE1 0x10000000 // shorter prepause | |||
#define FLAG_TEXTMODE 0x20000000 // word translates to replacement text, not phonemes | |||
#define FLAG_MAX3 0x08000000 // limit to 3 repeats | |||
#define FLAG_PAUSE1 0x10000000 // shorter prepause | |||
#define FLAG_TEXTMODE 0x20000000 // word translates to replacement text, not phonemes | |||
#define BITNUM_FLAG_TEXTMODE 29 | |||
#define FLAG_FOUND_ATTRIBUTES 0x40000000 // word was found in the dictionary list (has attributes) | |||
#define FLAG_FOUND 0x80000000 // pronunciation was found in the dictionary list | |||
#define FLAG_FOUND_ATTRIBUTES 0x40000000 // word was found in the dictionary list (has attributes) | |||
#define FLAG_FOUND 0x80000000 // pronunciation was found in the dictionary list | |||
// dictionary flags, word 2 | |||
#define FLAG_VERBF 0x1 /* verb follows */ | |||
#define FLAG_VERBSF 0x2 /* verb follows, may have -s suffix */ | |||
#define FLAG_NOUNF 0x4 /* noun follows */ | |||
#define FLAG_PASTF 0x8 /* past tense follows */ | |||
#define FLAG_VERB 0x10 /* pronunciation for verb */ | |||
#define FLAG_NOUN 0x20 /* pronunciation for noun */ | |||
#define FLAG_PAST 0x40 /* pronunciation for past tense */ | |||
#define FLAG_VERB_EXT 0x100 /* extend the 'verb follows' */ | |||
#define FLAG_CAPITAL 0x200 /* pronunciation if initial letter is upper case */ | |||
#define FLAG_ALLCAPS 0x400 // only if the word is all capitals | |||
#define FLAG_ACCENT 0x800 // character name is base-character name + accent name | |||
#define FLAG_HYPHENATED 0x1000 // multiple-words, but needs hyphen between parts 1 and 2 | |||
#define FLAG_SENTENCE 0x2000 // only if the clause is a sentence | |||
#define FLAG_VERBF 0x1 // verb follows | |||
#define FLAG_VERBSF 0x2 // verb follows, may have -s suffix | |||
#define FLAG_NOUNF 0x4 // noun follows | |||
#define FLAG_PASTF 0x8 // past tense follows | |||
#define FLAG_VERB 0x10 // pronunciation for verb | |||
#define FLAG_NOUN 0x20 // pronunciation for noun | |||
#define FLAG_PAST 0x40 // pronunciation for past tense | |||
#define FLAG_VERB_EXT 0x100 // extend the 'verb follows' | |||
#define FLAG_CAPITAL 0x200 // pronunciation if initial letter is upper case | |||
#define FLAG_ALLCAPS 0x400 // only if the word is all capitals | |||
#define FLAG_ACCENT 0x800 // character name is base-character name + accent name | |||
#define FLAG_HYPHENATED 0x1000 // multiple-words, but needs hyphen between parts 1 and 2 | |||
#define FLAG_SENTENCE 0x2000 // only if the clause is a sentence | |||
#define FLAG_ONLY 0x4000 | |||
#define FLAG_ONLY_S 0x8000 | |||
#define FLAG_STEM 0x10000 // must have a suffix | |||
#define FLAG_ATEND 0x20000 // use this pronunciation if at end of clause | |||
#define FLAG_ATSTART 0x40000 // use this pronunciation if at start of clause | |||
#define FLAG_NATIVE 0x80000 // not if we've switched translators | |||
#define FLAG_LOOKUP_SYMBOL 0x40000000 // to indicate called from Lookup() | |||
#define BITNUM_FLAG_ALLCAPS 0x2a | |||
#define BITNUM_FLAG_HYPHENATED 0x2c | |||
#define BITNUM_FLAG_ONLY 0x2e | |||
#define BITNUM_FLAG_ONLY_S 0x2f | |||
#define FLAG_STEM 0x10000 // must have a suffix | |||
#define FLAG_ATEND 0x20000 // use this pronunciation if at end of clause | |||
#define FLAG_ATSTART 0x40000 // use this pronunciation if at start of clause | |||
#define FLAG_NATIVE 0x80000 // not if we've switched translators | |||
#define FLAG_LOOKUP_SYMBOL 0x40000000 // to indicate called from Lookup() | |||
#define BITNUM_FLAG_ALLCAPS 0x2a | |||
#define BITNUM_FLAG_HYPHENATED 0x2c | |||
#define BITNUM_FLAG_ONLY 0x2e | |||
#define BITNUM_FLAG_ONLY_S 0x2f | |||
// wordflags, flags in source word | |||
#define FLAG_ALL_UPPER 0x1 /* no lower case letters in the word */ | |||
#define FLAG_FIRST_UPPER 0x2 /* first letter is upper case */ | |||
#define FLAG_UPPERS 0x3 // FLAG_ALL_UPPER | FLAG_FIRST_UPPER | |||
#define FLAG_HAS_PLURAL 0x4 /* upper-case word with s or 's lower-case ending */ | |||
#define FLAG_PHONEMES 0x8 /* word is phonemes */ | |||
#define FLAG_LAST_WORD 0x10 /* last word in clause */ | |||
#define FLAG_EMBEDDED 0x40 /* word is preceded by embedded commands */ | |||
#define FLAG_ALL_UPPER 0x1 // no lower case letters in the word | |||
#define FLAG_FIRST_UPPER 0x2 // first letter is upper case | |||
#define FLAG_UPPERS 0x3 // FLAG_ALL_UPPER | FLAG_FIRST_UPPER | |||
#define FLAG_HAS_PLURAL 0x4 // upper-case word with s or 's lower-case ending | |||
#define FLAG_PHONEMES 0x8 // word is phonemes | |||
#define FLAG_LAST_WORD 0x10 // last word in clause | |||
#define FLAG_EMBEDDED 0x40 // word is preceded by embedded commands | |||
#define FLAG_HYPHEN 0x80 | |||
#define FLAG_NOSPACE 0x100 // word is not seperated from previous word by a space | |||
#define FLAG_FIRST_WORD 0x200 // first word in clause | |||
#define FLAG_FOCUS 0x400 // the focus word of a clause | |||
#define FLAG_NOSPACE 0x100 // word is not seperated from previous word by a space | |||
#define FLAG_FIRST_WORD 0x200 // first word in clause | |||
#define FLAG_FOCUS 0x400 // the focus word of a clause | |||
#define FLAG_EMPHASIZED 0x800 | |||
#define FLAG_EMPHASIZED2 0xc00 // FLAG_FOCUS | FLAG_EMPHASIZED | |||
#define FLAG_EMPHASIZED2 0xc00 // FLAG_FOCUS | FLAG_EMPHASIZED | |||
#define FLAG_DONT_SWITCH_TRANSLATOR 0x1000 | |||
#define FLAG_SUFFIX_REMOVED 0x2000 | |||
#define FLAG_HYPHEN_AFTER 0x4000 | |||
@@ -128,11 +125,10 @@ extern "C" | |||
#define FLAG_TRANSLATOR2 0x400000 // retranslating using a different language | |||
#define FLAG_PREFIX_REMOVED 0x800000 // a prefix has been removed from this word | |||
#define FLAG_SUFFIX_VOWEL 0x08000000 // remember an initial vowel from the suffix | |||
#define FLAG_NO_TRACE 0x10000000 // passed to TranslateRules() to suppress dictionary lookup printout | |||
#define FLAG_SUFFIX_VOWEL 0x08000000 // remember an initial vowel from the suffix | |||
#define FLAG_NO_TRACE 0x10000000 // passed to TranslateRules() to suppress dictionary lookup printout | |||
#define FLAG_NO_PREFIX 0x20000000 | |||
#define FLAG_UNPRON_TEST 0x80000000 // do unpronounability test on the beginning of the word | |||
#define FLAG_UNPRON_TEST 0x80000000 // do unpronounability test on the beginning of the word | |||
// prefix/suffix flags (bits 8 to 14, bits 16 to 22) don't use 0x8000, 0x800000 | |||
#define SUFX_E 0x0100 // e may have been added | |||
@@ -149,60 +145,56 @@ extern "C" | |||
#define SUFX_UNPRON 0x8000 // used to return $unpron flag from *_rules | |||
#define FLAG_ALLOW_TEXTMODE 0x02 // allow dictionary to translate to text rather than phonemes | |||
#define FLAG_SUFX 0x04 | |||
#define FLAG_SUFX_S 0x08 | |||
#define FLAG_SUFX_E_ADDED 0x10 | |||
// codes in dictionary rules | |||
#define RULE_PRE 1 | |||
#define RULE_POST 2 | |||
#define RULE_PHONEMES 3 | |||
#define RULE_PH_COMMON 4 // At start of rule. Its phoneme string is used by subsequent rules | |||
#define RULE_CONDITION 5 // followed by condition number (byte) | |||
#define RULE_PRE 1 | |||
#define RULE_POST 2 | |||
#define RULE_PHONEMES 3 | |||
#define RULE_PH_COMMON 4 // At start of rule. Its phoneme string is used by subsequent rules | |||
#define RULE_CONDITION 5 // followed by condition number (byte) | |||
#define RULE_GROUP_START 6 | |||
#define RULE_GROUP_END 7 | |||
#define RULE_PRE_ATSTART 8 // as RULE_PRE but also match with 'start of word' | |||
#define RULE_LINENUM 9 // next 2 bytes give a line number, for debugging purposes | |||
#define RULE_SPACE 32 // ascii space | |||
#define RULE_SYLLABLE 21 // @ | |||
#define RULE_STRESSED 10 // & | |||
#define RULE_DOUBLE 11 // % | |||
#define RULE_INC_SCORE 12 // + | |||
#define RULE_DEL_FWD 13 // # | |||
#define RULE_ENDING 14 // S | |||
#define RULE_DIGIT 15 // D digit | |||
#define RULE_NONALPHA 16 // Z non-alpha | |||
#define RULE_LETTERGP 17 // A B C H F G Y letter group number | |||
#define RULE_LETTERGP2 18 // L + letter group number | |||
#define RULE_CAPITAL 19 // ! word starts with a capital letter | |||
#define RULE_REPLACEMENTS 20 // section for character replacements | |||
#define RULE_SKIPCHARS 23 // J | |||
#define RULE_NO_SUFFIX 24 // N | |||
#define RULE_NOTVOWEL 25 // K | |||
#define RULE_IFVERB 26 // V | |||
#define RULE_DOLLAR 28 // $ commands | |||
#define RULE_NOVOWELS 29 // X no vowels up to word boundary | |||
#define RULE_SPELLING 31 // W while spelling letter-by-letter | |||
#define RULE_LAST_RULE 31 | |||
#define RULE_GROUP_END 7 | |||
#define RULE_PRE_ATSTART 8 // as RULE_PRE but also match with 'start of word' | |||
#define RULE_LINENUM 9 // next 2 bytes give a line number, for debugging purposes | |||
#define RULE_SPACE 32 // ascii space | |||
#define RULE_SYLLABLE 21 // @ | |||
#define RULE_STRESSED 10 // & | |||
#define RULE_DOUBLE 11 // % | |||
#define RULE_INC_SCORE 12 // + | |||
#define RULE_DEL_FWD 13 // # | |||
#define RULE_ENDING 14 // S | |||
#define RULE_DIGIT 15 // D digit | |||
#define RULE_NONALPHA 16 // Z non-alpha | |||
#define RULE_LETTERGP 17 // A B C H F G Y letter group number | |||
#define RULE_LETTERGP2 18 // L + letter group number | |||
#define RULE_CAPITAL 19 // ! word starts with a capital letter | |||
#define RULE_REPLACEMENTS 20 // section for character replacements | |||
#define RULE_SKIPCHARS 23 // J | |||
#define RULE_NO_SUFFIX 24 // N | |||
#define RULE_NOTVOWEL 25 // K | |||
#define RULE_IFVERB 26 // V | |||
#define RULE_DOLLAR 28 // $ commands | |||
#define RULE_NOVOWELS 29 // X no vowels up to word boundary | |||
#define RULE_SPELLING 31 // W while spelling letter-by-letter | |||
#define RULE_LAST_RULE 31 | |||
#define DOLLAR_UNPR 0x01 | |||
#define DOLLAR_NOPREFIX 0x02 | |||
#define DOLLAR_LIST 0x03 | |||
#define LETTERGP_A 0 | |||
#define LETTERGP_B 1 | |||
#define LETTERGP_C 2 | |||
#define LETTERGP_H 3 | |||
#define LETTERGP_F 4 | |||
#define LETTERGP_G 5 | |||
#define LETTERGP_Y 6 | |||
#define LETTERGP_VOWEL2 7 | |||
#define LETTERGP_A 0 | |||
#define LETTERGP_B 1 | |||
#define LETTERGP_C 2 | |||
#define LETTERGP_H 3 | |||
#define LETTERGP_F 4 | |||
#define LETTERGP_G 5 | |||
#define LETTERGP_Y 6 | |||
#define LETTERGP_VOWEL2 7 | |||
// Punctuation types returned by ReadClause() | |||
// bits 0-11 pause x 10mS | |||
@@ -215,14 +207,14 @@ extern "C" | |||
// bit 22= dot after the last word | |||
// bit 23= pause is x 320mS (not x 10mS) | |||
#define CLAUSE_BIT_SENTENCE 0x80000 | |||
#define CLAUSE_BIT_CLAUSE 0x40000 | |||
#define CLAUSE_BIT_VOICE 0x20000 | |||
#define CLAUSE_BITS_INTONATION 0x7000 | |||
#define PUNCT_IN_WORD 0x100000 | |||
#define PUNCT_SAY_NAME 0x200000 | |||
#define CLAUSE_DOT 0x400000 | |||
#define CLAUSE_PAUSE_LONG 0x800000 | |||
#define CLAUSE_BIT_SENTENCE 0x80000 | |||
#define CLAUSE_BIT_CLAUSE 0x40000 | |||
#define CLAUSE_BIT_VOICE 0x20000 | |||
#define CLAUSE_BITS_INTONATION 0x7000 | |||
#define PUNCT_IN_WORD 0x100000 | |||
#define PUNCT_SAY_NAME 0x200000 | |||
#define CLAUSE_DOT 0x400000 | |||
#define CLAUSE_PAUSE_LONG 0x800000 | |||
#define CLAUSE_NONE ( 0 + 0x04000) | |||
#define CLAUSE_PARAGRAPH (70 + 0x80000) | |||
@@ -237,15 +229,15 @@ extern "C" | |||
#define CLAUSE_COLON (30 + 0x40000) | |||
#define CLAUSE_SEMICOLON (30 + 0x41000) | |||
#define SAYAS_CHARS 0x12 | |||
#define SAYAS_GLYPHS 0x13 | |||
#define SAYAS_CHARS 0x12 | |||
#define SAYAS_GLYPHS 0x13 | |||
#define SAYAS_SINGLE_CHARS 0x14 | |||
#define SAYAS_KEY 0x24 | |||
#define SAYAS_DIGITS 0x40 // + number of digits | |||
#define SAYAS_DIGITS1 0xc1 | |||
#define SAYAS_KEY 0x24 | |||
#define SAYAS_DIGITS 0x40 // + number of digits | |||
#define SAYAS_DIGITS1 0xc1 | |||
#define CHAR_EMPHASIS 0x0530 // this is an unused character code | |||
#define CHAR_COMMA_BREAK 0x0557 // unused character code | |||
#define CHAR_EMPHASIS 0x0530 // this is an unused character code | |||
#define CHAR_COMMA_BREAK 0x0557 // unused character code | |||
// Rule: | |||
// [4] [match] [1 pre] [2 post] [3 phonemes] 0 | |||
@@ -261,7 +253,6 @@ typedef struct { | |||
char *del_fwd; | |||
} MatchRecord; | |||
// used to mark words with the source[] buffer | |||
typedef struct { | |||
unsigned int flags; | |||
@@ -272,7 +263,6 @@ typedef struct { | |||
unsigned char length; | |||
} WORD_TAB; | |||
typedef struct { | |||
int type; | |||
int parameter[N_SPEECH_PARAM]; | |||
@@ -281,7 +271,6 @@ typedef struct { | |||
extern PARAM_STACK param_stack[]; | |||
extern const int param_defaults[N_SPEECH_PARAM]; | |||
typedef struct { | |||
const char *name; | |||
int offset; | |||
@@ -293,21 +282,20 @@ typedef struct { | |||
extern ALPHABET alphabets[]; | |||
extern ALPHABET *current_alphabet; | |||
// alphabet flags | |||
#define AL_DONT_NAME 0x01 // don't speak the alphabet name | |||
#define AL_NOT_LETTERS 0x02 // don't use the language for speaking letters | |||
#define AL_WORDS 0x04 // use the language to speak words | |||
#define AL_NOT_CODE 0x08 // don't speak the character code | |||
#define AL_NO_SYMBOL 0x10 // don't repeat "symbol" or "character" | |||
#define N_LOPTS 21 | |||
#define LOPT_DIERESES 1 | |||
#define AL_DONT_NAME 0x01 // don't speak the alphabet name | |||
#define AL_NOT_LETTERS 0x02 // don't use the language for speaking letters | |||
#define AL_WORDS 0x04 // use the language to speak words | |||
#define AL_NOT_CODE 0x08 // don't speak the character code | |||
#define AL_NO_SYMBOL 0x10 // don't repeat "symbol" or "character" | |||
#define N_LOPTS 21 | |||
#define LOPT_DIERESES 1 | |||
// 1=remove [:] from unstressed syllables, 2= remove from unstressed or non-penultimate syllables | |||
// bit 4=0, if stress < 4, bit 4=1, if not the highest stress in the word | |||
#define LOPT_IT_LENGTHEN 2 | |||
#define LOPT_IT_LENGTHEN 2 | |||
// 1=german | |||
#define LOPT_PREFIXES 3 | |||
#define LOPT_PREFIXES 3 | |||
// non-zero, change voiced/unoiced to match last consonant in a cluster | |||
// bit 0=use regressive voicing | |||
@@ -316,26 +304,26 @@ extern ALPHABET *current_alphabet; | |||
// bit 3=LANG=pl, propagate over liquids and nasals | |||
// bit 4=LANG=cz,sk don't progagate to [v] | |||
// bit 8=devoice word-final consonants | |||
#define LOPT_REGRESSIVE_VOICING 4 | |||
#define LOPT_REGRESSIVE_VOICING 4 | |||
// 0=default, 1=no check, other allow this character as an extra initial letter (default is 's') | |||
#define LOPT_UNPRONOUNCABLE 5 | |||
#define LOPT_UNPRONOUNCABLE 5 | |||
// select length_mods tables, (length_mod_tab) + (length_mod_tab0 * 100) | |||
#define LOPT_LENGTH_MODS 6 | |||
#define LOPT_LENGTH_MODS 6 | |||
// increase this to prevent sonorants being shortened before shortened (eg. unstressed) vowels | |||
#define LOPT_SONORANT_MIN 7 | |||
#define LOPT_SONORANT_MIN 7 | |||
// bit 0: don't break vowels at word boundary | |||
#define LOPT_WORD_MERGE 8 | |||
#define LOPT_WORD_MERGE 8 | |||
// max. amplitude for vowel at the end of a clause | |||
#define LOPT_MAXAMP_EOC 9 | |||
#define LOPT_MAXAMP_EOC 9 | |||
// bit 0=reduce even if phonemes are specified in the **_list file | |||
// bit 1=don't reduce the strongest vowel in a word which is marked 'unstressed' | |||
#define LOPT_REDUCE 10 | |||
#define LOPT_REDUCE 10 | |||
// LANG=cs,sk combine some prepositions with the following word, if the combination has N or fewer syllables | |||
// bits 0-3 N syllables | |||
@@ -348,15 +336,15 @@ extern ALPHABET *current_alphabet; | |||
// 1 = allow capitals inside a word | |||
// 2 = stressed syllable is indicated by capitals | |||
#define LOPT_CAPS_IN_WORD 13 | |||
#define LOPT_CAPS_IN_WORD 13 | |||
// bit 0=Italian "syntactic doubling" of consoants in the word after a word marked with $double attribute | |||
// bit 1=also after a word which ends with a stressed vowel | |||
#define LOPT_IT_DOUBLING 14 | |||
#define LOPT_IT_DOUBLING 14 | |||
// Call ApplySpecialAttributes() if $alt or $alt2 is set for a word | |||
// bit 1: stressed syllable: $alt change [e],[o] to [E],[O], $alt2 change [E],[O] to [e],[o] | |||
#define LOPT_ALT 15 | |||
#define LOPT_ALT 15 | |||
// pause for bracket (default=4), pause when annoucing bracket names (default=2) | |||
#define LOPT_BRACKET_PAUSE 16 | |||
@@ -368,20 +356,18 @@ extern ALPHABET *current_alphabet; | |||
#define LOPT_LONG_VOWEL_THRESHOLD 18 | |||
// bit 0: Don't allow suffices if there is no previous syllable | |||
#define LOPT_SUFFIX 19 | |||
#define LOPT_SUFFIX 19 | |||
// bit 0 Apostrophe at start of word is part of the word | |||
// bit 1 Apostrophe at end of word is part of the word | |||
#define LOPT_APOSTROPHE 20 | |||
#define LOPT_APOSTROPHE 20 | |||
// stress_rule | |||
#define STRESSPOSN_1L 0 // 1st syllable | |||
#define STRESSPOSN_2L 1 // 2nd syllable | |||
#define STRESSPOSN_2R 2 // penultimate | |||
#define STRESSPOSN_1R 3 // final syllable | |||
#define STRESSPOSN_3R 4 // antipenultimate | |||
#define STRESSPOSN_1L 0 // 1st syllable | |||
#define STRESSPOSN_2L 1 // 2nd syllable | |||
#define STRESSPOSN_2R 2 // penultimate | |||
#define STRESSPOSN_1R 3 // final syllable | |||
#define STRESSPOSN_3R 4 // antipenultimate | |||
typedef struct { | |||
// bits0-2 separate words with (1=pause_vshort, 2=pause_short, 3=pause, 4=pause_long 5=[?] phonemme) | |||
@@ -445,7 +431,6 @@ typedef struct { | |||
// bit15= Give stress to the first unstressed syllable | |||
int stress_flags; | |||
int unstressed_wd1; // stress for $u word of 1 syllable | |||
int unstressed_wd2; // stress for $u word of >1 syllable | |||
@@ -531,7 +516,7 @@ typedef struct { | |||
#define NUM2_PERCENT_BEFORE 0x10000 | |||
#define NUM2_OMIT_1_HUNDRED_ONLY 0x20000 | |||
#define NUM2_ORDINAL_AND_THOUSANDS 0x40000 | |||
#define NUM2_ORDINAL_DROP_VOWEL 0x80000 // currently only for tens and units | |||
#define NUM2_ORDINAL_DROP_VOWEL 0x80000 // currently only for tens and units | |||
#define NUM2_ZERO_TENS 0x100000 | |||
// bits 1-4 use variant form of numbers before thousands,millions,etc. | |||
// bits 6-8 use different forms of thousand, million, etc (M MA MB) | |||
@@ -588,7 +573,6 @@ typedef struct { | |||
int dict_dialect; // bitmap, use a dialect for foreign words | |||
} LANGUAGE_OPTIONS; | |||
// a parameter of ChangePhonemes() | |||
typedef struct { | |||
int flags; | |||
@@ -599,10 +583,7 @@ typedef struct { | |||
unsigned char vowel_stressed; // syllable number of the highest stressed vowel | |||
} CHANGEPH; | |||
typedef struct { | |||
LANGUAGE_OPTIONS langopts; | |||
int translator_name; | |||
int transpose_max; | |||
@@ -630,8 +611,8 @@ typedef struct { | |||
const wchar_t *letter_groups[8]; | |||
/* index1=option, index2 by 0=. 1=, 2=?, 3=! 4=none */ | |||
#define INTONATION_TYPES 8 | |||
#define PUNCT_INTONATIONS 6 | |||
#define INTONATION_TYPES 8 | |||
#define PUNCT_INTONATIONS 6 | |||
unsigned char punct_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS]; | |||
char *data_dictrules; // language_1 translation rules file | |||
@@ -671,7 +652,6 @@ typedef struct { | |||
int clause_terminator; | |||
} Translator; | |||
extern int option_tone2; | |||
#define OPTION_EMPHASIZE_ALLCAPS 0x100 | |||
#define OPTION_EMPHASIZE_PENULTIMATE 0x200 | |||
@@ -704,8 +684,6 @@ extern int clause_start_word; | |||
extern char *namedata; | |||
extern int pre_pause; | |||
#define N_MARKER_LENGTH 50 // max.length of a mark name | |||
extern char skip_marker[N_MARKER_LENGTH]; | |||
@@ -796,9 +774,9 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata); | |||
char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags); | |||
extern FILE *f_trans; // for logging | |||
extern FILE *f_trans; // for logging | |||
extern FILE *f_logespeak; | |||
extern int logging_type; // from config file | |||
extern int logging_type; // from config file | |||
#ifdef __cplusplus | |||
} |
@@ -22,15 +22,13 @@ extern "C" | |||
{ | |||
#endif | |||
typedef struct { | |||
char v_name[40]; | |||
char language_name[20]; | |||
int phoneme_tab_ix; // phoneme table number | |||
int pitch_base; // Hz<<12 | |||
int pitch_range; // standard = 0x1000 | |||
int phoneme_tab_ix; // phoneme table number | |||
int pitch_base; // Hz<<12 | |||
int pitch_range; // standard = 0x1000 | |||
int speedf1; | |||
int speedf2; | |||
@@ -44,7 +42,7 @@ typedef struct { | |||
int n_harmonic_peaks; // highest formant which is formed from adding harmonics | |||
int peak_shape; // alternative shape for formant peaks (0=standard 1=squarer) | |||
int voicing; // 100% = 64, level of formant-synthesized sound | |||
int formant_factor; // adjust nominal formant frequencies by this because of the voice's pitch (256ths) | |||
int formant_factor; // adjust nominal formant frequencies by this because of the voice's pitch (256ths) | |||
int consonant_amp; // amplitude of unvoiced consonants | |||
int consonant_ampv; // amplitude of the noise component of voiced consonants | |||
int samplerate; | |||
@@ -54,7 +52,7 @@ typedef struct { | |||
short freq[N_PEAKS]; // 100% = 256 | |||
short height[N_PEAKS]; // 100% = 256 | |||
short width[N_PEAKS]; // 100% = 256 | |||
short freqadd[N_PEAKS]; // Hz | |||
short freqadd[N_PEAKS]; // Hz | |||
// copies without temporary adjustments from embedded commands | |||
short freq2[N_PEAKS]; // 100% = 256 | |||
@@ -62,7 +60,7 @@ typedef struct { | |||
short width2[N_PEAKS]; // 100% = 256 | |||
int breath[N_PEAKS]; // amount of breath for each formant. breath[0] indicates whether any are set. | |||
int breathw[N_PEAKS]; // width of each breath formant | |||
int breathw[N_PEAKS]; // width of each breath formant | |||
// This table provides the opportunity for tone control. | |||
// Adjustment of harmonic amplitudes, steps of 8Hz |
@@ -56,8 +56,8 @@ MNEM_TAB genders[] = { | |||
int tone_points[12] = { 600, 170, 1200, 135, 2000, 110, 3000, 110, -1, 0 }; | |||
// limit the rate of change for each formant number | |||
static int formant_rate_22050[9] = { 240, 170, 170, 170, 170, 170, 170, 170, 170 }; // values for 22kHz sample rate | |||
int formant_rate[9]; // values adjusted for actual sample rate | |||
static int formant_rate_22050[9] = { 240, 170, 170, 170, 170, 170, 170, 170, 170 }; // values for 22kHz sample rate | |||
int formant_rate[9]; // values adjusted for actual sample rate | |||
#define DEFAULT_LANGUAGE_PRIORITY 5 | |||
#define N_VOICES_LIST 250 | |||
@@ -75,7 +75,7 @@ enum { | |||
V_PHONEMES, | |||
V_DICTIONARY, | |||
// these affect voice quality, are independent of language | |||
// these affect voice quality, are independent of language | |||
V_FORMANT, | |||
V_PITCH, | |||
V_ECHO, | |||
@@ -87,7 +87,7 @@ enum { | |||
V_BREATH, | |||
V_BREATHW, | |||
// these override defaults set by the translator | |||
// these override defaults set by the translator | |||
V_WORDGAP, | |||
V_INTONATION, | |||
V_TUNES, | |||
@@ -109,72 +109,74 @@ enum { | |||
V_ALPHABET2, | |||
V_DICTDIALECT, | |||
// these need a phoneme table to have been specified | |||
// these need a phoneme table to have been specified | |||
V_REPLACE, | |||
V_CONSONANTS | |||
}; | |||
static MNEM_TAB options_tab[] = { | |||
{ "reduce_t", LOPT_REDUCE_T }, | |||
{ "bracket", LOPT_BRACKET_PAUSE }, | |||
{ "reduce_t", LOPT_REDUCE_T }, | |||
{ "bracket", LOPT_BRACKET_PAUSE }, | |||
{ NULL, -1 } | |||
}; | |||
static MNEM_TAB keyword_tab[] = { | |||
{ "name", V_NAME }, | |||
{ "language", V_LANGUAGE }, | |||
{ "gender", V_GENDER }, | |||
{ "formant", V_FORMANT }, | |||
{ "pitch", V_PITCH }, | |||
{ "phonemes", V_PHONEMES }, | |||
{ "translator", V_TRANSLATOR }, | |||
{ "dictionary", V_DICTIONARY }, | |||
{ "name", V_NAME }, | |||
{ "language", V_LANGUAGE }, | |||
{ "gender", V_GENDER }, | |||
{ "formant", V_FORMANT }, | |||
{ "pitch", V_PITCH }, | |||
{ "phonemes", V_PHONEMES }, | |||
{ "translator", V_TRANSLATOR }, | |||
{ "dictionary", V_DICTIONARY }, | |||
{ "stressLength", V_STRESSLENGTH }, | |||
{ "stressAmp", V_STRESSAMP }, | |||
{ "stressAdd", V_STRESSADD }, | |||
{ "intonation", V_INTONATION }, | |||
{ "tunes", V_TUNES }, | |||
{ "dictrules", V_DICTRULES }, | |||
{ "stressrule", V_STRESSRULE }, | |||
{ "stressopt", V_STRESSOPT }, | |||
{ "charset", V_CHARSET }, | |||
{ "replace", V_REPLACE }, | |||
{ "words", V_WORDGAP }, | |||
{ "echo", V_ECHO }, | |||
{ "flutter", V_FLUTTER }, | |||
{ "roughness", V_ROUGHNESS }, | |||
{ "clarity", V_CLARITY }, | |||
{ "tone", V_TONE }, | |||
{ "voicing", V_VOICING }, | |||
{ "breath", V_BREATH }, | |||
{ "breathw", V_BREATHW }, | |||
{ "numbers", V_NUMBERS }, | |||
{ "option", V_OPTION }, | |||
{ "mbrola", V_MBROLA }, | |||
{ "consonants", V_CONSONANTS }, | |||
{ "klatt", V_KLATT }, | |||
{ "fast_test2", V_FAST }, | |||
{ "speed", V_SPEED }, | |||
{ "dict_min", V_DICTMIN }, | |||
{ "alphabet2", V_ALPHABET2 }, | |||
{ "dictdialect", V_DICTDIALECT }, | |||
{ "stressAmp", V_STRESSAMP }, | |||
{ "stressAdd", V_STRESSADD }, | |||
{ "intonation", V_INTONATION }, | |||
{ "tunes", V_TUNES }, | |||
{ "dictrules", V_DICTRULES }, | |||
{ "stressrule", V_STRESSRULE }, | |||
{ "stressopt", V_STRESSOPT }, | |||
{ "charset", V_CHARSET }, | |||
{ "replace", V_REPLACE }, | |||
{ "words", V_WORDGAP }, | |||
{ "echo", V_ECHO }, | |||
{ "flutter", V_FLUTTER }, | |||
{ "roughness", V_ROUGHNESS }, | |||
{ "clarity", V_CLARITY }, | |||
{ "tone", V_TONE }, | |||
{ "voicing", V_VOICING }, | |||
{ "breath", V_BREATH }, | |||
{ "breathw", V_BREATHW }, | |||
{ "numbers", V_NUMBERS }, | |||
{ "option", V_OPTION }, | |||
{ "mbrola", V_MBROLA }, | |||
{ "consonants", V_CONSONANTS }, | |||
{ "klatt", V_KLATT }, | |||
{ "fast_test2", V_FAST }, | |||
{ "speed", V_SPEED }, | |||
{ "dict_min", V_DICTMIN }, | |||
{ "alphabet2", V_ALPHABET2 }, | |||
{ "dictdialect", V_DICTDIALECT }, | |||
// these just set a value in langopts.param[] | |||
{ "l_dieresis", 0x100+LOPT_DIERESES }, | |||
{ "l_prefix", 0x100+LOPT_PREFIXES }, | |||
{ "l_regressive_v", 0x100+LOPT_REGRESSIVE_VOICING }, | |||
{ "l_dieresis", 0x100+LOPT_DIERESES }, | |||
{ "l_prefix", 0x100+LOPT_PREFIXES }, | |||
{ "l_regressive_v", 0x100+LOPT_REGRESSIVE_VOICING }, | |||
{ "l_unpronouncable", 0x100+LOPT_UNPRONOUNCABLE }, | |||
{ "l_sonorant_min", 0x100+LOPT_SONORANT_MIN }, | |||
{ "l_length_mods", 0x100+LOPT_LENGTH_MODS }, | |||
{ "apostrophe", 0x100+LOPT_APOSTROPHE }, | |||
{ NULL, 0 } | |||
{ "l_sonorant_min", 0x100+LOPT_SONORANT_MIN }, | |||
{ "l_length_mods", 0x100+LOPT_LENGTH_MODS }, | |||
{ "apostrophe", 0x100+LOPT_APOSTROPHE }, | |||
{ NULL, 0 } | |||
}; | |||
static MNEM_TAB dict_dialects[] = { | |||
{ "en-us", DICTDIALECT_EN_US }, | |||
{ "es-la", DICTDIALECT_ES_LA }, | |||
{ NULL, 0 } | |||
{ "en-us", DICTDIALECT_EN_US }, | |||
{ "es-la", DICTDIALECT_ES_LA }, | |||
{ NULL, 0 } | |||
}; | |||
#define N_VOICE_VARIANTS 12 | |||
@@ -188,7 +190,7 @@ voice_t *voice = &voicedata; | |||
static char *fgets_strip(char *buf, int size, FILE *f_in) | |||
{ | |||
// strip trailing spaces, and truncate lines at // comment | |||
// strip trailing spaces, and truncate lines at // comment | |||
int len; | |||
char *p; | |||
@@ -238,7 +240,7 @@ static void SetToneAdjust(voice_t *voice, int *tone_pts) | |||
if (pt > 0) | |||
tone_pts[pt+1] = tone_pts[pt-1]; | |||
} | |||
freq2 = tone_pts[pt] / 8; // 8Hz steps | |||
freq2 = tone_pts[pt] / 8; // 8Hz steps | |||
height2 = tone_pts[pt+1]; | |||
if ((freq2 - freq1) > 0) { | |||
rate = (double)(height2-height1)/(freq2-freq1); | |||
@@ -257,7 +259,7 @@ static void SetToneAdjust(voice_t *voice, int *tone_pts) | |||
void ReadTonePoints(char *string, int *tone_pts) | |||
{ | |||
// tone_pts[] is int[12] | |||
// tone_pts[] is int[12] | |||
int ix; | |||
for (ix = 0; ix < 12; ix++) | |||
@@ -271,14 +273,14 @@ void ReadTonePoints(char *string, int *tone_pts) | |||
static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *leafname) | |||
{ | |||
// Read a Voice file, allocate a VOICE_DATA and set data from the | |||
// file's language, gender, name lines | |||
// Read a Voice file, allocate a VOICE_DATA and set data from the | |||
// file's language, gender, name lines | |||
char linebuf[120]; | |||
char vname[80]; | |||
char vgender[80]; | |||
char vlanguage[80]; | |||
char languages[300]; // allow space for several alternate language names and priorities | |||
char languages[300]; // allow space for several alternate language names and priorities | |||
unsigned int len; | |||
int langix = 0; | |||
@@ -287,7 +289,7 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *le | |||
espeak_VOICE *voice_data; | |||
int priority; | |||
int age; | |||
int n_variants = 4; // default, number of variants of this voice before using another voice | |||
int n_variants = 4; // default, number of variants of this voice before using another voice | |||
int gender; | |||
#ifdef PLATFORM_WINDOWS | |||
@@ -336,7 +338,7 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *le | |||
gender = LookupMnem(genders, vgender); | |||
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); | |||
voice_data = (espeak_VOICE *)p; | |||
@@ -364,10 +366,10 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *le | |||
void VoiceReset(int tone_only) | |||
{ | |||
// Set voice to the default values | |||
// Set voice to the default values | |||
int pk; | |||
static unsigned char default_heights[N_PEAKS] = { 130, 128, 120, 116, 100, 100, 128, 128, 128 }; // changed for v.1.47 | |||
static unsigned char default_heights[N_PEAKS] = { 130, 128, 120, 116, 100, 100, 128, 128, 128 }; // changed for v.1.47 | |||
static unsigned char default_widths[N_PEAKS] = { 140, 128, 128, 160, 171, 171, 128, 128, 128 }; | |||
static int breath_widths[N_PEAKS] = { 0, 200, 200, 400, 400, 400, 600, 600, 600 }; | |||
@@ -385,7 +387,7 @@ void VoiceReset(int tone_only) | |||
voice->n_harmonic_peaks = 5; | |||
voice->peak_shape = 0; | |||
voice->voicing = 64; | |||
voice->consonant_amp = 90; // change from 100 to 90 for v.1.47 | |||
voice->consonant_amp = 90; // change from 100 to 90 for v.1.47 | |||
voice->consonant_ampv = 100; | |||
voice->samplerate = samplerate_native; | |||
memset(voice->klattv, 0, sizeof(voice->klattv)); | |||
@@ -406,7 +408,7 @@ void VoiceReset(int tone_only) | |||
voice->height[pk] = default_heights[pk]*2; | |||
voice->width[pk] = default_widths[pk]*2; | |||
voice->breath[pk] = 0; | |||
voice->breathw[pk] = breath_widths[pk]; // default breath formant woidths | |||
voice->breathw[pk] = breath_widths[pk]; // default breath formant woidths | |||
voice->freqadd[pk] = 0; | |||
// adjust formant smoothing depending on sample rate | |||
@@ -470,7 +472,7 @@ static void PhonemeReplacement(int type, char *p) | |||
return; | |||
if ((phon = LookupPhonemeString(phon_string1)) == 0) | |||
return; // not recognised | |||
return; // not recognised | |||
replace_phonemes[n_replace_phonemes].old_ph = phon; | |||
replace_phonemes[n_replace_phonemes].new_ph = LookupPhonemeString(phon_string2); | |||
@@ -479,7 +481,7 @@ static void PhonemeReplacement(int type, char *p) | |||
static int Read8Numbers(char *data_in, int *data) | |||
{ | |||
// Read 8 integer numbers | |||
// Read 8 integer numbers | |||
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]); | |||
@@ -487,7 +489,7 @@ static int Read8Numbers(char *data_in, int *data) | |||
static unsigned int StringToWord2(const char *string) | |||
{ | |||
// Convert a language name string to a word such as L('e','n') | |||
// Convert a language name string to a word such as L('e','n') | |||
int ix; | |||
int c; | |||
unsigned int value = 0; | |||
@@ -499,10 +501,10 @@ static unsigned int StringToWord2(const char *string) | |||
voice_t *LoadVoice(const char *vname, int control) | |||
{ | |||
// control, bit 0 1= no_default | |||
// bit 1 1 = change tone only, not language | |||
// bit 2 1 = don't report error on LoadDictionary | |||
// bit 4 1 = vname = full path | |||
// control, bit 0 1= no_default | |||
// bit 1 1 = change tone only, not language | |||
// bit 2 1 = don't report error on LoadDictionary | |||
// bit 4 1 = vname = full path | |||
FILE *f_voice = NULL; | |||
char *p; | |||
@@ -545,9 +547,9 @@ voice_t *LoadVoice(const char *vname, int control) | |||
int pitch1; | |||
int pitch2; | |||
static char voice_identifier[40]; // file name for current_voice_selected | |||
static char voice_name[40]; // voice name for current_voice_selected | |||
static char voice_languages[100]; // list of languages and priorities for current_voice_selected | |||
static char voice_identifier[40]; // file name for current_voice_selected | |||
static char voice_name[40]; // voice name for current_voice_selected | |||
static char voice_languages[100]; // list of languages and priorities for current_voice_selected | |||
// which directory to look for a named voice. List of voice names, must end in a space. | |||
static const char *voices_asia = | |||
@@ -565,12 +567,12 @@ voice_t *LoadVoice(const char *vname, int control) | |||
strcpy(voicename, "default"); | |||
sprintf(path_voices, "%s%cvoices%c", path_home, PATHSEP, PATHSEP); | |||
sprintf(buf, "%s%s", path_voices, voicename); // first, look in the main voices directory | |||
sprintf(buf, "%s%s", path_voices, voicename); // first, look in the main voices directory | |||
if (GetFileLength(buf) <= 0) { | |||
// then look in the appropriate subdirectory | |||
if ((voicename[0] == 'm') && (voicename[1] == 'b')) | |||
voice_dir = "mb"; // mbrola voices | |||
voice_dir = "mb"; // mbrola voices | |||
else { | |||
sprintf(name2, "%s ", voicename); | |||
if (strstr(voices_europe, voicename) != NULL) | |||
@@ -592,10 +594,10 @@ voice_t *LoadVoice(const char *vname, int control) | |||
f_voice = fopen(buf, "r"); | |||
language_type = "en"; // default | |||
language_type = "en"; // default | |||
if (f_voice == NULL) { | |||
if (control & 3) | |||
return NULL; // can't open file | |||
return NULL; // can't open file | |||
if (SelectPhonemeTableName(voicename) >= 0) | |||
language_type = voicename; | |||
@@ -630,7 +632,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
VoiceReset(tone_only); | |||
if (!tone_only) | |||
SelectPhonemeTableName(phonemes_name); // set up phoneme_tab | |||
SelectPhonemeTableName(phonemes_name); // set up phoneme_tab | |||
while ((f_voice != NULL) && (fgets_strip(buf, sizeof(buf), f_voice) != NULL)) { | |||
// isolate the attribute name | |||
@@ -711,10 +713,10 @@ voice_t *LoadVoice(const char *vname, int control) | |||
new_translator = SelectTranslator(translator_name); | |||
langopts = &new_translator->langopts; | |||
break; | |||
case V_DICTIONARY: // dictionary | |||
case V_DICTIONARY: // dictionary | |||
sscanf(p, "%s", new_dictionary); | |||
break; | |||
case V_PHONEMES: // phoneme table | |||
case V_PHONEMES: // phoneme table | |||
sscanf(p, "%s", phonemes_name); | |||
break; | |||
case V_FORMANT: | |||
@@ -728,19 +730,19 @@ voice_t *LoadVoice(const char *vname, int control) | |||
voice->pitch_base = (pitch1 - 9) << 12; | |||
voice->pitch_range = (pitch2 - pitch1) * 108; | |||
factor = (double)(pitch1 - 82)/82; | |||
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch | |||
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch | |||
} | |||
break; | |||
case V_STRESSLENGTH: // stressLength | |||
case V_STRESSLENGTH: // stressLength | |||
stress_lengths_set = Read8Numbers(p, stress_lengths); | |||
break; | |||
case V_STRESSAMP: // stressAmp | |||
case V_STRESSAMP: // stressAmp | |||
stress_amps_set = Read8Numbers(p, stress_amps); | |||
break; | |||
case V_STRESSADD: // stressAdd | |||
case V_STRESSADD: // stressAdd | |||
stress_add_set = Read8Numbers(p, stress_add); | |||
break; | |||
case V_INTONATION: // intonation | |||
case V_INTONATION: // intonation | |||
sscanf(p, "%d %d", &option_tone_flags, &option_tone2); | |||
if ((option_tone_flags & 0xff) != 0) | |||
langopts->intonation_group = option_tone_flags & 0xff; | |||
@@ -758,7 +760,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
langopts->tunes[ix] = value; | |||
} | |||
break; | |||
case V_DICTRULES: // conditional dictionary rules and list entries | |||
case V_DICTRULES: // conditional dictionary rules and list entries | |||
case V_NUMBERS: | |||
case V_STRESSOPT: | |||
// expect a list of numbers | |||
@@ -793,7 +795,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
} | |||
PhonemeReplacement(key, p); | |||
break; | |||
case V_WORDGAP: // words | |||
case V_WORDGAP: // words | |||
sscanf(p, "%d %d", &langopts->word_gap, &langopts->vowel_pause); | |||
break; | |||
case V_STRESSRULE: | |||
@@ -821,18 +823,18 @@ voice_t *LoadVoice(const char *vname, int control) | |||
voice->echo_amp = 0; | |||
sscanf(p, "%d %d", &voice->echo_delay, &voice->echo_amp); | |||
break; | |||
case V_FLUTTER: // flutter | |||
case V_FLUTTER: // flutter | |||
if (sscanf(p, "%d", &value) == 1) | |||
voice->flutter = value * 32; | |||
break; | |||
case V_ROUGHNESS: // roughness | |||
case V_ROUGHNESS: // roughness | |||
if (sscanf(p, "%d", &value) == 1) | |||
voice->roughness = value; | |||
break; | |||
case V_CLARITY: // formantshape | |||
case V_CLARITY: // formantshape | |||
if (sscanf(p, "%d", &value) == 1) { | |||
if (value > 4) { | |||
voice->peak_shape = 1; // squarer formant peaks | |||
voice->peak_shape = 1; // squarer formant peaks | |||
value = 4; | |||
} | |||
voice->n_harmonic_peaks = 1+value; | |||
@@ -871,14 +873,13 @@ voice_t *LoadVoice(const char *vname, int control) | |||
name2[0] = 0; | |||
sscanf(p, "%s %s %d", name1, name2, &srate); | |||
if (LoadMbrolaTable(name1, name2, &srate) != EE_OK) { | |||
if (LoadMbrolaTable(name1, name2, &srate) != EE_OK) | |||
fprintf(stderr, "mbrola voice not found\n"); | |||
} | |||
voice->samplerate = srate; | |||
} | |||
break; | |||
case V_KLATT: | |||
voice->klattv[0] = 1; // default source: IMPULSIVE | |||
voice->klattv[0] = 1; // default source: IMPULSIVE | |||
Read8Numbers(p, voice->klattv); | |||
voice->klattv[KLATT_Kopen] -= 40; | |||
break; | |||
@@ -929,7 +930,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
new_translator = SelectTranslator(translator_name); | |||
} | |||
SetSpeed(3); // for speed_percent | |||
SetSpeed(3); // for speed_percent | |||
for (ix = 0; ix < N_PEAKS; ix++) { | |||
voice->freq2[ix] = voice->freq[ix]; | |||
@@ -950,7 +951,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
LoadDictionary(new_translator, new_dictionary, control & 4); | |||
if (dictionary_name[0] == 0) { | |||
DeleteTranslator(new_translator); | |||
return NULL; // no dictionary loaded | |||
return NULL; // no dictionary loaded | |||
} | |||
new_translator->dict_condition = conditional_rules; | |||
@@ -960,7 +961,6 @@ voice_t *LoadVoice(const char *vname, int control) | |||
langopts = &new_translator->langopts; | |||
if ((value = langopts->param[LOPT_LENGTH_MODS]) != 0) | |||
SetLengthMods(new_translator, value); | |||
@@ -969,7 +969,6 @@ voice_t *LoadVoice(const char *vname, int control) | |||
if (!tone_only) | |||
translator = new_translator; | |||
// relative lengths of different stress syllables | |||
for (ix = 0; ix < stress_lengths_set; ix++) | |||
translator->stress_lengths[ix] = stress_lengths[ix]; | |||
@@ -985,8 +984,8 @@ voice_t *LoadVoice(const char *vname, int control) | |||
static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | |||
{ | |||
// Remove any voice variant suffix (name or number) from a voice name | |||
// Returns the voice variant name | |||
// Remove any voice variant suffix (name or number) from a voice name | |||
// Returns the voice variant name | |||
char *p; | |||
static char variant_name[40]; | |||
@@ -1001,9 +1000,9 @@ static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | |||
if ((p = strchr(vname, '+')) != NULL) { | |||
// The voice name has a +variant suffix | |||
variant_num = 0; | |||
*p++ = 0; // delete the suffix from the voice name | |||
*p++ = 0; // delete the suffix from the voice name | |||
if (IsDigit09(*p)) | |||
variant_num = atoi(p); // variant number | |||
variant_num = atoi(p); // variant number | |||
else { | |||
// voice variant name, not number | |||
sprintf(variant_name, "%s%s", variant_prefix, p); | |||
@@ -1013,9 +1012,9 @@ static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | |||
if (variant_num > 0) { | |||
if (variant_num < 10) | |||
sprintf(variant_name, "%sm%d", variant_prefix, variant_num); // male | |||
sprintf(variant_name, "%sm%d", variant_prefix, variant_num); // male | |||
else | |||
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; | |||
@@ -1023,8 +1022,8 @@ static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | |||
voice_t *LoadVoiceVariant(const char *vname, int variant_num) | |||
{ | |||
// Load a voice file. | |||
// Also apply a voice variant if specified by "variant", or by "+number" or "+name" in the "vname" | |||
// Load a voice file. | |||
// Also apply a voice variant if specified by "variant", or by "+number" or "+name" in the "vname" | |||
voice_t *v; | |||
char *variant_name; | |||
@@ -1047,9 +1046,9 @@ static int __cdecl VoiceNameSorter(const void *p1, const void *p2) | |||
espeak_VOICE *v1 = *(espeak_VOICE **)p1; | |||
espeak_VOICE *v2 = *(espeak_VOICE **)p2; | |||
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; | |||
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); | |||
} | |||
@@ -1080,7 +1079,7 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
int required_age; | |||
int diff; | |||
p = voice->languages; // list of languages+dialects for which this voice is suitable | |||
p = voice->languages; // list of languages+dialects for which this voice is suitable | |||
if (spec_n_parts < 0) { | |||
// match on the subdirectory | |||
@@ -1123,10 +1122,10 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
break; | |||
} | |||
p += (ix+1); | |||
matching_parts += matching; // number of parts which match | |||
matching_parts += matching; // number of parts which match | |||
if (matching_parts == 0) | |||
continue; // no matching parts for this language | |||
continue; // no matching parts for this language | |||
x = 5; | |||
// reduce the score if not all parts of the required language match | |||
@@ -1163,7 +1162,7 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
} | |||
if ((voice_spec->age <= 12) && (voice->gender == 2) && (voice->age > 12)) | |||
score += 5; // give some preference for non-child female voice if a child is requested | |||
score += 5; // give some preference for non-child female voice if a child is requested | |||
if (voice->age != 0) { | |||
if (voice_spec->age == 0) | |||
@@ -1174,14 +1173,14 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
ratio = (required_age*100)/voice->age; | |||
if (ratio < 100) | |||
ratio = 10000/ratio; | |||
ratio = (ratio - 100)/10; // 0=exact match, 10=out by factor of 2 | |||
ratio = (ratio - 100)/10; // 0=exact match, 10=out by factor of 2 | |||
x = 5 - ratio; | |||
if (x > 0) x = 0; | |||
score = score + x; | |||
if (voice_spec->age > 0) | |||
score += 10; // required age specified, favour voices with a specified age (near it) | |||
score += 10; // required age specified, favour voices with a specified age (near it) | |||
} | |||
if (score < 1) | |||
score = 1; | |||
@@ -1190,10 +1189,10 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int control) | |||
{ | |||
// control: bit0=1 include mbrola voices | |||
// control: bit0=1 include mbrola voices | |||
int ix; | |||
int score; | |||
int nv; // number of candidates | |||
int nv; // number of candidates | |||
int n_parts = 0; | |||
int lang_len = 0; | |||
espeak_VOICE *vp; | |||
@@ -1212,7 +1211,7 @@ static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int | |||
if ((n_parts == 1) && (control & 1)) { | |||
if (strcmp(language, "mbrola") == 0) { | |||
language[2] = 0; // truncate to "mb" | |||
language[2] = 0; // truncate to "mb" | |||
lang_len = 2; | |||
} | |||
@@ -1238,7 +1237,7 @@ static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int | |||
vp->score = score; | |||
} | |||
} | |||
voices[nv] = NULL; // list terminator | |||
voices[nv] = NULL; // list terminator | |||
if (nv == 0) | |||
return 0; | |||
@@ -1255,7 +1254,7 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | |||
int match_fname = -1; | |||
int match_fname2 = -1; | |||
int match_name = -1; | |||
const char *id; // this is the filename within espeak-data/voices | |||
const char *id; // this is the filename within espeak-data/voices | |||
char *variant_name; | |||
int last_part_len; | |||
char last_part[41]; | |||
@@ -1263,7 +1262,7 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | |||
if (voices == NULL) { | |||
if (n_voices_list == 0) | |||
espeak_ListVoices(NULL); // create the voices list | |||
espeak_ListVoices(NULL); // create the voices list | |||
voices = voices_list; | |||
} | |||
@@ -1278,21 +1277,21 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | |||
for (ix = 0; voices[ix] != NULL; ix++) { | |||
if (strcmp(name, voices[ix]->name) == 0) { | |||
match_name = ix; // found matching voice name | |||
match_name = ix; // found matching voice name | |||
break; | |||
} else { | |||
id = voices[ix]->identifier; | |||
if (strcmp(name, id) == 0) | |||
match_fname = ix; // matching identifier, use this if no matching name | |||
match_fname = ix; // matching identifier, use this if no matching name | |||
else if (strcmp(last_part, &id[strlen(id)-last_part_len]) == 0) | |||
match_fname2 = ix; | |||
} | |||
} | |||
if (match_name < 0) { | |||
match_name = match_fname; // no matching name, try matching filename | |||
match_name = match_fname; // no matching name, try matching filename | |||
if (match_name < 0) | |||
match_name = match_fname2; // try matching just the last part of the filename | |||
match_name = match_fname2; // try matching just the last part of the filename | |||
} | |||
if (match_name < 0) | |||
@@ -1303,9 +1302,10 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | |||
char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
{ | |||
// Returns a path within espeak-voices, with a possible +variant suffix | |||
// variant is an output-only parameter | |||
int nv; // number of candidates | |||
// Returns a path within espeak-voices, with a possible +variant suffix | |||
// variant is an output-only parameter | |||
int nv; // number of candidates | |||
int ix, ix2; | |||
int j; | |||
int n_variants; | |||
@@ -1327,7 +1327,7 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
memcpy(&voice_select2, voice_select, sizeof(voice_select2)); | |||
if (n_voices_list == 0) | |||
espeak_ListVoices(NULL); // create the voices list | |||
espeak_ListVoices(NULL); // create the voices list | |||
if ((voice_select2.languages == NULL) || (voice_select2.languages[0] == 0)) { | |||
// no language is specified. Get language from the named voice | |||
@@ -1372,13 +1372,13 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
else if (voice_select2.gender == 1) | |||
gender = 1; | |||
#define AGE_OLD 60 | |||
#define AGE_OLD 60 | |||
if (voice_select2.age < AGE_OLD) | |||
aged = 0; | |||
p = p_start = variant_lists[gender]; | |||
if (aged == 0) | |||
p++; // the first voice in the variants list is older | |||
p++; // the first voice in the variants list is older | |||
// add variants for the top voices | |||
n_variants = 0; | |||
@@ -1401,8 +1401,8 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
continue; | |||
} | |||
vp2 = &voice_variants[n_variants++]; // allocate space for voice variant | |||
memcpy(vp2, vp, sizeof(espeak_VOICE)); // copy from the original voice | |||
vp2 = &voice_variants[n_variants++]; // allocate space for voice variant | |||
memcpy(vp2, vp, sizeof(espeak_VOICE)); // copy from the original voice | |||
vp2->variant = variant_number; | |||
voices2[ix2++] = vp2; | |||
p++; | |||
@@ -1411,8 +1411,8 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
} | |||
// add any more variants to the end of the list | |||
while ((vp != NULL) && ((variant_number = *p++) != 0) && (n_variants < N_VOICE_VARIANTS)) { | |||
vp2 = &voice_variants[n_variants++]; // allocate space for voice variant | |||
memcpy(vp2, vp, sizeof(espeak_VOICE)); // copy from the original voice | |||
vp2 = &voice_variants[n_variants++]; // allocate space for voice variant | |||
memcpy(vp2, vp, sizeof(espeak_VOICE)); // copy from the original voice | |||
vp2->variant = variant_number; | |||
voices2[ix2++] = vp2; | |||
} | |||
@@ -1456,7 +1456,7 @@ static void GetVoices(const char *path) | |||
regs.r[6] = 0; | |||
while (regs.r[3] > 0) { | |||
error = _kernel_swi(0x0c+0x20000, ®s, ®s); /* OS_GBPB 10, read directory entries */ | |||
error = _kernel_swi(0x0c+0x20000, ®s, ®s); // OS_GBPB 10, read directory entries | |||
if ((error != NULL) || (regs.r[3] == 0)) | |||
break; | |||
type = (int *)(&buf[16]); | |||
@@ -1484,7 +1484,7 @@ static void GetVoices(const char *path) | |||
WIN32_FIND_DATAA FindFileData; | |||
HANDLE hFind = INVALID_HANDLE_VALUE; | |||
#undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string | |||
#undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string | |||
sprintf(fname, "%s\\*", path); | |||
hFind = FindFirstFileA(fname, &FindFileData); | |||
if (hFind == INVALID_HANDLE_VALUE) | |||
@@ -1492,7 +1492,7 @@ static void GetVoices(const char *path) | |||
do { | |||
if (n_voices_list >= (N_VOICES_LIST-2)) | |||
break; // voices list is full | |||
break; // voices list is full | |||
if (FindFileData.cFileName[0] != '.') { | |||
sprintf(fname, "%s%c%s", path, PATHSEP, FindFileData.cFileName); | |||
@@ -1520,12 +1520,12 @@ static void GetVoices(const char *path) | |||
DIR *dir; | |||
struct dirent *ent; | |||
if ((dir = opendir((char *)path)) == NULL) // note: (char *) is needed for WINCE | |||
if ((dir = opendir((char *)path)) == NULL) // note: (char *) is needed for WINCE | |||
return; | |||
while ((ent = readdir(dir)) != NULL) { | |||
if (n_voices_list >= (N_VOICES_LIST-2)) | |||
break; // voices list is full | |||
break; // voices list is full | |||
if (ent->d_name[0] == '.') | |||
continue; | |||
@@ -1574,7 +1574,7 @@ espeak_ERROR SetVoiceByName(const char *name) | |||
} | |||
memset(&voice_selector, 0, sizeof(voice_selector)); | |||
voice_selector.name = (char *)name; // include variant name in voice stack ?? | |||
voice_selector.name = (char *)name; // include variant name in voice stack ?? | |||
// first check for a voice with this filename | |||
// This may avoid the need to call espeak_ListVoices(). | |||
@@ -1590,7 +1590,7 @@ espeak_ERROR SetVoiceByName(const char *name) | |||
} | |||
if (n_voices_list == 0) | |||
espeak_ListVoices(NULL); // create the voices list | |||
espeak_ListVoices(NULL); // create the voices list | |||
if ((v = SelectVoiceByName(voices_list, buf)) != NULL) { | |||
if (LoadVoice(v->identifier, 0) != NULL) { | |||
@@ -1602,7 +1602,7 @@ espeak_ERROR SetVoiceByName(const char *name) | |||
return EE_OK; | |||
} | |||
} | |||
return EE_INTERNAL_ERROR; // voice name not found | |||
return EE_INTERNAL_ERROR; // voice name not found | |||
} | |||
espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector) | |||
@@ -1645,7 +1645,7 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) | |||
sprintf(path_voices, "%s%cvoices", path_home, PATHSEP); | |||
len_path_voices = strlen(path_voices)+1; | |||
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; | |||
#else | |||
@@ -1661,7 +1661,7 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) | |||
len_path_voices = strlen(path_voices)+1; | |||
GetVoices(path_voices); | |||
voices_list[n_voices_list] = NULL; // voices list terminator | |||
voices_list[n_voices_list] = NULL; // voices list terminator | |||
voices = (espeak_VOICE **)realloc(voices, sizeof(espeak_VOICE *)*(n_voices_list+1)); | |||
// sort the voices list |
@@ -48,7 +48,7 @@ struct timespec { | |||
long tv_sec; | |||
long tv_nsec; | |||
}; | |||
#endif /* HAVE_STRUCT_TIMESPEC */ | |||
#endif | |||
enum { ONE_BILLION = 1000000000 }; | |||
@@ -99,7 +99,8 @@ void *wave_pulse_test_get_write_buffer(); | |||
int wave_pulse_get_remaining_time(uint32_t sample, uint32_t *time); | |||
// wrappers | |||
int wave_init(int srate) { | |||
int wave_init(int srate) | |||
{ | |||
pulse_running = is_pulse_running(); | |||
if (pulse_running) | |||
@@ -108,70 +109,80 @@ int wave_init(int srate) { | |||
return wave_port_init(srate); | |||
} | |||
void *wave_open(const char *the_api) { | |||
void *wave_open(const char *the_api) | |||
{ | |||
if (pulse_running) | |||
return wave_pulse_open(the_api); | |||
else | |||
return wave_port_open(the_api); | |||
} | |||
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) { | |||
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) | |||
{ | |||
if (pulse_running) | |||
return wave_pulse_write(theHandler, theMono16BitsWaveBuffer, theSize); | |||
else | |||
return wave_port_write(theHandler, theMono16BitsWaveBuffer, theSize); | |||
} | |||
int wave_close(void *theHandler) { | |||
int wave_close(void *theHandler) | |||
{ | |||
if (pulse_running) | |||
return wave_pulse_close(theHandler); | |||
else | |||
return wave_port_close(theHandler); | |||
} | |||
int wave_is_busy(void *theHandler) { | |||
int wave_is_busy(void *theHandler) | |||
{ | |||
if (pulse_running) | |||
return wave_pulse_is_busy(theHandler); | |||
else | |||
return wave_port_is_busy(theHandler); | |||
} | |||
void wave_terminate() { | |||
void wave_terminate() | |||
{ | |||
if (pulse_running) | |||
wave_pulse_terminate(); | |||
else | |||
wave_port_terminate(); | |||
} | |||
uint32_t wave_get_read_position(void *theHandler) { | |||
uint32_t wave_get_read_position(void *theHandler) | |||
{ | |||
if (pulse_running) | |||
return wave_pulse_get_read_position(theHandler); | |||
else | |||
return wave_port_get_read_position(theHandler); | |||
} | |||
uint32_t wave_get_write_position(void *theHandler) { | |||
uint32_t wave_get_write_position(void *theHandler) | |||
{ | |||
if (pulse_running) | |||
return wave_pulse_get_write_position(theHandler); | |||
else | |||
return wave_port_get_write_position(theHandler); | |||
} | |||
void wave_flush(void *theHandler) { | |||
void wave_flush(void *theHandler) | |||
{ | |||
if (pulse_running) | |||
wave_pulse_flush(theHandler); | |||
else | |||
wave_port_flush(theHandler); | |||
} | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
{ | |||
if (pulse_running) | |||
wave_pulse_set_callback_is_output_enabled(cb); | |||
else | |||
wave_port_set_callback_is_output_enabled(cb); | |||
} | |||
void *wave_test_get_write_buffer() { | |||
void *wave_test_get_write_buffer() | |||
{ | |||
if (pulse_running) | |||
return wave_pulse_test_get_write_buffer(); | |||
else | |||
@@ -200,7 +211,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
#define wave_test_get_write_buffer wave_port_test_get_write_buffer | |||
#define wave_get_remaining_time wave_port_get_remaining_time | |||
#endif // USE_PULSEAUDIO | |||
#endif | |||
static t_wave_callback *my_callback_is_output_enabled = NULL; | |||
@@ -320,9 +331,8 @@ static int pa_callback(const void *inputBuffer, void *outputBuffer, | |||
mInCallbackFinishedState = true; | |||
size_t aUsedMem = 0; | |||
aUsedMem = (size_t)(aWrite - myRead); | |||
if (aUsedMem) { | |||
if (aUsedMem) | |||
memcpy(outputBuffer, myRead, aUsedMem); | |||
} | |||
char *p = (char *)outputBuffer + aUsedMem; | |||
memset(p, 0, n - aUsedMem); | |||
myRead = aWrite; | |||
@@ -418,17 +428,17 @@ static int wave_open_sound() | |||
PaDeviceID playbackDevice = Pa_GetDefaultOutputDeviceID(); | |||
PaError err = Pa_OpenStream(&pa_stream, | |||
/* capture parameters */ | |||
// capture parameters | |||
paNoDevice, | |||
0, | |||
paInt16, | |||
NULL, | |||
/* playback parameters */ | |||
// playback parameters | |||
playbackDevice, | |||
out_channels, | |||
paInt16, | |||
NULL, | |||
/* general parameters */ | |||
// general parameters | |||
wave_samplerate, FRAMES_PER_BUFFER, 0, | |||
paNoFlag, | |||
pa_callback, (void *)userdata); | |||
@@ -440,17 +450,17 @@ static int wave_open_sound() | |||
// failed to open with mono, try stereo | |||
out_channels = 2; | |||
PaError err = Pa_OpenStream(&pa_stream, | |||
/* capture parameters */ | |||
// capture parameters | |||
paNoDevice, | |||
0, | |||
paInt16, | |||
NULL, | |||
/* playback parameters */ | |||
// playback parameters | |||
playbackDevice, | |||
out_channels, | |||
paInt16, | |||
NULL, | |||
/* general parameters */ | |||
// general parameters | |||
wave_samplerate, FRAMES_PER_BUFFER, 0, | |||
paNoFlag, | |||
pa_callback, (void *)userdata); | |||
@@ -461,45 +471,40 @@ static int wave_open_sound() | |||
#else | |||
myOutputParameters.channelCount = out_channels; | |||
unsigned long framesPerBuffer = paFramesPerBufferUnspecified; | |||
err = Pa_OpenStream( | |||
&pa_stream, | |||
NULL, /* no input */ | |||
&myOutputParameters, | |||
wave_samplerate, | |||
framesPerBuffer, | |||
paNoFlag, | |||
pa_callback, | |||
(void *)userdata); | |||
err = Pa_OpenStream(&pa_stream, | |||
NULL, // no input | |||
&myOutputParameters, | |||
wave_samplerate, | |||
framesPerBuffer, | |||
paNoFlag, | |||
pa_callback, | |||
(void *)userdata); | |||
if ((err != paNoError) | |||
&& (err != paInvalidChannelCount)) { // err==paUnanticipatedHostError | |||
&& (err != paInvalidChannelCount)) { | |||
fprintf(stderr, "wave_open_sound > Pa_OpenStream : err=%d (%s)\n", err, Pa_GetErrorText(err)); | |||
framesPerBuffer = FRAMES_PER_BUFFER; | |||
err = Pa_OpenStream( | |||
&pa_stream, | |||
NULL, /* no input */ | |||
&myOutputParameters, | |||
wave_samplerate, | |||
framesPerBuffer, | |||
paNoFlag, | |||
// paClipOff | paDitherOff, | |||
pa_callback, | |||
(void *)userdata); | |||
err = Pa_OpenStream(&pa_stream, | |||
NULL, // no input | |||
&myOutputParameters, | |||
wave_samplerate, | |||
framesPerBuffer, | |||
paNoFlag, | |||
pa_callback, | |||
(void *)userdata); | |||
} | |||
if (err == paInvalidChannelCount) { | |||
SHOW_TIME("wave_open_sound > try stereo"); | |||
// failed to open with mono, try stereo | |||
out_channels = 2; | |||
myOutputParameters.channelCount = out_channels; | |||
err = Pa_OpenStream( | |||
&pa_stream, | |||
NULL, /* no input */ | |||
&myOutputParameters, | |||
wave_samplerate, | |||
framesPerBuffer, | |||
paNoFlag, | |||
// paClipOff | paDitherOff, | |||
pa_callback, | |||
(void *)userdata); | |||
err = Pa_OpenStream(&pa_stream, | |||
NULL, // no input | |||
&myOutputParameters, | |||
wave_samplerate, | |||
framesPerBuffer, | |||
paNoFlag, | |||
pa_callback, | |||
(void *)userdata); | |||
} | |||
mInCallbackFinishedState = false; | |||
#endif | |||
@@ -748,7 +753,7 @@ size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSiz | |||
myWrite = myBuffer; | |||
myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem/2, theSize - aFreeMem/2); | |||
} else { // 1 channel (mono) | |||
// copy with wrap around at the end of ringbuffer | |||
// copy with wrap around at the end of ringbuffer | |||
copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem); | |||
myWrite = myBuffer; | |||
myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem, theSize - aFreeMem); | |||
@@ -832,7 +837,6 @@ int wave_close(void *theHandler) | |||
// DMM: This doesn't seem to be true; it seems to be necessary to | |||
// call StopStream if the callback brought us here, and AbortStream | |||
// if the user brought us here. | |||
// | |||
#if (USE_PORTAUDIO == 19) | |||
if (pa_stream) { | |||
@@ -937,35 +941,57 @@ void *wave_test_get_write_buffer() | |||
#else | |||
int wave_init(int srate) { | |||
int wave_init(int srate) | |||
{ | |||
return 1; | |||
} | |||
void *wave_open(const char *the_api) { | |||
void *wave_open(const char *the_api) | |||
{ | |||
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) | |||
{ | |||
return theSize; | |||
} | |||
int wave_close(void *theHandler) { | |||
int wave_close(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
int wave_is_busy(void *theHandler) { | |||
int wave_is_busy(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
void wave_terminate() { | |||
void wave_terminate() | |||
{ | |||
} | |||
uint32_t wave_get_read_position(void *theHandler) { | |||
uint32_t wave_get_read_position(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
uint32_t wave_get_write_position(void *theHandler) { | |||
uint32_t wave_get_write_position(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
void wave_flush(void *theHandler) { | |||
void wave_flush(void *theHandler) | |||
{ | |||
} | |||
typedef int (t_wave_callback)(void); | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
{ | |||
} | |||
extern void *wave_test_get_write_buffer() { | |||
extern void *wave_test_get_write_buffer() | |||
{ | |||
return NULL; | |||
} | |||
@@ -976,7 +1002,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
return 0; | |||
} | |||
#endif // of USE_PORTAUDIO | |||
#endif | |||
void clock_gettime2(struct timespec *ts) | |||
{ | |||
@@ -1004,4 +1030,4 @@ void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
ts->tv_nsec = (long int)t_ns; | |||
} | |||
#endif // USE_ASYNC | |||
#endif |
@@ -55,7 +55,6 @@ extern int wave_get_remaining_time(uint32_t sample, uint32_t *time); | |||
typedef int (t_wave_callback)(void); | |||
extern void wave_set_callback_is_output_enabled(t_wave_callback *cb); | |||
// general functions | |||
extern void clock_gettime2(struct timespec *ts); | |||
extern void add_time_in_ms(struct timespec *ts, int time_in_ms); |
@@ -102,7 +102,8 @@ int is_pulse_running() | |||
} else | |||
return 0; | |||
} | |||
#endif // USE_PORTAUDIO | |||
#endif | |||
static pthread_mutex_t pulse_mutex; | |||
@@ -138,7 +139,8 @@ static int wave_samplerate; | |||
if (!connected) { SHOW("CHECK_CONNECTED_NO_RETVAL: !pulse_connected\n", ""); return; } \ | |||
} while (0); | |||
static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { | |||
static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) | |||
{ | |||
ENTER(__FUNCTION__); | |||
assert(c); | |||
@@ -150,7 +152,8 @@ static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t | |||
return; | |||
} | |||
static void context_state_cb(pa_context *c, void *userdata) { | |||
static void context_state_cb(pa_context *c, void *userdata) | |||
{ | |||
ENTER(__FUNCTION__); | |||
assert(c); | |||
@@ -169,7 +172,8 @@ static void context_state_cb(pa_context *c, void *userdata) { | |||
} | |||
} | |||
static void stream_state_cb(pa_stream *s, void *userdata) { | |||
static void stream_state_cb(pa_stream *s, void *userdata) | |||
{ | |||
ENTER(__FUNCTION__); | |||
assert(s); | |||
@@ -186,7 +190,8 @@ static void stream_state_cb(pa_stream *s, void *userdata) { | |||
} | |||
} | |||
static void stream_success_cb(pa_stream *s, int success, void *userdata) { | |||
static void stream_success_cb(pa_stream *s, int success, void *userdata) | |||
{ | |||
ENTER(__FUNCTION__); | |||
assert(s); | |||
@@ -196,7 +201,8 @@ static void stream_success_cb(pa_stream *s, int success, void *userdata) { | |||
pa_threaded_mainloop_signal(mainloop, 0); | |||
} | |||
static void context_success_cb(pa_context *c, int success, void *userdata) { | |||
static void context_success_cb(pa_context *c, int success, void *userdata) | |||
{ | |||
ENTER(__FUNCTION__); | |||
assert(c); | |||
@@ -206,20 +212,23 @@ static void context_success_cb(pa_context *c, int success, void *userdata) { | |||
pa_threaded_mainloop_signal(mainloop, 0); | |||
} | |||
static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { | |||
static void stream_request_cb(pa_stream *s, size_t length, void *userdata) | |||
{ | |||
ENTER(__FUNCTION__); | |||
assert(s); | |||
pa_threaded_mainloop_signal(mainloop, 0); | |||
} | |||
static void stream_latency_update_cb(pa_stream *s, void *userdata) { | |||
static void stream_latency_update_cb(pa_stream *s, void *userdata) | |||
{ | |||
assert(s); | |||
pa_threaded_mainloop_signal(mainloop, 0); | |||
} | |||
static int pulse_free(void) { | |||
static int pulse_free(void) | |||
{ | |||
ENTER(__FUNCTION__); | |||
size_t l = 0; | |||
pa_operation *o = NULL; | |||
@@ -273,7 +282,8 @@ fail: | |||
return (int)l; | |||
} | |||
static int pulse_playing(const pa_timing_info *the_timing_info) { | |||
static int pulse_playing(const pa_timing_info *the_timing_info) | |||
{ | |||
ENTER(__FUNCTION__); | |||
int r = 0; | |||
const pa_timing_info *i; | |||
@@ -306,7 +316,8 @@ fail: | |||
return r; | |||
} | |||
static void pulse_write(void *ptr, int length) { | |||
static void pulse_write(void *ptr, int length) | |||
{ | |||
ENTER(__FUNCTION__); | |||
SHOW("pulse_write > length=%d\n", length); | |||
@@ -327,7 +338,8 @@ fail: | |||
pa_threaded_mainloop_unlock(mainloop); | |||
} | |||
static int drain(void) { | |||
static int drain(void) | |||
{ | |||
pa_operation *o = NULL; | |||
int success = 0; | |||
int ret = PULSE_ERROR; | |||
@@ -367,8 +379,8 @@ fail: | |||
return ret; | |||
} | |||
static void pulse_close(void) { | |||
static void pulse_close(void) | |||
{ | |||
ENTER(__FUNCTION__); | |||
drain(); | |||
@@ -448,7 +460,7 @@ static int pulse_open() | |||
goto unlock_and_fail; | |||
} | |||
/* Wait until the context is ready */ | |||
// Wait until the context is ready | |||
SHOW_TIME("pa_threaded_mainloop_wait"); | |||
pa_threaded_mainloop_wait(mainloop); | |||
@@ -484,7 +496,7 @@ static int pulse_open() | |||
goto unlock_and_fail; | |||
} | |||
/* Wait until the stream is ready */ | |||
// Wait until the stream is ready | |||
SHOW_TIME("pa_threaded_mainloop_wait"); | |||
pa_threaded_mainloop_wait(mainloop); | |||
@@ -493,7 +505,7 @@ static int pulse_open() | |||
goto unlock_and_fail; | |||
} | |||
/* Now subscribe to events */ | |||
// Now subscribe to events | |||
SHOW_TIME("pa_context_subscribe"); | |||
if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) { | |||
SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); | |||
@@ -714,9 +726,8 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
// TBD: take in account time suplied by portaudio V18 API | |||
a_time = sample - a_timing_info.read_index; | |||
a_time = 0.5 + (a_time * 1000.0) / wave_samplerate; | |||
} else { | |||
} else | |||
a_time = 0; | |||
} | |||
SHOW("wave_get_remaining_time > sample=%d, time=%d\n", sample, (uint32_t)a_time); | |||
@@ -732,34 +743,57 @@ void *wave_test_get_write_buffer() | |||
#else | |||
int wave_init(return 1; ) { | |||
int wave_init(int srate) | |||
{ | |||
return 1; | |||
} | |||
void *wave_open(const char *the_api) { | |||
void *wave_open(const char *the_api) | |||
{ | |||
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) | |||
{ | |||
return theSize; | |||
} | |||
int wave_close(void *theHandler) { | |||
int wave_close(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
int wave_is_busy(void *theHandler) { | |||
int wave_is_busy(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
void wave_terminate() { | |||
void wave_terminate() | |||
{ | |||
} | |||
uint32_t wave_get_read_position(void *theHandler) { | |||
uint32_t wave_get_read_position(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
uint32_t wave_get_write_position(void *theHandler) { | |||
uint32_t wave_get_write_position(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
void wave_flush(void *theHandler) { | |||
void wave_flush(void *theHandler) | |||
{ | |||
} | |||
typedef int (t_wave_callback)(void); | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
{ | |||
} | |||
extern void *wave_test_get_write_buffer() { | |||
extern void *wave_test_get_write_buffer() | |||
{ | |||
return NULL; | |||
} | |||
@@ -770,7 +804,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
return 0; | |||
} | |||
#endif // of USE_PULSEAUDIO | |||
#endif | |||
#ifndef USE_PORTAUDIO | |||
@@ -799,6 +833,6 @@ void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
} | |||
ts->tv_nsec = (long int)t_ns; | |||
} | |||
#endif // ifndef USE_PORTAUDIO | |||
#endif // USE_ASYNC | |||
#endif | |||
#endif |
@@ -75,7 +75,8 @@ static uint32_t wave_samplerate; | |||
// sun_audio_fd: modified to hold the file descriptor of the opened | |||
// audio device. | |||
// | |||
int wave_init(int srate) { | |||
int wave_init(int srate) | |||
{ | |||
ENTER("wave_init"); | |||
audio_info_t ainfo; | |||
@@ -478,9 +479,9 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
// | |||
actual_index = sample - total_samples_skipped; | |||
if ((sample < total_samples_skipped) || | |||
(actual_index <= ainfo.play.samples)) { | |||
(actual_index <= ainfo.play.samples)) | |||
*time = 0; | |||
} else { | |||
else { | |||
a_time = ((actual_index - ainfo.play.samples) * 1000) / wave_samplerate; | |||
*time = (uint32_t)a_time; | |||
} | |||
@@ -491,35 +492,57 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
#else | |||
init wave_init() { | |||
int wave_init(int srate) | |||
{ | |||
return 1; | |||
} | |||
void *wave_open(const char *the_api) { | |||
void *wave_open(const char *the_api) | |||
{ | |||
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) | |||
{ | |||
return theSize; | |||
} | |||
int wave_close(void *theHandler) { | |||
int wave_close(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
int wave_is_busy(void *theHandler) { | |||
int wave_is_busy(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
void wave_terminate() { | |||
void wave_terminate() | |||
{ | |||
} | |||
uint32_t wave_get_read_position(void *theHandler) { | |||
uint32_t wave_get_read_position(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
uint32_t wave_get_write_position(void *theHandler) { | |||
uint32_t wave_get_write_position(void *theHandler) | |||
{ | |||
return 0; | |||
} | |||
void wave_flush(void *theHandler) { | |||
void wave_flush(void *theHandler) | |||
{ | |||
} | |||
typedef int (t_wave_callback)(void); | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
{ | |||
} | |||
extern void *wave_test_get_write_buffer() { | |||
extern void *wave_test_get_write_buffer() | |||
{ | |||
return NULL; | |||
} | |||
@@ -530,7 +553,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
return 0; | |||
} | |||
#endif // of USE_PORTAUDIO | |||
#endif | |||
void clock_gettime2(struct timespec *ts) | |||
{ | |||
@@ -558,4 +581,4 @@ void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
ts->tv_nsec = (long int)t_ns; | |||
} | |||
#endif // USE_ASYNC | |||
#endif |
@@ -62,16 +62,16 @@ voice_t *wvoice; | |||
FILE *f_log = NULL; | |||
int option_waveout = 0; | |||
static int option_harmonic1 = 10; // 10 | |||
static int option_harmonic1 = 10; | |||
static int flutter_amp = 64; | |||
static int general_amplitude = 60; | |||
static int consonant_amp = 26; // 24 | |||
static int consonant_amp = 26; | |||
int embedded_value[N_EMBEDDED_VALUES]; | |||
static int PHASE_INC_FACTOR; | |||
int samplerate = 0; // this is set by Wavegeninit() | |||
int samplerate = 0; // this is set by Wavegeninit() | |||
int samplerate_native = 0; | |||
extern int option_device_number; | |||
extern int option_quiet; | |||
@@ -84,7 +84,7 @@ int echo_head; | |||
int echo_tail; | |||
int echo_amp = 0; | |||
short echo_buf[N_ECHO_BUF]; | |||
static int echo_length = 0; // period (in sample\) to ensure completion of echo at the end of speech, set in WavegenSetEcho() | |||
static int echo_length = 0; // period (in sample\) to ensure completion of echo at the end of speech, set in WavegenSetEcho() | |||
static int voicing; | |||
static RESONATOR rbreath[N_PEAKS]; | |||
@@ -92,13 +92,13 @@ static RESONATOR rbreath[N_PEAKS]; | |||
static int harm_sqrt_n = 0; | |||
#define N_LOWHARM 30 | |||
static int harm_inc[N_LOWHARM]; // only for these harmonics do we interpolate amplitude between steps | |||
static int harm_inc[N_LOWHARM]; // only for these harmonics do we interpolate amplitude between steps | |||
static int *harmspect; | |||
static int hswitch = 0; | |||
static int hspect[2][MAX_HARMONIC]; // 2 copies, we interpolate between then | |||
static int hspect[2][MAX_HARMONIC]; // 2 copies, we interpolate between then | |||
static int max_hval = 0; | |||
static int nsamples = 0; // number to do | |||
static int nsamples = 0; // number to do | |||
static int modulation_type = 0; | |||
static int glottal_flag = 0; | |||
static int glottal_reduce = 0; | |||
@@ -109,12 +109,12 @@ static int amp_ix; | |||
static int amp_inc; | |||
static unsigned char *amplitude_env = NULL; | |||
static int samplecount = 0; // number done | |||
static int samplecount_start = 0; // count at start of this segment | |||
static int end_wave = 0; // continue to end of wave cycle | |||
static int samplecount = 0; // number done | |||
static int samplecount_start = 0; // count at start of this segment | |||
static int end_wave = 0; // continue to end of wave cycle | |||
static int wavephase; | |||
static int phaseinc; | |||
static int cycle_samples; // number of samples in a cycle at current pitch | |||
static int cycle_samples; // number of samples in a cycle at current pitch | |||
static int cbytes; | |||
static int hf_factor; | |||
@@ -132,10 +132,10 @@ int wcmdq_head = 0; | |||
int wcmdq_tail = 0; | |||
// pitch,speed, | |||
int embedded_default[N_EMBEDDED_VALUES] = { 0, 50, 175, 100, 50, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0 }; | |||
static int embedded_max[N_EMBEDDED_VALUES] = { 0, 0x7fff, 750, 300, 99, 99, 99, 0, 750, 0, 0, 0, 0, 4, 0 }; | |||
int embedded_default[N_EMBEDDED_VALUES] = { 0, 50, 175, 100, 50, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0 }; | |||
static int embedded_max[N_EMBEDDED_VALUES] = { 0, 0x7fff, 750, 300, 99, 99, 99, 0, 750, 0, 0, 0, 0, 4, 0 }; | |||
#define N_CALLBACK_IX N_WAV_BUF-2 // adjust this delay to match display with the currently spoken word | |||
#define N_CALLBACK_IX N_WAV_BUF-2 // adjust this delay to match display with the currently spoken word | |||
int current_source_index = 0; | |||
extern FILE *f_wave; | |||
@@ -232,22 +232,22 @@ static int wavemult_max = 0; | |||
// the presets are for 22050 Hz sample rate. | |||
// A different rate will need to recalculate the presets in WavegenInit() | |||
static unsigned char wavemult[N_WAVEMULT] = { | |||
0, 0, 0, 2, 3, 5, 8, 11, 14, 18, 22, 27, 32, 37, 43, 49, | |||
55, 62, 69, 76, 83, 90, 98, 105, 113, 121, 128, 136, 144, 152, 159, 166, | |||
0, 0, 0, 2, 3, 5, 8, 11, 14, 18, 22, 27, 32, 37, 43, 49, | |||
55, 62, 69, 76, 83, 90, 98, 105, 113, 121, 128, 136, 144, 152, 159, 166, | |||
174, 181, 188, 194, 201, 207, 213, 218, 224, 228, 233, 237, 240, 244, 246, 249, | |||
251, 252, 253, 253, 253, 253, 252, 251, 249, 246, 244, 240, 237, 233, 228, 224, | |||
218, 213, 207, 201, 194, 188, 181, 174, 166, 159, 152, 144, 136, 128, 121, 113, | |||
105, 98, 90, 83, 76, 69, 62, 55, 49, 43, 37, 32, 27, 22, 18, 14, | |||
11, 8, 5, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |||
105, 98, 90, 83, 76, 69, 62, 55, 49, 43, 37, 32, 27, 22, 18, 14, | |||
11, 8, 5, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |||
}; | |||
// set from y = pow(2,x) * 128, x=-1 to 1 | |||
unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1] = { | |||
64, 65, 66, 67, 68, 69, 70, 71, | |||
72, 73, 74, 75, 76, 77, 78, 79, | |||
80, 81, 82, 83, 84, 86, 87, 88, | |||
89, 91, 92, 93, 94, 96, 97, 98, | |||
64, 65, 66, 67, 68, 69, 70, 71, | |||
72, 73, 74, 75, 76, 77, 78, 79, | |||
80, 81, 82, 83, 84, 86, 87, 88, | |||
89, 91, 92, 93, 94, 96, 97, 98, | |||
100, 101, 103, 104, 105, 107, 108, 110, | |||
111, 113, 115, 116, 118, 119, 121, 123, | |||
124, 126, 128, 130, 132, 133, 135, 137, | |||
@@ -310,19 +310,19 @@ unsigned char pk_shape1[PEAKSHAPEW+1] = { | |||
245, 244, 242, 241, 239, 238, 236, 234, 233, 231, 229, 227, 225, 223, 220, 218, | |||
216, 213, 211, 209, 207, 205, 203, 201, 199, 197, 195, 193, 191, 189, 187, 185, | |||
183, 180, 178, 176, 173, 171, 169, 166, 164, 161, 159, 156, 154, 151, 148, 146, | |||
143, 140, 138, 135, 132, 129, 126, 123, 120, 118, 115, 112, 108, 105, 102, 99, | |||
96, 95, 93, 91, 90, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, | |||
72, 70, 69, 68, 67, 66, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, | |||
55, 54, 53, 52, 52, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 46, | |||
45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 44, 43, | |||
42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33, | |||
32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24, | |||
23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 18, 17, 17, 16, | |||
16, 15, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10, | |||
10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, | |||
5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, | |||
2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0 | |||
143, 140, 138, 135, 132, 129, 126, 123, 120, 118, 115, 112, 108, 105, 102, 99, | |||
96, 95, 93, 91, 90, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, | |||
72, 70, 69, 68, 67, 66, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, | |||
55, 54, 53, 52, 52, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 46, | |||
45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 44, 43, | |||
42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33, | |||
32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24, | |||
23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 18, 17, 17, 16, | |||
16, 15, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10, | |||
10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, | |||
5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, | |||
2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0 | |||
}; | |||
static unsigned char pk_shape2[PEAKSHAPEW+1] = { | |||
@@ -331,18 +331,18 @@ static unsigned char pk_shape2[PEAKSHAPEW+1] = { | |||
243, 243, 242, 241, 239, 237, 235, 233, 231, 229, 227, 225, 223, 221, 218, 216, | |||
213, 211, 208, 205, 203, 200, 197, 194, 191, 187, 184, 181, 178, 174, 171, 167, | |||
163, 160, 156, 152, 148, 144, 140, 136, 132, 127, 123, 119, 114, 110, 105, 100, | |||
96, 94, 91, 88, 86, 83, 81, 78, 76, 74, 71, 69, 66, 64, 62, 60, | |||
57, 55, 53, 51, 49, 47, 44, 42, 40, 38, 36, 34, 32, 30, 29, 27, | |||
25, 23, 21, 19, 18, 16, 14, 12, 11, 9, 7, 6, 4, 3, 1, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0 | |||
96, 94, 91, 88, 86, 83, 81, 78, 76, 74, 71, 69, 66, 64, 62, 60, | |||
57, 55, 53, 51, 49, 47, 44, 42, 40, 38, 36, 34, 32, 30, 29, 27, | |||
25, 23, 21, 19, 18, 16, 14, 12, 11, 9, 7, 6, 4, 3, 1, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
0 | |||
}; | |||
static unsigned char *pk_shape; | |||
@@ -389,7 +389,7 @@ static int WaveCallback(const void *inputBuffer, void *outputBuffer, | |||
out_ptr = out_start = outbuffer; | |||
out_end = out_start + outbuffer_size; | |||
} | |||
out_end2 = &outbuffer[pa_size]; // top of data needed for the portaudio buffer | |||
out_end2 = &outbuffer[pa_size]; // top of data needed for the portaudio buffer | |||
#ifdef LIBRARY | |||
event_list_ix = 0; | |||
@@ -398,19 +398,17 @@ static int WaveCallback(const void *inputBuffer, void *outputBuffer, | |||
result = WavegenFill(1); | |||
// copy from the outbut buffer into the portaudio buffer | |||
if (result && (out_ptr > out_end2)) { | |||
result = 0; // don't end yet, there is more data in the buffer than can fit in portaudio | |||
} | |||
if (result && (out_ptr > out_end2)) | |||
result = 0; // don't end yet, there is more data in the buffer than can fit in portaudio | |||
while (out_ptr < out_end2) | |||
*out_ptr++ = 0; // fill with zeros up to the size of the portaudio buffer | |||
*out_ptr++ = 0; // fill with zeros up to the size of the portaudio buffer | |||
memcpy(outputBuffer, outbuffer, pa_size); | |||
// move the remaining contents of the start of the output buffer | |||
for (p = out_end2; p < out_end; p++) { | |||
for (p = out_end2; p < out_end; p++) | |||
p[-pa_size] = p[0]; | |||
} | |||
out_ptr -= pa_size; | |||
#ifdef LIBRARY | |||
@@ -421,25 +419,23 @@ static int WaveCallback(const void *inputBuffer, void *outputBuffer, | |||
event_list[event_list_ix].user_data = 0; | |||
if (synth_callback(NULL, 0, event_list) == 1) { | |||
SpeakNextClause(NULL, NULL, 2); // stop speaking | |||
SpeakNextClause(NULL, NULL, 2); // stop speaking | |||
result = 1; | |||
} | |||
} | |||
#endif | |||
#ifdef ARCH_BIG | |||
{ | |||
// swap the order of bytes in each sound sample in the portaudio buffer | |||
int c; | |||
unsigned char *buf_end; | |||
out_buf = (unsigned char *)outputBuffer; | |||
buf_end = out_buf + framesPerBuffer*2; | |||
while (out_buf < buf_end) { | |||
c = out_buf[0]; | |||
out_buf[0] = out_buf[1]; | |||
out_buf[1] = c; | |||
out_buf += 2; | |||
} | |||
// swap the order of bytes in each sound sample in the portaudio buffer | |||
int c; | |||
unsigned char *buf_end; | |||
out_buf = (unsigned char *)outputBuffer; | |||
buf_end = out_buf + framesPerBuffer*2; | |||
while (out_buf < buf_end) { | |||
c = out_buf[0]; | |||
out_buf[0] = out_buf[1]; | |||
out_buf[1] = c; | |||
out_buf += 2; | |||
} | |||
#endif | |||
@@ -591,7 +587,7 @@ int WavegenCloseSound() | |||
return 1; | |||
} | |||
} else | |||
WavegenOpenSound(); // still items in the queue, shouldn't be closed | |||
WavegenOpenSound(); // still items in the queue, shouldn't be closed | |||
} | |||
return 0; | |||
} | |||
@@ -612,19 +608,24 @@ int WavegenInitSound() | |||
} | |||
return 0; | |||
} | |||
#else | |||
int WavegenOpenSound() | |||
{ | |||
return 0; | |||
} | |||
int WavegenCloseSound() | |||
{ | |||
return 0; | |||
} | |||
int WavegenInitSound() | |||
{ | |||
return 0; | |||
} | |||
#endif | |||
void WavegenInit(int rate, int wavemult_fact) | |||
@@ -633,11 +634,11 @@ void WavegenInit(int rate, int wavemult_fact) | |||
double x; | |||
if (wavemult_fact == 0) | |||
wavemult_fact = 60; // default | |||
wavemult_fact = 60; // default | |||
wvoice = NULL; | |||
samplerate = samplerate_native = rate; | |||
PHASE_INC_FACTOR = 0x8000000 / samplerate; // assumes pitch is Hz*32 | |||
PHASE_INC_FACTOR = 0x8000000 / samplerate; // assumes pitch is Hz*32 | |||
Flutter_inc = (64 * samplerate)/rate; | |||
samplecount = 0; | |||
nsamples = 0; | |||
@@ -666,7 +667,7 @@ void WavegenInit(int rate, int wavemult_fact) | |||
} | |||
} | |||
pk_shape = pk_shape2; // pk_shape2 | |||
pk_shape = pk_shape2; | |||
#ifdef INCLUDE_KLATT | |||
KlattInit(); | |||
@@ -712,11 +713,11 @@ static void WavegenSetEcho(void) | |||
amp = 0; | |||
echo_head = (delay * samplerate)/1000; | |||
echo_length = echo_head; // ensure completion of echo at the end of speech. Use 1 delay period? | |||
echo_length = echo_head; // ensure completion of echo at the end of speech. Use 1 delay period? | |||
if (amp == 0) | |||
echo_length = 0; | |||
if (amp > 20) | |||
echo_length = echo_head * 2; // perhaps allow 2 echo periods if the echo is loud. | |||
echo_length = echo_head * 2; // perhaps allow 2 echo periods if the echo is loud. | |||
// echo_amp units are 1/256ths of the amplitude of the original sound. | |||
echo_amp = amp; | |||
@@ -727,21 +728,21 @@ static void WavegenSetEcho(void) | |||
int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | |||
{ | |||
// Calculate the amplitude of each harmonics from the formants | |||
// Only for formants 0 to 5 | |||
// Calculate the amplitude of each harmonics from the formants | |||
// Only for formants 0 to 5 | |||
// control 0=initial call, 1=every 64 cycles | |||
// control 0=initial call, 1=every 64 cycles | |||
// pitch and freqs are Hz<<16 | |||
int f; | |||
wavegen_peaks_t *p; | |||
int fp; // centre freq of peak | |||
int fhi; // high freq of peak | |||
int h; // harmonic number | |||
int fp; // centre freq of peak | |||
int fhi; // high freq of peak | |||
int h; // harmonic number | |||
int pk; | |||
int hmax; | |||
int hmax_samplerate; // highest harmonic allowed for the samplerate | |||
int hmax_samplerate; // highest harmonic allowed for the samplerate | |||
int x; | |||
int ix; | |||
int h1; | |||
@@ -759,7 +760,7 @@ int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | |||
hmax = MAX_HARMONIC-1; | |||
// restrict highest harmonic to half the samplerate | |||
hmax_samplerate = (((samplerate * 19)/40) << 16)/pitch; // only 95% of Nyquist freq | |||
hmax_samplerate = (((samplerate * 19)/40) << 16)/pitch; // only 95% of Nyquist freq | |||
if (hmax > hmax_samplerate) | |||
hmax = hmax_samplerate; | |||
@@ -787,7 +788,7 @@ int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | |||
int h2; | |||
// increase bass | |||
y = peaks[1].height * 10; // addition as a multiple of 1/256s | |||
h2 = (1000<<16)/pitch; // decrease until 1000Hz | |||
h2 = (1000<<16)/pitch; // decrease until 1000Hz | |||
if (h2 > 0) { | |||
x = y/h2; | |||
h = 1; | |||
@@ -819,26 +820,25 @@ int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | |||
htab[h] = (x * x) >> 8; | |||
if ((ix = (f >> 19)) < N_TONE_ADJUST) | |||
htab[h] = (htab[h] * wvoice->tone_adjust[ix]) >> 13; // index tone_adjust with Hz/8 | |||
htab[h] = (htab[h] * wvoice->tone_adjust[ix]) >> 13; // index tone_adjust with Hz/8 | |||
} | |||
// adjust the amplitude of the first harmonic, affects tonal quality | |||
h1 = htab[1] * option_harmonic1; | |||
htab[1] = h1/8; | |||
// calc intermediate increments of LF harmonics | |||
if (control & 1) { | |||
for (h = 1; h < N_LOWHARM; h++) | |||
harm_inc[h] = (htab[h] - harmspect[h]) >> 3; | |||
} | |||
return hmax; // highest harmonic number | |||
return hmax; // highest harmonic number | |||
} | |||
static void AdvanceParameters() | |||
{ | |||
// Called every 64 samples to increment the formant freq, height, and widths | |||
// Called every 64 samples to increment the formant freq, height, and widths | |||
int x; | |||
int ix; | |||
@@ -859,7 +859,7 @@ static void AdvanceParameters() | |||
Flutter_ix += Flutter_inc; | |||
wdata.pitch += x; | |||
if (wdata.pitch < 102400) | |||
wdata.pitch = 102400; // min pitch, 25 Hz (25 << 12) | |||
wdata.pitch = 102400; // min pitch, 25 Hz (25 << 12) | |||
if (samplecount == samplecount_start) | |||
return; | |||
@@ -912,9 +912,9 @@ static double resonator(RESONATOR *r, double input) | |||
static void setresonator(RESONATOR *rp, int freq, int bwidth, int init) | |||
{ | |||
// freq Frequency of resonator in Hz | |||
// bwidth Bandwidth of resonator in Hz | |||
// init Initialize internal data | |||
// freq Frequency of resonator in Hz | |||
// bwidth Bandwidth of resonator in Hz | |||
// init Initialize internal data | |||
double x; | |||
double arg; | |||
@@ -1007,7 +1007,7 @@ int Wavegen() | |||
static int agc = 256; | |||
static int h_switch_sign = 0; | |||
static int cycle_count = 0; | |||
static int amplitude2 = 0; // adjusted for pitch | |||
static int amplitude2 = 0; // adjusted for pitch | |||
// continue until the output buffer is full, or | |||
// the required number of samples have been produced | |||
@@ -1033,7 +1033,7 @@ int Wavegen() | |||
// pitch is Hz<<12 | |||
phaseinc = (wdata.pitch>>7) * PHASE_INC_FACTOR; | |||
cycle_samples = samplerate/(wdata.pitch >> 12); // sr/(pitch*2) | |||
cycle_samples = samplerate/(wdata.pitch >> 12); // sr/(pitch*2) | |||
hf_factor = wdata.pitch >> 11; | |||
maxh = maxh2; | |||
@@ -1270,7 +1270,7 @@ static int PlayWave(int length, int resume, unsigned char *data, int scale, int | |||
// 8 bit data, shift by the specified scale factor | |||
value = (signed char)data[ix++] * scale; | |||
} | |||
value *= (consonant_amp * general_amplitude); // reduce strength of consonant | |||
value *= (consonant_amp * general_amplitude); // reduce strength of consonant | |||
value = value >> 10; | |||
value = (value * amp)/32; | |||
@@ -1353,14 +1353,14 @@ void SetEmbedded(int control, int value) | |||
switch (command) | |||
{ | |||
case EMBED_T: | |||
WavegenSetEcho(); // and drop through to case P | |||
WavegenSetEcho(); // and drop through to case P | |||
case EMBED_P: | |||
SetPitchFormants(); | |||
break; | |||
case EMBED_A: // amplitude | |||
case EMBED_A: // amplitude | |||
general_amplitude = GetAmplitude(); | |||
break; | |||
case EMBED_F: // emphasis | |||
case EMBED_F: // emphasis | |||
general_amplitude = GetAmplitude(); | |||
break; | |||
case EMBED_H: | |||
@@ -1383,7 +1383,7 @@ void WavegenSetVoice(voice_t *v) | |||
consonant_amp = (v->consonant_amp * 26) /100; | |||
if (samplerate <= 11000) { | |||
consonant_amp = consonant_amp*2; // emphasize consonants at low sample rates | |||
consonant_amp = consonant_amp*2; // emphasize consonants at low sample rates | |||
option_harmonic1 = 6; | |||
} | |||
WavegenSetEcho(); | |||
@@ -1400,7 +1400,7 @@ static void SetAmplitude(int length, unsigned char *amp_env, int value) | |||
amp_inc = (256 * ENV_LEN * STEPSIZE)/length; | |||
wdata.amplitude = (value * general_amplitude)/16; | |||
wdata.amplitude_v = (wdata.amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds | |||
wdata.amplitude_v = (wdata.amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds | |||
amplitude_env = amp_env; | |||
} | |||
@@ -1413,14 +1413,14 @@ void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pit | |||
int pitch_value; | |||
if (pitch1 > pitch2) { | |||
x = pitch1; // swap values | |||
x = pitch1; // swap values | |||
pitch1 = pitch2; | |||
pitch2 = x; | |||
} | |||
if ((pitch_value = embedded_value[EMBED_P]) > MAX_PITCH_VALUE) | |||
pitch_value = MAX_PITCH_VALUE; | |||
pitch_value -= embedded_value[EMBED_T]; // adjust tone for announcing punctuation | |||
pitch_value -= embedded_value[EMBED_T]; // adjust tone for announcing punctuation | |||
if (pitch_value < 0) | |||
pitch_value = 0; | |||
@@ -1436,10 +1436,10 @@ void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pit | |||
void SetPitch(int length, unsigned char *env, int pitch1, int pitch2) | |||
{ | |||
// length in samples | |||
// length in samples | |||
if ((wdata.pitch_env = env) == NULL) | |||
wdata.pitch_env = env_fall; // default | |||
wdata.pitch_env = env_fall; // default | |||
wdata.pitch_ix = 0; | |||
if (length == 0) | |||
@@ -1449,7 +1449,7 @@ void SetPitch(int length, unsigned char *env, int pitch1, int pitch2) | |||
SetPitch2(wvoice, pitch1, pitch2, &wdata.pitch_base, &wdata.pitch_range); | |||
// set initial pitch | |||
wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12 | |||
wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12 | |||
flutter_amp = wvoice->flutter; | |||
} | |||
@@ -1462,8 +1462,8 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
int length4; | |||
int qix; | |||
int cmd; | |||
static int glottal_reduce_tab1[4] = { 0x30, 0x30, 0x40, 0x50 }; // vowel before [?], amp * 1/256 | |||
static int glottal_reduce_tab2[4] = { 0x90, 0xa0, 0xb0, 0xc0 }; // vowel after [?], amp * 1/256 | |||
static int glottal_reduce_tab1[4] = { 0x30, 0x30, 0x40, 0x50 }; // vowel before [?], amp * 1/256 | |||
static int glottal_reduce_tab2[4] = { 0x90, 0xa0, 0xb0, 0xc0 }; // vowel after [?], amp * 1/256 | |||
harm_sqrt_n = 0; | |||
end_wave = 1; | |||
@@ -1473,11 +1473,11 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
glottal_flag = 0; | |||
if (modn & 0x400) { | |||
glottal_flag = 3; // before a glottal stop | |||
glottal_flag = 3; // before a glottal stop | |||
glottal_reduce = glottal_reduce_tab1[(modn >> 8) & 3]; | |||
} | |||
if (modn & 0x800) { | |||
glottal_flag = 4; // after a glottal stop | |||
glottal_flag = 4; // after a glottal stop | |||
glottal_reduce = glottal_reduce_tab2[(modn >> 8) & 3]; | |||
} | |||
@@ -1487,11 +1487,11 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
cmd = wcmdq[qix][0]; | |||
if (cmd == WCMD_SPECT) { | |||
end_wave = 0; // next wave generation is from another spectrum | |||
end_wave = 0; // next wave generation is from another spectrum | |||
break; | |||
} | |||
if ((cmd == WCMD_WAVE) || (cmd == WCMD_PAUSE)) | |||
break; // next is not from spectrum, so continue until end of wave cycle | |||
break; // next is not from spectrum, so continue until end of wave cycle | |||
} | |||
// round the length to a multiple of the stepsize | |||
@@ -1513,7 +1513,7 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
peaks[ix].freq1 = (fr1->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8; | |||
peaks[ix].freq = (int)peaks[ix].freq1; | |||
next = (fr2->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8; | |||
peaks[ix].freq_inc = ((next - peaks[ix].freq1) * (STEPSIZE/4)) / length4; // lower headroom for fixed point math | |||
peaks[ix].freq_inc = ((next - peaks[ix].freq1) * (STEPSIZE/4)) / length4; // lower headroom for fixed point math | |||
} | |||
peaks[ix].height1 = (fr1->fheight[ix] * v->height[ix]) << 6; | |||
@@ -1532,9 +1532,8 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
peaks[ix].right = (int)peaks[ix].right1; | |||
next = (fr2->fright[ix] * v->width[ix]) << 10; | |||
peaks[ix].right_inc = ((next - peaks[ix].right1) * STEPSIZE) / length2; | |||
} else { | |||
} else | |||
peaks[ix].right = peaks[ix].left; | |||
} | |||
} | |||
} | |||
} | |||
@@ -1549,7 +1548,7 @@ static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_ | |||
void Write4Bytes(FILE *f, int value) | |||
{ | |||
// Write 4 bytes to a file, least significant first | |||
// Write 4 bytes to a file, least significant first | |||
int ix; | |||
for (ix = 0; ix < 4; ix++) { | |||
@@ -1560,9 +1559,9 @@ void Write4Bytes(FILE *f, int value) | |||
int WavegenFill2(int fill_zeros) | |||
{ | |||
// Pick up next wavegen commands from the queue | |||
// return: 0 output buffer has been filled | |||
// return: 1 input command queue is now empty | |||
// Pick up next wavegen commands from the queue | |||
// return: 0 output buffer has been filled | |||
// return: 1 input command queue is now empty | |||
intptr_t *q; | |||
int length; | |||
@@ -1577,14 +1576,14 @@ int WavegenFill2(int fill_zeros) | |||
// continue to play silence until echo is completed | |||
resume = PlaySilence(echo_complete, resume); | |||
if (resume == 1) | |||
return 0; // not yet finished | |||
return 0; // not yet finished | |||
} | |||
if (fill_zeros) { | |||
while (out_ptr < out_end) | |||
*out_ptr++ = 0; | |||
} | |||
return 1; // queue empty, close sound channel | |||
return 1; // queue empty, close sound channel | |||
} | |||
result = 0; | |||
@@ -1628,15 +1627,15 @@ int WavegenFill2(int fill_zeros) | |||
wdata.mix_wavefile_offset = 0; | |||
wdata.mix_wavefile = (unsigned char *)q[2]; | |||
break; | |||
case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file | |||
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | |||
case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file | |||
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | |||
case WCMD_SPECT: | |||
echo_complete = echo_length; | |||
result = Wavegen2(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3]); | |||
break; | |||
#ifdef INCLUDE_KLATT | |||
case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file | |||
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | |||
case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file | |||
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | |||
case WCMD_KLATT: | |||
echo_complete = echo_length; | |||
result = Wavegen_Klatt2(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3]); | |||
@@ -1663,7 +1662,7 @@ int WavegenFill2(int fill_zeros) | |||
break; | |||
case WCMD_FMT_AMPLITUDE: | |||
if ((wdata.amplitude_fmt = q[1]) == 0) | |||
wdata.amplitude_fmt = 100; // percentage, but value=0 means 100% | |||
wdata.amplitude_fmt = 100; // percentage, but value=0 means 100% | |||
break; | |||
#if HAVE_SONIC_H | |||
case WCMD_SONIC_SPEED: | |||
@@ -1683,7 +1682,7 @@ int WavegenFill2(int fill_zeros) | |||
} | |||
#if HAVE_SONIC_H | |||
/* Speed up the audio samples with libsonic. */ | |||
// Speed up the audio samples with libsonic. | |||
static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text) | |||
{ | |||
if (length_in > 0) { | |||
@@ -1704,7 +1703,7 @@ static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text | |||
} | |||
#endif | |||
/* Call WavegenFill2, and then speed up the output samples. */ | |||
// Call WavegenFill2, and then speed up the output samples. | |||
int WavegenFill(int fill_zeros) | |||
{ | |||
int finished; | |||
@@ -1725,7 +1724,7 @@ int WavegenFill(int fill_zeros) | |||
out_ptr = p_start + length; | |||
if (length >= max_length) | |||
finished = 0; // there may be more data to flush | |||
finished = 0; // there may be more data to flush | |||
} | |||
#endif | |||
return finished; |
@@ -53,7 +53,7 @@ | |||
#include "translate.h" | |||
extern void Write4Bytes(FILE *f, int value); | |||
char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
char filetype[5]; | |||
char wavefile[200]; | |||
@@ -204,7 +204,7 @@ static int OpenWaveFile(const char *path, int rate) | |||
if (path[0] != 0) { | |||
if (strcmp(path, "stdout") == 0) { | |||
#ifdef PLATFORM_WINDOWS | |||
// prevent Windows adding 0x0d before 0x0a bytes | |||
// prevent Windows adding 0x0d before 0x0a bytes | |||
_setmode(_fileno(stdout), _O_BINARY); | |||
#endif | |||
f_wave = stdout; | |||
@@ -296,14 +296,14 @@ static void init_path(char *argv0, char *path_specified) | |||
if (((env = getenv("ESPEAK_DATA_PATH")) != NULL) && ((strlen(env)+12) < sizeof(path_home))) { | |||
sprintf(path_home, "%s\\espeak-data", env); | |||
if (GetFileLength(path_home) == -2) | |||
return; // an espeak-data directory exists in the directory specified by environment variable | |||
return; // an espeak-data directory exists in the directory specified by environment variable | |||
} | |||
strcpy(path_home, argv0); | |||
if ((p = strrchr(path_home, '\\')) != NULL) { | |||
strcpy(&p[1], "espeak-data"); | |||
if (GetFileLength(path_home) == -2) | |||
return; // an espeak-data directory exists in the same directory as the espeak program | |||
return; // an espeak-data directory exists in the same directory as the espeak program | |||
} | |||
// otherwise, look in the Windows Registry | |||
@@ -322,7 +322,7 @@ static void init_path(char *argv0, char *path_specified) | |||
if ((env = getenv("ESPEAK_DATA_PATH")) != NULL) { | |||
snprintf(path_home, sizeof(path_home), "%s/espeak-data", env); | |||
if (GetFileLength(path_home) == -2) | |||
return; // an espeak-data directory exists | |||
return; // an espeak-data directory exists | |||
} | |||
snprintf(path_home, sizeof(path_home), "%s/espeak-data", getenv("HOME")); | |||
@@ -336,7 +336,7 @@ static int initialise(void) | |||
{ | |||
int param; | |||
int result; | |||
int srate = 22050; // default sample rate | |||
int srate = 22050; // default sample rate | |||
// It seems that the wctype functions don't work until the locale has been set | |||
// to something other than the default "C". Then, not only Latin1 but also the | |||
@@ -409,7 +409,7 @@ int main(int argc, char **argv) | |||
FILE *f_text = NULL; | |||
const char *p_text = NULL; | |||
char *data_path = NULL; // use default path for espeak-data | |||
char *data_path = NULL; // use default path for espeak-data | |||
int option_index = 0; | |||
int c; | |||
@@ -417,7 +417,7 @@ int main(int argc, char **argv) | |||
int speed = 175; | |||
int ix; | |||
char *optarg2; | |||
int amp = 100; // default | |||
int amp = 100; // default | |||
int wordgap = 0; | |||
int flag_stdin = 0; | |||
int flag_compile = 0; | |||
@@ -439,7 +439,7 @@ int main(int argc, char **argv) | |||
option_wordgap = 0; | |||
option_endpause = 1; | |||
option_phoneme_input = 1; | |||
option_multibyte = espeakCHARS_AUTO; // auto | |||
option_multibyte = espeakCHARS_AUTO; | |||
f_trans = stdout; | |||
#ifdef NEED_GETOPT | |||
@@ -463,7 +463,7 @@ int main(int argc, char **argv) | |||
if (c == '-') { | |||
if (p[0] == 0) | |||
break; // -- means don't interpret further - as commands | |||
break; // -- means don't interpret further - as commands | |||
opt_string = ""; | |||
for (ix = 0;; ix++) { | |||
@@ -488,10 +488,10 @@ int main(int argc, char **argv) | |||
} | |||
#else | |||
while (true) { | |||
c = getopt_long(argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value | |||
c = getopt_long(argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value | |||
long_options, &option_index); | |||
/* Detect the end of the options. */ | |||
// Detect the end of the options. | |||
if (c == -1) | |||
break; | |||
optarg2 = optarg; | |||
@@ -555,20 +555,20 @@ int main(int argc, char **argv) | |||
case 'z': | |||
option_endpause = 0; | |||
break; | |||
case 0x100: // --stdin | |||
case 0x100: // --stdin | |||
flag_stdin = 1; | |||
break; | |||
case 0x105: // --stdout | |||
case 0x105: // --stdout | |||
option_waveout = 1; | |||
strcpy(wavefile, "stdout"); | |||
break; | |||
case 0x101: // --compile-debug | |||
case 0x102: // --compile | |||
case 0x101: // --compile-debug | |||
case 0x102: // --compile | |||
if (optarg2 != NULL) | |||
strncpy0(voicename, optarg2, sizeof(voicename)); | |||
flag_compile = c; | |||
break; | |||
case 0x103: // --punct | |||
case 0x103: // --punct | |||
option_punctuation = 1; | |||
if (optarg2 != NULL) { | |||
ix = 0; | |||
@@ -577,29 +577,29 @@ int main(int argc, char **argv) | |||
option_punctuation = 2; | |||
} | |||
break; | |||
case 0x104: // --voices | |||
case 0x104: // --voices | |||
init_path(argv[0], data_path); | |||
DisplayVoices(stdout, optarg2); | |||
exit(0); | |||
case 0x106: // -- split | |||
case 0x106: // -- split | |||
if (optarg2 == NULL) | |||
samples_split = 30; // default 30 minutes | |||
samples_split = 30; // default 30 minutes | |||
else | |||
samples_split = atoi(optarg2); | |||
break; | |||
case 0x107: // --path | |||
case 0x107: // --path | |||
data_path = optarg2; | |||
break; | |||
case 0x108: // --phonout | |||
case 0x108: // --phonout | |||
if ((f_trans = fopen(optarg2, "w")) == NULL) { | |||
fprintf(stderr, "Can't write to: %s\n", optarg2); | |||
f_trans = stderr; | |||
} | |||
break; | |||
case 0x109: // --pho | |||
case 0x109: // --pho | |||
phoneme_options |= espeakPHONEMES_MBROLA; | |||
break; | |||
case 0x10a: // --ipa | |||
case 0x10a: // --ipa | |||
phoneme_options |= espeakPHONEMES_IPA; | |||
if (optarg2 != NULL) { | |||
// deprecated and obsolete | |||
@@ -613,33 +613,33 @@ int main(int argc, char **argv) | |||
phoneme_options |= espeakPHONEMES_TIE; | |||
break; | |||
case 3: | |||
phonemes_separator = 0x200d; // ZWJ | |||
phonemes_separator = 0x200d; // ZWJ | |||
phoneme_options |= espeakPHONEMES_TIE; | |||
break; | |||
} | |||
} | |||
break; | |||
case 0x10b: // --version | |||
case 0x10b: // --version | |||
init_path(argv[0], data_path); | |||
printf("speak text-to-speech: %s Data at: %s\n", version_string, path_home); | |||
exit(0); | |||
case 0x10c: // --sep | |||
case 0x10c: // --sep | |||
phoneme_options |= espeakPHONEMES_SHOW; | |||
if (optarg2 == 0) | |||
phonemes_separator = ' '; | |||
else | |||
utf8_in(&phonemes_separator, optarg2); | |||
if (phonemes_separator == 'z') | |||
phonemes_separator = 0x200c; // ZWNJ | |||
phonemes_separator = 0x200c; // ZWNJ | |||
break; | |||
case 0x10d: // --tie | |||
case 0x10d: // --tie | |||
phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); | |||
if (optarg2 == 0) | |||
phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
else | |||
utf8_in(&phonemes_separator, optarg2); | |||
if (phonemes_separator == 'z') | |||
phonemes_separator = 0x200d; // ZWJ | |||
phonemes_separator = 0x200d; // ZWJ | |||
break; | |||
default: | |||
exit(0); | |||
@@ -665,14 +665,14 @@ int main(int argc, char **argv) | |||
#ifdef PLATFORM_DOS | |||
char path_dsource[sizeof(path_home)+20]; | |||
strcpy(path_dsource, path_home); | |||
path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
strcat(path_dsource, "dictsource\\"); | |||
CompileDictionary(path_dsource, dictionary_name, NULL, NULL, flag_compile & 0x1); | |||
#else | |||
#ifdef PLATFORM_WINDOWS | |||
char path_dsource[sizeof(path_home)+20]; | |||
strcpy(path_dsource, path_home); | |||
path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
strcat(path_dsource, "dictsource\\"); | |||
CompileDictionary(path_dsource, dictionary_name, NULL, NULL, flag_compile & 0x1); | |||
#else | |||
@@ -690,9 +690,8 @@ int main(int argc, char **argv) | |||
option_phonemes = phoneme_options | (phonemes_separator << 8); | |||
if (pitch_adjustment != 50) { | |||
if (pitch_adjustment != 50) | |||
SetParameter(espeakPITCH, pitch_adjustment, 0); | |||
} | |||
DoVoiceChange(voice); | |||
if (filename[0] == 0) { | |||
@@ -703,7 +702,7 @@ int main(int argc, char **argv) | |||
} else { | |||
f_text = stdin; | |||
if (flag_stdin == 0) | |||
option_linelength = -1; // single input lines on stdin | |||
option_linelength = -1; // single input lines on stdin | |||
} | |||
} else | |||
f_text = fopen(filename, "r"); | |||
@@ -743,7 +742,7 @@ int main(int argc, char **argv) | |||
for (;;) { | |||
if (WavegenFile() != 0) { | |||
if (ix == 0) | |||
break; // finished, wavegen command queue is empty | |||
break; // finished, wavegen command queue is empty | |||
} | |||
if (Generate(phoneme_list, &n_phoneme_list, 1) == 0) | |||
@@ -767,13 +766,13 @@ int main(int argc, char **argv) | |||
// NOTE: if nanosleep() isn't recognised on your system, try replacing | |||
// this by sleep(1); | |||
#ifdef PLATFORM_WINDOWS | |||
Sleep(300); // 0.3s | |||
Sleep(300); // 0.3s | |||
#else | |||
#ifdef USE_NANOSLEEP | |||
struct timespec period; | |||
struct timespec remaining; | |||
period.tv_sec = 0; | |||
period.tv_nsec = 300000000; // 0.3 sec | |||
period.tv_nsec = 300000000; // 0.3 sec | |||
nanosleep(&period, &remaining); | |||
#else | |||
sleep(1); | |||
@@ -785,6 +784,6 @@ int main(int argc, char **argv) | |||
} | |||
if ((f_trans != stdout) && (f_trans != stderr)) | |||
fclose(f_trans); // needed for WinCe | |||
fclose(f_trans); | |||
return 0; | |||
} |