mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-10-31 13:38:47 +00:00
Check and fix source code formatting.
This commit is contained in:
+33
-36
@@ -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;
|
||||
}
|
||||
|
||||
+283
-280
File diff suppressed because it is too large
Load Diff
+127
-123
@@ -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
|
||||
{ "$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 },
|
||||
// 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
|
||||
{ "$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
|
||||
{ "$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
|
||||
{ "$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
|
||||
// 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]);
|
||||
|
||||
+225
-228
File diff suppressed because it is too large
Load Diff
@@ -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 {
|
||||
|
||||
+19
-18
@@ -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;
|
||||
}
|
||||
|
||||
+10
-9
@@ -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");
|
||||
|
||||
+105
-115
@@ -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++;
|
||||
}
|
||||
|
||||
+150
-173
@@ -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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
+10
-11
@@ -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);
|
||||
|
||||
+163
-157
@@ -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];
|
||||
|
||||
+341
-329
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
+83
-105
@@ -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 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_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 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
|
||||
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
|
||||
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];
|
||||
|
||||
|
||||
+364
-359
File diff suppressed because it is too large
Load Diff
+202
-201
File diff suppressed because it is too large
Load Diff
+152
-174
@@ -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 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 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_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_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_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 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 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
|
||||
|
||||
+146
-146
@@ -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 },
|
||||
{ "name", V_NAME },
|
||||
{ "language", V_LANGUAGE },
|
||||
{ "gender", V_GENDER },
|
||||
|
||||
{ "formant", V_FORMANT },
|
||||
{ "pitch", V_PITCH },
|
||||
{ "phonemes", V_PHONEMES },
|
||||
{ "translator", V_TRANSLATOR },
|
||||
{ "dictionary", V_DICTIONARY },
|
||||
{ "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
|
||||
|
||||
+92
-66
@@ -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
|
||||
|
||||
+126
-127
@@ -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;
|
||||
|
||||
+39
-40
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user