| @@ -173,7 +173,7 @@ void DisplayVoices(FILE *f_out, char *language) | |||
| static void Write4Bytes(FILE *f, int value) | |||
| { | |||
| // Write 4 bytes to a file, least significant first | |||
| // Write 4 bytes to a file, least significant first | |||
| int ix; | |||
| for (ix = 0; ix < 4; ix++) { | |||
| @@ -233,14 +233,13 @@ static void CloseWavFile() | |||
| fclose(f_wavfile); | |||
| f_wavfile = NULL; | |||
| } | |||
| static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) | |||
| { | |||
| char fname[210]; | |||
| if (quiet) return 0; // -q quiet mode | |||
| if (quiet) return 0; // -q quiet mode | |||
| if (wav == NULL) { | |||
| CloseWavFile(); | |||
| @@ -267,10 +266,8 @@ static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) | |||
| sprintf(fname, "%s_%.2d%s", wavefile, wavefile_count+1, filetype); | |||
| if (OpenWavFile(fname, samplerate) != 0) | |||
| return 1; | |||
| } else { | |||
| if (OpenWavFile(wavefile, samplerate) != 0) | |||
| return 1; | |||
| } | |||
| } else if (OpenWavFile(wavefile, samplerate) != 0) | |||
| return 1; | |||
| } | |||
| if (numsamples > 0) { | |||
| @@ -298,7 +295,7 @@ struct option { | |||
| }; | |||
| int optind; | |||
| static int optional_argument; | |||
| static const char *arg_opts = "abfgklpsvw"; // which options have arguments | |||
| static const char *arg_opts = "abfgklpsvw"; // which options have arguments | |||
| static char *opt_string = ""; | |||
| #define no_argument 0 | |||
| #define required_argument 1 | |||
| @@ -334,7 +331,7 @@ int main(int argc, char **argv) | |||
| FILE *f_text = NULL; | |||
| char *p_text = NULL; | |||
| FILE *f_phonemes_out = stdout; | |||
| char *data_path = NULL; // use default path for espeak-data | |||
| char *data_path = NULL; // use default path for espeak-data | |||
| int option_index = 0; | |||
| int c; | |||
| @@ -360,7 +357,7 @@ int main(int argc, char **argv) | |||
| espeak_VOICE voice_select; | |||
| char filename[200]; | |||
| char voicename[40]; | |||
| #define N_PUNCTLIST 100 | |||
| #define N_PUNCTLIST 100 | |||
| wchar_t option_punctlist[N_PUNCTLIST]; | |||
| voicename[0] = 0; | |||
| @@ -389,7 +386,7 @@ int main(int argc, char **argv) | |||
| if (c == '-') { | |||
| if (p[0] == 0) | |||
| break; // -- means don't interpret further - as commands | |||
| break; // -- means don't interpret further - as commands | |||
| opt_string = ""; | |||
| for (ix = 0;; ix++) { | |||
| @@ -417,7 +414,7 @@ int main(int argc, char **argv) | |||
| c = getopt_long(argc, argv, "a:b:f:g:hk:l:mp:qs:v:w:xXz", | |||
| long_options, &option_index); | |||
| /* Detect the end of the options. */ | |||
| // Detect the end of the options. | |||
| if (c == -1) | |||
| break; | |||
| optarg2 = optarg; | |||
| @@ -478,23 +475,23 @@ int main(int argc, char **argv) | |||
| option_waveout = 1; | |||
| strncpy0(wavefile, optarg2, sizeof(filename)); | |||
| break; | |||
| case 'z': // remove pause from the end of a sentence | |||
| case 'z': // remove pause from the end of a sentence | |||
| synth_flags &= ~espeakENDPAUSE; | |||
| break; | |||
| case 0x100: // --stdin | |||
| case 0x100: // --stdin | |||
| flag_stdin = 1; | |||
| break; | |||
| case 0x105: // --stdout | |||
| case 0x105: // --stdout | |||
| option_waveout = 1; | |||
| strcpy(wavefile, "stdout"); | |||
| break; | |||
| case 0x101: // --compile-debug | |||
| case 0x102: // --compile | |||
| case 0x101: // --compile-debug | |||
| case 0x102: // --compile | |||
| strncpy0(voicename, optarg2, sizeof(voicename)); | |||
| flag_compile = c; | |||
| quiet = 1; | |||
| break; | |||
| case 0x103: // --punct | |||
| case 0x103: // --punct | |||
| option_punctuation = 1; | |||
| if (optarg2 != NULL) { | |||
| ix = 0; | |||
| @@ -503,27 +500,27 @@ int main(int argc, char **argv) | |||
| option_punctuation = 2; | |||
| } | |||
| break; | |||
| case 0x104: // --voices | |||
| case 0x104: // --voices | |||
| espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0); | |||
| DisplayVoices(stdout, optarg2); | |||
| exit(0); | |||
| case 0x106: // -- split | |||
| case 0x106: // -- split | |||
| if (optarg2 == NULL) | |||
| samples_split_seconds = 30 * 60; // default 30 minutes | |||
| samples_split_seconds = 30 * 60; // default 30 minutes | |||
| else | |||
| samples_split_seconds = atoi(optarg2) * 60; | |||
| break; | |||
| case 0x107: // --path | |||
| case 0x107: // --path | |||
| data_path = optarg2; | |||
| break; | |||
| case 0x108: // --phonout | |||
| case 0x108: // --phonout | |||
| if ((f_phonemes_out = fopen(optarg2, "w")) == NULL) | |||
| fprintf(stderr, "Can't write to: %s\n", optarg2); | |||
| break; | |||
| case 0x109: // --pho | |||
| case 0x109: // --pho | |||
| phoneme_options |= espeakPHONEMES_MBROLA; | |||
| break; | |||
| case 0x10a: // --ipa | |||
| case 0x10a: // --ipa | |||
| phoneme_options |= espeakPHONEMES_IPA; | |||
| if (optarg2 != NULL) { | |||
| // deprecated and obsolete | |||
| @@ -537,43 +534,43 @@ int main(int argc, char **argv) | |||
| phoneme_options |= espeakPHONEMES_TIE; | |||
| break; | |||
| case 3: | |||
| phonemes_separator = 0x200d; // ZWJ | |||
| phonemes_separator = 0x200d; // ZWJ | |||
| phoneme_options |= espeakPHONEMES_TIE; | |||
| break; | |||
| } | |||
| } | |||
| break; | |||
| case 0x10b: // --version | |||
| case 0x10b: // --version | |||
| PrintVersion(); | |||
| exit(0); | |||
| case 0x10c: // --sep | |||
| case 0x10c: // --sep | |||
| phoneme_options |= espeakPHONEMES_SHOW; | |||
| if (optarg2 == 0) | |||
| phonemes_separator = ' '; | |||
| else | |||
| utf8_in(&phonemes_separator, optarg2); | |||
| if (phonemes_separator == 'z') | |||
| phonemes_separator = 0x200c; // ZWNJ | |||
| phonemes_separator = 0x200c; // ZWNJ | |||
| break; | |||
| case 0x10d: // --tie | |||
| case 0x10d: // --tie | |||
| phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); | |||
| if (optarg2 == 0) | |||
| phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
| phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
| else | |||
| utf8_in(&phonemes_separator, optarg2); | |||
| if (phonemes_separator == 'z') | |||
| phonemes_separator = 0x200d; // ZWJ | |||
| phonemes_separator = 0x200d; // ZWJ | |||
| break; | |||
| case 0x10e: // --compile-mbrola | |||
| case 0x10e: // --compile-mbrola | |||
| samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0); | |||
| espeak_ng_CompileMbrolaVoice(optarg2, stdout); | |||
| exit(0); | |||
| case 0x10f: // --compile-intonations | |||
| case 0x10f: // --compile-intonations | |||
| samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY); | |||
| espeak_ng_CompileIntonation(stdout); | |||
| exit(0); | |||
| case 0x110: // --compile-phonemes | |||
| case 0x110: // --compile-phonemes | |||
| samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY); | |||
| espeak_ng_CompilePhonemeData(22050, stdout); | |||
| exit(0); | |||
| @@ -707,6 +704,6 @@ int main(int argc, char **argv) | |||
| } | |||
| if (f_phonemes_out != stdout) | |||
| fclose(f_phonemes_out); // needed for WinCE | |||
| fclose(f_phonemes_out); | |||
| return 0; | |||
| } | |||
| @@ -54,9 +54,9 @@ static char *hash_chains[N_HASH_DICT]; | |||
| static char letterGroupsDefined[N_LETTER_GROUPS]; | |||
| MNEM_TAB mnem_rules[] = { | |||
| { "unpr", DOLLAR_UNPR }, | |||
| { "unpr", DOLLAR_UNPR }, | |||
| { "noprefix", DOLLAR_NOPREFIX }, // rule fails if a prefix has been removed | |||
| { "list", DOLLAR_LIST }, // a pronunciation is given in the *_list file | |||
| { "list", DOLLAR_LIST }, // a pronunciation is given in the *_list file | |||
| { "w_alt1", 0x11 }, | |||
| { "w_alt2", 0x12 }, | |||
| @@ -64,7 +64,7 @@ MNEM_TAB mnem_rules[] = { | |||
| { "w_alt4", 0x14 }, | |||
| { "w_alt5", 0x15 }, | |||
| { "w_alt6", 0x16 }, | |||
| { "w_alt", 0x11 }, // note: put longer names before their sub-strings | |||
| { "w_alt", 0x11 }, // note: put longer names before their sub-strings | |||
| { "p_alt1", 0x21 }, | |||
| { "p_alt2", 0x22 }, | |||
| @@ -72,82 +72,84 @@ MNEM_TAB mnem_rules[] = { | |||
| { "p_alt4", 0x24 }, | |||
| { "p_alt5", 0x25 }, | |||
| { "p_alt6", 0x26 }, | |||
| { "p_alt", 0x21 }, | |||
| { "p_alt", 0x21 }, | |||
| { NULL, -1 } | |||
| }; | |||
| MNEM_TAB mnem_flags[] = { | |||
| // these in the first group put a value in bits0-3 of dictionary_flags | |||
| { "$1", 0x41 }, // stress on 1st syllable | |||
| { "$2", 0x42 }, // stress on 2nd syllable | |||
| { "$3", 0x43 }, | |||
| { "$4", 0x44 }, | |||
| { "$5", 0x45 }, | |||
| { "$6", 0x46 }, | |||
| { "$7", 0x47 }, | |||
| { "$u", 0x48 }, // reduce to unstressed | |||
| { "$u1", 0x49 }, | |||
| { "$u2", 0x4a }, | |||
| { "$u3", 0x4b }, | |||
| { "$u+", 0x4c }, // reduce to unstressed, but stress at end of clause | |||
| { "$1", 0x41 }, // stress on 1st syllable | |||
| { "$2", 0x42 }, // stress on 2nd syllable | |||
| { "$3", 0x43 }, | |||
| { "$4", 0x44 }, | |||
| { "$5", 0x45 }, | |||
| { "$6", 0x46 }, | |||
| { "$7", 0x47 }, | |||
| { "$u", 0x48 }, // reduce to unstressed | |||
| { "$u1", 0x49 }, | |||
| { "$u2", 0x4a }, | |||
| { "$u3", 0x4b }, | |||
| { "$u+", 0x4c }, // reduce to unstressed, but stress at end of clause | |||
| { "$u1+", 0x4d }, | |||
| { "$u2+", 0x4e }, | |||
| { "$u3+", 0x4f }, | |||
| // these set the corresponding numbered bit if dictionary_flags | |||
| { "$pause", 8 }, // ensure pause before this word | |||
| { "$strend", 9 }, // full stress if at end of clause | |||
| { "$strend2", 10 }, // full stress if at end of clause, or only followed by unstressed | |||
| { "$unstressend", 11 }, // reduce stress at end of clause | |||
| { "$pause", 8 }, // ensure pause before this word | |||
| { "$strend", 9 }, // full stress if at end of clause | |||
| { "$strend2", 10 }, // full stress if at end of clause, or only followed by unstressed | |||
| { "$unstressend", 11 }, // reduce stress at end of clause | |||
| { "$accent_before", 12 }, // used with accent names, say this accent name before the letter name | |||
| { "$abbrev", 13 }, // use this pronuciation rather than split into letters | |||
| // language specific | |||
| { "$double", 14 }, // IT double the initial consonant of next word | |||
| { "$alt", 15 }, // use alternative pronunciation | |||
| { "$alt1", 15 }, // synonym for $alt | |||
| { "$alt2", 16 }, | |||
| { "$alt3", 17 }, | |||
| { "$alt4", 18 }, | |||
| { "$alt5", 19 }, | |||
| { "$alt6", 20 }, | |||
| { "$alt7", 21 }, | |||
| { "$combine", 23 }, // Combine with the next word | |||
| { "$dot", 24 }, // ignore '.' after this word (abbreviation) | |||
| { "$hasdot", 25 }, // use this pronunciation if there is a dot after the word | |||
| { "$max3", 27 }, // limit to 3 repetitions | |||
| { "$brk", 28 }, // a shorter $pause | |||
| { "$text", 29 }, // word translates to replcement text, not phonemes | |||
| // flags in dictionary word 2 | |||
| { "$verbf", 0x20 }, // verb follows | |||
| { "$verbsf", 0x21 }, // verb follows, allow -s suffix | |||
| { "$nounf", 0x22 }, // noun follows | |||
| { "$pastf", 0x23 }, // past tense follows | |||
| { "$verb", 0x24 }, // use this pronunciation when its a verb | |||
| { "$noun", 0x25 }, // use this pronunciation when its a noun | |||
| { "$past", 0x26 }, // use this pronunciation when its past tense | |||
| { "$abbrev", 13 }, // use this pronuciation rather than split into letters | |||
| // language specific | |||
| { "$double", 14 }, // IT double the initial consonant of next word | |||
| { "$alt", 15 }, // use alternative pronunciation | |||
| { "$alt1", 15 }, // synonym for $alt | |||
| { "$alt2", 16 }, | |||
| { "$alt3", 17 }, | |||
| { "$alt4", 18 }, | |||
| { "$alt5", 19 }, | |||
| { "$alt6", 20 }, | |||
| { "$alt7", 21 }, | |||
| { "$combine", 23 }, // Combine with the next word | |||
| { "$dot", 24 }, // ignore '.' after this word (abbreviation) | |||
| { "$hasdot", 25 }, // use this pronunciation if there is a dot after the word | |||
| { "$max3", 27 }, // limit to 3 repetitions | |||
| { "$brk", 28 }, // a shorter $pause | |||
| { "$text", 29 }, // word translates to replcement text, not phonemes | |||
| // flags in dictionary word 2 | |||
| { "$verbf", 0x20 }, // verb follows | |||
| { "$verbsf", 0x21 }, // verb follows, allow -s suffix | |||
| { "$nounf", 0x22 }, // noun follows | |||
| { "$pastf", 0x23 }, // past tense follows | |||
| { "$verb", 0x24 }, // use this pronunciation when its a verb | |||
| { "$noun", 0x25 }, // use this pronunciation when its a noun | |||
| { "$past", 0x26 }, // use this pronunciation when its past tense | |||
| { "$verbextend", 0x28 }, // extend influence of 'verb follows' | |||
| { "$capital", 0x29 }, // use this pronunciation if initial letter is upper case | |||
| { "$allcaps", 0x2a }, // use this pronunciation if initial letter is upper case | |||
| { "$accent", 0x2b }, // character name is base-character name + accent name | |||
| { "$sentence", 0x2d }, // only if this clause is a sentence (i.e. terminator is {. ? !} not {, ; :} | |||
| { "$only", 0x2e }, // only match on this word without suffix | |||
| { "$onlys", 0x2f }, // only match with none, or with 's' suffix | |||
| { "$stem", 0x30 }, // must have a suffix | |||
| { "$atend", 0x31 }, // use this pronunciation if at end of clause | |||
| { "$atstart", 0x32 }, // use this pronunciation at start of clause | |||
| { "$native", 0x33 }, // not if we've switched translators | |||
| { "$capital", 0x29 }, // use this pronunciation if initial letter is upper case | |||
| { "$allcaps", 0x2a }, // use this pronunciation if initial letter is upper case | |||
| { "$accent", 0x2b }, // character name is base-character name + accent name | |||
| { "$sentence", 0x2d }, // only if this clause is a sentence (i.e. terminator is {. ? !} not {, ; :} | |||
| { "$only", 0x2e }, // only match on this word without suffix | |||
| { "$onlys", 0x2f }, // only match with none, or with 's' suffix | |||
| { "$stem", 0x30 }, // must have a suffix | |||
| { "$atend", 0x31 }, // use this pronunciation if at end of clause | |||
| { "$atstart", 0x32 }, // use this pronunciation at start of clause | |||
| { "$native", 0x33 }, // not if we've switched translators | |||
| // doesn't set dictionary_flags | |||
| { "$?", 100 }, // conditional rule, followed by byte giving the condition number | |||
| { "$?", 100 }, // conditional rule, followed by byte giving the condition number | |||
| { "$textmode", 200 }, | |||
| { "$textmode", 200 }, | |||
| { "$phonememode", 201 }, | |||
| { NULL, -1 } | |||
| { NULL, -1 } | |||
| }; | |||
| #define LEN_GROUP_NAME 12 | |||
| @@ -161,7 +163,7 @@ typedef struct { | |||
| int isspace2(unsigned int c) | |||
| { | |||
| // can't use isspace() because on Windows, isspace(0xe1) gives TRUE ! | |||
| // can't use isspace() because on Windows, isspace(0xe1) gives TRUE ! | |||
| int c2; | |||
| if (((c2 = (c & 0xff)) == 0) || (c > ' ')) | |||
| @@ -171,7 +173,7 @@ int isspace2(unsigned int c) | |||
| static FILE *fopen_log(const char *fname, const char *access) | |||
| { | |||
| // performs fopen, but produces error message to f_log if it fails | |||
| // performs fopen, but produces error message to f_log if it fails | |||
| FILE *f; | |||
| if ((f = fopen(fname, access)) == NULL) { | |||
| @@ -181,7 +183,7 @@ static FILE *fopen_log(const char *fname, const char *access) | |||
| return f; | |||
| } | |||
| /* Lookup a mnemonic string in a table, return its name */ | |||
| // Lookup a mnemonic string in a table, return its name | |||
| const char *LookupMnemName(MNEM_TAB *table, const int value) | |||
| { | |||
| while (table->mnem != NULL) { | |||
| @@ -189,7 +191,7 @@ const char *LookupMnemName(MNEM_TAB *table, const int value) | |||
| return table->mnem; | |||
| table++; | |||
| } | |||
| return ""; /* not found */ | |||
| return ""; // not found | |||
| } | |||
| void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len) | |||
| @@ -222,7 +224,7 @@ void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len) | |||
| char *DecodeRule(const char *group_chars, int group_length, char *rule, int control) | |||
| { | |||
| /* Convert compiled match template to ascii */ | |||
| // Convert compiled match template to ascii | |||
| unsigned char rb; | |||
| unsigned char c; | |||
| @@ -243,9 +245,12 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
| char suffix[20]; | |||
| static char output[80]; | |||
| static char symbols[] = | |||
| { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', | |||
| '&', '%', '+', '#', 'S', 'D', 'Z', 'A', 'L', '!', ' ', '@', '?', 'J', 'N', 'K', 'V', '?', 'T', 'X', '?', 'W' }; | |||
| static char symbols[] = { | |||
| ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', | |||
| '&', '%', '+', '#', 'S', 'D', 'Z', 'A', 'L', '!', | |||
| ' ', '@', '?', 'J', 'N', 'K', 'V', '?', 'T', 'X', | |||
| '?', 'W' | |||
| }; | |||
| static char symbols_lg[] = { 'A', 'B', 'C', 'H', 'F', 'G', 'Y' }; | |||
| @@ -268,7 +273,8 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
| finished = 1; | |||
| break; | |||
| case RULE_PRE_ATSTART: | |||
| at_start = 1; // drop through to next case | |||
| at_start = 1; | |||
| // fallthrough: | |||
| case RULE_PRE: | |||
| match_type = RULE_PRE; | |||
| *p = 0; | |||
| @@ -283,7 +289,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
| case RULE_PH_COMMON: | |||
| break; | |||
| case RULE_CONDITION: | |||
| /* conditional rule, next byte gives condition number */ | |||
| // conditional rule, next byte gives condition number | |||
| condition_num = *rule++; | |||
| break; | |||
| case RULE_LINENUM: | |||
| @@ -365,7 +371,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
| } | |||
| *p = 0; | |||
| buf[p_end - p] = 0; // prevent overflow in output[] | |||
| buf[p_end - p] = 0; // prevent overflow in output[] | |||
| strcat(p, buf); | |||
| ix = strlen(output); | |||
| while (ix < 8) | |||
| @@ -376,7 +382,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont | |||
| static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| { | |||
| // Compile a line in the language_list file | |||
| // Compile a line in the language_list file | |||
| unsigned char c; | |||
| char *p; | |||
| char *word; | |||
| @@ -394,7 +400,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| int len_word; | |||
| int len_phonetic; | |||
| int text_not_phonemes; // this word specifies replacement text, not phonemes | |||
| int text_not_phonemes; // this word specifies replacement text, not phonemes | |||
| unsigned int wc; | |||
| int all_upper_case; | |||
| @@ -441,7 +447,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| } | |||
| if ((c == '$') && isalnum(p[1])) { | |||
| /* read keyword parameter */ | |||
| // read keyword parameter | |||
| mnemptr = p; | |||
| while (!isspace2(c = *p)) p++; | |||
| *p = 0; | |||
| @@ -462,9 +468,8 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| } | |||
| } | |||
| if ((c == '/') && (p[1] == '/') && (multiple_words == 0)) { | |||
| c = '\n'; /* "//" treat comment as end of line */ | |||
| } | |||
| if ((c == '/') && (p[1] == '/') && (multiple_words == 0)) | |||
| c = '\n'; // "//" treat comment as end of line | |||
| switch (step) | |||
| { | |||
| @@ -486,7 +491,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| c = ' '; | |||
| } | |||
| if (isspace2(c)) { | |||
| p[0] = 0; /* terminate english word */ | |||
| p[0] = 0; // terminate english word | |||
| if (multiple_words) { | |||
| multiple_string = multiple_string_end = p+1; | |||
| @@ -509,7 +514,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| if (isspace2(c)) | |||
| multiple_words++; | |||
| else if (c == ')') { | |||
| p[0] = ' '; // terminate extra string | |||
| p[0] = ' '; // terminate extra string | |||
| multiple_string_end = p+1; | |||
| step = 3; | |||
| } | |||
| @@ -522,7 +527,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| break; | |||
| case 4: | |||
| if (isspace2(c)) { | |||
| p[0] = 0; /* terminate phonetic */ | |||
| p[0] = 0; // terminate phonetic | |||
| step = 5; | |||
| } | |||
| break; | |||
| @@ -533,7 +538,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| } | |||
| if (word[0] == 0) | |||
| return 0; /* blank line */ | |||
| return 0; // blank line | |||
| if (text_mode) | |||
| text_not_phonemes = 1; | |||
| @@ -541,7 +546,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| if (text_not_phonemes) { | |||
| if (word[0] == '_') { | |||
| // This is a special word, used by eSpeak. Translate this into phonemes now | |||
| strcat(phonetic, " "); // need a space to indicate word-boundary | |||
| strcat(phonetic, " "); // need a space to indicate word-boundary | |||
| // PROBLEM vowel reductions are not applied to the translated phonemes | |||
| // condition rules are not applied | |||
| @@ -574,7 +579,6 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| if (text_not_phonemes != translator->langopts.textmode) | |||
| flag_codes[n_flag_codes++] = BITNUM_FLAG_TEXTMODE; | |||
| if (sscanf(word, "U+%x", &wc) == 1) { | |||
| // Character code | |||
| ix = utf8_out(wc, word); | |||
| @@ -609,7 +613,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| *hash = HashDictionary(word); | |||
| len_phonetic = strlen(encoded_ph); | |||
| dict_line[1] = len_word; // bit 6 indicates whether the word has been compressed | |||
| dict_line[1] = len_word; // bit 6 indicates whether the word has been compressed | |||
| len_word &= 0x3f; | |||
| memcpy(&dict_line[2], word, len_word); | |||
| @@ -647,7 +651,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash) | |||
| static void compile_dictlist_start(void) | |||
| { | |||
| // initialise dictionary list | |||
| // initialise dictionary list | |||
| int ix; | |||
| char *p; | |||
| char *p2; | |||
| @@ -666,7 +670,7 @@ static void compile_dictlist_start(void) | |||
| static void compile_dictlist_end(FILE *f_out) | |||
| { | |||
| // Write out the compiled dictionary list | |||
| // Write out the compiled dictionary list | |||
| int hash; | |||
| int length; | |||
| char *p; | |||
| @@ -725,7 +729,7 @@ static int compile_dictlist_file(const char *path, const char *filename) | |||
| linenum++; | |||
| length = compile_line(buf, dict_line, &hash); | |||
| if (length == 0) continue; /* blank line */ | |||
| if (length == 0) continue; // blank line | |||
| hash_counts[hash]++; | |||
| @@ -758,7 +762,7 @@ static char rule_phonemes[80]; | |||
| static char group_name[LEN_GROUP_NAME+1]; | |||
| static int group3_ix; | |||
| #define N_RULES 3000 // max rules for each group | |||
| #define N_RULES 3000 // max rules for each group | |||
| int isHexDigit(int c) | |||
| { | |||
| @@ -773,7 +777,7 @@ int isHexDigit(int c) | |||
| static void copy_rule_string(char *string, int *state_out) | |||
| { | |||
| // state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes | |||
| // state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes | |||
| static char *outbuf[5] = { rule_cond, rule_pre, rule_match, rule_post, rule_phonemes }; | |||
| static int next_state[5] = { 2, 2, 4, 4, 4 }; | |||
| char *output; | |||
| @@ -799,7 +803,7 @@ static void copy_rule_string(char *string, int *state_out) | |||
| rule_phonemes[len++] = ' '; | |||
| output = &rule_phonemes[len]; | |||
| } | |||
| sxflags = 0x808000; // to ensure non-zero bytes | |||
| sxflags = 0x808000; // to ensure non-zero bytes | |||
| for (p = string, ix = 0;;) { | |||
| literal = 0; | |||
| @@ -810,7 +814,7 @@ static void copy_rule_string(char *string, int *state_out) | |||
| p += 2; | |||
| } | |||
| if (c == '\\') { | |||
| c = *p++; // treat next character literally | |||
| c = *p++; // treat next character literally | |||
| if ((c >= '0') && (c <= '3') && (p[0] >= '0') && (p[0] <= '7') && (p[1] >= '0') && (p[1] <= '7')) { | |||
| // character code given by 3 digit octal value; | |||
| c = (c-'0')*64 + (p[0]-'0')*8 + (p[1]-'0'); | |||
| @@ -837,8 +841,9 @@ static void copy_rule_string(char *string, int *state_out) | |||
| break; | |||
| case 'Y': | |||
| c = 'I'; // drop through to next case | |||
| case 'A': // vowel | |||
| c = 'I'; | |||
| // fallthrough: | |||
| case 'A': // vowel | |||
| case 'B': | |||
| case 'C': | |||
| case 'H': | |||
| @@ -947,10 +952,10 @@ static void copy_rule_string(char *string, int *state_out) | |||
| error_count++; | |||
| } | |||
| break; | |||
| case 'P': | |||
| sxflags |= SUFX_P; // Prefix, now drop through to Suffix | |||
| case 'P': // Prefix | |||
| sxflags |= SUFX_P; | |||
| // fallthrough | |||
| case 'S': | |||
| case 'S': // Suffix | |||
| output[ix++] = RULE_ENDING; | |||
| value = 0; | |||
| while (!isspace2(c = *p++) && (c != 0)) { | |||
| @@ -962,7 +967,7 @@ static void copy_rule_string(char *string, int *state_out) | |||
| case 'i': | |||
| sxflags |= SUFX_I; | |||
| break; | |||
| case 'p': // obsolete, replaced by 'P' above | |||
| case 'p': // obsolete, replaced by 'P' above | |||
| sxflags |= SUFX_P; | |||
| break; | |||
| case 'v': | |||
| @@ -1041,13 +1046,13 @@ static char *compile_rule(char *input) | |||
| switch (c = input[ix]) | |||
| { | |||
| case ')': // end of prefix section | |||
| case ')': // end of prefix section | |||
| *p = 0; | |||
| state = 1; | |||
| copy_rule_string(buf, &state); | |||
| p = buf; | |||
| break; | |||
| case '(': // start of suffix section | |||
| case '(': // start of suffix section | |||
| *p = 0; | |||
| state = 2; | |||
| copy_rule_string(buf, &state); | |||
| @@ -1058,14 +1063,14 @@ static char *compile_rule(char *input) | |||
| error_count++; | |||
| } | |||
| break; | |||
| case '\n': // end of line | |||
| case '\n': // end of line | |||
| case '\r': | |||
| case 0: // end of line | |||
| case 0: // end of line | |||
| *p = 0; | |||
| copy_rule_string(buf, &state); | |||
| finish = 1; | |||
| break; | |||
| case '\t': // end of section section | |||
| case '\t': // end of section section | |||
| case ' ': | |||
| *p = 0; | |||
| copy_rule_string(buf, &state); | |||
| @@ -1180,7 +1185,7 @@ int __cdecl string_sorter(char **a, char **b) | |||
| static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b) | |||
| { | |||
| // Sort long names before short names | |||
| // Sort long names before short names | |||
| int ix; | |||
| ix = strlen(b->name) - strlen(a->name); | |||
| if (ix != 0) return ix; | |||
| @@ -1314,23 +1319,23 @@ static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name | |||
| qsort((void *)rules, n_rules, sizeof(char *), (int(__cdecl *)(const void *, const void *))string_sorter); | |||
| if (strcmp(name, "9") == 0) | |||
| len_name = 0; // don't remove characters from numeric match strings | |||
| len_name = 0; // don't remove characters from numeric match strings | |||
| for (ix = 0; ix < n_rules; ix++) { | |||
| p = rules[ix]; | |||
| len1 = strlen(p) + 1; // phoneme string | |||
| len1 = strlen(p) + 1; // phoneme string | |||
| p3 = &p[len1]; | |||
| p2 = p3 + len_name; // remove group name from start of match string | |||
| p2 = p3 + len_name; // remove group name from start of match string | |||
| len2 = strlen(p2); | |||
| nextchar_count[(unsigned char)(p2[0])]++; // the next byte after the group name | |||
| nextchar_count[(unsigned char)(p2[0])]++; // the next byte after the group name | |||
| if ((common[0] != 0) && (strcmp(p, common) == 0)) { | |||
| fwrite(p2, len2, 1, f_out); | |||
| fputc(0, f_out); // no phoneme string, it's the same as previous rule | |||
| fputc(0, f_out); // no phoneme string, it's the same as previous rule | |||
| } else { | |||
| if ((ix < n_rules-1) && (strcmp(p, rules[ix+1]) == 0)) { | |||
| common = rules[ix]; // phoneme string is same as next, set as common | |||
| common = rules[ix]; // phoneme string is same as next, set as common | |||
| fputc(RULE_PH_COMMON, f_out); | |||
| } | |||
| @@ -1358,7 +1363,7 @@ static int compile_lettergroup(char *input, FILE *f_out) | |||
| int length; | |||
| int max_length = 0; | |||
| #define N_LETTERGP_ITEMS 200 | |||
| #define N_LETTERGP_ITEMS 200 | |||
| char *items[N_LETTERGP_ITEMS]; | |||
| char item_length[N_LETTERGP_ITEMS]; | |||
| @@ -1395,7 +1400,7 @@ static int compile_lettergroup(char *input, FILE *f_out) | |||
| items[n_items] = p_start = p; | |||
| while ((*p & 0xff) > ' ') { | |||
| if (*p == '_') *p = ' '; // allow '_' for word break | |||
| if (*p == '_') *p = ' '; // allow '_' for word break | |||
| p++; | |||
| } | |||
| *p++ = 0; | |||
| @@ -1408,9 +1413,8 @@ static int compile_lettergroup(char *input, FILE *f_out) | |||
| // write out the items, longest first | |||
| while (max_length > 1) { | |||
| for (ix = 0; ix < n_items; ix++) { | |||
| if (item_length[ix] == max_length) { | |||
| if (item_length[ix] == max_length) | |||
| fwrite(items[ix], 1, max_length, f_out); | |||
| } | |||
| } | |||
| max_length--; | |||
| } | |||
| @@ -1457,7 +1461,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
| if ((p = (unsigned char *)strstr(buf, "//")) != NULL) | |||
| *p = 0; | |||
| if (buf[0] == '\r') buf++; // ignore extra \r in \r\n | |||
| if (buf[0] == '\r') buf++; // ignore extra \r in \r\n | |||
| } | |||
| if ((buf == NULL) || (buf[0] == '.')) { | |||
| @@ -1478,11 +1482,11 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
| if (compile_mode == 2) { | |||
| // end of the character replacements section | |||
| fwrite(&n_rules, 1, 4, f_out); // write a zero word to terminate the replacemenmt list | |||
| fwrite(&n_rules, 1, 4, f_out); // write a zero word to terminate the replacemenmt list | |||
| compile_mode = 0; | |||
| } | |||
| if (buf == NULL) break; // end of file | |||
| if (buf == NULL) break; // end of file | |||
| if (memcmp(buf, ".L", 2) == 0) { | |||
| compile_lettergroup(&buf[2], f_out); | |||
| @@ -1503,7 +1507,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
| compile_mode = 1; | |||
| p = (unsigned char *)&buf[6]; | |||
| while ((p[0] == ' ') || (p[0] == '\t')) p++; // Note: Windows isspace(0xe1) gives TRUE ! | |||
| while ((p[0] == ' ') || (p[0] == '\t')) p++; // Note: Windows isspace(0xe1) gives TRUE ! | |||
| ix = 0; | |||
| while ((*p > ' ') && (ix < LEN_GROUP_NAME)) | |||
| group_name[ix++] = *p++; | |||
| @@ -1522,7 +1526,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
| if (translator->letter_bits_offset > 0) { | |||
| utf8_in(&wc, group_name); | |||
| if (((ix = (wc - translator->letter_bits_offset)) >= 0) && (ix < 128)) | |||
| group3_ix = ix+1; // not zero | |||
| group3_ix = ix+1; // not zero | |||
| } | |||
| } | |||
| @@ -1541,7 +1545,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
| switch (compile_mode) | |||
| { | |||
| case 1: // .group | |||
| case 1: // .group | |||
| prule = compile_rule(buf); | |||
| if (prule != NULL) { | |||
| if (n_rules < N_RULES) | |||
| @@ -1556,7 +1560,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
| } | |||
| break; | |||
| case 2: // .replace | |||
| case 2: // .replace | |||
| { | |||
| int replace1; | |||
| int replace2; | |||
| @@ -1580,11 +1584,11 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
| ix += 16; | |||
| } | |||
| if (replace1 != 0) { | |||
| Write4Bytes(f_out, replace1); // write as little-endian | |||
| Write4Bytes(f_out, replace2); // if big-endian, reverse the bytes in LoadDictionary() | |||
| Write4Bytes(f_out, replace1); // write as little-endian | |||
| Write4Bytes(f_out, replace2); // if big-endian, reverse the bytes in LoadDictionary() | |||
| } | |||
| } | |||
| break; | |||
| break; | |||
| } | |||
| } | |||
| fclose(f_temp); | |||
| @@ -1631,8 +1635,8 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | |||
| int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err, int flags) | |||
| { | |||
| // fname: space to write the filename in case of error | |||
| // flags: bit 0: include source line number information, for debug purposes. | |||
| // fname: space to write the filename in case of error | |||
| // flags: bit 0: include source line number information, for debug purposes. | |||
| FILE *f_in; | |||
| FILE *f_out; | |||
| @@ -78,7 +78,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
| char name2[40]; | |||
| char mbrola_voice[40]; | |||
| char buf[sizeof(path_home)+30]; | |||
| int mbrola_ctrl = 20; // volume in 1/16 ths | |||
| int mbrola_ctrl = 20; // volume in 1/16 ths | |||
| MBROLA_TAB data[N_PHONEME_TAB]; | |||
| strcpy(buf, filepath); | |||
| @@ -91,7 +91,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
| buf[sizeof(phoneme)-1] = 0; | |||
| if ((p = strstr(buf, "//")) != NULL) | |||
| *p = 0; // truncate line at comment | |||
| *p = 0; // truncate line at comment | |||
| if (memcmp(buf, "volume", 6) == 0) { | |||
| mbrola_ctrl = atoi(&buf[6]); | |||
| @@ -128,7 +128,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
| return ENE_WRITE_ERROR; | |||
| } | |||
| data[count].name = 0; // list terminator | |||
| data[count].name = 0; // list terminator | |||
| Write4Bytes(f_out, mbrola_ctrl); | |||
| pw_end = (int *)(&data[count+1]); | |||
| @@ -89,8 +89,8 @@ typedef struct { | |||
| typedef enum { | |||
| CS_UNDEFINED, // The command has just been created | |||
| CS_PENDING, // stored in the fifo | |||
| CS_PROCESSED // processed | |||
| CS_PENDING, // stored in the fifo | |||
| CS_PROCESSED // processed | |||
| } t_command_state; | |||
| typedef struct { | |||
| @@ -50,9 +50,11 @@ static bool thread_inited; | |||
| static t_espeak_callback *my_callback = NULL; | |||
| static int my_event_is_running = 0; | |||
| enum { MIN_TIMEOUT_IN_MS = 10, | |||
| ACTIVITY_TIMEOUT = 50, // in ms, check that the stream is active | |||
| MAX_ACTIVITY_CHECK = 6 }; | |||
| enum { | |||
| MIN_TIMEOUT_IN_MS = 10, | |||
| ACTIVITY_TIMEOUT = 50, // in ms, check that the stream is active | |||
| MAX_ACTIVITY_CHECK = 6 | |||
| }; | |||
| typedef struct t_node { | |||
| void *data; | |||
| @@ -359,9 +361,9 @@ static int get_remaining_time(uint32_t sample, uint32_t *time_in_ms, int *stop_i | |||
| for (i = 0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++) { | |||
| err = wave_get_remaining_time(sample, time_in_ms); | |||
| if (err || wave_is_busy(NULL) || (*time_in_ms == 0)) { // if err, stream not available: quit | |||
| // if wave is busy, time_in_ms is known: quit | |||
| // if wave is not busy but remaining time == 0, event is reached: quit | |||
| if (err || // if err, stream not available: quit | |||
| wave_is_busy(NULL) || // if wave is busy, time_in_ms is known: quit | |||
| (*time_in_ms == 0)) { // if wave is not busy but remaining time == 0, event is reached: quit | |||
| break; | |||
| } | |||
| @@ -412,20 +414,19 @@ static void *polling_thread(void *p) | |||
| SHOW_TIME("polling_thread > unlocked\n"); | |||
| a_stop_is_required = 0; | |||
| a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); // NOTE: may set a_stop_is_required to -1 | |||
| a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); // NOTE: may set a_stop_is_required to -1 | |||
| if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
| SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
| while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
| } | |||
| ; | |||
| while (0 == sem_trywait(&my_sem_stop_is_required)) | |||
| ; | |||
| } else | |||
| a_stop_is_required = 0; | |||
| // In this loop, my_event_is_running = 1 | |||
| while (head && (a_stop_is_required <= 0)) { | |||
| SHOW_TIME("polling_thread > check head\n"); | |||
| while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
| } | |||
| while (0 == sem_trywait(&my_sem_start_is_required)) | |||
| ; | |||
| espeak_EVENT *event = (espeak_EVENT *)(head->data); | |||
| assert(event); | |||
| @@ -465,8 +466,8 @@ static void *polling_thread(void *p) | |||
| if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
| SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
| while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
| } | |||
| while (0 == sem_trywait(&my_sem_stop_is_required)) | |||
| ; | |||
| } else | |||
| a_stop_is_required = 0; | |||
| } else // The event will be notified soon: sleep until timeout or stop request | |||
| @@ -483,8 +484,8 @@ static void *polling_thread(void *p) | |||
| a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); | |||
| if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
| SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
| while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
| } | |||
| while (0 == sem_trywait(&my_sem_stop_is_required)) | |||
| ; | |||
| } else | |||
| a_stop_is_required = 0; | |||
| } | |||
| @@ -573,8 +574,8 @@ static void init() | |||
| { | |||
| ENTER("event > init"); | |||
| while (event_delete((espeak_EVENT *)pop())) { | |||
| } | |||
| while (event_delete((espeak_EVENT *)pop())) | |||
| ; | |||
| node_counter = 0; | |||
| } | |||
| @@ -43,8 +43,6 @@ | |||
| static pthread_mutex_t my_mutex; | |||
| static int my_command_is_running = 0; | |||
| static int my_stop_is_required = 0; | |||
| // + fifo | |||
| // | |||
| // my_thread: reads commands from the fifo, and runs them. | |||
| static pthread_t my_thread; | |||
| @@ -57,9 +55,12 @@ static espeak_ERROR push(t_espeak_command *the_command); | |||
| static t_espeak_command *pop(); | |||
| static void init(int process_parameters); | |||
| static int node_counter = 0; | |||
| enum { MAX_NODE_COUNTER = 400, | |||
| INACTIVITY_TIMEOUT = 50, // in ms, check that the stream is inactive | |||
| MAX_INACTIVITY_CHECK = 2 }; | |||
| enum { | |||
| MAX_NODE_COUNTER = 400, | |||
| INACTIVITY_TIMEOUT = 50, // in ms, check that the stream is inactive | |||
| MAX_INACTIVITY_CHECK = 2 | |||
| }; | |||
| void fifo_init() | |||
| { | |||
| @@ -338,8 +339,8 @@ static void *say_thread(void *p) | |||
| display_espeak_command(a_command); | |||
| // purge start semaphore | |||
| SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); | |||
| while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
| } | |||
| while (0 == sem_trywait(&my_sem_start_is_required)) | |||
| ; | |||
| if (my_stop_is_required) { | |||
| SHOW_TIME("say_thread > my_command_is_running = 0\n"); | |||
| @@ -361,8 +362,8 @@ static void *say_thread(void *p) | |||
| // purge start semaphore | |||
| SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); | |||
| while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
| } | |||
| while (0 == sem_trywait(&my_sem_start_is_required)) | |||
| ; | |||
| // acknowledge the stop request | |||
| SHOW_TIME("say_thread > post my_sem_stop_is_acknowledged\n"); | |||
| @@ -46,7 +46,7 @@ | |||
| typedef struct { | |||
| char stress; | |||
| char env; | |||
| char flags; // bit 0=pitch rising, bit1=emnphasized, bit2=end of clause | |||
| char flags; // bit 0=pitch rising, bit1=emnphasized, bit2=end of clause | |||
| char nextph_type; | |||
| unsigned char pitch1; | |||
| unsigned char pitch2; | |||
| @@ -54,18 +54,17 @@ typedef struct { | |||
| static SYLLABLE *syllable_tab; | |||
| static int tone_pitch_env; /* used to return pitch envelope */ | |||
| static int tone_pitch_env; // used to return pitch envelope | |||
| /* Pitch data for tone types */ | |||
| /*****************************/ | |||
| #define PITCHfall 0 | |||
| #define PITCHrise 2 | |||
| #define PITCHfrise 4 // and 3 must be for the variant preceded by 'r' | |||
| #define PITCHfrise2 6 // and 5 must be the 'r' variant | |||
| #define PITCHrisefall 8 | |||
| #define PITCHfall 0 | |||
| #define PITCHrise 2 | |||
| #define PITCHfrise 4 // and 3 must be for the variant preceded by 'r' | |||
| #define PITCHfrise2 6 // and 5 must be the 'r' variant | |||
| #define PITCHrisefall 8 | |||
| /* 0 fall */ | |||
| unsigned char env_fall[128] = { | |||
| 0xff, 0xfd, 0xfa, 0xf8, 0xf6, 0xf4, 0xf2, 0xf0, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, | |||
| 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xd0, 0xce, 0xcc, 0xca, 0xc8, 0xc6, 0xc4, 0xc2, 0xc0, | |||
| @@ -77,7 +76,6 @@ unsigned char env_fall[128] = { | |||
| 0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0e, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x00 | |||
| }; | |||
| /* 1 rise */ | |||
| unsigned char env_rise[128] = { | |||
| 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, | |||
| 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, | |||
| @@ -213,7 +211,7 @@ unsigned char *envelope_data[N_ENVELOPE_DATA] = { | |||
| env_risefallrise, env_risefallrise | |||
| }; | |||
| /* indexed by stress */ | |||
| // indexed by stress | |||
| static int min_drop[] = { 6, 7, 9, 9, 20, 20, 20, 25 }; | |||
| // pitch change during the main part of the clause | |||
| @@ -224,8 +222,8 @@ static signed char oflow[] = { 0, 40, 24, 8, 0 }; | |||
| static signed char oflow_emf[] = { 10, 52, 32, 20, 10 }; | |||
| static signed char oflow_less[] = { 6, 38, 24, 14, 4 }; | |||
| #define N_TONE_HEAD_TABLE 13 | |||
| #define N_TONE_NUCLEUS_TABLE 13 | |||
| #define N_TONE_HEAD_TABLE 13 | |||
| #define N_TONE_NUCLEUS_TABLE 13 | |||
| typedef struct { | |||
| unsigned char pre_start; | |||
| @@ -243,11 +241,11 @@ typedef struct { | |||
| } TONE_HEAD; | |||
| typedef struct { | |||
| unsigned char pitch_env0; /* pitch envelope, tonic syllable at end */ | |||
| unsigned char pitch_env0; // pitch envelope, tonic syllable at end | |||
| unsigned char tonic_max0; | |||
| unsigned char tonic_min0; | |||
| unsigned char pitch_env1; /* followed by unstressed */ | |||
| unsigned char pitch_env1; // followed by unstressed | |||
| unsigned char tonic_max1; | |||
| unsigned char tonic_min1; | |||
| @@ -261,57 +259,56 @@ typedef struct { | |||
| #define T_EMPH 1 | |||
| static TONE_HEAD tone_head_table[N_TONE_HEAD_TABLE] = { | |||
| { 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 0 statement | |||
| { 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 1 comma | |||
| { 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 2 question | |||
| { 46, 57, 90, 50, drops_0, 3, 9, 5, oflow_emf }, // 3 exclamation | |||
| { 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 4 statement, emphatic | |||
| { 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less },// 5 statement, less intonation | |||
| { 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less },// 6 comma, less intonation | |||
| { 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less },// 7 comma, less intonation, less rise | |||
| { 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 8 pitch raises at end of sentence | |||
| { 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 9 comma | |||
| { 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 10 question | |||
| { 34, 41, 41, 32, drops_0, 3, 7, 5, oflow_less }, // 11 test | |||
| { 46, 57, 55, 50, drops_0, 3, 7, 5, oflow_less }, // 12 test | |||
| { 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 0 statement | |||
| { 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 1 comma | |||
| { 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 2 question | |||
| { 46, 57, 90, 50, drops_0, 3, 9, 5, oflow_emf }, // 3 exclamation | |||
| { 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 4 statement, emphatic | |||
| { 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less }, // 5 statement, less intonation | |||
| { 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less }, // 6 comma, less intonation | |||
| { 46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less }, // 7 comma, less intonation, less rise | |||
| { 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 8 pitch raises at end of sentence | |||
| { 46, 57, 78, 46, drops_0, 3, 7, 5, oflow }, // 9 comma | |||
| { 46, 57, 78, 50, drops_0, 3, 7, 5, oflow }, // 10 question | |||
| { 34, 41, 41, 32, drops_0, 3, 7, 5, oflow_less }, // 11 test | |||
| { 46, 57, 55, 50, drops_0, 3, 7, 5, oflow_less }, // 12 test | |||
| }; | |||
| static TONE_NUCLEUS tone_nucleus_table[N_TONE_NUCLEUS_TABLE] = { | |||
| { PITCHfall, 64, 8, PITCHfall, 70, 18, NULL, 24, 12, 0 }, // 0 statement | |||
| { PITCHfrise, 80, 18, PITCHfrise2, 78, 22, NULL, 34, 52, 0 }, // 1 comma | |||
| { PITCHfrise, 88, 22, PITCHfrise2, 82, 22, NULL, 34, 64, 0 }, // 2 question | |||
| { PITCHfall, 92, 8, PITCHfall, 92, 80, NULL, 76, 8, T_EMPH }, // 3 exclamation | |||
| { PITCHfall, 86, 4, PITCHfall, 94, 66, NULL, 34, 10, 0 }, // 4 statement, emphatic | |||
| { PITCHfall, 62, 10, PITCHfall, 62, 20, NULL, 28, 16, 0 }, // 5 statement, less intonation | |||
| { PITCHfrise, 68, 18, PITCHfrise2, 68, 22, NULL, 30, 44, 0 }, // 6 comma, less intonation | |||
| { PITCHfrise2, 64, 16, PITCHfall, 66, 32, NULL, 32, 18, 0 }, // 7 comma, less intonation, less rise | |||
| { PITCHrise, 68, 46, PITCHfall, 42, 32, NULL, 46, 58, 0 }, // 8 pitch raises at end of sentence | |||
| { PITCHfrise, 78, 24, PITCHfrise2, 72, 22, NULL, 42, 52, 0 }, // 9 comma | |||
| { PITCHfrise, 88, 34, PITCHfall, 64, 32, NULL, 46, 82, 0 }, // 10 question | |||
| { PITCHfall, 56, 12, PITCHfall, 56, 20, NULL, 24, 12, 0 }, // 11 test | |||
| { PITCHfall, 70, 18, PITCHfall, 70, 24, NULL, 32, 20, 0 }, // 12 test | |||
| { PITCHfall, 64, 8, PITCHfall, 70, 18, NULL, 24, 12, 0 }, // 0 statement | |||
| { PITCHfrise, 80, 18, PITCHfrise2, 78, 22, NULL, 34, 52, 0 }, // 1 comma | |||
| { PITCHfrise, 88, 22, PITCHfrise2, 82, 22, NULL, 34, 64, 0 }, // 2 question | |||
| { PITCHfall, 92, 8, PITCHfall, 92, 80, NULL, 76, 8, T_EMPH }, // 3 exclamation | |||
| { PITCHfall, 86, 4, PITCHfall, 94, 66, NULL, 34, 10, 0 }, // 4 statement, emphatic | |||
| { PITCHfall, 62, 10, PITCHfall, 62, 20, NULL, 28, 16, 0 }, // 5 statement, less intonation | |||
| { PITCHfrise, 68, 18, PITCHfrise2, 68, 22, NULL, 30, 44, 0 }, // 6 comma, less intonation | |||
| { PITCHfrise2, 64, 16, PITCHfall, 66, 32, NULL, 32, 18, 0 }, // 7 comma, less intonation, less rise | |||
| { PITCHrise, 68, 46, PITCHfall, 42, 32, NULL, 46, 58, 0 }, // 8 pitch raises at end of sentence | |||
| { PITCHfrise, 78, 24, PITCHfrise2, 72, 22, NULL, 42, 52, 0 }, // 9 comma | |||
| { PITCHfrise, 88, 34, PITCHfall, 64, 32, NULL, 46, 82, 0 }, // 10 question | |||
| { PITCHfall, 56, 12, PITCHfall, 56, 20, NULL, 24, 12, 0 }, // 11 test | |||
| { PITCHfall, 70, 18, PITCHfall, 70, 24, NULL, 32, 20, 0 }, // 12 test | |||
| }; | |||
| /* index by 0=. 1=, 2=?, 3=! 4=none, 5=emphasized */ | |||
| // index by 0=. 1=, 2=?, 3=! 4=none, 5=emphasized | |||
| unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS] = { | |||
| { 0, 1, 2, 3, 0, 4 }, | |||
| { 0, 1, 2, 3, 0, 4 }, | |||
| { 5, 6, 2, 3, 0, 4 }, | |||
| { 5, 7, 1, 3, 0, 4 }, | |||
| { 8, 9, 10, 3, 0, 0 }, | |||
| { 8, 8, 10, 3, 0, 0 }, | |||
| { 11, 11, 11, 11, 0, 0 }, // 6 test | |||
| { 0, 1, 2, 3, 0, 4 }, | |||
| { 0, 1, 2, 3, 0, 4 }, | |||
| { 5, 6, 2, 3, 0, 4 }, | |||
| { 5, 7, 1, 3, 0, 4 }, | |||
| { 8, 9, 10, 3, 0, 0 }, | |||
| { 8, 8, 10, 3, 0, 0 }, | |||
| { 11, 11, 11, 11, 0, 0 }, // 6 test | |||
| { 12, 12, 12, 12, 0, 0 } | |||
| }; | |||
| int n_tunes = 0; | |||
| TUNE *tunes = NULL; | |||
| #define SECONDARY 3 | |||
| #define PRIMARY 4 | |||
| #define SECONDARY 3 | |||
| #define PRIMARY 4 | |||
| #define PRIMARY_STRESSED 6 | |||
| #define PRIMARY_LAST 7 | |||
| #define PRIMARY_LAST 7 | |||
| static int number_pre; | |||
| static int number_body; | |||
| @@ -326,16 +323,16 @@ static void count_pitch_vowels(int start, int end, int clause_end) | |||
| int ix; | |||
| int stress; | |||
| int max_stress = 0; | |||
| int max_stress_posn = 0; // last syllable ot the highest stress | |||
| int max_stress_posn2 = 0; // penuntimate syllable of the highest stress | |||
| int max_stress_posn = 0; // last syllable ot the highest stress | |||
| int max_stress_posn2 = 0; // penuntimate syllable of the highest stress | |||
| number_pre = -1; /* number of vowels before 1st primary stress */ | |||
| number_pre = -1; // number of vowels before 1st primary stress | |||
| number_body = 0; | |||
| number_tail = 0; /* number between tonic syllable and next primary */ | |||
| number_tail = 0; // number between tonic syllable and next primary | |||
| last_primary = -1; | |||
| for (ix = start; ix < end; ix++) { | |||
| stress = syllable_tab[ix].stress; /* marked stress level */ | |||
| stress = syllable_tab[ix].stress; // marked stress level | |||
| if (stress >= max_stress) { | |||
| if (stress > max_stress) | |||
| @@ -360,9 +357,9 @@ static void count_pitch_vowels(int start, int end, int clause_end) | |||
| tone_posn = max_stress_posn; | |||
| tone_posn2 = max_stress_posn2; | |||
| if (no_tonic) { | |||
| tone_posn = tone_posn2 = end; // next position after the end of the truncated clause | |||
| } else if (last_primary >= 0) { | |||
| if (no_tonic) | |||
| tone_posn = tone_posn2 = end; // next position after the end of the truncated clause | |||
| else if (last_primary >= 0) { | |||
| if (end == clause_end) | |||
| syllable_tab[last_primary].stress = PRIMARY_LAST; | |||
| } else { | |||
| @@ -371,7 +368,7 @@ static void count_pitch_vowels(int start, int end, int clause_end) | |||
| } | |||
| } | |||
| /* Count number of primary stresses up to tonic syllable or body_reset */ | |||
| // Count number of primary stresses up to tonic syllable or body_reset | |||
| static int count_increments(int ix, int end_ix, int min_stress) | |||
| { | |||
| int count = 0; | |||
| @@ -434,7 +431,7 @@ static int SetHeadIntonation(TUNE *tune, int syl_ix, int end_ix, int control) | |||
| int pitch = 0; | |||
| int increment = 0; | |||
| int n_steps = 0; | |||
| int stage; // onset, head, last | |||
| int stage; // onset, head, last | |||
| int initial; | |||
| int overflow_ix = 0; | |||
| int pitch_range; | |||
| @@ -445,16 +442,16 @@ static int SetHeadIntonation(TUNE *tune, int syl_ix, int end_ix, int control) | |||
| int unstressed_inc; | |||
| int used_onset = 0; | |||
| int head_final = end_ix; | |||
| int secondary = 2; // 2 | |||
| int secondary = 2; | |||
| pitch_range = (tune->head_end - tune->head_start) << 8; | |||
| pitch_range_abs = abs(pitch_range); | |||
| drops = drops_0; // this should be controled by tune->head_drops | |||
| drops = drops_0; // this should be controled by tune->head_drops | |||
| initial = 1; | |||
| stage = 0; | |||
| if (tune->onset == 255) | |||
| stage = 1; // no onset specified | |||
| stage = 1; // no onset specified | |||
| if (tune->head_last != 255) { | |||
| // find the last primary stress in the body | |||
| @@ -624,7 +621,7 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t | |||
| } else if (stress >= SECONDARY) | |||
| set_pitch(syl, (pitch >> 8), drops[stress]); | |||
| else { | |||
| /* unstressed, drop pitch if preceded by PRIMARY */ | |||
| // unstressed, drop pitch if preceded by PRIMARY | |||
| if ((syllable_tab[ix-1].stress & 0x3f) >= SECONDARY) | |||
| set_pitch(syl, (pitch >> 8) - th->body_lower_u, drops[stress]); | |||
| else | |||
| @@ -638,8 +635,8 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t | |||
| static void SetPitchGradient(int start_ix, int end_ix, int start_pitch, int end_pitch) | |||
| { | |||
| // Set a linear pitch change over a number of syllables. | |||
| // Used for pre-head, unstressed syllables in the body, and the tail | |||
| // Set a linear pitch change over a number of syllables. | |||
| // Used for pre-head, unstressed syllables in the body, and the tail | |||
| int ix; | |||
| int stress; | |||
| @@ -691,24 +688,21 @@ static int calc_pitches2(int start, int end, int tune_number) | |||
| tune = &tunes[tune_number]; | |||
| ix = start; | |||
| /* vowels before the first primary stress */ | |||
| /******************************************/ | |||
| // vowels before the first primary stress | |||
| SetPitchGradient(ix, ix+number_pre, tune->prehead_start, tune->prehead_end); | |||
| ix += number_pre; | |||
| /* body of tonic segment */ | |||
| /*************************/ | |||
| // body of tonic segment | |||
| if (option_tone_flags & OPTION_EMPHASIZE_PENULTIMATE) | |||
| tone_posn = tone_posn2; // put tone on the penultimate stressed word | |||
| tone_posn = tone_posn2; // put tone on the penultimate stressed word | |||
| ix = SetHeadIntonation(tune, ix, tone_posn, 0); | |||
| if (no_tonic) | |||
| return 0; | |||
| /* tonic syllable */ | |||
| /******************/ | |||
| // tonic syllable | |||
| if (number_tail == 0) { | |||
| tone_pitch_env = tune->nucleus0_env; | |||
| @@ -724,8 +718,7 @@ static int calc_pitches2(int start, int end, int tune_number) | |||
| if (syllable_tab[tone_posn].stress == PRIMARY) | |||
| syllable_tab[tone_posn].stress = PRIMARY_STRESSED; | |||
| /* tail, after the tonic syllable */ | |||
| /**********************************/ | |||
| // tail, after the tonic syllable | |||
| SetPitchGradient(ix, end, tune->tail_start, tune->tail_end); | |||
| @@ -751,28 +744,24 @@ static int calc_pitches(int control, int start, int end, int tune_number) | |||
| tn = &tone_nucleus_table[tune_number]; | |||
| ix = start; | |||
| /* vowels before the first primary stress */ | |||
| /******************************************/ | |||
| // vowels before the first primary stress | |||
| SetPitchGradient(ix, ix+number_pre, th->pre_start, th->pre_end); | |||
| ix += number_pre; | |||
| /* body of tonic segment */ | |||
| /*************************/ | |||
| // body of tonic segment | |||
| if (option_tone_flags & OPTION_EMPHASIZE_PENULTIMATE) | |||
| tone_posn = tone_posn2; // put tone on the penultimate stressed word | |||
| tone_posn = tone_posn2; // put tone on the penultimate stressed word | |||
| ix = calc_pitch_segment(ix, tone_posn, th, tn, PRIMARY, continuing); | |||
| if (no_tonic) | |||
| return 0; | |||
| /* tonic syllable */ | |||
| /******************/ | |||
| // tonic syllable | |||
| if (tn->flags & T_EMPH) { | |||
| if (tn->flags & T_EMPH) | |||
| syllable_tab[ix].flags |= SYL_EMPHASIS; | |||
| } | |||
| if (number_tail == 0) { | |||
| tone_pitch_env = tn->pitch_env0; | |||
| @@ -788,8 +777,7 @@ static int calc_pitches(int control, int start, int end, int tune_number) | |||
| if (syllable_tab[tone_posn].stress == PRIMARY) | |||
| syllable_tab[tone_posn].stress = PRIMARY_STRESSED; | |||
| /* tail, after the tonic syllable */ | |||
| /**********************************/ | |||
| // tail, after the tonic syllable | |||
| SetPitchGradient(ix, end, tn->tail_start, tn->tail_end); | |||
| @@ -798,7 +786,8 @@ static int calc_pitches(int control, int start, int end, int tune_number) | |||
| static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| { | |||
| // clause_tone: 0=. 1=, 2=?, 3=! 4=none | |||
| // clause_tone: 0=. 1=, 2=?, 3=! 4=none | |||
| PHONEME_LIST *p; | |||
| int ix; | |||
| int count_stressed = 0; | |||
| @@ -808,14 +797,14 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| int pause; | |||
| int tone_promoted; | |||
| PHONEME_TAB *tph; | |||
| PHONEME_TAB *prev_tph; // forget across word boundary | |||
| PHONEME_TAB *prevw_tph; // remember across word boundary | |||
| PHONEME_TAB *prev_tph; // forget across word boundary | |||
| PHONEME_TAB *prevw_tph; // remember across word boundary | |||
| PHONEME_LIST *prev_p; | |||
| int pitch_adjust = 0; // pitch gradient through the clause - inital value | |||
| int pitch_decrement = 0; // decrease by this for each stressed syllable | |||
| int pitch_low = 0; // until it drops to this | |||
| int pitch_high = 0; // then reset to this | |||
| int pitch_adjust = 0; // pitch gradient through the clause - inital value | |||
| int pitch_decrement = 0; // decrease by this for each stressed syllable | |||
| int pitch_low = 0; // until it drops to this | |||
| int pitch_high = 0; // then reset to this | |||
| // count number of stressed syllables | |||
| p = &phoneme_list[0]; | |||
| @@ -838,7 +827,7 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| // LANG=vi | |||
| p = &phoneme_list[final_stressed]; | |||
| if (p->tone_ph == 0) | |||
| p->tone_ph = PhonemeCode('7'); // change default tone (tone 1) to falling tone at end of clause | |||
| p->tone_ph = PhonemeCode('7'); // change default tone (tone 1) to falling tone at end of clause | |||
| } | |||
| pause = 1; | |||
| @@ -850,12 +839,12 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| // perform tone sandhi | |||
| for (ix = 0; ix < n_phoneme_list; ix++, p++) { | |||
| if ((p->type == phPAUSE) && (p->ph->std_length > 50)) { | |||
| pause = 1; // there is a pause since the previous vowel | |||
| prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone | |||
| pause = 1; // there is a pause since the previous vowel | |||
| prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone | |||
| } | |||
| if (p->newword) | |||
| prev_tph = phoneme_tab[phonPAUSE]; // forget across word boundaries | |||
| prev_tph = phoneme_tab[phonPAUSE]; // forget across word boundaries | |||
| if (p->synthflags & SFLAG_SYLLABLE) { | |||
| tone_ph = p->tone_ph; | |||
| @@ -865,10 +854,10 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| if (tr->translator_name == L('z', 'h')) { | |||
| if (tone_ph == 0) { | |||
| if (pause || tone_promoted) { | |||
| tone_ph = PhonemeCode2('5', '5'); // no previous vowel, use tone 1 | |||
| tone_ph = PhonemeCode2('5', '5'); // no previous vowel, use tone 1 | |||
| tone_promoted = 1; | |||
| } else | |||
| tone_ph = PhonemeCode2('1', '1'); // default tone 5 | |||
| tone_ph = PhonemeCode2('1', '1'); // default tone 5 | |||
| p->tone_ph = tone_ph; | |||
| tph = phoneme_tab[tone_ph]; | |||
| @@ -883,12 +872,12 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| } | |||
| if (prevw_tph->mnemonic == 0x343132) { // [214] | |||
| if (tph->mnemonic == 0x343132) // [214] | |||
| if (tph->mnemonic == 0x343132) // [214] | |||
| prev_p->tone_ph = PhonemeCode2('3', '5'); | |||
| else | |||
| prev_p->tone_ph = PhonemeCode2('2', '1'); | |||
| } | |||
| if ((prev_tph->mnemonic == 0x3135) && (tph->mnemonic == 0x3135)) // [51] + [51] | |||
| if ((prev_tph->mnemonic == 0x3135) && (tph->mnemonic == 0x3135)) // [51] + [51] | |||
| prev_p->tone_ph = PhonemeCode2('5', '3'); | |||
| if (tph->mnemonic == 0x3131) { // [11] Tone 5 | |||
| @@ -901,7 +890,7 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| p->tone_ph = PhonemeCode2('4', '4'); | |||
| // tone 5 is unstressed (shorter) | |||
| p->stresslevel = 0; // diminished stress | |||
| p->stresslevel = 0; // diminished stress | |||
| } | |||
| } | |||
| @@ -929,7 +918,7 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| } | |||
| if (tone_ph == 0) { | |||
| tone_ph = phonDEFAULTTONE; // no tone specified, use default tone 1 | |||
| tone_ph = phonDEFAULTTONE; // no tone specified, use default tone 1 | |||
| p->tone_ph = tone_ph; | |||
| } | |||
| p->pitch1 = pitch_adjust + phoneme_tab[tone_ph]->start_type; | |||
| @@ -940,7 +929,8 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone) | |||
| void CalcPitches(Translator *tr, int clause_type) | |||
| { | |||
| // clause_type: 0=. 1=, 2=?, 3=! 4=none | |||
| // clause_type: 0=. 1=, 2=?, 3=! 4=none | |||
| PHONEME_LIST *p; | |||
| SYLLABLE *syl; | |||
| int ix; | |||
| @@ -961,7 +951,7 @@ void CalcPitches(Translator *tr, int clause_type) | |||
| SYLLABLE syllable_tab2[N_PHONEME_LIST]; | |||
| syllable_tab = syllable_tab2; // don't use permanent storage. it's only needed during the call of CalcPitches() | |||
| syllable_tab = syllable_tab2; // don't use permanent storage. it's only needed during the call of CalcPitches() | |||
| n_st = 0; | |||
| n_primary = 0; | |||
| for (ix = 0; ix < (n_phoneme_list-1); ix++) { | |||
| @@ -977,10 +967,10 @@ void CalcPitches(Translator *tr, int clause_type) | |||
| } else if ((p->ph->code == phonPAUSE_CLAUSE) && (n_st > 0)) | |||
| syllable_tab[n_st-1].flags |= SYL_END_CLAUSE; | |||
| } | |||
| syllable_tab[n_st].stress = 0; // extra 0 entry at the end | |||
| syllable_tab[n_st].stress = 0; // extra 0 entry at the end | |||
| if (n_st == 0) | |||
| return; // nothing to do | |||
| return; // nothing to do | |||
| if (tr->langopts.tone_language == 1) { | |||
| CalcPitches_Tone(tr, clause_type); | |||
| @@ -996,11 +986,11 @@ void CalcPitches(Translator *tr, int clause_type) | |||
| group_tone_comma = tr->langopts.tunes[1]; | |||
| } else { | |||
| group_tone = tr->punct_to_tone[option][clause_type]; | |||
| group_tone_comma = tr->punct_to_tone[option][1]; // emphatic form of statement | |||
| group_tone_comma = tr->punct_to_tone[option][1]; // emphatic form of statement | |||
| } | |||
| if (clause_type == 4) | |||
| no_tonic = 1; /* incomplete clause, used for abbreviations such as Mr. Dr. Mrs. */ | |||
| no_tonic = 1; // incomplete clause, used for abbreviations such as Mr. Dr. Mrs. | |||
| else | |||
| no_tonic = 0; | |||
| @@ -1056,12 +1046,12 @@ void CalcPitches(Translator *tr, int clause_type) | |||
| count_pitch_vowels(st_start, ix, n_st); | |||
| if ((ix < n_st) || (clause_type == 0)) { | |||
| calc_pitches(option, st_start, ix, group_tone); // split into > 1 tone groups | |||
| calc_pitches(option, st_start, ix, group_tone); // split into > 1 tone groups | |||
| if ((clause_type == 1) || (clause_type == 2)) | |||
| group_tone = tr->langopts.tunes[1]; // , or ? remainder has comma-tone | |||
| group_tone = tr->langopts.tunes[1]; // , or ? remainder has comma-tone | |||
| else | |||
| group_tone = tr->langopts.tunes[0]; // . or ! remainder has statement tone | |||
| group_tone = tr->langopts.tunes[0]; // . or ! remainder has statement tone | |||
| } else | |||
| calc_pitches(option, st_start, ix, group_tone); | |||
| @@ -1114,7 +1104,7 @@ void CalcPitches(Translator *tr, int clause_type) | |||
| } | |||
| if (syl->flags & SYL_EMPHASIS) | |||
| p->stresslevel |= 8; // emphasized | |||
| p->stresslevel |= 8; // emphasized | |||
| st_ix++; | |||
| } | |||
| @@ -53,7 +53,7 @@ static int sample_count; | |||
| #define getrandom(min, max) ((rand()%(long)(((max)+1)-(min)))+(min)) | |||
| #endif | |||
| /* function prototypes for functions private to this file */ | |||
| // function prototypes for functions private to this file | |||
| static void flutter(klatt_frame_ptr); | |||
| static double sampled_source(int); | |||
| @@ -71,50 +71,50 @@ static klatt_global_t kt_globals; | |||
| #define NUMBER_OF_SAMPLES 100 | |||
| static int scale_wav_tab[] = { 45, 38, 45, 45, 55 }; // scale output from different voicing sources | |||
| static int scale_wav_tab[] = { 45, 38, 45, 45, 55 }; // scale output from different voicing sources | |||
| // For testing, this can be overwritten in KlattInit() | |||
| static short natural_samples2[256] = { | |||
| 2583, 2516, 2450, 2384, 2319, 2254, 2191, 2127, | |||
| 2067, 2005, 1946, 1890, 1832, 1779, 1726, 1675, | |||
| 1626, 1579, 1533, 1491, 1449, 1409, 1372, 1336, | |||
| 1302, 1271, 1239, 1211, 1184, 1158, 1134, 1111, | |||
| 1089, 1069, 1049, 1031, 1013, 996, 980, 965, | |||
| 950, 936, 921, 909, 895, 881, 869, 855, | |||
| 843, 830, 818, 804, 792, 779, 766, 754, | |||
| 740, 728, 715, 702, 689, 676, 663, 651, | |||
| 637, 626, 612, 601, 588, 576, 564, 552, | |||
| 540, 530, 517, 507, 496, 485, 475, 464, | |||
| 454, 443, 434, 424, 414, 404, 394, 385, | |||
| 375, 366, 355, 347, 336, 328, 317, 308, | |||
| 299, 288, 280, 269, 260, 250, 240, 231, | |||
| 220, 212, 200, 192, 181, 172, 161, 152, | |||
| 142, 133, 123, 113, 105, 94, 86, 76, | |||
| 67, 57, 49, 39, 30, 22, 11, 4, | |||
| -5, -14, -23, -32, -41, -50, -60, -69, | |||
| -78, -87, -96, -107, -115, -126, -134, -144, | |||
| -154, -164, -174, -183, -193, -203, -213, -222, | |||
| -233, -242, -252, -262, -271, -281, -291, -301, | |||
| -310, -320, -330, -339, -349, -357, -368, -377, | |||
| -387, -397, -406, -417, -426, -436, -446, -456, | |||
| -467, -477, -487, -499, -509, -521, -532, -543, | |||
| -555, -567, -579, -591, -603, -616, -628, -641, | |||
| -653, -666, -679, -692, -705, -717, -732, -743, | |||
| -758, -769, -783, -795, -808, -820, -834, -845, | |||
| -860, -872, -885, -898, -911, -926, -939, -955, | |||
| -968, -986, -999, -1018, -1034, -1054, -1072, -1094, | |||
| 2583, 2516, 2450, 2384, 2319, 2254, 2191, 2127, | |||
| 2067, 2005, 1946, 1890, 1832, 1779, 1726, 1675, | |||
| 1626, 1579, 1533, 1491, 1449, 1409, 1372, 1336, | |||
| 1302, 1271, 1239, 1211, 1184, 1158, 1134, 1111, | |||
| 1089, 1069, 1049, 1031, 1013, 996, 980, 965, | |||
| 950, 936, 921, 909, 895, 881, 869, 855, | |||
| 843, 830, 818, 804, 792, 779, 766, 754, | |||
| 740, 728, 715, 702, 689, 676, 663, 651, | |||
| 637, 626, 612, 601, 588, 576, 564, 552, | |||
| 540, 530, 517, 507, 496, 485, 475, 464, | |||
| 454, 443, 434, 424, 414, 404, 394, 385, | |||
| 375, 366, 355, 347, 336, 328, 317, 308, | |||
| 299, 288, 280, 269, 260, 250, 240, 231, | |||
| 220, 212, 200, 192, 181, 172, 161, 152, | |||
| 142, 133, 123, 113, 105, 94, 86, 76, | |||
| 67, 57, 49, 39, 30, 22, 11, 4, | |||
| -5, -14, -23, -32, -41, -50, -60, -69, | |||
| -78, -87, -96, -107, -115, -126, -134, -144, | |||
| -154, -164, -174, -183, -193, -203, -213, -222, | |||
| -233, -242, -252, -262, -271, -281, -291, -301, | |||
| -310, -320, -330, -339, -349, -357, -368, -377, | |||
| -387, -397, -406, -417, -426, -436, -446, -456, | |||
| -467, -477, -487, -499, -509, -521, -532, -543, | |||
| -555, -567, -579, -591, -603, -616, -628, -641, | |||
| -653, -666, -679, -692, -705, -717, -732, -743, | |||
| -758, -769, -783, -795, -808, -820, -834, -845, | |||
| -860, -872, -885, -898, -911, -926, -939, -955, | |||
| -968, -986, -999, -1018, -1034, -1054, -1072, -1094, | |||
| -1115, -1138, -1162, -1188, -1215, -1244, -1274, -1307, | |||
| -1340, -1377, -1415, -1453, -1496, -1538, -1584, -1631, | |||
| -1680, -1732, -1783, -1839, -1894, -1952, -2010, -2072, | |||
| -2133, -2196, -2260, -2325, -2390, -2456, -2522, -2589, | |||
| }; | |||
| static short natural_samples[100] = { | |||
| -310, -400, 530, 356, 224, 89, 23, -10, -58, -16, 461, 599, 536, 701, 770, | |||
| 605, 497, 461, 560, 404, 110, 224, 131, 104, -97, 155, 278, -154, -1165, | |||
| -598, 737, 125, -592, 41, 11, -247, -10, 65, 92, 80, -304, 71, 167, -1, 122, | |||
| 233, 161, -43, 278, 479, 485, 407, 266, 650, 134, 80, 236, 68, 260, 269, 179, | |||
| 53, 140, 275, 293, 296, 104, 257, 152, 311, 182, 263, 245, 125, 314, 140, 44, | |||
| 203, 230, -235, -286, 23, 107, 92, -91, 38, 464, 443, 176, 98, -784, -2449, | |||
| -310, -400, 530, 356, 224, 89, 23, -10, -58, -16, 461, 599, 536, 701, 770, | |||
| 605, 497, 461, 560, 404, 110, 224, 131, 104, -97, 155, 278, -154, -1165, | |||
| -598, 737, 125, -592, 41, 11, -247, -10, 65, 92, 80, -304, 71, 167, -1, 122, | |||
| 233, 161, -43, 278, 479, 485, 407, 266, 650, 134, 80, 236, 68, 260, 269, 179, | |||
| 53, 140, 275, 293, 296, 104, 257, 152, 311, 182, 263, 245, 125, 314, 140, 44, | |||
| 203, 230, -235, -286, 23, 107, 92, -91, 38, 464, 443, 176, 98, -784, -2449, | |||
| -1891, -1045, -1600, -1462, -1384, -1261, -949, -730 | |||
| }; | |||
| @@ -182,7 +182,7 @@ static void flutter(klatt_frame_ptr frame) | |||
| fla = (double)kt_globals.f0_flutter / 50; | |||
| flb = (double)kt_globals.original_f0 / 100; | |||
| flc = sin(PI*12.7*time_count); // because we are calling flutter() more frequently, every 2.9mS | |||
| flc = sin(PI*12.7*time_count); // because we are calling flutter() more frequently, every 2.9mS | |||
| fld = sin(PI*7.1*time_count); | |||
| fle = sin(PI*4.7*time_count); | |||
| delta_f0 = fla * flb * (flc + fld + fle) * 10; | |||
| @@ -262,30 +262,26 @@ static int parwave(klatt_frame_ptr frame) | |||
| static double sourc; | |||
| int ix; | |||
| flutter(frame); /* add f0 flutter */ | |||
| flutter(frame); // add f0 flutter | |||
| /* MAIN LOOP, for each output sample of current frame: */ | |||
| // MAIN LOOP, for each output sample of current frame: | |||
| for (kt_globals.ns = 0; kt_globals.ns < kt_globals.nspfr; kt_globals.ns++) { | |||
| /* Get low-passed random number for aspiration and frication noise */ | |||
| // Get low-passed random number for aspiration and frication noise | |||
| noise = gen_noise(noise); | |||
| /* | |||
| Amplitude modulate noise (reduce noise amplitude during | |||
| second half of glottal period) if voicing simultaneously present. | |||
| */ | |||
| // Amplitude modulate noise (reduce noise amplitude during | |||
| // second half of glottal period) if voicing simultaneously present. | |||
| if (kt_globals.nper > kt_globals.nmod) | |||
| noise *= (double)0.5; | |||
| /* Compute frication noise */ | |||
| // Compute frication noise | |||
| frics = kt_globals.amp_frica * noise; | |||
| /* | |||
| Compute voicing waveform. Run glottal source simulation at 4 | |||
| times normal sample rate to minimize quantization noise in | |||
| period of female voice. | |||
| */ | |||
| // Compute voicing waveform. Run glottal source simulation at 4 | |||
| // times normal sample rate to minimize quantization noise in | |||
| // period of female voice. | |||
| for (n4 = 0; n4 < 4; n4++) { | |||
| switch (kt_globals.glsource) | |||
| @@ -304,55 +300,46 @@ static int parwave(klatt_frame_ptr frame) | |||
| break; | |||
| } | |||
| /* Reset period when counter 'nper' reaches T0 */ | |||
| // Reset period when counter 'nper' reaches T0 | |||
| if (kt_globals.nper >= kt_globals.T0) { | |||
| kt_globals.nper = 0; | |||
| pitch_synch_par_reset(frame); | |||
| } | |||
| /* | |||
| Low-pass filter voicing waveform before downsampling from 4*samrate | |||
| to samrate samples/sec. Resonator f=.09*samrate, bw=.06*samrate | |||
| */ | |||
| // Low-pass filter voicing waveform before downsampling from 4*samrate | |||
| // to samrate samples/sec. Resonator f=.09*samrate, bw=.06*samrate | |||
| voice = resonator(&(kt_globals.rsn[RLP]), voice); | |||
| /* Increment counter that keeps track of 4*samrate samples per sec */ | |||
| // Increment counter that keeps track of 4*samrate samples per sec | |||
| kt_globals.nper++; | |||
| } | |||
| /* | |||
| Tilt spectrum of voicing source down by soft low-pass filtering, amount | |||
| of tilt determined by TLTdb | |||
| */ | |||
| // Tilt spectrum of voicing source down by soft low-pass filtering, amount | |||
| // of tilt determined by TLTdb | |||
| voice = (voice * kt_globals.onemd) + (vlast * kt_globals.decay); | |||
| vlast = voice; | |||
| /* | |||
| Add breathiness during glottal open phase. Amount of breathiness | |||
| determined by parameter Aturb Use nrand rather than noise because | |||
| noise is low-passed. | |||
| */ | |||
| // Add breathiness during glottal open phase. Amount of breathiness | |||
| // determined by parameter Aturb Use nrand rather than noise because | |||
| // noise is low-passed. | |||
| if (kt_globals.nper < kt_globals.nopen) | |||
| voice += kt_globals.amp_breth * kt_globals.nrand; | |||
| /* Set amplitude of voicing */ | |||
| // Set amplitude of voicing | |||
| glotout = kt_globals.amp_voice * voice; | |||
| par_glotout = kt_globals.par_amp_voice * voice; | |||
| /* Compute aspiration amplitude and add to voicing source */ | |||
| // Compute aspiration amplitude and add to voicing source | |||
| aspiration = kt_globals.amp_aspir * noise; | |||
| glotout += aspiration; | |||
| par_glotout += aspiration; | |||
| /* | |||
| Cascade vocal tract, excited by laryngeal sources. | |||
| Nasal antiresonator, then formants FNP, F5, F4, F3, F2, F1 | |||
| */ | |||
| // Cascade vocal tract, excited by laryngeal sources. | |||
| // Nasal antiresonator, then formants FNP, F5, F4, F3, F2, F1 | |||
| out = 0; | |||
| if (kt_globals.synthesis_model != ALL_PARALLEL) { | |||
| @@ -368,15 +355,13 @@ static int parwave(klatt_frame_ptr frame) | |||
| out = resonator2(&(kt_globals.rsn[R1c]), casc_next_in); | |||
| } | |||
| /* Excite parallel F1 and FNP by voicing waveform */ | |||
| sourc = par_glotout; /* Source is voicing plus aspiration */ | |||
| // Excite parallel F1 and FNP by voicing waveform | |||
| sourc = par_glotout; // Source is voicing plus aspiration | |||
| /* | |||
| Standard parallel vocal tract Formants F6,F5,F4,F3,F2, | |||
| outputs added with alternating sign. Sound source for other | |||
| parallel resonators is frication plus first difference of | |||
| voicing waveform. | |||
| */ | |||
| // Standard parallel vocal tract Formants F6,F5,F4,F3,F2, | |||
| // outputs added with alternating sign. Sound source for other | |||
| // parallel resonators is frication plus first difference of | |||
| // voicing waveform. | |||
| out += resonator(&(kt_globals.rsn[R1p]), sourc); | |||
| out += resonator(&(kt_globals.rsn[Rnpp]), sourc); | |||
| @@ -392,30 +377,27 @@ static int parwave(klatt_frame_ptr frame) | |||
| out = outbypas - out; | |||
| out = resonator(&(kt_globals.rsn[Rout]), out); | |||
| temp = (int)(out * wdata.amplitude * kt_globals.amp_gain0); /* Convert back to integer */ | |||
| temp = (int)(out * wdata.amplitude * kt_globals.amp_gain0); // Convert back to integer | |||
| // mix with a recorded WAV if required for this phoneme | |||
| { | |||
| int z2; | |||
| signed char c; | |||
| int sample; | |||
| z2 = 0; | |||
| if (wdata.mix_wavefile_ix < wdata.n_mix_wavefile) { | |||
| if (wdata.mix_wave_scale == 0) { | |||
| // a 16 bit sample | |||
| c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1]; | |||
| sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256); | |||
| wdata.mix_wavefile_ix += 2; | |||
| } else { | |||
| // a 8 bit sample, scaled | |||
| sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale; | |||
| } | |||
| z2 = sample * wdata.amplitude_v / 1024; | |||
| z2 = (z2 * wdata.mix_wave_amp)/40; | |||
| temp += z2; | |||
| int z2; | |||
| signed char c; | |||
| int sample; | |||
| z2 = 0; | |||
| if (wdata.mix_wavefile_ix < wdata.n_mix_wavefile) { | |||
| if (wdata.mix_wave_scale == 0) { | |||
| // a 16 bit sample | |||
| c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1]; | |||
| sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256); | |||
| wdata.mix_wavefile_ix += 2; | |||
| } else { | |||
| // a 8 bit sample, scaled | |||
| sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale; | |||
| } | |||
| z2 = sample * wdata.amplitude_v / 1024; | |||
| z2 = (z2 * wdata.mix_wave_amp)/40; | |||
| temp += z2; | |||
| } | |||
| // if fadeout is set, fade to zero over 64 samples, to avoid clicks at end of synthesis | |||
| @@ -459,7 +441,6 @@ void KlattReset(int control) | |||
| kt_globals.minus_pi_t = -PI / kt_globals.samrate; | |||
| kt_globals.two_pi_t = -2.0 * kt_globals.minus_pi_t; | |||
| setabc(kt_globals.FLPhz, kt_globals.BLPhz, &(kt_globals.rsn[RLP])); | |||
| } | |||
| if (control > 0) { | |||
| @@ -514,7 +495,7 @@ static void frame_init(klatt_frame_ptr frame) | |||
| Gain0_tmp = 57; | |||
| kt_globals.amp_gain0 = DBtoLIN(Gain0_tmp) / kt_globals.scale_wav; | |||
| /* Set coefficients of variable cascade resonators */ | |||
| // Set coefficients of variable cascade resonators | |||
| for (ix = 1; ix <= 9; ix++) { | |||
| // formants 1 to 8, plus nasal pole | |||
| setabc(frame->Fhz[ix], frame->Bhz[ix], &(kt_globals.rsn[ix])); | |||
| @@ -535,14 +516,14 @@ static void frame_init(klatt_frame_ptr frame) | |||
| kt_globals.rsn[F_NZ].b_inc = (kt_globals.rsn_next[F_NZ].b - kt_globals.rsn[F_NZ].b) / 64.0; | |||
| kt_globals.rsn[F_NZ].c_inc = (kt_globals.rsn_next[F_NZ].c - kt_globals.rsn[F_NZ].c) / 64.0; | |||
| /* Set coefficients of parallel resonators, and amplitude of outputs */ | |||
| // Set coefficients of parallel resonators, and amplitude of outputs | |||
| for (ix = 0; ix <= 6; ix++) { | |||
| setabc(frame->Fhz[ix], frame->Bphz[ix], &(kt_globals.rsn[Rparallel+ix])); | |||
| kt_globals.rsn[Rparallel+ix].a *= amp_par[ix]; | |||
| } | |||
| /* output low-pass filter */ | |||
| // output low-pass filter | |||
| setabc((long)0.0, (long)(kt_globals.samrate/2), &(kt_globals.rsn[Rout])); | |||
| } | |||
| @@ -631,40 +612,39 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) | |||
| static long skew; | |||
| static short B0[224] = { | |||
| 1200, 1142, 1088, 1038, 991, 948, 907, 869, 833, 799, 768, 738, 710, 683, 658, | |||
| 634, 612, 590, 570, 551, 533, 515, 499, 483, 468, 454, 440, 427, 415, 403, | |||
| 391, 380, 370, 360, 350, 341, 332, 323, 315, 307, 300, 292, 285, 278, 272, | |||
| 265, 259, 253, 247, 242, 237, 231, 226, 221, 217, 212, 208, 204, 199, 195, | |||
| 192, 188, 184, 180, 177, 174, 170, 167, 164, 161, 158, 155, 153, 150, 147, | |||
| 145, 142, 140, 137, 135, 133, 131, 128, 126, 124, 122, 120, 119, 117, 115, | |||
| 113, 111, 110, 108, 106, 105, 103, 102, 100, 99, 97, 96, 95, 93, 92, 91, 90, | |||
| 88, 87, 86, 85, 84, 83, 82, 80, 79, 78, 77, 76, 75, 75, 74, 73, 72, 71, | |||
| 70, 69, 68, 68, 67, 66, 65, 64, 64, 63, 62, 61, 61, 60, 59, 59, 58, 57, | |||
| 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, | |||
| 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 41, 41, 40, 40, | |||
| 39, 39, 38, 38, 38, 38, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 33, | |||
| 33, 33, 33, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, | |||
| 28, 28, 28, 28, 27, 27 | |||
| 634, 612, 590, 570, 551, 533, 515, 499, 483, 468, 454, 440, 427, 415, 403, | |||
| 391, 380, 370, 360, 350, 341, 332, 323, 315, 307, 300, 292, 285, 278, 272, | |||
| 265, 259, 253, 247, 242, 237, 231, 226, 221, 217, 212, 208, 204, 199, 195, | |||
| 192, 188, 184, 180, 177, 174, 170, 167, 164, 161, 158, 155, 153, 150, 147, | |||
| 145, 142, 140, 137, 135, 133, 131, 128, 126, 124, 122, 120, 119, 117, 115, | |||
| 113, 111, 110, 108, 106, 105, 103, 102, 100, 99, 97, 96, 95, 93, 92, 91, 90, | |||
| 88, 87, 86, 85, 84, 83, 82, 80, 79, 78, 77, 76, 75, 75, 74, 73, 72, 71, | |||
| 70, 69, 68, 68, 67, 66, 65, 64, 64, 63, 62, 61, 61, 60, 59, 59, 58, 57, | |||
| 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, | |||
| 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 41, 41, 40, 40, | |||
| 39, 39, 38, 38, 38, 38, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 33, | |||
| 33, 33, 33, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, | |||
| 28, 28, 28, 28, 27, 27 | |||
| }; | |||
| if (frame->F0hz10 > 0) { | |||
| /* T0 is 4* the number of samples in one pitch period */ | |||
| // T0 is 4* the number of samples in one pitch period | |||
| kt_globals.T0 = (40 * kt_globals.samrate) / frame->F0hz10; | |||
| kt_globals.amp_voice = DBtoLIN(frame->AVdb_tmp); | |||
| /* Duration of period before amplitude modulation */ | |||
| // Duration of period before amplitude modulation | |||
| kt_globals.nmod = kt_globals.T0; | |||
| if (frame->AVdb_tmp > 0) | |||
| kt_globals.nmod >>= 1; | |||
| /* Breathiness of voicing waveform */ | |||
| // Breathiness of voicing waveform | |||
| kt_globals.amp_breth = DBtoLIN(frame->Aturb) * 0.1; | |||
| /* Set open phase of glottal period where 40 <= open phase <= 263 */ | |||
| // Set open phase of glottal period where 40 <= open phase <= 263 | |||
| kt_globals.nopen = 4 * frame->Kopen; | |||
| @@ -675,31 +655,28 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) | |||
| kt_globals.nopen = kt_globals.T0 - 2; | |||
| if (kt_globals.nopen < 40) { | |||
| /* F0 max = 1000 Hz */ | |||
| // F0 max = 1000 Hz | |||
| kt_globals.nopen = 40; | |||
| } | |||
| /* Reset a & b, which determine shape of "natural" glottal waveform */ | |||
| // Reset a & b, which determine shape of "natural" glottal waveform | |||
| kt_globals.pulse_shape_b = B0[kt_globals.nopen-40]; | |||
| kt_globals.pulse_shape_a = (kt_globals.pulse_shape_b * kt_globals.nopen) * 0.333; | |||
| /* Reset width of "impulsive" glottal pulse */ | |||
| // Reset width of "impulsive" glottal pulse | |||
| temp = kt_globals.samrate / kt_globals.nopen; | |||
| setabc((long)0, temp, &(kt_globals.rsn[RGL])); | |||
| /* Make gain at F1 about constant */ | |||
| // Make gain at F1 about constant | |||
| temp1 = kt_globals.nopen *.00833; | |||
| kt_globals.rsn[RGL].a *= temp1 * temp1; | |||
| /* | |||
| Truncate skewness so as not to exceed duration of closed phase | |||
| of glottal period. | |||
| */ | |||
| // Truncate skewness so as not to exceed duration of closed phase | |||
| // of glottal period. | |||
| temp = kt_globals.T0 - kt_globals.nopen; | |||
| if (frame->Kskew > temp) | |||
| @@ -709,11 +686,11 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) | |||
| else | |||
| skew = -frame->Kskew; | |||
| /* Add skewness to closed portion of voicing period */ | |||
| // Add skewness to closed portion of voicing period | |||
| kt_globals.T0 = kt_globals.T0 + skew; | |||
| skew = -skew; | |||
| } else { | |||
| kt_globals.T0 = 4; /* Default for f0 undefined */ | |||
| kt_globals.T0 = 4; // Default for f0 undefined | |||
| kt_globals.amp_voice = 0.0; | |||
| kt_globals.nmod = kt_globals.T0; | |||
| kt_globals.amp_breth = 0.0; | |||
| @@ -721,10 +698,10 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame) | |||
| kt_globals.pulse_shape_b = 0.0; | |||
| } | |||
| /* Reset these pars pitch synchronously or at update rate if f0=0 */ | |||
| // Reset these pars pitch synchronously or at update rate if f0=0 | |||
| if ((kt_globals.T0 != 4) || (kt_globals.ns == 0)) { | |||
| /* Set one-pole low-pass filter that tilts glottal source */ | |||
| // Set one-pole low-pass filter that tilts glottal source | |||
| kt_globals.decay = (0.033 * frame->TLTdb); | |||
| @@ -747,18 +724,18 @@ static void setabc(long int f, long int bw, resonator_ptr rp) | |||
| double r; | |||
| double arg; | |||
| /* Let r = exp(-pi bw t) */ | |||
| // Let r = exp(-pi bw t) | |||
| arg = kt_globals.minus_pi_t * bw; | |||
| r = exp(arg); | |||
| /* Let c = -r**2 */ | |||
| // Let c = -r**2 | |||
| rp->c = -(r * r); | |||
| /* Let b = r * 2*cos(2 pi f t) */ | |||
| // Let b = r * 2*cos(2 pi f t) | |||
| arg = kt_globals.two_pi_t * f; | |||
| rp->b = r * cos(arg) * 2.0; | |||
| /* Let a = 1.0 - b - c */ | |||
| // Let a = 1.0 - b - c | |||
| rp->a = 1.0 - rp->b - rp->c; | |||
| } | |||
| @@ -776,28 +753,28 @@ static void setzeroabc(long int f, long int bw, resonator_ptr rp) | |||
| f = -f; | |||
| /* First compute ordinary resonator coefficients */ | |||
| /* Let r = exp(-pi bw t) */ | |||
| // First compute ordinary resonator coefficients | |||
| // Let r = exp(-pi bw t) | |||
| arg = kt_globals.minus_pi_t * bw; | |||
| r = exp(arg); | |||
| /* Let c = -r**2 */ | |||
| // Let c = -r**2 | |||
| rp->c = -(r * r); | |||
| /* Let b = r * 2*cos(2 pi f t) */ | |||
| // Let b = r * 2*cos(2 pi f t) | |||
| arg = kt_globals.two_pi_t * f; | |||
| rp->b = r * cos(arg) * 2.; | |||
| /* Let a = 1.0 - b - c */ | |||
| // Let a = 1.0 - b - c | |||
| rp->a = 1.0 - rp->b - rp->c; | |||
| /* Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) */ | |||
| /* If f == 0 then rp->a gets set to 0 which makes a'=1/a set a', b' and c' to | |||
| * INF, causing an audible sound spike when triggered (e.g. apiration with the | |||
| * nasal register set to f=0, bw=0). | |||
| */ | |||
| // Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) | |||
| // If f == 0 then rp->a gets set to 0 which makes a'=1/a set a', b' and c' to | |||
| // INF, causing an audible sound spike when triggered (e.g. apiration with the | |||
| // nasal register set to f=0, bw=0). | |||
| if (rp->a != 0) { | |||
| /* Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) */ | |||
| // Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) | |||
| rp->a = 1.0 / rp->a; | |||
| rp->c *= -rp->a; | |||
| rp->b *= -rp->a; | |||
| @@ -847,15 +824,15 @@ static double gen_noise(double noise) | |||
| static double DBtoLIN(long dB) | |||
| { | |||
| static short amptable[88] = { | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, | |||
| 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, 32, | |||
| 35, 40, 45, 51, 57, 64, 71, 80, 90, 101, 114, 128, | |||
| 142, 159, 179, 202, 227, 256, 284, 318, 359, 405, | |||
| 455, 512, 568, 638, 719, 881, 911, 1024, 1137, 1276, | |||
| 1438, 1622, 1823, 2048, 2273, 2552, 2875, 3244, 3645, | |||
| 4096, 4547, 5104, 5751, 6488, 7291, 8192, 9093, 10207, | |||
| 11502, 12976, 14582, 16384, 18350, 20644, 23429, | |||
| 26214, 29491, 32767 | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, | |||
| 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, 32, | |||
| 35, 40, 45, 51, 57, 64, 71, 80, 90, 101, 114, 128, | |||
| 142, 159, 179, 202, 227, 256, 284, 318, 359, 405, | |||
| 455, 512, 568, 638, 719, 881, 911, 1024, 1137, 1276, | |||
| 1438, 1622, 1823, 2048, 2273, 2552, 2875, 3244, 3645, | |||
| 4096, 4547, 5104, 5751, 6488, 7291, 8192, 9093, 10207, | |||
| 11502, 12976, 14582, 16384, 18350, 20644, 23429, | |||
| 26214, 29491, 32767 | |||
| }; | |||
| if ((dB < 0) || (dB > 87)) | |||
| @@ -939,14 +916,14 @@ int Wavegen_Klatt(int resume) | |||
| if (kt_globals.nspfr > STEPSIZE) | |||
| kt_globals.nspfr = STEPSIZE; | |||
| frame_init(&kt_frame); /* get parameters for next frame of speech */ | |||
| frame_init(&kt_frame); // get parameters for next frame of speech | |||
| if (parwave(&kt_frame) == 1) | |||
| return 1; // output buffer is full | |||
| return 1; // output buffer is full | |||
| } | |||
| if (end_wave > 0) { | |||
| fade = 64; // not followd by formant synthesis | |||
| fade = 64; // not followed by formant synthesis | |||
| // fade out to avoid a click | |||
| kt_globals.fadeout = fade; | |||
| @@ -954,7 +931,7 @@ int Wavegen_Klatt(int resume) | |||
| sample_count -= fade; | |||
| kt_globals.nspfr = fade; | |||
| if (parwave(&kt_frame) == 1) | |||
| return 1; // output buffer is full | |||
| return 1; // output buffer is full | |||
| } | |||
| return 0; | |||
| @@ -979,7 +956,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
| end_wave = 0; | |||
| if (control & 2) | |||
| end_wave = 1; // fadeout at the end | |||
| end_wave = 1; // fadeout at the end | |||
| if (control & 1) { | |||
| end_wave = 1; | |||
| for (qix = wcmdq_head+1;; qix++) { | |||
| @@ -988,7 +965,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
| cmd = wcmdq[qix][0]; | |||
| if (cmd == WCMD_KLATT) { | |||
| end_wave = 0; // next wave generation is from another spectrum | |||
| end_wave = 0; // next wave generation is from another spectrum | |||
| fr3 = (frame_t *)wcmdq[qix][2]; | |||
| for (ix = 1; ix < 6; ix++) { | |||
| @@ -1001,7 +978,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
| break; | |||
| } | |||
| if ((cmd == WCMD_WAVE) || (cmd == WCMD_PAUSE)) | |||
| break; // next is not from spectrum, so continue until end of wave cycle | |||
| break; // next is not from spectrum, so continue until end of wave cycle | |||
| } | |||
| } | |||
| @@ -1047,7 +1024,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
| // nasal zero frequency | |||
| peaks[0].freq1 = fr1->klattp[KLATT_FNZ] * 2; | |||
| if (peaks[0].freq1 == 0) | |||
| peaks[0].freq1 = kt_frame.Fhz[F_NP]; // if no nasal zero, set it to same freq as nasal pole | |||
| peaks[0].freq1 = kt_frame.Fhz[F_NP]; // if no nasal zero, set it to same freq as nasal pole | |||
| peaks[0].freq = (int)peaks[0].freq1; | |||
| next = fr2->klattp[KLATT_FNZ] * 2; | |||
| @@ -1063,12 +1040,12 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v | |||
| if (fr1->frflags & FRFLAG_KLATT) { | |||
| // the frame contains additional parameters for parallel resonators | |||
| for (ix = 1; ix < 7; ix++) { | |||
| peaks[ix].bp1 = fr1->klatt_bp[ix] * 4; // parallel bandwidth | |||
| peaks[ix].bp1 = fr1->klatt_bp[ix] * 4; // parallel bandwidth | |||
| peaks[ix].bp = (int)peaks[ix].bp1; | |||
| next = fr2->klatt_bp[ix] * 4; | |||
| peaks[ix].bp_inc = ((next - peaks[ix].bp1) * STEPSIZE) / length; | |||
| peaks[ix].ap1 = fr1->klatt_ap[ix]; // parallal amplitude | |||
| peaks[ix].ap1 = fr1->klatt_ap[ix]; // parallal amplitude | |||
| peaks[ix].ap = (int)peaks[ix].ap1; | |||
| next = fr2->klatt_ap[ix]; | |||
| peaks[ix].ap_inc = ((next - peaks[ix].ap1) * STEPSIZE) / length; | |||
| @@ -1099,7 +1076,7 @@ void KlattInit() | |||
| kt_globals.synthesis_model = CASCADE_PARALLEL; | |||
| kt_globals.samrate = 22050; | |||
| kt_globals.glsource = IMPULSIVE; // IMPULSIVE, NATURAL, SAMPLED | |||
| kt_globals.glsource = IMPULSIVE; | |||
| kt_globals.scale_wav = scale_wav_tab[kt_globals.glsource]; | |||
| kt_globals.natural_samples = natural_samples; | |||
| kt_globals.num_samples = NUMBER_OF_SAMPLES; | |||
| @@ -1120,14 +1097,14 @@ void KlattInit() | |||
| kt_frame.Bhz_next[F_NZ] = bandwidth[F_NZ]; | |||
| kt_frame.F0hz10 = 1000; | |||
| kt_frame.AVdb = 59; // 59 | |||
| kt_frame.AVdb = 59; | |||
| kt_frame.ASP = 0; | |||
| kt_frame.Kopen = 40; // 40 | |||
| kt_frame.Kopen = 40; | |||
| kt_frame.Aturb = 0; | |||
| kt_frame.TLTdb = 0; | |||
| kt_frame.AF = 50; | |||
| kt_frame.Kskew = 0; | |||
| kt_frame.AB = 0; | |||
| kt_frame.AVpdb = 0; | |||
| kt_frame.Gain0 = 62; // 60 | |||
| kt_frame.Gain0 = 62; | |||
| } | |||
| @@ -59,7 +59,7 @@ struct datablock { | |||
| struct datablock *next; | |||
| int done; | |||
| int size; | |||
| char buffer[1]; /* 1 or more, dynamically allocated */ | |||
| char buffer[1]; // 1 or more, dynamically allocated | |||
| }; | |||
| static struct datablock *mbr_pending_data_head, *mbr_pending_data_tail; | |||
| @@ -296,24 +296,24 @@ static int mbrola_has_errors(void) | |||
| } | |||
| if (result == 0) { | |||
| /* EOF on stderr, assume mbrola died. */ | |||
| // EOF on stderr, assume mbrola died. | |||
| return mbrola_died(); | |||
| } | |||
| buf_ptr[result] = 0; | |||
| for (; (lf = strchr(buf_ptr, '\n')); buf_ptr = lf + 1) { | |||
| /* inhibit the reset signal messages */ | |||
| // inhibit the reset signal messages | |||
| if (strncmp(buf_ptr, "Got a reset signal", 18) == 0 || | |||
| strncmp(buf_ptr, "Input Flush Signal", 18) == 0) | |||
| continue; | |||
| *lf = 0; | |||
| log("mbrola: %s", buf_ptr); | |||
| /* is this the last line? */ | |||
| // is this the last line? | |||
| if (lf == &buf_ptr[result - 1]) { | |||
| snprintf(mbr_errorbuf, sizeof(mbr_errorbuf), | |||
| "%s", buf_ptr); | |||
| /* don't consider this fatal at this point */ | |||
| // don't consider this fatal at this point | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -369,9 +369,9 @@ static int send_to_mbrola(const char *cmd) | |||
| static int mbrola_is_idle(void) | |||
| { | |||
| char *p; | |||
| char buffer[20]; /* looking for "12345 (mbrola) S" so 20 is plenty*/ | |||
| char buffer[20]; // looking for "12345 (mbrola) S" so 20 is plenty | |||
| /* look in /proc to determine if mbrola is still running or sleeping */ | |||
| // look in /proc to determine if mbrola is still running or sleeping | |||
| if (lseek(mbr_proc_stat, 0, SEEK_SET) != 0) | |||
| return 0; | |||
| if (read(mbr_proc_stat, buffer, sizeof(buffer)) != sizeof(buffer)) | |||
| @@ -494,7 +494,7 @@ int init_MBR(const char *voice_path) | |||
| return -1; | |||
| } | |||
| /* we should actually be getting only 44 bytes */ | |||
| // we should actually be getting only 44 bytes | |||
| result = receive_from_mbrola(wavhdr, 45); | |||
| if (result != 44) { | |||
| if (result >= 0) | |||
| @@ -503,7 +503,7 @@ int init_MBR(const char *voice_path) | |||
| return -1; | |||
| } | |||
| /* parse wavhdr to get mbrola voice samplerate */ | |||
| // parse wavhdr to get mbrola voice samplerate | |||
| if (memcmp(wavhdr, "RIFF", 4) != 0 || | |||
| memcmp(wavhdr+8, "WAVEfmt ", 8) != 0) { | |||
| err("mbrola did not return a .wav header"); | |||
| @@ -512,9 +512,8 @@ int init_MBR(const char *voice_path) | |||
| } | |||
| mbr_samplerate = wavhdr[24] + (wavhdr[25]<<8) + | |||
| (wavhdr[26]<<16) + (wavhdr[27]<<24); | |||
| // log("mbrowrap: voice samplerate = %d", mbr_samplerate); | |||
| /* remember the voice path for setVolumeRatio_MBR() */ | |||
| // remember the voice path for setVolumeRatio_MBR() | |||
| if (mbr_voice_path != voice_path) { | |||
| free(mbr_voice_path); | |||
| mbr_voice_path = strdup(voice_path); | |||
| @@ -64,7 +64,7 @@ | |||
| #define M_RETROFLEX 20 | |||
| #define M_HOOK 21 | |||
| #define M_MIDDLE_DOT M_DOT_ABOVE // duplicate of M_DOT_ABOVE | |||
| #define M_MIDDLE_DOT M_DOT_ABOVE // duplicate of M_DOT_ABOVE | |||
| #define M_IMPLOSIVE M_HOOK | |||
| static int n_digit_lookup; | |||
| @@ -109,17 +109,16 @@ static ACCENTS accents_tab[] = { | |||
| #define LETTER(ch, mod1, mod2) (ch-59)+(mod1 << 6)+(mod2 << 11) | |||
| #define LIGATURE(ch1, ch2, mod1) (ch1-59)+((ch2-59) << 6)+(mod1 << 12)+M_LIGATURE | |||
| #define L_ALPHA 60 // U+3B1 | |||
| #define L_SCHWA 61 // U+259 | |||
| #define L_OPEN_E 62 // U+25B | |||
| #define L_GAMMA 63 // U+3B3 | |||
| #define L_IOTA 64 // U+3B9 | |||
| #define L_OE 65 // U+153 | |||
| #define L_OMEGA 66 // U+3C9 | |||
| #define L_ALPHA 60 // U+3B1 | |||
| #define L_SCHWA 61 // U+259 | |||
| #define L_OPEN_E 62 // U+25B | |||
| #define L_GAMMA 63 // U+3B3 | |||
| #define L_IOTA 64 // U+3B9 | |||
| #define L_OE 65 // U+153 | |||
| #define L_OMEGA 66 // U+3C9 | |||
| #define L_PHI 67 // U+3C6 | |||
| #define L_ESH 68 // U+283 | |||
| #define L_PHI 67 // U+3C6 | |||
| #define L_ESH 68 // U+283 | |||
| #define L_UPSILON 69 // U+3C5 | |||
| #define L_EZH 70 // U+292 | |||
| #define L_GLOTTAL 71 // U+294 | |||
| @@ -127,13 +126,14 @@ static ACCENTS accents_tab[] = { | |||
| #define L_RLONG 73 // U+27C | |||
| static const short non_ascii_tab[] = { | |||
| 0, 0x3b1, 0x259, 0x25b, 0x3b3, 0x3b9, 0x153, 0x3c9, | |||
| 0, | |||
| 0x3b1, 0x259, 0x25b, 0x3b3, 0x3b9, 0x153, 0x3c9, | |||
| 0x3c6, 0x283, 0x3c5, 0x292, 0x294, 0x27e, 0x27c | |||
| }; | |||
| // characters U+00e0 to U+017f | |||
| static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('a', M_GRAVE, 0), // U+00e0 | |||
| LETTER('a', M_GRAVE, 0), // U+00e0 | |||
| LETTER('a', M_ACUTE, 0), | |||
| LETTER('a', M_CIRCUMFLEX, 0), | |||
| LETTER('a', M_TILDE, 0), | |||
| @@ -149,23 +149,23 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('i', M_ACUTE, 0), | |||
| LETTER('i', M_CIRCUMFLEX, 0), | |||
| LETTER('i', M_DIAERESIS, 0), | |||
| LETTER('d', M_NAME, 0), // eth // U+00f0 | |||
| LETTER('d', M_NAME, 0), // eth U+00f0 | |||
| LETTER('n', M_TILDE, 0), | |||
| LETTER('o', M_GRAVE, 0), | |||
| LETTER('o', M_ACUTE, 0), | |||
| LETTER('o', M_CIRCUMFLEX, 0), | |||
| LETTER('o', M_TILDE, 0), | |||
| LETTER('o', M_DIAERESIS, 0), | |||
| 0, // division sign | |||
| 0, // division sign | |||
| LETTER('o', M_STROKE, 0), | |||
| LETTER('u', M_GRAVE, 0), | |||
| LETTER('u', M_ACUTE, 0), | |||
| LETTER('u', M_CIRCUMFLEX, 0), | |||
| LETTER('u', M_DIAERESIS, 0), | |||
| LETTER('y', M_ACUTE, 0), | |||
| LETTER('t', M_NAME, 0), // thorn | |||
| LETTER('t', M_NAME, 0), // thorn | |||
| LETTER('y', M_DIAERESIS, 0), | |||
| CAPITAL, // U+0100 | |||
| CAPITAL, // U+0100 | |||
| LETTER('a', M_MACRON, 0), | |||
| CAPITAL, | |||
| LETTER('a', M_BREVE, 0), | |||
| @@ -181,7 +181,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('c', M_CARON, 0), | |||
| CAPITAL, | |||
| LETTER('d', M_CARON, 0), | |||
| CAPITAL, // U+0110 | |||
| CAPITAL, // U+0110 | |||
| LETTER('d', M_STROKE, 0), | |||
| CAPITAL, | |||
| LETTER('e', M_MACRON, 0), | |||
| @@ -197,7 +197,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('g', M_CIRCUMFLEX, 0), | |||
| CAPITAL, | |||
| LETTER('g', M_BREVE, 0), | |||
| CAPITAL, // U+0120 | |||
| CAPITAL, // U+0120 | |||
| LETTER('g', M_DOT_ABOVE, 0), | |||
| CAPITAL, | |||
| LETTER('g', M_CEDILLA, 0), | |||
| @@ -213,7 +213,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('i', M_BREVE, 0), | |||
| CAPITAL, | |||
| LETTER('i', M_OGONEK, 0), | |||
| CAPITAL, // U+0130 | |||
| CAPITAL, // U+0130 | |||
| LETTER('i', M_NAME, 0), // dotless i | |||
| CAPITAL, | |||
| LIGATURE('i', 'j', 0), | |||
| @@ -221,7 +221,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('j', M_CIRCUMFLEX, 0), | |||
| CAPITAL, | |||
| LETTER('k', M_CEDILLA, 0), | |||
| LETTER('k', M_NAME, 0), // kra | |||
| LETTER('k', M_NAME, 0), // kra | |||
| CAPITAL, | |||
| LETTER('l', M_ACUTE, 0), | |||
| CAPITAL, | |||
| @@ -229,7 +229,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
| CAPITAL, | |||
| LETTER('l', M_CARON, 0), | |||
| CAPITAL, | |||
| LETTER('l', M_MIDDLE_DOT, 0), // U+0140 | |||
| LETTER('l', M_MIDDLE_DOT, 0), // U+0140 | |||
| CAPITAL, | |||
| LETTER('l', M_STROKE, 0), | |||
| CAPITAL, | |||
| @@ -238,14 +238,14 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('n', M_CEDILLA, 0), | |||
| CAPITAL, | |||
| LETTER('n', M_CARON, 0), | |||
| LETTER('n', M_NAME, 0), // apostrophe n | |||
| LETTER('n', M_NAME, 0), // apostrophe n | |||
| CAPITAL, | |||
| LETTER('n', M_NAME, 0), // eng | |||
| LETTER('n', M_NAME, 0), // eng | |||
| CAPITAL, | |||
| LETTER('o', M_MACRON, 0), | |||
| CAPITAL, | |||
| LETTER('o', M_BREVE, 0), | |||
| CAPITAL, // U+0150 | |||
| CAPITAL, // U+0150 | |||
| LETTER('o', M_DOUBLE_ACUTE, 0), | |||
| CAPITAL, | |||
| LIGATURE('o', 'e', 0), | |||
| @@ -261,7 +261,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('s', M_CIRCUMFLEX, 0), | |||
| CAPITAL, | |||
| LETTER('s', M_CEDILLA, 0), | |||
| CAPITAL, // U+0160 | |||
| CAPITAL, // U+0160 | |||
| LETTER('s', M_CARON, 0), | |||
| CAPITAL, | |||
| LETTER('t', M_CEDILLA, 0), | |||
| @@ -277,7 +277,7 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('u', M_BREVE, 0), | |||
| CAPITAL, | |||
| LETTER('u', M_RING, 0), | |||
| CAPITAL, // U+0170 | |||
| CAPITAL, // U+0170 | |||
| LETTER('u', M_DOUBLE_ACUTE, 0), | |||
| CAPITAL, | |||
| LETTER('u', M_OGONEK, 0), | |||
| @@ -285,43 +285,43 @@ static const unsigned short letter_accents_0e0[] = { | |||
| LETTER('w', M_CIRCUMFLEX, 0), | |||
| CAPITAL, | |||
| LETTER('y', M_CIRCUMFLEX, 0), | |||
| CAPITAL, // Y-DIAERESIS | |||
| CAPITAL, // Y-DIAERESIS | |||
| CAPITAL, | |||
| LETTER('z', M_ACUTE, 0), | |||
| CAPITAL, | |||
| LETTER('z', M_DOT_ABOVE, 0), | |||
| CAPITAL, | |||
| LETTER('z', M_CARON, 0), | |||
| LETTER('s', M_NAME, 0), // long-s // U+17f | |||
| LETTER('s', M_NAME, 0), // long-s U+17f | |||
| }; | |||
| // characters U+0250 to U+029F | |||
| static const unsigned short letter_accents_250[] = { | |||
| LETTER('a', M_TURNED, 0), // U+250 | |||
| LETTER('a', M_TURNED, 0), // U+250 | |||
| LETTER(L_ALPHA, 0, 0), | |||
| LETTER(L_ALPHA, M_TURNED, 0), | |||
| LETTER('b', M_IMPLOSIVE, 0), | |||
| 0, // open-o | |||
| 0, // open-o | |||
| LETTER('c', M_CURL, 0), | |||
| LETTER('d', M_RETROFLEX, 0), | |||
| LETTER('d', M_IMPLOSIVE, 0), | |||
| LETTER('e', M_REVERSED, 0), // U+258 | |||
| 0, // schwa | |||
| LETTER('e', M_REVERSED, 0), // U+258 | |||
| 0, // schwa | |||
| LETTER(L_SCHWA, M_HOOK, 0), | |||
| 0, // open-e | |||
| 0, // open-e | |||
| LETTER(L_OPEN_E, M_REVERSED, 0), | |||
| LETTER(L_OPEN_E, M_HOOK, M_REVERSED), | |||
| 0, | |||
| LETTER('j', M_BAR, 0), | |||
| LETTER('g', M_IMPLOSIVE, 0), // U+260 | |||
| LETTER('g', M_IMPLOSIVE, 0), // U+260 | |||
| LETTER('g', 0, 0), | |||
| LETTER('g', M_SMALLCAP, 0), | |||
| LETTER(L_GAMMA, 0, 0), | |||
| 0, // ramshorn | |||
| 0, // ramshorn | |||
| LETTER('h', M_TURNED, 0), | |||
| LETTER('h', M_HOOK, 0), | |||
| 0, | |||
| LETTER('i', M_BAR, 0), // U+268 | |||
| LETTER('i', M_BAR, 0), // U+268 | |||
| LETTER(L_IOTA, 0, 0), | |||
| LETTER('i', M_SMALLCAP, 0), | |||
| LETTER('l', M_TILDE, 0), | |||
| @@ -337,23 +337,23 @@ static const unsigned short letter_accents_250[] = { | |||
| LETTER('o', M_BAR, 0), | |||
| LIGATURE('o', 'e', M_SMALLCAP), | |||
| 0, | |||
| LETTER(L_PHI, 0, 0), // U+278 | |||
| LETTER(L_PHI, 0, 0), // U+278 | |||
| LETTER('r', M_TURNED, 0), | |||
| LETTER(L_RLONG, M_TURNED, 0), | |||
| LETTER('r', M_RETROFLEX, M_TURNED), | |||
| 0, | |||
| LETTER('r', M_RETROFLEX, 0), | |||
| 0, // r-tap | |||
| 0, // r-tap | |||
| LETTER(L_RTAP, M_REVERSED, 0), | |||
| LETTER('r', M_SMALLCAP, 0), // U+280 | |||
| LETTER('r', M_SMALLCAP, 0), // U+280 | |||
| LETTER('r', M_TURNED, M_SMALLCAP), | |||
| LETTER('s', M_RETROFLEX, 0), | |||
| 0, // esh | |||
| 0, // esh | |||
| LETTER('j', M_HOOK, 0), | |||
| LETTER(L_ESH, M_REVERSED, 0), | |||
| LETTER(L_ESH, M_CURL, 0), | |||
| LETTER('t', M_TURNED, 0), | |||
| LETTER('t', M_RETROFLEX, 0), // U+288 | |||
| LETTER('t', M_RETROFLEX, 0), // U+288 | |||
| LETTER('u', M_BAR, 0), | |||
| LETTER(L_UPSILON, 0, 0), | |||
| LETTER('v', M_HOOK, 0), | |||
| @@ -361,15 +361,15 @@ static const unsigned short letter_accents_250[] = { | |||
| LETTER('w', M_TURNED, 0), | |||
| LETTER('y', M_TURNED, 0), | |||
| LETTER('y', M_SMALLCAP, 0), | |||
| LETTER('z', M_RETROFLEX, 0), // U+290 | |||
| LETTER('z', M_RETROFLEX, 0), // U+290 | |||
| LETTER('z', M_CURL, 0), | |||
| 0, // ezh | |||
| 0, // ezh | |||
| LETTER(L_EZH, M_CURL, 0), | |||
| 0, // glottal stop | |||
| 0, // glottal stop | |||
| LETTER(L_GLOTTAL, M_REVERSED, 0), | |||
| LETTER(L_GLOTTAL, M_TURNED, 0), | |||
| 0, | |||
| 0, // bilabial click // U+298 | |||
| 0, // bilabial click U+298 | |||
| LETTER('b', M_SMALLCAP, 0), | |||
| 0, | |||
| LETTER('g', M_IMPLOSIVE, M_SMALLCAP), | |||
| @@ -377,14 +377,14 @@ static const unsigned short letter_accents_250[] = { | |||
| LETTER('j', M_CURL, 0), | |||
| LETTER('k', M_TURNED, 0), | |||
| LETTER('l', M_SMALLCAP, 0), | |||
| LETTER('q', M_HOOK, 0), // U+2a0 | |||
| LETTER('q', M_HOOK, 0), // U+2a0 | |||
| LETTER(L_GLOTTAL, M_STROKE, 0), | |||
| LETTER(L_GLOTTAL, M_STROKE, M_REVERSED), | |||
| LIGATURE('d', 'z', 0), | |||
| 0, // dezh | |||
| 0, // dezh | |||
| LIGATURE('d', 'z', M_CURL), | |||
| LIGATURE('t', 's', 0), | |||
| 0, // tesh | |||
| 0, // tesh | |||
| LIGATURE('t', 's', M_CURL), | |||
| }; | |||
| @@ -476,7 +476,7 @@ void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf) | |||
| void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1, int control) | |||
| { | |||
| // control, bit 0: not the first letter of a word | |||
| // control, bit 0: not the first letter of a word | |||
| int len; | |||
| static char single_letter[10] = { 0, 0 }; | |||
| @@ -494,18 +494,18 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b | |||
| single_letter[1] = '_'; | |||
| if (Lookup(tr, &single_letter[1], ph_buf3) != 0) | |||
| return; // the character is specified as _* so ignore it when speaking normal text | |||
| return; // the character is specified as _* so ignore it when speaking normal text | |||
| // check whether this character is specified for English | |||
| if (tr->translator_name == L('e', 'n')) | |||
| return; // we are already using English | |||
| return; // we are already using English | |||
| SetTranslator2("en"); | |||
| if (Lookup(translator2, &single_letter[2], ph_buf3) != 0) { | |||
| // yes, switch to English and re-translate the word | |||
| sprintf(ph_buf1, "%c", phonSWITCH); | |||
| } | |||
| SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table | |||
| SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table | |||
| return; | |||
| } | |||
| @@ -518,7 +518,7 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b | |||
| if (next_byte != ' ') | |||
| next_byte = RULE_SPELLING; | |||
| single_letter[3+len] = next_byte; // follow by space-space if the end of the word, or space-31 | |||
| single_letter[3+len] = next_byte; // follow by space-space if the end of the word, or space-31 | |||
| single_letter[1] = '_'; | |||
| @@ -543,31 +543,31 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b | |||
| SetWordStress(tr, ph_buf1, dict_flags, -1, control & 1); | |||
| } | |||
| // unicode ranges for non-ascii digits 0-9 | |||
| // unicode ranges for non-ascii digits 0-9 (these must be in ascending order) | |||
| static const int number_ranges[] = { | |||
| 0x660, 0x6f0, // arabic | |||
| 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6, 0xc66, 0xce6, 0xd66, // indic | |||
| 0x660, 0x6f0, // arabic | |||
| 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6, 0xc66, 0xce6, 0xd66, // indic | |||
| 0xe50, 0xed0, 0xf20, 0x1040, 0x1090, | |||
| 0 | |||
| }; // these must be in ascending order | |||
| }; | |||
| int NonAsciiNumber(int letter) | |||
| { | |||
| // Change non-ascii digit into ascii digit '0' to '9', (or -1 if not) | |||
| // Change non-ascii digit into ascii digit '0' to '9', (or -1 if not) | |||
| const int *p; | |||
| int base; | |||
| for (p = number_ranges; (base = *p) != 0; p++) { | |||
| if (letter < base) | |||
| break; // not found | |||
| break; // not found | |||
| if (letter < (base+10)) | |||
| return letter-base+'0'; | |||
| } | |||
| return -1; | |||
| } | |||
| #define L_SUB 0x4000 // subscript | |||
| #define L_SUP 0x8000 // superscript | |||
| #define L_SUB 0x4000 // subscript | |||
| #define L_SUP 0x8000 // superscript | |||
| static const char *modifiers[] = { NULL, "_sub", "_sup", NULL }; | |||
| @@ -638,11 +638,19 @@ static unsigned short derived_letters[] = { | |||
| 0, 0 | |||
| }; | |||
| static const char *hex_letters[] = { "'e:j", "b'i:", "s'i:", "d'i:", "'i:", "'ef" }; // names, using phonemes available to all languages | |||
| // names, using phonemes available to all languages | |||
| static const char *hex_letters[] = { | |||
| "'e:j", | |||
| "b'i:", | |||
| "s'i:", | |||
| "d'i:", | |||
| "'i:", | |||
| "'ef" | |||
| }; | |||
| int IsSuperscript(int letter) | |||
| { | |||
| // is this a subscript or superscript letter ? | |||
| // is this a subscript or superscript letter ? | |||
| int ix; | |||
| int c; | |||
| @@ -657,11 +665,11 @@ int IsSuperscript(int letter) | |||
| int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
| { | |||
| // get pronunciation for an isolated letter | |||
| // return number of bytes used by the letter | |||
| // control bit 0: a non-initial letter in a word | |||
| // bit 1: say 'capital' | |||
| // bit 2: say character code for unknown letters | |||
| // get pronunciation for an isolated letter | |||
| // return number of bytes used by the letter | |||
| // control bit 0: a non-initial letter in a word | |||
| // bit 1: say 'capital' | |||
| // bit 2: say character code for unknown letters | |||
| int n_bytes; | |||
| int letter; | |||
| @@ -693,7 +701,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
| n_bytes = utf8_in(&letter, word); | |||
| if ((letter & 0xfff00) == 0x0e000) | |||
| letter &= 0xff; // uncode private usage area | |||
| letter &= 0xff; // uncode private usage area | |||
| if (control & 2) { | |||
| // include CAPITAL information | |||
| @@ -711,7 +719,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
| // don't say "superscript" during normal text reading | |||
| Lookup(tr, modifier, capital); | |||
| if (capital[0] == 0) { | |||
| capital[2] = SetTranslator2("en"); // overwrites previous contents of translator2 | |||
| capital[2] = SetTranslator2("en"); // overwrites previous contents of translator2 | |||
| Lookup(translator2, modifier, &capital[3]); | |||
| if (capital[3] != 0) { | |||
| capital[0] = phonPAUSE; | |||
| @@ -755,7 +763,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
| ph_buf2[0] = 0; | |||
| if (Lookup(translator, alphabet->name, ph_alphabet) == 0) { // the original language for the current voice | |||
| // Can't find the local name for this alphabet, use the English name | |||
| ph_alphabet[2] = SetTranslator2("en"); // overwrites previous contents of translator2 | |||
| ph_alphabet[2] = SetTranslator2("en"); // overwrites previous contents of translator2 | |||
| Lookup(translator2, alphabet->name, ph_buf2); | |||
| } else if (translator != tr) { | |||
| phontab_1 = tr->phoneme_tab_ix; | |||
| @@ -777,7 +785,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
| } | |||
| } | |||
| // caution: SetWordStress() etc don't expect phonSWITCH + phoneme table number | |||
| // caution: SetWordStress() etc don't expect phonSWITCH + phoneme table number | |||
| if (ph_buf[0] == 0) { | |||
| if ((al_offset != 0) && (al_offset == translator->langopts.alt_alphabet)) | |||
| @@ -805,8 +813,8 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
| if ((initial = (code/28)/21) != 11) { | |||
| p3 += utf8_out(initial + 0x1100, p3); | |||
| } | |||
| utf8_out(((code/28) % 21) + 0x1161, p3); // medial | |||
| utf8_out((code % 28) + 0x11a7, &p3[3]); // final | |||
| utf8_out(((code/28) % 21) + 0x1161, p3); // medial | |||
| utf8_out((code % 28) + 0x11a7, &p3[3]); // final | |||
| p3[6] = ' '; | |||
| p3[7] = 0; | |||
| ph_buf[3] = 0; | |||
| @@ -821,13 +829,13 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
| LookupLetter(translator2, letter, word[n_bytes], &ph_buf[3], control & 1); | |||
| } | |||
| SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table | |||
| SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table | |||
| if (ph_buf[3] != 0) { | |||
| ph_buf[0] = phonPAUSE; | |||
| ph_buf[1] = phonSWITCH; | |||
| len = strlen(&ph_buf[3]) + 3; | |||
| ph_buf[len] = phonSWITCH; // switch back | |||
| ph_buf[len] = phonSWITCH; // switch back | |||
| ph_buf[len+1] = tr->phoneme_tab_ix; | |||
| ph_buf[len+2] = 0; | |||
| } | |||
| @@ -890,16 +898,15 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | |||
| if (tr->langopts.accents & 2) // 'capital' before or after the word ? | |||
| sprintf(ph_buf2, "%c%s%s%s", 0xff, ph_alphabet, ph_buf, capital); | |||
| else | |||
| sprintf(ph_buf2, "%c%s%s%s", 0xff, ph_alphabet, capital, ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress() | |||
| if ((len + strlen(ph_buf2)) < N_WORD_PHONEMES) { | |||
| sprintf(ph_buf2, "%c%s%s%s", 0xff, ph_alphabet, capital, ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress() | |||
| if ((len + strlen(ph_buf2)) < N_WORD_PHONEMES) | |||
| strcpy(&phonemes[len], ph_buf2); | |||
| } | |||
| return n_bytes; | |||
| } | |||
| void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) | |||
| { | |||
| // Individual letter names, reduce the stress of some. | |||
| // Individual letter names, reduce the stress of some. | |||
| int ix; | |||
| unsigned int c; | |||
| int n_stress = 0; | |||
| @@ -927,17 +934,17 @@ void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) | |||
| } else { | |||
| if (count != n_stress) { | |||
| if (((count % 3) != 0) || (count == n_stress-1)) | |||
| c = phonSTRESS_3; // reduce to secondary stress | |||
| c = phonSTRESS_3; // reduce to secondary stress | |||
| } | |||
| } | |||
| } else if (c == 0xff) { | |||
| if ((control < 2) || (ix == 0)) | |||
| continue; // don't insert pauses | |||
| continue; // don't insert pauses | |||
| if (control == 4) | |||
| c = phonPAUSE; // pause after each character | |||
| c = phonPAUSE; // pause after each character | |||
| if (((count % 3) == 0) || (control > 2)) | |||
| c = phonPAUSE_NOLINK; // pause following a primary stress | |||
| c = phonPAUSE_NOLINK; // pause following a primary stress | |||
| else | |||
| c = phonPAUSE_VSHORT; | |||
| } | |||
| @@ -981,14 +988,14 @@ static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB | |||
| nextflags = TranslateWord(tr, &word_end[2], 0, NULL, NULL); | |||
| if ((tr->prev_dict_flags[0] & FLAG_ALT_TRANS) && ((c2 == 0) || (wtab[0].flags & FLAG_COMMA_AFTER) || iswdigit(c2))) | |||
| ordinal = 0; // TEST 09.02.10 | |||
| ordinal = 0; // TEST 09.02.10 | |||
| if (nextflags & FLAG_ALT_TRANS) | |||
| ordinal = 0; | |||
| if (nextflags & FLAG_ALT3_TRANS) { | |||
| if (word[-2] == '-') | |||
| ordinal = 0; // eg. december 2-5. között | |||
| ordinal = 0; // e.g. december 2-5. között | |||
| if (tr->prev_dict_flags[0] & (FLAG_ALT_TRANS | FLAG_ALT3_TRANS)) | |||
| ordinal = 0x22; | |||
| @@ -1002,14 +1009,14 @@ static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB | |||
| static int hu_number_e(const char *word, int thousandplex, int value) | |||
| { | |||
| // lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett | |||
| // lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett | |||
| if ((word[0] == 'a') || (word[0] == 'e')) { | |||
| if ((word[1] == ' ') || (word[1] == 'z') || ((word[1] == 't') && (word[2] == 't'))) | |||
| return 0; | |||
| if (((thousandplex == 1) || ((value % 1000) == 0)) && (word[1] == 'l')) | |||
| return 0; // 1000-el | |||
| return 0; // 1000-el | |||
| return 1; | |||
| } | |||
| @@ -1044,13 +1051,13 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) | |||
| flags[1] = 0; | |||
| if (((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && !(wtab[0].flags & FLAG_ALL_UPPER)) || IsDigit09(word[-2])) | |||
| return 0; // not '2xx' | |||
| return 0; // not '2xx' | |||
| if (word[1] == ' ') { | |||
| if ((tr->langopts.numbers & (NUM_ROMAN_CAPITALS | NUM_ROMAN_ORDINAL | NUM_ORDINAL_DOT)) && (wtab[0].flags & FLAG_HAS_DOT)) { | |||
| // allow single letter Roman ordinal followed by dot. | |||
| } else | |||
| return 0; // only one letter, don't speak as a Roman Number | |||
| return 0; // only one letter, don't speak as a Roman Number | |||
| } | |||
| word_start = word; | |||
| @@ -1084,7 +1091,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) | |||
| } | |||
| if (IsDigit09(word[0])) | |||
| return 0; // eg. 'xx2' | |||
| return 0; // e.g. 'xx2' | |||
| acc += prev; | |||
| if (acc < tr->langopts.min_roman) | |||
| @@ -1093,7 +1100,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) | |||
| if (acc > tr->langopts.max_roman) | |||
| return 0; | |||
| Lookup(tr, "_roman", ph_roman); // precede by "roman" if _rom is defined in *_list | |||
| Lookup(tr, "_roman", ph_roman); // precede by "roman" if _rom is defined in *_list | |||
| p = &ph_out[0]; | |||
| if ((tr->langopts.numbers & NUM_ROMAN_AFTER) == 0) { | |||
| @@ -1145,25 +1152,25 @@ static const char *M_Variant(int value) | |||
| switch ((translator->langopts.numbers2 >> 6) & 0x7) | |||
| { | |||
| case 1: // lang=ru use singular for xx1 except for x11 | |||
| case 1: // lang=ru use singular for xx1 except for x11 | |||
| if ((teens == 0) && ((value % 10) == 1)) | |||
| return "1M"; | |||
| break; | |||
| case 2: // lang=cs,sk | |||
| case 2: // lang=cs,sk | |||
| if ((value >= 2) && (value <= 4)) | |||
| return "0MA"; | |||
| break; | |||
| case 3: // lang=pl | |||
| case 3: // lang=pl | |||
| if ((teens == 0) && (((value % 10) >= 2) && ((value % 10) <= 4))) | |||
| return "0MA"; | |||
| break; | |||
| case 4: // lang=lt | |||
| case 4: // lang=lt | |||
| if ((teens == 1) || ((value % 10) == 0)) | |||
| return "0MB"; | |||
| if ((value % 10) == 1) | |||
| return "0MA"; | |||
| break; | |||
| case 5: // lang=bs,hr,sr | |||
| case 5: // lang=bs,hr,sr | |||
| if (teens == 0) { | |||
| if ((value % 10) == 1) | |||
| return "1M"; | |||
| @@ -1177,7 +1184,7 @@ static const char *M_Variant(int value) | |||
| static int LookupThousands(Translator *tr, int value, int thousandplex, int thousands_exact, char *ph_out) | |||
| { | |||
| // thousands_exact: bit 0 no hundreds,tens,or units, bit 1 ordinal numberr | |||
| // thousands_exact: bit 0 no hundreds,tens,or units, bit 1 ordinal numberr | |||
| int found; | |||
| int found_value = 0; | |||
| char string[12]; | |||
| @@ -1266,15 +1273,15 @@ static int LookupThousands(Translator *tr, int value, int thousandplex, int thou | |||
| static int LookupNum2(Translator *tr, int value, int thousandplex, const int control, char *ph_out) | |||
| { | |||
| // Lookup a 2 digit number | |||
| // control bit 0: ordinal number | |||
| // control bit 1: final tens and units (not number of thousands) (use special form of '1', LANG=de "eins") | |||
| // control bit 2: tens and units only, no higher digits | |||
| // control bit 3: use feminine form of '2' (for thousands | |||
| // control bit 4: speak zero tens | |||
| // control bit 5: variant of ordinal number (lang=hu) | |||
| // bit 8 followed by decimal fraction | |||
| // bit 9: use #f form for both tens and units (lang=ml) | |||
| // Lookup a 2 digit number | |||
| // control bit 0: ordinal number | |||
| // control bit 1: final tens and units (not number of thousands) (use special form of '1', LANG=de "eins") | |||
| // control bit 2: tens and units only, no higher digits | |||
| // control bit 3: use feminine form of '2' (for thousands | |||
| // control bit 4: speak zero tens | |||
| // control bit 5: variant of ordinal number (lang=hu) | |||
| // bit 8 followed by decimal fraction | |||
| // bit 9: use #f form for both tens and units (lang=ml) | |||
| int found; | |||
| int ix; | |||
| @@ -1285,7 +1292,7 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
| int found_ordinal = 0; | |||
| int next_phtype; | |||
| int ord_type = 'o'; | |||
| char string[12]; // for looking up entries in *_list | |||
| char string[12]; // for looking up entries in *_list | |||
| char ph_ordinal[20]; | |||
| char ph_tens[50]; | |||
| char ph_digits[50]; | |||
| @@ -1322,10 +1329,10 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
| strcpy(ph_ordinal, ph_ordinal2); | |||
| if (control & 4) { | |||
| sprintf(string, "_%d%cx", value, ord_type); // LANG=hu, special word for 1. 2. when there are no higher digits | |||
| sprintf(string, "_%d%cx", value, ord_type); // LANG=hu, special word for 1. 2. when there are no higher digits | |||
| if ((found = Lookup(tr, string, ph_digits)) != 0) { | |||
| if (ph_ordinal2x[0] != 0) | |||
| strcpy(ph_ordinal, ph_ordinal2x); // alternate pronunciation (lang=an) | |||
| strcpy(ph_ordinal, ph_ordinal2x); // alternate pronunciation (lang=an) | |||
| } | |||
| } | |||
| if (found == 0) { | |||
| @@ -1346,7 +1353,7 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
| } else { | |||
| // followed by hundreds or thousands etc | |||
| if ((tr->langopts.numbers2 & NUM2_ORDINAL_AND_THOUSANDS) && (thousandplex <= 1)) | |||
| sprintf(string, "_%do", value); // LANG=TA | |||
| sprintf(string, "_%do", value); // LANG=TA | |||
| else | |||
| sprintf(string, "_%da", value); | |||
| found = Lookup(tr, string, ph_digits); | |||
| @@ -1369,9 +1376,9 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
| // speak leading zero | |||
| Lookup(tr, "_0", ph_tens); | |||
| } else { | |||
| if (found) { | |||
| if (found) | |||
| ph_tens[0] = 0; | |||
| } else { | |||
| else { | |||
| if (is_ordinal) { | |||
| sprintf(string, "_%dX%c", tens, ord_type); | |||
| if (Lookup(tr, string, ph_tens) != 0) { | |||
| @@ -1416,9 +1423,8 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
| if ((is_ordinal) && ((tr->langopts.numbers & NUM_SWAP_TENS) == 0)) { | |||
| // ordinal | |||
| sprintf(string, "_%d%c", units, ord_type); | |||
| if ((found = Lookup(tr, string, ph_digits)) != 0) { | |||
| if ((found = Lookup(tr, string, ph_digits)) != 0) | |||
| found_ordinal = 1; | |||
| } | |||
| } | |||
| if (found == 0) { | |||
| if ((number_control & 1) && (control & 2)) { | |||
| @@ -1511,11 +1517,12 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con | |||
| static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int control) | |||
| { | |||
| // Translate a 3 digit number | |||
| // control bit 0, previous thousands | |||
| // bit 1, ordinal number | |||
| // bit 5 variant form of ordinal number | |||
| // bit 8 followed by decimal fraction | |||
| // Translate a 3 digit number | |||
| // control bit 0, previous thousands | |||
| // bit 1, ordinal number | |||
| // bit 5 variant form of ordinal number | |||
| // bit 8 followed by decimal fraction | |||
| int found; | |||
| int hundreds; | |||
| int tensunits; | |||
| @@ -1526,7 +1533,7 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
| int tplex; | |||
| int say_zero_hundred = 0; | |||
| int say_one_hundred; | |||
| char string[12]; // for looking up entries in **_list | |||
| char string[12]; // for looking up entries in **_list | |||
| char buf1[100]; | |||
| char buf2[100]; | |||
| char ph_100[20]; | |||
| @@ -1544,9 +1551,8 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
| ph_thousands[0] = 0; | |||
| ph_thousand_and[0] = 0; | |||
| if ((tr->langopts.numbers & NUM_ZERO_HUNDRED) && ((control & 1) || (hundreds >= 10))) { | |||
| say_zero_hundred = 1; // lang=vi | |||
| } | |||
| if ((tr->langopts.numbers & NUM_ZERO_HUNDRED) && ((control & 1) || (hundreds >= 10))) | |||
| say_zero_hundred = 1; // lang=vi | |||
| if ((hundreds > 0) || say_zero_hundred) { | |||
| found = 0; | |||
| @@ -1579,14 +1585,14 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
| if (LookupThousands(tr, hundreds / 10, tplex, exact | ordinal, ph_10T) == 0) { | |||
| x = 0; | |||
| if (tr->langopts.numbers2 & (1 << tplex)) | |||
| x = 8; // use variant (feminine) for before thousands and millions | |||
| x = 8; // use variant (feminine) for before thousands and millions | |||
| if (tr->translator_name == L('m', 'l')) | |||
| x = 0x208; | |||
| LookupNum2(tr, hundreds/10, thousandplex, x, ph_digits); | |||
| } | |||
| if (tr->langopts.numbers2 & 0x200) | |||
| sprintf(ph_thousands, "%s%c%s%c", ph_10T, phonEND_WORD, ph_digits, phonEND_WORD); // say "thousands" before its number, not after | |||
| sprintf(ph_thousands, "%s%c%s%c", ph_10T, phonEND_WORD, ph_digits, phonEND_WORD); // say "thousands" before its number, not after | |||
| else | |||
| sprintf(ph_thousands, "%s%c%s%c", ph_digits, phonEND_WORD, ph_10T, phonEND_WORD); | |||
| @@ -1674,18 +1680,18 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
| if ((tensunits != 0) || (suppress_null == 0)) { | |||
| x = 0; | |||
| if (thousandplex == 0) { | |||
| x = 2; // allow "eins" for 1 rather than "ein" | |||
| x = 2; // allow "eins" for 1 rather than "ein" | |||
| if (ordinal) | |||
| x = 3; // ordinal number | |||
| x = 3; // ordinal number | |||
| if ((value < 100) && !(control & 1)) | |||
| x |= 4; // tens and units only, no higher digits | |||
| x |= 4; // tens and units only, no higher digits | |||
| if (ordinal & 0x20) | |||
| x |= 0x20; // variant form of ordinal number | |||
| x |= 0x20; // variant form of ordinal number | |||
| } else if (tr->langopts.numbers2 & (1 << thousandplex)) | |||
| x = 8; // use variant (feminine) for before thousands and millions | |||
| x = 8; // use variant (feminine) for before thousands and millions | |||
| if ((tr->translator_name == L('m', 'l')) && (thousandplex == 1)) | |||
| x |= 0x208; // use #f form for both tens and units | |||
| x |= 0x208; // use #f form for both tens and units | |||
| if ((tr->langopts.numbers2 & NUM2_ZERO_TENS) && ((control & 1) || (hundreds > 0))) { | |||
| // LANG=zh, | |||
| @@ -1694,13 +1700,13 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
| if (LookupNum2(tr, tensunits, thousandplex, x | (control & 0x100), buf2) != 0) { | |||
| if (tr->langopts.numbers & NUM_SINGLE_AND) | |||
| ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units | |||
| ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units | |||
| } | |||
| } else { | |||
| if (ph_ordinal2[0] != 0) { | |||
| ix = strlen(buf1); | |||
| if ((ix > 0) && (buf1[ix-1] == phonPAUSE_SHORT)) | |||
| buf1[ix-1] = 0; // remove pause before addding ordinal suffix | |||
| buf1[ix-1] = 0; // remove pause before addding ordinal suffix | |||
| strcpy(buf2, ph_ordinal2); | |||
| } | |||
| } | |||
| @@ -1712,7 +1718,7 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null | |||
| bool CheckThousandsGroup(char *word, int group_len) | |||
| { | |||
| // Is this a group of 3 digits which looks like a thousands group? | |||
| // Is this a group of 3 digits which looks like a thousands group? | |||
| int ix; | |||
| if (IsDigit09(word[group_len]) || IsDigit09(-1)) | |||
| @@ -1727,9 +1733,9 @@ bool CheckThousandsGroup(char *word, int group_len) | |||
| static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | |||
| { | |||
| // Number translation with various options | |||
| // the "word" may be up to 4 digits | |||
| // "words" of 3 digits may be preceded by another number "word" for thousands or millions | |||
| // Number translation with various options | |||
| // the "word" may be up to 4 digits | |||
| // "words" of 3 digits may be preceded by another number "word" for thousands or millions | |||
| int n_digits; | |||
| int value; | |||
| @@ -1752,13 +1758,13 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| int group_len; | |||
| int len; | |||
| char *p; | |||
| char string[32]; // for looking up entries in **_list | |||
| char string[32]; // for looking up entries in **_list | |||
| char buf1[100]; | |||
| char ph_append[50]; | |||
| char ph_buf[200]; | |||
| char ph_buf2[50]; | |||
| char ph_zeros[50]; | |||
| char suffix[30]; // string[] must be long enough for sizeof(suffix)+2 | |||
| char suffix[30]; // string[] must be long enough for sizeof(suffix)+2 | |||
| char buf_digit_lookup[50]; | |||
| static const char str_pause[2] = { phonPAUSE_NOLINK, 0 }; | |||
| @@ -1778,9 +1784,9 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| group_len = 4; | |||
| // is there a previous thousands part (as a previous "word") ? | |||
| if ((n_digits == group_len) && (word[-2] == tr->langopts.thousands_sep) && IsDigit09(word[-3])) { | |||
| if ((n_digits == group_len) && (word[-2] == tr->langopts.thousands_sep) && IsDigit09(word[-3])) | |||
| prev_thousands = 1; | |||
| } else if ((tr->langopts.thousands_sep == ' ') || (tr->langopts.numbers & NUM_ALLOW_SPACE)) { | |||
| else if ((tr->langopts.thousands_sep == ' ') || (tr->langopts.numbers & NUM_ALLOW_SPACE)) { | |||
| // thousands groups can be separated by spaces | |||
| if ((n_digits == 3) && !(wtab->flags & FLAG_MULTIPLE_SPACES) && IsDigit09(word[-2])) | |||
| prev_thousands = 1; | |||
| @@ -1802,7 +1808,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| } | |||
| if ((ordinal == 0) || (tr->translator_name == L('h', 'u'))) { | |||
| // NOTE lang=hu, allow both dot and ordinal suffix, eg. "december 21.-én" | |||
| // NOTE lang=hu, allow both dot and ordinal suffix, eg. "december 21.-én" | |||
| // look for an ordinal number suffix after the number | |||
| ix++; | |||
| p = suffix; | |||
| @@ -1817,7 +1823,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| if (suffix[0] != 0) { | |||
| if ((tr->langopts.ordinal_indicator != NULL) && (strcmp(suffix, tr->langopts.ordinal_indicator) == 0)) | |||
| ordinal = 2; | |||
| else if (!IsDigit09(suffix[0])) { // not _#9 (tab) | |||
| else if (!IsDigit09(suffix[0])) { // not _#9 (tab) | |||
| sprintf(string, "_#%s", suffix); | |||
| if (Lookup(tr, string, ph_ordinal2)) { | |||
| // this is an ordinal suffix | |||
| @@ -1825,7 +1831,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| flags[0] |= FLAG_SKIPWORDS; | |||
| skipwords = 1; | |||
| sprintf(string, "_x#%s", suffix); | |||
| Lookup(tr, string, ph_ordinal2x); // is there an alternate pronunciation? | |||
| Lookup(tr, string, ph_ordinal2x); // is there an alternate pronunciation? | |||
| } | |||
| } | |||
| } | |||
| @@ -1843,7 +1849,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| } else { | |||
| if (n_digits > 3) { | |||
| flags[0] &= ~FLAG_SKIPWORDS; | |||
| return 0; // long number string with leading zero, speak as individual digits | |||
| return 0; // long number string with leading zero, speak as individual digits | |||
| } | |||
| // speak leading zeros | |||
| @@ -1887,7 +1893,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| if (tr->translator_name == L('h', 'u')) { | |||
| // variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt | |||
| if ((wtab[thousandplex].flags & FLAG_HYPHEN_AFTER) && (thousands_exact == 1) && hu_number_e(&word[suffix_ix], thousandplex, value)) | |||
| number_control |= 1; // use _1e variant of number | |||
| number_control |= 1; // use _1e variant of number | |||
| } | |||
| if ((word[n_digits] == tr->langopts.decimal_sep) && IsDigit09(word[n_digits+1])) { | |||
| @@ -1920,7 +1926,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| char *p2; | |||
| // look for combinations of the number with the next word | |||
| p = word; | |||
| while (IsDigit09(p[1])) p++; // just use the last digit | |||
| while (IsDigit09(p[1])) p++; // just use the last digit | |||
| if (IsDigit09(p[-1])) { | |||
| p2 = p - 1; | |||
| if (LookupDictList(tr, &p2, buf_digit_lookup, flags, FLAG_SUFX, wtab)) // lookup 2 digits | |||
| @@ -1959,7 +1965,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| LookupNum3(tr, value, ph_buf, suppress_null, thousandplex, prev_thousands | ordinal | decimal_point); | |||
| if ((thousandplex > 0) && (tr->langopts.numbers2 & 0x200)) | |||
| sprintf(ph_out, "%s%s%c%s%s", ph_zeros, ph_append, phonEND_WORD, ph_buf2, ph_buf); // say "thousands" before its number | |||
| sprintf(ph_out, "%s%s%c%s%s", ph_zeros, ph_append, phonEND_WORD, ph_buf2, ph_buf); // say "thousands" before its number | |||
| else | |||
| sprintf(ph_out, "%s%s%s%c%s", ph_zeros, ph_buf2, ph_buf, phonEND_WORD, ph_append); | |||
| @@ -1976,7 +1982,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| { | |||
| case NUM_DFRACTION_4: | |||
| max_decimal_count = 5; | |||
| // fallthrough | |||
| // fallthrough: | |||
| case NUM_DFRACTION_2: | |||
| // French/Polish decimal fraction | |||
| while (word[n_digits] == '0') { | |||
| @@ -1991,15 +1997,15 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| n_digits += decimal_count; | |||
| } | |||
| break; | |||
| case NUM_DFRACTION_1: // italian, say "hundredths" if leading zero | |||
| case NUM_DFRACTION_5: // hungarian, always say "tenths" etc. | |||
| case NUM_DFRACTION_6: // kazakh, always say "tenths" etc, before the decimal fraction | |||
| case NUM_DFRACTION_1: // italian, say "hundredths" if leading zero | |||
| case NUM_DFRACTION_5: // hungarian, always say "tenths" etc. | |||
| case NUM_DFRACTION_6: // kazakh, always say "tenths" etc, before the decimal fraction | |||
| LookupNum3(tr, atoi(&word[n_digits]), ph_buf, 0, 0, 0); | |||
| if ((word[n_digits] == '0') || (decimal_mode != NUM_DFRACTION_1)) { | |||
| // decimal part has leading zeros, so add a "hundredths" or "thousandths" suffix | |||
| sprintf(string, "_0Z%d", decimal_count); | |||
| if (Lookup(tr, string, buf1) == 0) | |||
| break; // revert to speaking single digits | |||
| break; // revert to speaking single digits | |||
| if (decimal_mode == NUM_DFRACTION_6) | |||
| strcat(ph_out, buf1); | |||
| @@ -2056,7 +2062,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| utf8_in(&next_char, p); | |||
| if (!iswalpha2(next_char) && (thousands_exact == 0)) | |||
| strcat(ph_out, str_pause); // don't add pause for 100s, 6th, etc. | |||
| strcat(ph_out, str_pause); // don't add pause for 100s, 6th, etc. | |||
| } | |||
| *flags |= FLAG_FOUND; | |||
| @@ -2070,7 +2076,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned | |||
| int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | |||
| { | |||
| if ((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS)) | |||
| return 0; // speak digits individually | |||
| return 0; // speak digits individually | |||
| if (tr->langopts.numbers != 0) | |||
| return TranslateNumber_1(tr, word1, ph_out, flags, wtab, control); | |||
| @@ -22,7 +22,6 @@ extern "C" | |||
| { | |||
| #endif | |||
| // phoneme types | |||
| #define phPAUSE 0 | |||
| #define phSTRESS 1 | |||
| @@ -37,7 +36,6 @@ extern "C" | |||
| #define phDELETED 14 | |||
| #define phINVALID 15 | |||
| // phoneme properties | |||
| // bits 16-19 give place of articulation | |||
| #define phARTICULATION 0xf0000 | |||
| @@ -118,11 +116,8 @@ typedef struct { | |||
| unsigned char end_type; | |||
| unsigned char std_length; // for vowels, in mS/2; for phSTRESS phonemes, this is the stress/tone type | |||
| unsigned char length_mod; // a length_mod group number, used to access length_mod_tab | |||
| } PHONEME_TAB; | |||
| // Several phoneme tables may be loaded into memory. phoneme_tab points to | |||
| // one for the current voice | |||
| extern int n_phoneme_tab; | |||
| @@ -138,8 +133,6 @@ typedef struct { | |||
| int equivalence_tables; // lists of equivalent phonemes to match other languages, byte index into phondata | |||
| } PHONEME_TAB_LIST; | |||
| // table of phonemes to be replaced with different phonemes, for the current voice | |||
| #define N_REPLACE_PHONEMES 60 | |||
| typedef struct { | |||
| @@ -151,15 +144,12 @@ typedef struct { | |||
| extern int n_replace_phonemes; | |||
| extern REPLACE_PHONEMES replace_phonemes[N_REPLACE_PHONEMES]; | |||
| // Table of phoneme programs and lengths. Used by MakeVowelLists | |||
| typedef struct { | |||
| unsigned int addr; | |||
| unsigned int length; | |||
| } PHONEME_PROG_LOG; | |||
| #define PH(c1, c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name | |||
| #define PH3(c1, c2, c3) (c3<<16)+(c2<<8)+c1 | |||
| #define PhonemeCode2(c1, c2) PhonemeCode((c2<<8)+c1) | |||
| @@ -32,15 +32,17 @@ | |||
| #include "synthesize.h" | |||
| #include "translate.h" | |||
| const unsigned char pause_phonemes[8] = { 0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG }; | |||
| const unsigned char pause_phonemes[8] = { | |||
| 0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG | |||
| }; | |||
| extern int n_ph_list2; | |||
| extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes | |||
| extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes | |||
| static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) | |||
| { | |||
| // Copy the phonemes list and perform any substitutions that are required for the | |||
| // current voice | |||
| // Copy the phonemes list and perform any substitutions that are required for the | |||
| // current voice | |||
| int ix; | |||
| int k; | |||
| int replace_flags; | |||
| @@ -67,24 +69,24 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) | |||
| replace_flags = replace_phonemes[k].type; | |||
| if ((replace_flags & 1) && (word_end == 0)) | |||
| continue; // this replacement only occurs at the end of a word | |||
| continue; // this replacement only occurs at the end of a word | |||
| if ((replace_flags & 2) && ((plist2->stresslevel & 0x7) > 3)) | |||
| continue; // this replacement doesn't occur in stressed syllables | |||
| continue; // this replacement doesn't occur in stressed syllables | |||
| if ((replace_flags & 4) && (plist2->sourceix == 0)) | |||
| continue; // this replacement only occurs at the start of a word | |||
| continue; // this replacement only occurs at the start of a word | |||
| // substitute the replacement phoneme | |||
| plist2->phcode = replace_phonemes[k].new_ph; | |||
| if ((plist2->stresslevel > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED)) | |||
| plist2->stresslevel = 0; // the replacement must be unstressed | |||
| plist2->stresslevel = 0; // the replacement must be unstressed | |||
| break; | |||
| } | |||
| } | |||
| if (plist2->phcode == 0) | |||
| continue; // phoneme has been replaced by NULL, so don't copy it | |||
| continue; // phoneme has been replaced by NULL, so don't copy it | |||
| } | |||
| // copy phoneme into the output list | |||
| @@ -144,7 +146,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| // the last word is unstressed, look for a previous word that can be stressed | |||
| while (--j >= 0) { | |||
| if (plist2[j].synthflags & SFLAG_PROMOTE_STRESS) { // dictionary flags indicated that this stress can be promoted | |||
| plist2[j].stresslevel = 4; // promote to stressed | |||
| plist2[j].stresslevel = 4; // promote to stressed | |||
| break; | |||
| } | |||
| if (plist2[j].stresslevel >= 4) { | |||
| @@ -196,7 +198,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| stop_propagation = 0; | |||
| voicing = 0; | |||
| if (regression & 0x100) | |||
| voicing = 1; // word-end devoicing | |||
| voicing = 1; // word-end devoicing | |||
| continue; | |||
| } | |||
| @@ -215,12 +217,12 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| if ((voicing == 0) && (regression & 0xf)) | |||
| voicing = 1; | |||
| else if ((voicing == 2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants | |||
| plist2[j].phcode = ph->end_type; // change to voiced equivalent | |||
| plist2[j].phcode = ph->end_type; // change to voiced equivalent | |||
| } else if ((type == phVSTOP) || type == (phVFRICATIVE)) { | |||
| if ((voicing == 0) && (regression & 0xf)) | |||
| voicing = 2; | |||
| else if ((voicing == 1) && (ph->end_type != 0)) | |||
| plist2[j].phcode = ph->end_type; // change to unvoiced equivalent | |||
| plist2[j].phcode = ph->end_type; // change to unvoiced equivalent | |||
| } else { | |||
| if (regression & 0x8) { | |||
| // LANG=Polish, propagate through liquids and nasals | |||
| @@ -264,7 +266,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| nextw++; | |||
| if (ph_list3[nextw].sourceix) | |||
| break; // start of the next word | |||
| break; // start of the next word | |||
| } | |||
| for (k = j; k < nextw; k++) | |||
| ph_list3[k].wordstress = word_stress; | |||
| @@ -307,7 +309,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| ph = phoneme_tab[insert_ph]; | |||
| plist3->ph = ph; | |||
| insert_ph = 0; | |||
| inserted = 1; // don't insert the same phoneme repeatedly | |||
| inserted = 1; // don't insert the same phoneme repeatedly | |||
| } else { | |||
| // otherwise get the next phoneme from the list | |||
| if (plist3->sourceix != 0) | |||
| @@ -320,7 +322,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| // change phoneme table | |||
| SelectPhonemeTable(plist3->tone_ph); | |||
| } | |||
| next = phoneme_tab[plist3[1].phcode]; // the phoneme after this one | |||
| next = phoneme_tab[plist3[1].phcode]; // the phoneme after this one | |||
| plist3[1].ph = next; | |||
| } | |||
| @@ -348,7 +350,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| if (ph->type == phVOWEL) { | |||
| plist3->synthflags |= SFLAG_SYLLABLE; | |||
| if (ph2->type != phVOWEL) | |||
| plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
| plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
| } else | |||
| plist3->synthflags &= ~SFLAG_SYLLABLE; | |||
| @@ -365,12 +367,12 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| plist3->phcode = alternative; | |||
| if (alternative == 1) | |||
| deleted = 1; // NULL phoneme, discard | |||
| deleted = 1; // NULL phoneme, discard | |||
| else { | |||
| if (ph->type == phVOWEL) { | |||
| plist3->synthflags |= SFLAG_SYLLABLE; | |||
| if (ph2->type != phVOWEL) | |||
| plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
| plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
| } else | |||
| plist3->synthflags &= ~SFLAG_SYLLABLE; | |||
| @@ -408,14 +410,13 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| // stress. But not for the last phoneme of a stressed word | |||
| if ((tr->langopts.stress_flags & S_NO_DIM) || ((word_stress > 3) && ((plist3+1)->sourceix != 0))) { | |||
| // An unstressed final vowel of a stressed word | |||
| unstress_count = 1; // try again for next syllable | |||
| unstress_count = 1; // try again for next syllable | |||
| } else | |||
| plist3->stresslevel = 0; // change stress to 'diminished' | |||
| plist3->stresslevel = 0; // change stress to 'diminished' | |||
| } | |||
| } | |||
| } else { | |||
| } else | |||
| unstress_count = 0; | |||
| } | |||
| } | |||
| if ((plist3+1)->synthflags & SFLAG_LENGTHEN) { | |||
| @@ -483,7 +484,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| if (deleted == 0) { | |||
| phlist[ix].ph = ph; | |||
| phlist[ix].type = ph->type; | |||
| phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module | |||
| phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module | |||
| phlist[ix].synthflags = plist3->synthflags; | |||
| phlist[ix].stresslevel = plist3->stresslevel & 0xf; | |||
| phlist[ix].wordstress = plist3->wordstress; | |||
| @@ -493,10 +494,10 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| if (plist3->sourceix != 0) { | |||
| phlist[ix].sourceix = plist3->sourceix; | |||
| phlist[ix].newword = 1; // this phoneme is the start of a word | |||
| phlist[ix].newword = 1; // this phoneme is the start of a word | |||
| if (start_sentence) { | |||
| phlist[ix].newword = 5; // start of sentence + start of word | |||
| phlist[ix].newword = 5; // start of sentence + start of word | |||
| start_sentence = 0; | |||
| } | |||
| } else | |||
| @@ -505,26 +506,26 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
| phlist[ix].length = phdata.pd_param[i_SET_LENGTH]*2; | |||
| if ((ph->code == phonPAUSE_LONG) && (option_wordgap > 0) && (plist3[1].sourceix != 0)) { | |||
| phlist[ix].ph = phoneme_tab[phonPAUSE_SHORT]; | |||
| phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed | |||
| phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed | |||
| } | |||
| if (ph->type == phVOWEL || ph->type == phLIQUID || ph->type == phNASAL || ph->type == phVSTOP || ph->type == phVFRICATIVE || (ph->phflags & phPREVOICE)) { | |||
| phlist[ix].length = 128; // length_mod | |||
| phlist[ix].length = 128; // length_mod | |||
| phlist[ix].env = PITCHfall; | |||
| } | |||
| phlist[ix].prepause = 0; | |||
| phlist[ix].amp = 20; // default, will be changed later | |||
| phlist[ix].amp = 20; // default, will be changed later | |||
| phlist[ix].pitch1 = 255; | |||
| phlist[ix].pitch2 = 255; | |||
| ix++; | |||
| } | |||
| } | |||
| phlist[ix].newword = 2; // end of clause | |||
| phlist[ix].newword = 2; // end of clause | |||
| phlist[ix].phcode = phonPAUSE; | |||
| phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes | |||
| phlist[ix].length = post_pause; // length of the pause, depends on the punctuation | |||
| phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes | |||
| phlist[ix].length = post_pause; // length of the pause, depends on the punctuation | |||
| phlist[ix].sourceix = end_sourceix; | |||
| phlist[ix].synthflags = 0; | |||
| phlist[ix++].ph = phoneme_tab[phonPAUSE]; | |||
| @@ -40,10 +40,10 @@ extern int saved_parameters[]; | |||
| // convert from words-per-minute to internal speed factor | |||
| // Use this to calibrate speed for wpm 80-350 | |||
| static unsigned char speed_lookup[] = { | |||
| 255, 255, 255, 255, 255, // 80 | |||
| 253, 249, 245, 242, 238, // 85 | |||
| 235, 232, 228, 225, 222, // 90 | |||
| 218, 216, 213, 210, 207, // 95 | |||
| 255, 255, 255, 255, 255, // 80 | |||
| 253, 249, 245, 242, 238, // 85 | |||
| 235, 232, 228, 225, 222, // 90 | |||
| 218, 216, 213, 210, 207, // 95 | |||
| 204, 201, 198, 196, 193, // 100 | |||
| 191, 188, 186, 183, 181, // 105 | |||
| 179, 176, 174, 172, 169, // 110 | |||
| @@ -56,54 +56,54 @@ static unsigned char speed_lookup[] = { | |||
| 118, 117, 115, 114, 113, // 145 | |||
| 112, 111, 110, 109, 107, // 150 | |||
| 106, 105, 104, 103, 102, // 155 | |||
| 101, 100, 99, 98, 97,// 160 | |||
| 96, 95, 94, 93, 92, // 165 | |||
| 91, 90, 89, 89, 88, // 170 | |||
| 87, 86, 85, 84, 83, // 175 | |||
| 82, 82, 81, 80, 80, // 180 | |||
| 79, 78, 77, 76, 76, // 185 | |||
| 75, 75, 74, 73, 72, // 190 | |||
| 71, 71, 70, 69, 69, // 195 | |||
| 68, 67, 67, 66, 66, // 200 | |||
| 65, 64, 64, 63, 62, // 205 | |||
| 62, 61, 61, 60, 59, // 210 | |||
| 59, 58, 58, 57, 57, // 215 | |||
| 56, 56, 55, 54, 54, // 220 | |||
| 53, 53, 52, 52, 52, // 225 | |||
| 51, 50, 50, 49, 49, // 230 | |||
| 48, 48, 47, 47, 46, // 235 | |||
| 46, 46, 45, 45, 44, // 240 | |||
| 44, 44, 43, 43, 42, // 245 | |||
| 41, 40, 40, 40, 39, // 250 | |||
| 39, 39, 38, 38, 38, // 255 | |||
| 37, 37, 37, 36, 36, // 260 | |||
| 35, 35, 35, 35, 34, // 265 | |||
| 34, 34, 33, 33, 33, // 270 | |||
| 32, 32, 31, 31, 31, // 275 | |||
| 30, 30, 30, 29, 29, // 280 | |||
| 29, 29, 28, 28, 27, // 285 | |||
| 27, 27, 27, 26, 26, // 290 | |||
| 26, 26, 25, 25, 25, // 295 | |||
| 24, 24, 24, 24, 23, // 300 | |||
| 23, 23, 23, 22, 22, // 305 | |||
| 22, 21, 21, 21, 21, // 310 | |||
| 20, 20, 20, 20, 19, // 315 | |||
| 19, 19, 18, 18, 17, // 320 | |||
| 17, 17, 16, 16, 16, // 325 | |||
| 16, 16, 16, 15, 15, // 330 | |||
| 15, 15, 14, 14, 14, // 335 | |||
| 13, 13, 13, 12, 12, // 340 | |||
| 12, 12, 11, 11, 11, // 345 | |||
| 11, 10, 10, 10, 9, // 350 | |||
| 9, 9, 8, 8, 8, // 355 | |||
| 101, 100, 99, 98, 97, // 160 | |||
| 96, 95, 94, 93, 92, // 165 | |||
| 91, 90, 89, 89, 88, // 170 | |||
| 87, 86, 85, 84, 83, // 175 | |||
| 82, 82, 81, 80, 80, // 180 | |||
| 79, 78, 77, 76, 76, // 185 | |||
| 75, 75, 74, 73, 72, // 190 | |||
| 71, 71, 70, 69, 69, // 195 | |||
| 68, 67, 67, 66, 66, // 200 | |||
| 65, 64, 64, 63, 62, // 205 | |||
| 62, 61, 61, 60, 59, // 210 | |||
| 59, 58, 58, 57, 57, // 215 | |||
| 56, 56, 55, 54, 54, // 220 | |||
| 53, 53, 52, 52, 52, // 225 | |||
| 51, 50, 50, 49, 49, // 230 | |||
| 48, 48, 47, 47, 46, // 235 | |||
| 46, 46, 45, 45, 44, // 240 | |||
| 44, 44, 43, 43, 42, // 245 | |||
| 41, 40, 40, 40, 39, // 250 | |||
| 39, 39, 38, 38, 38, // 255 | |||
| 37, 37, 37, 36, 36, // 260 | |||
| 35, 35, 35, 35, 34, // 265 | |||
| 34, 34, 33, 33, 33, // 270 | |||
| 32, 32, 31, 31, 31, // 275 | |||
| 30, 30, 30, 29, 29, // 280 | |||
| 29, 29, 28, 28, 27, // 285 | |||
| 27, 27, 27, 26, 26, // 290 | |||
| 26, 26, 25, 25, 25, // 295 | |||
| 24, 24, 24, 24, 23, // 300 | |||
| 23, 23, 23, 22, 22, // 305 | |||
| 22, 21, 21, 21, 21, // 310 | |||
| 20, 20, 20, 20, 19, // 315 | |||
| 19, 19, 18, 18, 17, // 320 | |||
| 17, 17, 16, 16, 16, // 325 | |||
| 16, 16, 16, 15, 15, // 330 | |||
| 15, 15, 14, 14, 14, // 335 | |||
| 13, 13, 13, 12, 12, // 340 | |||
| 12, 12, 11, 11, 11, // 345 | |||
| 11, 10, 10, 10, 9, // 350 | |||
| 9, 9, 8, 8, 8, // 355 | |||
| }; | |||
| // speed_factor1 adjustments for speeds 350 to 374: pauses | |||
| static unsigned char pause_factor_350[] = { | |||
| 22, 22, 22, 22, 22, 22, 22, 21, 21, 21, // 350 | |||
| 21, 20, 20, 19, 19, 18, 17, 16, 15, 15, // 360 | |||
| 15, 15, 15, 15, 15 | |||
| }; // 370 | |||
| 15, 15, 15, 15, 15 // 370 | |||
| }; | |||
| // wav_factor adjustments for speeds 350 to 450 | |||
| // Use this to calibrate speed for wpm 350-450 | |||
| @@ -114,22 +114,22 @@ static unsigned char wav_factor_350[] = { | |||
| 111, 111, 110, 109, 108, // 365 | |||
| 107, 106, 106, 104, 103, // 370 | |||
| 103, 102, 102, 102, 101, // 375 | |||
| 101, 99, 98, 98, 97,// 380 | |||
| 96, 96, 95, 94, 93, // 385 | |||
| 91, 90, 91, 90, 89, // 390 | |||
| 88, 86, 85, 86, 85, // 395 | |||
| 85, 84, 82, 81, 80, // 400 | |||
| 79, 77, 78, 78, 76, // 405 | |||
| 77, 75, 75, 74, 73, // 410 | |||
| 71, 72, 70, 69, 69, // 415 | |||
| 69, 67, 65, 64, 63, // 420 | |||
| 63, 63, 61, 61, 59, // 425 | |||
| 59, 59, 58, 56, 57, // 430 | |||
| 58, 56, 54, 53, 52, // 435 | |||
| 52, 53, 52, 52, 50, // 440 | |||
| 48, 47, 47, 45, 46, // 445 | |||
| 45 | |||
| }; // 450 | |||
| 101, 99, 98, 98, 97, // 380 | |||
| 96, 96, 95, 94, 93, // 385 | |||
| 91, 90, 91, 90, 89, // 390 | |||
| 88, 86, 85, 86, 85, // 395 | |||
| 85, 84, 82, 81, 80, // 400 | |||
| 79, 77, 78, 78, 76, // 405 | |||
| 77, 75, 75, 74, 73, // 410 | |||
| 71, 72, 70, 69, 69, // 415 | |||
| 69, 67, 65, 64, 63, // 420 | |||
| 63, 63, 61, 61, 59, // 425 | |||
| 59, 59, 58, 56, 57, // 430 | |||
| 58, 56, 54, 53, 52, // 435 | |||
| 52, 53, 52, 52, 50, // 440 | |||
| 48, 47, 47, 45, 46, // 445 | |||
| 45 // 450 | |||
| }; | |||
| static int speed1 = 130; | |||
| static int speed2 = 121; | |||
| @@ -148,7 +148,7 @@ void SetSpeed(int control) | |||
| speed.loud_consonants = 0; | |||
| speed.min_sample_len = 450; | |||
| speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change | |||
| speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change | |||
| speed.lenmod2_factor = 100; | |||
| speed.min_pause = 5; | |||
| @@ -232,9 +232,9 @@ void SetSpeed(int control) | |||
| s1 = (x * voice->speedf1)/256; | |||
| if (wpm >= 170) | |||
| speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
| speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
| else | |||
| speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
| speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
| if (wpm >= 350) | |||
| speed.wav_factor = wav_factor_350[wpm-350]; | |||
| @@ -245,10 +245,10 @@ void SetSpeed(int control) | |||
| speed.min_sample_len = 420 - (wpm - 440); | |||
| } | |||
| // adjust for different sample rates | |||
| // adjust for different sample rates | |||
| speed.min_sample_len = (speed.min_sample_len * samplerate_native) / 22050; | |||
| speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
| speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
| speed.clause_pause_factor = 0; | |||
| if (wpm > 430) | |||
| @@ -268,11 +268,11 @@ void SetSpeed(int control) | |||
| } | |||
| } | |||
| #else // not using sonic speed-up | |||
| #else | |||
| void SetSpeed(int control) | |||
| { | |||
| // This is the earlier version of SetSpeed() before sonic speed-up was added | |||
| // This is the earlier version of SetSpeed() before sonic speed-up was added | |||
| int x; | |||
| int s1; | |||
| int wpm; | |||
| @@ -280,7 +280,7 @@ void SetSpeed(int control) | |||
| speed.loud_consonants = 0; | |||
| speed.min_sample_len = 450; | |||
| speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change | |||
| speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change | |||
| speed.lenmod2_factor = 100; | |||
| wpm = embedded_value[EMBED_S]; | |||
| @@ -332,9 +332,9 @@ void SetSpeed(int control) | |||
| s1 = (x * voice->speedf1)/256; | |||
| if (wpm >= 170) | |||
| speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
| speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
| else | |||
| speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
| speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
| if (wpm >= 350) | |||
| speed.wav_factor = wav_factor_350[wpm-350]; | |||
| @@ -345,7 +345,7 @@ void SetSpeed(int control) | |||
| speed.min_sample_len = 420 - (wpm - 440); | |||
| } | |||
| speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
| speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
| speed.clause_pause_factor = 0; | |||
| if (wpm > 430) | |||
| @@ -367,11 +367,10 @@ void SetSpeed(int control) | |||
| #endif | |||
| void SetParameter(int parameter, int value, int relative) | |||
| { | |||
| // parameter: reset-all, amp, pitch, speed, linelength, expression, capitals, number grouping | |||
| // relative 0=absolute 1=relative | |||
| // parameter: reset-all, amp, pitch, speed, linelength, expression, capitals, number grouping | |||
| // relative 0=absolute 1=relative | |||
| int new_value = value; | |||
| int default_value; | |||
| @@ -432,7 +431,7 @@ static void DoEmbedded2(int *embix) | |||
| if ((word & 0x1f) == EMBED_S) { | |||
| // speed | |||
| SetEmbedded(word & 0x7f, word >> 8); // adjusts embedded_value[EMBED_S] | |||
| SetEmbedded(word & 0x7f, word >> 8); // adjusts embedded_value[EMBED_S] | |||
| SetSpeed(1); | |||
| } | |||
| } while ((word & 0x80) == 0); | |||
| @@ -529,7 +528,7 @@ void CalcLengths(Translator *tr) | |||
| if ((p->ph->phflags & phSIBILANT) && next->type == phSTOP && !next->newword) { | |||
| if (prev->type == phVOWEL) | |||
| p->length = 200; // ?? should do this if it's from a prefix | |||
| p->length = 200; // ?? should do this if it's from a prefix | |||
| else | |||
| p->length = 150; | |||
| } else | |||
| @@ -553,7 +552,7 @@ void CalcLengths(Translator *tr) | |||
| p->prepause = 40; | |||
| if (prev->type == phVOWEL) { | |||
| p->prepause = 0; // use murmur instead to link from the preceding vowel | |||
| p->prepause = 0; // use murmur instead to link from the preceding vowel | |||
| } else if (prev->type == phPAUSE) { | |||
| // reduce by the length of the preceding pause | |||
| if (prev->length < p->prepause) | |||
| @@ -575,8 +574,8 @@ void CalcLengths(Translator *tr) | |||
| break; | |||
| case phLIQUID: | |||
| case phNASAL: | |||
| p->amp = tr->stress_amps[0]; // unless changed later | |||
| p->length = 256; // TEMPORARY | |||
| p->amp = tr->stress_amps[0]; // unless changed later | |||
| p->length = 256; // TEMPORARY | |||
| min_drop = 0; | |||
| if (p->newword) { | |||
| @@ -698,7 +697,7 @@ void CalcLengths(Translator *tr) | |||
| length_mod = length_mod / 128; | |||
| if (length_mod < 8) | |||
| length_mod = 8; // restrict how much lengths can be reduced | |||
| length_mod = 8; // restrict how much lengths can be reduced | |||
| if (stress >= 7) { | |||
| // tonic syllable, include a constant component so it doesn't decrease directly with speed | |||
| @@ -724,7 +723,7 @@ void CalcLengths(Translator *tr) | |||
| // this is the last syllable in the clause, lengthen it - more for short vowels | |||
| len = (p->ph->std_length * 2); | |||
| if (tr->langopts.stress_flags & S_EO_CLAUSE1) | |||
| len = 200; // don't lengthen short vowels more than long vowels at end-of-clause | |||
| len = 200; // don't lengthen short vowels more than long vowels at end-of-clause | |||
| length_mod = length_mod * (256 + (280 - len)/3)/256; | |||
| } | |||
| @@ -748,7 +747,7 @@ void CalcLengths(Translator *tr) | |||
| // pre-vocalic part | |||
| // set last-pitch | |||
| env2 = p->env + 1; // version for use with preceding semi-vowel | |||
| env2 = p->env + 1; // version for use with preceding semi-vowel | |||
| if (p->tone_ph != 0) { | |||
| InterpretPhoneme2(p->tone_ph, &phdata_tone); | |||
| @@ -761,7 +760,7 @@ void CalcLengths(Translator *tr) | |||
| if (pre_sonorant || pre_voiced) { | |||
| // set pitch for pre-vocalic part | |||
| if (pitch_start == 255) | |||
| last_pitch = pitch_start; // pitch is not set | |||
| last_pitch = pitch_start; // pitch is not set | |||
| if (pitch_start - last_pitch > 16) | |||
| last_pitch = pitch_start - 16; | |||
| @@ -76,12 +76,12 @@ t_espeak_callback *synth_callback = NULL; | |||
| int (*uri_callback)(int, const char *, const char *) = NULL; | |||
| int (*phoneme_callback)(const char *) = NULL; | |||
| char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
| char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
| extern int saved_parameters[N_SPEECH_PARAM]; // Parameters saved on synthesis start | |||
| void WVoiceChanged(voice_t *wvoice) | |||
| { | |||
| // Voice change in wavegen | |||
| // Voice change in wavegen | |||
| voice_samplerate = wvoice->samplerate; | |||
| } | |||
| @@ -235,7 +235,7 @@ static void select_output(espeak_AUDIO_OUTPUT output_type) | |||
| my_mode = output_type; | |||
| my_audio = NULL; | |||
| synchronous_mode = 1; | |||
| option_waveout = 1; // inhibit portaudio callback from wavegen.cpp | |||
| option_waveout = 1; // inhibit portaudio callback from wavegen.cpp | |||
| out_samplerate = 0; | |||
| switch (my_mode) | |||
| @@ -265,7 +265,7 @@ int GetFileLength(const char *filename) | |||
| return 0; | |||
| if (S_ISDIR(statbuf.st_mode)) | |||
| return -2; // a directory | |||
| return -2; // a directory | |||
| return statbuf.st_size; | |||
| } | |||
| @@ -275,7 +275,7 @@ char *Alloc(int size) | |||
| { | |||
| char *p; | |||
| if ((p = (char *)malloc(size)) == NULL) | |||
| fprintf(stderr, "Can't allocate memory\n"); // I was told that size+1 fixes a crash on 64-bit systems | |||
| fprintf(stderr, "Can't allocate memory\n"); // I was told that size+1 fixes a crash on 64-bit systems | |||
| return p; | |||
| } | |||
| @@ -302,7 +302,7 @@ static void init_path(const char *path) | |||
| if ((env = getenv("ESPEAK_DATA_PATH")) != NULL) { | |||
| sprintf(path_home, "%s/espeak-data", env); | |||
| if (GetFileLength(path_home) == -2) | |||
| return; // an espeak-data directory exists | |||
| return; // an espeak-data directory exists | |||
| } | |||
| buf[0] = 0; | |||
| @@ -324,7 +324,7 @@ static void init_path(const char *path) | |||
| if ((env = getenv("ESPEAK_DATA_PATH")) != NULL) { | |||
| snprintf(path_home, sizeof(path_home), "%s/espeak-data", env); | |||
| if (GetFileLength(path_home) == -2) | |||
| return; // an espeak-data directory exists | |||
| return; // an espeak-data directory exists | |||
| } | |||
| snprintf(path_home, sizeof(path_home), "%s/espeak-data", getenv("HOME")); | |||
| @@ -337,7 +337,7 @@ static int initialise(int control) | |||
| { | |||
| int param; | |||
| int result; | |||
| int srate = 22050; // default sample rate 22050 Hz | |||
| int srate = 22050; // default sample rate 22050 Hz | |||
| err = EE_OK; | |||
| LoadConfig(); | |||
| @@ -380,7 +380,7 @@ static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, | |||
| #endif | |||
| if ((outbuf == NULL) || (event_list == NULL)) | |||
| return EE_INTERNAL_ERROR; // espeak_Initialize() has not been called | |||
| return EE_INTERNAL_ERROR; // espeak_Initialize() has not been called | |||
| option_multibyte = flags & 7; | |||
| option_ssml = flags & espeakSSML; | |||
| @@ -402,13 +402,13 @@ static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, | |||
| if (my_mode == AUDIO_OUTPUT_SYNCH_PLAYBACK) { | |||
| for (;;) { | |||
| #ifdef PLATFORM_WINDOWS | |||
| Sleep(300); // 0.3s | |||
| Sleep(300); // 0.3s | |||
| #else | |||
| #ifdef USE_NANOSLEEP | |||
| struct timespec period; | |||
| struct timespec remaining; | |||
| period.tv_sec = 0; | |||
| period.tv_nsec = 300000000; // 0.3 sec | |||
| period.tv_nsec = 300000000; // 0.3 sec | |||
| nanosleep(&period, &remaining); | |||
| #else | |||
| sleep(1); | |||
| @@ -446,7 +446,7 @@ static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, | |||
| } else | |||
| finished = synth_callback((short *)outbuf, length, event_list); | |||
| if (finished) { | |||
| SpeakNextClause(NULL, 0, 2); // stop | |||
| SpeakNextClause(NULL, 0, 2); // stop | |||
| break; | |||
| } | |||
| @@ -465,9 +465,9 @@ static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, | |||
| if (dispatch_audio(NULL, 0, NULL) < 0) // TBD: test case | |||
| return err = EE_INTERNAL_ERROR; | |||
| } else | |||
| synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data | |||
| synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data | |||
| #else | |||
| synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data | |||
| synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data | |||
| #endif | |||
| break; | |||
| } | |||
| @@ -615,7 +615,7 @@ void sync_espeak_Key(const char *key) | |||
| my_unique_identifier = 0; | |||
| my_user_data = NULL; | |||
| Synthesize(0, key, 0); // speak key as a text string | |||
| Synthesize(0, key, 0); // speak key as a text string | |||
| } | |||
| void sync_espeak_Char(wchar_t character) | |||
| @@ -959,18 +959,19 @@ ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist) | |||
| ESPEAK_API void espeak_SetPhonemeTrace(int phonememode, FILE *stream) | |||
| { | |||
| ENTER("espeak_SetPhonemes"); | |||
| /* phonememode: Controls the output of phoneme symbols for the text | |||
| bits 0-2: | |||
| value=0 No phoneme output (default) | |||
| value=1 Output the translated phoneme symbols for the text | |||
| value=2 as (1), but produces IPA phoneme names rather than ascii | |||
| bit 3: output a trace of how the translation was done (showing the matching rules and list entries) | |||
| bit 4: produce pho data for mbrola | |||
| bit 7: use (bits 8-23) as a tie within multi-letter phonemes names | |||
| bits 8-23: separator character, between phoneme names | |||
| stream output stream for the phoneme symbols (and trace). If stream=NULL then it uses stdout. | |||
| */ | |||
| /* phonememode: Controls the output of phoneme symbols for the text | |||
| bits 0-2: | |||
| value=0 No phoneme output (default) | |||
| value=1 Output the translated phoneme symbols for the text | |||
| value=2 as (1), but produces IPA phoneme names rather than ascii | |||
| bit 3: output a trace of how the translation was done (showing the matching rules and list entries) | |||
| bit 4: produce pho data for mbrola | |||
| bit 7: use (bits 8-23) as a tie within multi-letter phonemes names | |||
| bits 8-23: separator character, between phoneme names | |||
| stream output stream for the phoneme symbols (and trace). If stream=NULL then it uses stdout. | |||
| */ | |||
| option_phonemes = phonememode; | |||
| f_trans = stream; | |||
| if (stream == NULL) | |||
| @@ -1007,7 +1008,7 @@ ESPEAK_API espeak_ERROR espeak_Cancel(void) | |||
| wave_close(my_audio); | |||
| SHOW_TIME("espeak_Cancel > LEAVE"); | |||
| #endif | |||
| embedded_value[EMBED_T] = 0; // reset echo for pronunciation announcements | |||
| embedded_value[EMBED_T] = 0; // reset echo for pronunciation announcements | |||
| for (int i = 0; i < N_SPEECH_PARAM; i++) | |||
| SetParameter(i, saved_parameters[i], 0); | |||
| @@ -63,10 +63,10 @@ static double read_double(FILE *stream) | |||
| float polint(float xa[], float ya[], int n, float x) | |||
| { | |||
| // General polinomial interpolation routine, xa[1...n] ya[1...n] | |||
| // General polinomial interpolation routine, xa[1...n] ya[1...n] | |||
| int i, m, ns = 1; | |||
| float den, dif, dift, ho, hp, w; | |||
| float y; // result | |||
| float y; // result | |||
| float c[9], d[9]; | |||
| dif = fabs(x-xa[1]); | |||
| @@ -86,7 +86,7 @@ float polint(float xa[], float ya[], int n, float x) | |||
| hp = xa[i+m]-x; | |||
| w = c[i+1]-d[i]; | |||
| if ((den = ho-hp) == 0.0) | |||
| return ya[2]; // two input xa are identical | |||
| return ya[2]; // two input xa are identical | |||
| den = w/den; | |||
| d[i] = hp*den; | |||
| c[i] = ho*den; | |||
| @@ -265,7 +265,8 @@ static float GetFrameLength(SpectSeq *spect, int frame) | |||
| if (frame >= spect->numframes-1) return 0; | |||
| for (ix = frame+1; ix < spect->numframes-1; ix++) { | |||
| if (spect->frames[ix]->keyframe) break; // reached next keyframe | |||
| if (spect->frames[ix]->keyframe) | |||
| break; // reached next keyframe | |||
| adjust += spect->frames[ix]->length_adjust; | |||
| } | |||
| return (spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust; | |||
| @@ -289,11 +290,11 @@ int LoadSpectSeq(SpectSeq *spect, const char *filename) | |||
| fread(&id2, sizeof(uint32_t), 1, stream); | |||
| if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEQ)) | |||
| spect->file_format = 0; // eSpeak formants | |||
| spect->file_format = 0; // eSpeak formants | |||
| else if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEK)) | |||
| spect->file_format = 1; // formants for Klatt synthesizer | |||
| spect->file_format = 1; // formants for Klatt synthesizer | |||
| else if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSQ2)) | |||
| spect->file_format = 2; // formants for Klatt synthesizer | |||
| spect->file_format = 2; // formants for Klatt synthesizer | |||
| else { | |||
| fprintf(stderr, "Unsupported spectral file format.\n"); | |||
| fclose(stream); | |||
| @@ -26,7 +26,6 @@ extern "C" | |||
| #define MAX_DISPLAY_FREQ 9500 | |||
| #define FRAME_HEIGHT 240 | |||
| #define T_ZOOMOUT 301 | |||
| #define T_ZOOMIN 302 | |||
| #define T_USEPITCHENV 303 | |||
| @@ -50,7 +49,6 @@ extern "C" | |||
| #define T_KOPEN 320 | |||
| #define T_FNZ 321 | |||
| #define FILEID1_SPECTSEQ 0x43455053 | |||
| #define FILEID2_SPECTSEQ 0x51455354 // for eSpeak sequence | |||
| #define FILEID2_SPECTSEK 0x4b455354 // for Klatt sequence | |||
| @@ -64,7 +62,6 @@ extern "C" | |||
| #define FILEID1_PRAATSEQ 0x41415250 | |||
| #define FILEID2_PRAATSEQ 0x51455354 | |||
| typedef struct { | |||
| unsigned short pitch1; | |||
| unsigned short pitch2; | |||
| @@ -74,7 +71,7 @@ typedef struct { | |||
| typedef struct { | |||
| short freq; | |||
| short bandw; | |||
| } formant_t; | |||
| } formant_t; | |||
| typedef struct { | |||
| short pkfreq; | |||
| @@ -84,8 +81,7 @@ typedef struct { | |||
| short klt_bw; | |||
| short klt_ap; | |||
| short klt_bp; | |||
| } peak_t; | |||
| } peak_t; | |||
| typedef struct { | |||
| int keyframe; | |||
| @@ -100,11 +96,11 @@ typedef struct { | |||
| unsigned short nx; | |||
| short markers; | |||
| int max_y; | |||
| USHORT *spect; // sqrt of harmonic amplitudes, 1-nx at 'pitch' | |||
| USHORT *spect; // sqrt of harmonic amplitudes, 1-nx at 'pitch' | |||
| short klatt_param[N_KLATTP2]; | |||
| formant_t formants[N_PEAKS]; // this is just the estimate given by Praat | |||
| formant_t formants[N_PEAKS]; // this is just the estimate given by Praat | |||
| peak_t peaks[N_PEAKS]; | |||
| } SpectFrame; | |||
| @@ -69,8 +69,6 @@ typedef signed __int32 intptr_t; | |||
| #endif | |||
| #endif | |||
| typedef struct { | |||
| const char *mnem; | |||
| int value; | |||
| @@ -106,7 +106,7 @@ static int mbr_name_prefix = 0; | |||
| espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate) | |||
| { | |||
| // Load a phoneme name translation table from espeak-data/mbrola | |||
| // Load a phoneme name translation table from espeak-data/mbrola | |||
| int size; | |||
| int ix; | |||
| @@ -141,16 +141,16 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int | |||
| close_MBR(); | |||
| #endif | |||
| #ifdef PLATFORM_WINDOWS | |||
| if (load_MBR() == FALSE) { // load mbrola.dll | |||
| if (load_MBR() == FALSE) { // load mbrola.dll | |||
| fprintf(stderr, "Can't load mbrola.dll\n"); | |||
| return EE_INTERNAL_ERROR; | |||
| } | |||
| #endif | |||
| if (init_MBR(path) != 0) // initialise the required mbrola voice | |||
| if (init_MBR(path) != 0) // initialise the required mbrola voice | |||
| return EE_NOT_FOUND; | |||
| setNoError_MBR(1); // don't stop on phoneme errors | |||
| setNoError_MBR(1); // don't stop on phoneme errors | |||
| // read eSpeak's mbrola phoneme translation data, eg. en1_phtrans | |||
| sprintf(path, "%s/mbrola_ph/%s", path_home, phtrans); | |||
| @@ -180,14 +180,15 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int | |||
| else | |||
| SetParameter(espeakVOICETYPE, 1, 0); | |||
| strcpy(mbrola_name, mbrola_voice); | |||
| mbrola_delay = 1000; // improve synchronization of events | |||
| mbrola_delay = 1000; // improve synchronization of events | |||
| return EE_OK; | |||
| } | |||
| static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev, PHONEME_TAB *ph_next, int *name2, int *split, int *control) | |||
| { | |||
| // Look up a phoneme in the mbrola phoneme name translation table | |||
| // It may give none, 1, or 2 mbrola phonemes | |||
| // Look up a phoneme in the mbrola phoneme name translation table | |||
| // It may give none, 1, or 2 mbrola phonemes | |||
| MBROLA_TAB *pr; | |||
| PHONEME_TAB *other_ph; | |||
| int found = 0; | |||
| @@ -218,7 +219,7 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev | |||
| if (pr->control & 2) | |||
| other_ph = ph_prev; | |||
| else if ((pr->control & 8) && ((plist+1)->newword)) | |||
| other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary | |||
| other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary | |||
| else | |||
| other_ph = ph_next; | |||
| @@ -228,14 +229,14 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev | |||
| found = 1; | |||
| } | |||
| if ((pr->control & 4) && (plist->newword == 0)) // only at start of word | |||
| if ((pr->control & 4) && (plist->newword == 0)) // only at start of word | |||
| found = 0; | |||
| if ((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word | |||
| if ((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word | |||
| found = 0; | |||
| if ((pr->control & 0x20) && (plist->stresslevel < plist->wordstress)) | |||
| found = 0; // only in stressed syllables | |||
| found = 0; // only in stressed syllables | |||
| if (found) { | |||
| *name2 = pr->mbr_name2; | |||
| @@ -262,7 +263,7 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev | |||
| static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
| { | |||
| // final=1: only give the final pitch value. | |||
| // final=1: only give the final pitch value. | |||
| int x; | |||
| int ix; | |||
| int pitch_base; | |||
| @@ -273,7 +274,7 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
| int min = 999; | |||
| int y_max = 0; | |||
| int y_min = 0; | |||
| int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s) | |||
| int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s) | |||
| int y2; | |||
| int y[4]; | |||
| int env_split; | |||
| @@ -311,7 +312,7 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
| y[3] = y[2] + (127 - y[2])/2; | |||
| // set initial pitch | |||
| p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12 | |||
| p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12 | |||
| p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base; | |||
| if (split >= 0) { | |||
| @@ -355,7 +356,7 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
| int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbrola) | |||
| { | |||
| // Generate a mbrola pho file | |||
| // Generate a mbrola pho file | |||
| unsigned int name; | |||
| int len; | |||
| int len1; | |||
| @@ -412,7 +413,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
| if (name == 0) { | |||
| phix++; | |||
| continue; // ignore this phoneme | |||
| continue; // ignore this phoneme | |||
| } | |||
| if ((ph->type == phPAUSE) && (name == ph->mnemonic)) { | |||
| @@ -446,10 +447,10 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
| case phVOWEL: | |||
| len = ph->std_length; | |||
| if (p->synthflags & SFLAG_LENGTHEN) | |||
| len += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol | |||
| len += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol | |||
| if (ph_next->type == phPAUSE) | |||
| len += 50; // lengthen vowels before a pause | |||
| len += 50; // lengthen vowels before a pause | |||
| len = (len * p->length)/256; | |||
| if (name2 == 0) { | |||
| @@ -477,7 +478,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
| InterpretPhoneme(NULL, 0, p, &phdata, NULL); | |||
| len = DoSample3(&phdata, 0, -1); | |||
| len = (len * 1000)/samplerate; // convert to mS | |||
| len = (len * 1000)/samplerate; // convert to mS | |||
| len += PauseLength(p->prepause, 1); | |||
| break; | |||
| case phVSTOP: | |||
| @@ -487,10 +488,10 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
| len = 0; | |||
| InterpretPhoneme(NULL, 0, p, &phdata, NULL); | |||
| if (p->synthflags & SFLAG_LENGTHEN) | |||
| len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc. | |||
| len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc. | |||
| len += DoSample3(&phdata, p->length, -1); | |||
| len = (len * 1000)/samplerate; // convert to mS | |||
| len = (len * 1000)/samplerate; // convert to mS | |||
| break; | |||
| case phNASAL: | |||
| if (next->type != phVOWEL) { | |||
| @@ -528,11 +529,11 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
| } | |||
| if (f_mbrola) | |||
| fwrite(mbr_buf, 1, (ptr-mbr_buf), f_mbrola); // write .pho to a file | |||
| fwrite(mbr_buf, 1, (ptr-mbr_buf), f_mbrola); // write .pho to a file | |||
| else { | |||
| int res = write_MBR(mbr_buf); | |||
| if (res < 0) | |||
| return 0; /* don't get stuck on error */ | |||
| return 0; // don't get stuck on error | |||
| if (res == 0) | |||
| return 1; | |||
| wcmdq[wcmdq_tail][0] = WCMD_MBROLA_DATA; | |||
| @@ -575,7 +576,7 @@ int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| int MbrolaFill(int length, int resume, int amplitude) | |||
| { | |||
| // Read audio data from Mbrola (length is in millisecs) | |||
| // Read audio data from Mbrola (length is in millisecs) | |||
| static int n_samples; | |||
| int req_samples, result; | |||
| @@ -596,7 +597,7 @@ int MbrolaFill(int length, int resume, int amplitude) | |||
| for (ix = 0; ix < result; ix++) { | |||
| value16 = out_ptr[0] + (out_ptr[1] << 8); | |||
| value = value16 * amplitude; | |||
| value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices | |||
| value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices | |||
| if (value > 0x7fff) | |||
| value = 0x7fff; | |||
| if (value < -0x8000) | |||
| @@ -611,12 +612,12 @@ int MbrolaFill(int length, int resume, int amplitude) | |||
| void MbrolaReset(void) | |||
| { | |||
| // Reset the Mbrola engine and flush the pending audio | |||
| // Reset the Mbrola engine and flush the pending audio | |||
| reset_MBR(); | |||
| } | |||
| #else // INCLUDE_MBROLA | |||
| #else | |||
| // mbrola interface is not compiled, provide dummy functions. | |||
| @@ -639,4 +640,4 @@ void MbrolaReset(void) | |||
| { | |||
| } | |||
| #endif // INCLUDE_MBROLA | |||
| #endif | |||
| @@ -59,7 +59,7 @@ int n_phoneme_tables; | |||
| PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; | |||
| int phoneme_tab_number = 0; | |||
| int wavefile_ix; // a wavefile to play along with the synthesis | |||
| int wavefile_ix; // a wavefile to play along with the synthesis | |||
| int wavefile_amp; | |||
| int wavefile_ix2; | |||
| int wavefile_amp2; | |||
| @@ -128,8 +128,8 @@ int LoadPhData(int *srate) | |||
| n_tunes = length / sizeof(TUNE); | |||
| // read the version number and sample rate from the first 8 bytes of phondata | |||
| version = 0; // bytes 0-3, version number | |||
| rate = 0; // bytes 4-7, sample rate | |||
| version = 0; // bytes 0-3, version number | |||
| rate = 0; // bytes 4-7, sample rate | |||
| for (ix = 0; ix < 4; ix++) { | |||
| version += (wavefile_data[ix] << (ix*8)); | |||
| rate += (wavefile_data[ix+4] << (ix*8)); | |||
| @@ -248,7 +248,7 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, | |||
| if (which == 1) | |||
| nf = seq_break + 1; | |||
| else { | |||
| frames = &frames_buf[seq_break]; // body of vowel, skip past initial frames | |||
| frames = &frames_buf[seq_break]; // body of vowel, skip past initial frames | |||
| nf -= seq_break; | |||
| } | |||
| } | |||
| @@ -289,16 +289,15 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, | |||
| if (length1 > 0) { | |||
| if (which == 2) { | |||
| // adjust the length of the main part to match the standard length specified for the vowel | |||
| // less the front part of the vowel and any added suffix | |||
| // less the front part of the vowel and any added suffix | |||
| length_std = fmt_params->std_length + seq_len_adjust - 45; | |||
| if (length_std < 10) | |||
| length_std = 10; | |||
| if (plist->synthflags & SFLAG_LENGTHEN) | |||
| length_std += (phoneme_tab[phonLENGTHEN]->std_length * 2); // phoneme was followed by an extra : symbol | |||
| // can adjust vowel length for stressed syllables here | |||
| length_std += (phoneme_tab[phonLENGTHEN]->std_length * 2); // phoneme was followed by an extra : symbol | |||
| // can adjust vowel length for stressed syllables here | |||
| length_factor = (length_std * 256)/ length1; | |||
| @@ -335,7 +334,7 @@ unsigned char *GetEnvelope(int index) | |||
| { | |||
| if (index == 0) { | |||
| fprintf(stderr, "espeak: No envelope\n"); | |||
| return envelope_data[0]; // not found, use a default envelope | |||
| return envelope_data[0]; // not found, use a default envelope | |||
| } | |||
| return (unsigned char *)&phondata_ptr[index]; | |||
| } | |||
| @@ -364,14 +363,14 @@ static void SetUpPhonemeTable(int number, int recursing) | |||
| n_phoneme_tab = ph_code; | |||
| if (recursing == 0) | |||
| phoneme_tab_flags[ph_code] |= 1; // not inherited | |||
| phoneme_tab_flags[ph_code] |= 1; // not inherited | |||
| } | |||
| } | |||
| void SelectPhonemeTable(int number) | |||
| { | |||
| n_phoneme_tab = 0; | |||
| SetUpPhonemeTable(number, 0); // recursively for included phoneme tables | |||
| SetUpPhonemeTable(number, 0); // recursively for included phoneme tables | |||
| n_phoneme_tab++; | |||
| current_phoneme_table = number; | |||
| } | |||
| @@ -394,8 +393,8 @@ int LookupPhonemeTable(const char *name) | |||
| int SelectPhonemeTableName(const char *name) | |||
| { | |||
| // Look up a phoneme set by name, and select it if it exists | |||
| // Returns the phoneme table number | |||
| // Look up a phoneme set by name, and select it if it exists | |||
| // Returns the phoneme table number | |||
| int ix; | |||
| if ((ix = LookupPhonemeTable(name)) == -1) | |||
| @@ -407,7 +406,7 @@ int SelectPhonemeTableName(const char *name) | |||
| void LoadConfig(void) | |||
| { | |||
| // Load configuration file, if one exists | |||
| // Load configuration file, if one exists | |||
| char buf[sizeof(path_home)+10]; | |||
| FILE *f; | |||
| int ix; | |||
| @@ -462,8 +461,8 @@ static void InvalidInstn(PHONEME_TAB *ph, int instn) | |||
| static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, int control) | |||
| { | |||
| // condition: | |||
| // 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress | |||
| // condition: | |||
| // 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress | |||
| int stress_level; | |||
| PHONEME_LIST *pl; | |||
| @@ -476,7 +475,7 @@ static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, | |||
| if (phoneme_tab[plist[1].phcode]->type == phVOWEL) | |||
| pl = &plist[1]; | |||
| else | |||
| return false; // no stress elevel for this consonant | |||
| return false; // no stress elevel for this consonant | |||
| } | |||
| stress_level = pl->stresslevel & 0xf; | |||
| @@ -574,19 +573,19 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
| switch (which) | |||
| { | |||
| case 0: // prevPh | |||
| case 5: // prevPhW | |||
| case 0: // prevPh | |||
| case 5: // prevPhW | |||
| plist--; | |||
| check_endtype = 1; | |||
| break; | |||
| case 1: // thisPh | |||
| case 1: // thisPh | |||
| break; | |||
| case 2: // nextPh | |||
| case 4: // nextPhW | |||
| case 2: // nextPh | |||
| case 4: // nextPhW | |||
| plist++; | |||
| break; | |||
| case 3: // next2Ph | |||
| case 6: // next2PhW | |||
| case 3: // next2Ph | |||
| case 6: // next2PhW | |||
| plist += 2; | |||
| break; | |||
| case 7: | |||
| @@ -600,13 +599,13 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
| } | |||
| } | |||
| break; | |||
| case 8: // prevVowel in this word | |||
| case 8: // prevVowel in this word | |||
| if ((worddata == NULL) || (worddata->prev_vowel.ph == NULL)) | |||
| return false; // no previous vowel | |||
| return false; // no previous vowel | |||
| plist = &(worddata->prev_vowel); | |||
| check_endtype = 1; | |||
| break; | |||
| case 9: // next3PhW | |||
| case 9: // next3PhW | |||
| for (ix = 1; ix <= 3; ix++) { | |||
| if (plist[ix].sourceix) | |||
| return false; | |||
| @@ -641,8 +640,8 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
| // not an exact match, check for a vowel type (eg. #i ) | |||
| if ((check_endtype) && (ph->type == phVOWEL)) | |||
| return data == ph->end_type; // prevPh() match on end_type | |||
| return data == ph->start_type; // thisPh() or nextPh(), match on start_type | |||
| return data == ph->end_type; // prevPh() match on end_type | |||
| return data == ph->start_type; // thisPh() or nextPh(), match on start_type | |||
| } | |||
| data = instn & 0x1f; | |||
| @@ -670,16 +669,16 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
| case 3: | |||
| case 4: | |||
| return StressCondition(tr, plist, data, 0); | |||
| case 5: // isBreak, Either pause phoneme, or (stop/vstop/vfric not followed by vowel or (liquid in same word)) | |||
| case 5: // isBreak, Either pause phoneme, or (stop/vstop/vfric not followed by vowel or (liquid in same word)) | |||
| return (ph->type == phPAUSE) || (plist_this->synthflags & SFLAG_NEXT_PAUSE); | |||
| case 6: // isWordStart | |||
| case 6: // isWordStart | |||
| return plist->sourceix != 0; | |||
| case 7: // notWordStart | |||
| case 7: // notWordStart | |||
| return plist->sourceix == 0; | |||
| case 8: // isWordEnd | |||
| case 8: // isWordEnd | |||
| return plist[1].sourceix || (plist[1].ph->type == phPAUSE); | |||
| break; | |||
| case 9: // isAfterStress | |||
| case 9: // isAfterStress | |||
| if (plist->sourceix != 0) | |||
| return false; | |||
| do { | |||
| @@ -689,28 +688,27 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
| } while (plist->sourceix == 0); | |||
| break; | |||
| case 10: // isNotVowel | |||
| case 10: // isNotVowel | |||
| return ph->type != phVOWEL; | |||
| case 11: // isFinalVowel | |||
| case 11: // isFinalVowel | |||
| for (;;) { | |||
| plist++; | |||
| // plist->ph = phoneme_tab[plist->phcode]; // Why was this line here?? It corrupts plist if we have language switching if phoneme_tab is wrong language | |||
| if (plist->sourceix != 0) | |||
| return true; // start of next word, without finding another vowel | |||
| return true; // start of next word, without finding another vowel | |||
| if (plist->ph->type == phVOWEL) | |||
| return false; | |||
| } | |||
| break; | |||
| case 12: // isVoiced | |||
| case 12: // isVoiced | |||
| return (ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED); | |||
| case 13: // isFirstVowel | |||
| case 13: // isFirstVowel | |||
| return CountVowelPosition(plist) == 1; | |||
| case 14: // isSecondVowel | |||
| case 14: // isSecondVowel | |||
| return CountVowelPosition(plist) == 2; | |||
| case 15: // isSeqFlag1 | |||
| case 15: // isSeqFlag1 | |||
| // is this preceded by a sequence if 1 or more vowels which have 'flag1' ? (lang=hi) | |||
| if (plist->sourceix != 0) | |||
| return false; // this is the first phoneme in the word, so no. | |||
| return false; // this is the first phoneme in the word, so no. | |||
| count = 0; | |||
| for (;;) { | |||
| @@ -719,13 +717,13 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
| if (plist->ph->phflags & phFLAG1) | |||
| count++; | |||
| else | |||
| break; // stop when we find a vowel without flag1 | |||
| break; // stop when we find a vowel without flag1 | |||
| } | |||
| if (plist->sourceix != 0) | |||
| break; | |||
| } | |||
| return count > 0; | |||
| case 0x10: // isTranslationGiven | |||
| case 0x10: // isTranslationGiven | |||
| return (plist->synthflags & SFLAG_DICTIONARY) != 0; | |||
| } | |||
| break; | |||
| @@ -736,11 +734,11 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
| // Other conditions | |||
| switch (data) | |||
| { | |||
| case 1: // PreVoicing | |||
| case 1: // PreVoicing | |||
| return control & 1; | |||
| case 2: // KlattSynth | |||
| case 2: // KlattSynth | |||
| return voice->klattv[0] != 0; | |||
| case 3: // MbrolaSynth | |||
| case 3: // MbrolaSynth | |||
| return mbrola_name[0] != 0; | |||
| } | |||
| } | |||
| @@ -755,16 +753,16 @@ static void SwitchOnVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT | |||
| if (instn_type == 2) { | |||
| phdata->pd_control |= pd_FORNEXTPH; | |||
| voweltype = plist[1].ph->start_type; // SwitchNextVowelType | |||
| voweltype = plist[1].ph->start_type; // SwitchNextVowelType | |||
| } else | |||
| voweltype = plist[-1].ph->end_type; // SwitchPrevVowelType | |||
| voweltype = plist[-1].ph->end_type; // SwitchPrevVowelType | |||
| voweltype -= phonVOWELTYPES; | |||
| if ((voweltype >= 0) && (voweltype < 6)) { | |||
| prog = *p_prog + voweltype*2; | |||
| phdata->sound_addr[instn_type] = (((prog[1] & 0xf) << 16) + prog[2]) * 4; | |||
| x = (prog[1] >> 4) & 0xff; | |||
| phdata->sound_param[instn_type] = x; // sign extend | |||
| phdata->sound_param[instn_type] = x; // sign extend | |||
| } | |||
| *p_prog += 12; | |||
| @@ -795,7 +793,7 @@ int NumInstnWords(USHORT *prog) | |||
| case 6: | |||
| type2 = (instn & 0xf00) >> 9; | |||
| if ((type2 == 5) || (type2 == 6)) | |||
| return 12; // switch on vowel type | |||
| return 12; // switch on vowel type | |||
| return 1; | |||
| case 2: | |||
| case 3: | |||
| @@ -818,9 +816,10 @@ int NumInstnWords(USHORT *prog) | |||
| void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata) | |||
| { | |||
| // control: | |||
| // bit 0: PreVoicing | |||
| // bit 8: change phonemes | |||
| // control: | |||
| // bit 0: PreVoicing | |||
| // bit 8: change phonemes | |||
| PHONEME_TAB *ph; | |||
| USHORT *prog; | |||
| USHORT instn; | |||
| @@ -835,7 +834,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| #define N_RETURN 10 | |||
| int n_return = 0; | |||
| USHORT *return_addr[N_RETURN]; // return address stack | |||
| USHORT *return_addr[N_RETURN]; // return address stack | |||
| ph = plist->ph; | |||
| @@ -860,7 +859,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| switch (instn >> 12) | |||
| { | |||
| case 0: // 0xxx | |||
| case 0: // 0xxx | |||
| data = instn & 0xff; | |||
| if (instn2 == 0) { | |||
| @@ -870,10 +869,8 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| case i_RETURN: | |||
| end_flag = 1; | |||
| break; | |||
| case i_CONTINUE: | |||
| break; | |||
| default: | |||
| InvalidInstn(ph, instn); | |||
| break; | |||
| @@ -897,7 +894,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| phdata->ipa_string[ix] = 0; | |||
| } else if (instn2 < N_PHONEME_DATA_PARAM) { | |||
| if (instn2 == i_CHANGE_PHONEME2) | |||
| phdata->pd_param[i_CHANGE_PHONEME] = data; // also set ChangePhoneme | |||
| phdata->pd_param[i_CHANGE_PHONEME] = data; // also set ChangePhoneme | |||
| phdata->pd_param[instn2] = data; | |||
| if ((instn2 == i_CHANGE_PHONEME) && (control & 0x100)) { | |||
| // found ChangePhoneme() in PhonemeList mode, exit | |||
| @@ -908,13 +905,13 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| break; | |||
| case 1: | |||
| if (tr == NULL) | |||
| break; // ignore if in synthesis stage | |||
| break; // ignore if in synthesis stage | |||
| if (instn2 < 8) { | |||
| // ChangeIf | |||
| if (StressCondition(tr, plist, instn2 & 7, 1) == true) { | |||
| phdata->pd_param[i_CHANGE_PHONEME] = instn & 0xff; | |||
| end_flag = 1; // change phoneme, exit | |||
| end_flag = 1; // change phoneme, exit | |||
| } | |||
| } | |||
| break; | |||
| @@ -947,7 +944,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| // instruction after a condition is not JUMP_FALSE, so skip the instruction. | |||
| prog += NumInstnWords(prog); | |||
| if ((prog[0] & 0xfe00) == 0x6000) | |||
| prog++; // and skip ELSE jump | |||
| prog++; // and skip ELSE jump | |||
| } | |||
| } | |||
| prog--; | |||
| @@ -959,16 +956,13 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| case 0: | |||
| prog += (instn & 0xff) - 1; | |||
| break; | |||
| case 4: | |||
| // conditional jumps should have been processed in the Condition section | |||
| break; | |||
| case 5: // NexttVowelStarts | |||
| case 5: // NexttVowelStarts | |||
| SwitchOnVowelType(plist, phdata, &prog, 2); | |||
| break; | |||
| case 6: // PrevVowelTypeEndings | |||
| case 6: // PrevVowelTypeEndings | |||
| SwitchOnVowelType(plist, phdata, &prog, 3); | |||
| break; | |||
| } | |||
| @@ -995,7 +989,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| break; | |||
| } | |||
| break; | |||
| case 10: // Vowelin, Vowelout | |||
| case 10: // Vowelin, Vowelout | |||
| if (instn2 == 1) | |||
| ix = 0; | |||
| else | |||
| @@ -1005,11 +999,11 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| phdata->vowel_transition[ix+1] = (prog[2] << 16) + prog[3]; | |||
| prog += 3; | |||
| break; | |||
| case 11: // FMT | |||
| case 12: // WAV | |||
| case 13: // VowelStart | |||
| case 14: // VowelEnd | |||
| case 15: // addWav | |||
| case 11: // FMT | |||
| case 12: // WAV | |||
| case 13: // VowelStart | |||
| case 14: // VowelEnd | |||
| case 15: // addWav | |||
| instn2 = (instn >> 12) - 11; | |||
| phdata->sound_addr[instn2] = ((instn & 0xf) << 18) + (prog[1] << 2); | |||
| param_sc = phdata->sound_param[instn2] = (instn >> 4) & 0xff; | |||
| @@ -1054,17 +1048,17 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| plist->std_length = phdata->pd_param[i_SET_LENGTH]; | |||
| if (phdata->sound_addr[0] != 0) { | |||
| plist->phontab_addr = phdata->sound_addr[0]; // FMT address | |||
| plist->phontab_addr = phdata->sound_addr[0]; // FMT address | |||
| plist->sound_param = phdata->sound_param[0]; | |||
| } else { | |||
| plist->phontab_addr = phdata->sound_addr[1]; // WAV address | |||
| plist->phontab_addr = phdata->sound_addr[1]; // WAV address | |||
| plist->sound_param = phdata->sound_param[1]; | |||
| } | |||
| } | |||
| void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata) | |||
| { | |||
| // Examine the program of a single isolated phoneme | |||
| // Examine the program of a single isolated phoneme | |||
| int ix; | |||
| PHONEME_LIST plist[4]; | |||
| memset(plist, 0, sizeof(plist)); | |||
| @@ -76,7 +76,7 @@ static PHONEME_LIST next_pause; | |||
| const char *WordToString(unsigned int word) | |||
| { | |||
| // Convert a phoneme mnemonic word into a string | |||
| // Convert a phoneme mnemonic word into a string | |||
| int ix; | |||
| static char buf[5]; | |||
| @@ -131,11 +131,11 @@ static void DoAmplitude(int amp, unsigned char *amp_env) | |||
| intptr_t *q; | |||
| last_amp_cmd = wcmdq_tail; | |||
| amp_length = 0; // total length of vowel with this amplitude envelope | |||
| amp_length = 0; // total length of vowel with this amplitude envelope | |||
| q = wcmdq[wcmdq_tail]; | |||
| q[0] = WCMD_AMPLITUDE; | |||
| q[1] = 0; // fill in later from amp_length | |||
| q[1] = 0; // fill in later from amp_length | |||
| q[2] = (intptr_t)amp_env; | |||
| q[3] = amp; | |||
| WcmdqInc(); | |||
| @@ -154,14 +154,14 @@ static void DoPitch(unsigned char *env, int pitch1, int pitch2) | |||
| env = envelope_data[PITCHfall]; | |||
| } | |||
| last_pitch_cmd = wcmdq_tail; | |||
| pitch_length = 0; // total length of spect with this pitch envelope | |||
| pitch_length = 0; // total length of spect with this pitch envelope | |||
| if (pitch2 < 0) | |||
| pitch2 = 0; | |||
| q = wcmdq[wcmdq_tail]; | |||
| q[0] = WCMD_PITCH; | |||
| q[1] = 0; // length, fill in later from pitch_length | |||
| q[1] = 0; // length, fill in later from pitch_length | |||
| q[2] = (intptr_t)env; | |||
| q[3] = (pitch1 << 16) + pitch2; | |||
| WcmdqInc(); | |||
| @@ -179,16 +179,16 @@ int PauseLength(int pause, int control) | |||
| } else | |||
| len = (pause * speed.wav_factor)/256; | |||
| if (len < speed.min_pause) { | |||
| len = speed.min_pause; // mS, limit the amount to which pauses can be shortened | |||
| } | |||
| if (len < speed.min_pause) | |||
| len = speed.min_pause; // mS, limit the amount to which pauses can be shortened | |||
| return len; | |||
| } | |||
| static void DoPause(int length, int control) | |||
| { | |||
| // length in nominal mS | |||
| // control = 1, less shortening at fast speeds | |||
| // length in nominal mS | |||
| // control = 1, less shortening at fast speeds | |||
| unsigned int len; | |||
| int srate2; | |||
| @@ -198,9 +198,9 @@ static void DoPause(int length, int control) | |||
| len = PauseLength(length, control); | |||
| if (len < 90000) | |||
| len = (len * samplerate) / 1000; // convert from mS to number of samples | |||
| len = (len * samplerate) / 1000; // convert from mS to number of samples | |||
| else { | |||
| srate2 = samplerate / 25; // avoid overflow | |||
| srate2 = samplerate / 25; // avoid overflow | |||
| len = (len * srate2) / 40; | |||
| } | |||
| } | |||
| @@ -218,7 +218,7 @@ static void DoPause(int length, int control) | |||
| } | |||
| } | |||
| extern int seq_len_adjust; // temporary fix to advance the start point for playing the wav sample | |||
| extern int seq_len_adjust; // temporary fix to advance the start point for playing the wav sample | |||
| static int DoSample2(int index, int which, int std_length, int control, int length_mod, int amp) | |||
| { | |||
| @@ -235,7 +235,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
| p = &wavefile_data[index]; | |||
| wav_scale = p[2]; | |||
| wav_length = (p[1] * 256); | |||
| wav_length += p[0]; // length in bytes | |||
| wav_length += p[0]; // length in bytes | |||
| if (wav_length == 0) | |||
| return 0; | |||
| @@ -243,7 +243,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
| min_length = speed.min_sample_len; | |||
| if (wav_scale == 0) | |||
| min_length *= 2; // 16 bit samples | |||
| min_length *= 2; // 16 bit samples | |||
| if (std_length > 0) { | |||
| std_length = (std_length * samplerate)/1000; | |||
| @@ -294,7 +294,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
| last_wcmdq = wcmdq_tail; | |||
| q = wcmdq[wcmdq_tail]; | |||
| q[0] = WCMD_WAVE2; | |||
| q[1] = length | (wav_length << 16); // length in samples | |||
| q[1] = length | (wav_length << 16); // length in samples | |||
| q[2] = (intptr_t)(&wavefile_data[index]); | |||
| q[3] = wav_scale + (amp << 8); | |||
| WcmdqInc(); | |||
| @@ -312,7 +312,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
| last_wcmdq = wcmdq_tail; | |||
| q = wcmdq[wcmdq_tail]; | |||
| q[0] = WCMD_WAVE; | |||
| q[1] = x; // length in samples | |||
| q[1] = x; // length in samples | |||
| q[2] = (intptr_t)(&wavefile_data[index]); | |||
| q[3] = wav_scale + (amp << 8); | |||
| WcmdqInc(); | |||
| @@ -325,7 +325,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
| last_wcmdq = wcmdq_tail; | |||
| q = wcmdq[wcmdq_tail]; | |||
| q[0] = WCMD_WAVE; | |||
| q[1] = len4*2; // length in samples | |||
| q[1] = len4*2; // length in samples | |||
| q[2] = (intptr_t)(&wavefile_data[index+x]); | |||
| q[3] = wav_scale + (amp << 8); | |||
| WcmdqInc(); | |||
| @@ -340,7 +340,7 @@ static int DoSample2(int index, int which, int std_length, int control, int leng | |||
| last_wcmdq = wcmdq_tail; | |||
| q = wcmdq[wcmdq_tail]; | |||
| q[0] = WCMD_WAVE; | |||
| q[1] = length; // length in samples | |||
| q[1] = length; // length in samples | |||
| q[2] = (intptr_t)(&wavefile_data[index+x]); | |||
| q[3] = wav_scale + (amp << 8); | |||
| WcmdqInc(); | |||
| @@ -381,7 +381,7 @@ static frame_t *AllocFrame() | |||
| // enough to use a round-robin without checks. | |||
| // Only needed for modifying spectra for blending to consonants | |||
| #define N_FRAME_POOL N_WCMDQ | |||
| #define N_FRAME_POOL N_WCMDQ | |||
| static int ix = 0; | |||
| static frame_t frame_pool[N_FRAME_POOL]; | |||
| @@ -393,15 +393,15 @@ static frame_t *AllocFrame() | |||
| static void set_frame_rms(frame_t *fr, int new_rms) | |||
| { | |||
| // Each frame includes its RMS amplitude value, so to set a new | |||
| // RMS just adjust the formant amplitudes by the appropriate ratio | |||
| // Each frame includes its RMS amplitude value, so to set a new | |||
| // RMS just adjust the formant amplitudes by the appropriate ratio | |||
| int x; | |||
| int h; | |||
| int ix; | |||
| static const short sqrt_tab[200] = { | |||
| 0, 64, 90, 110, 128, 143, 156, 169, 181, 192, 202, 212, 221, 230, 239, 247, | |||
| 0, 64, 90, 110, 128, 143, 156, 169, 181, 192, 202, 212, 221, 230, 239, 247, | |||
| 256, 263, 271, 278, 286, 293, 300, 306, 313, 320, 326, 332, 338, 344, 350, 356, | |||
| 362, 367, 373, 378, 384, 389, 394, 399, 404, 409, 414, 419, 424, 429, 434, 438, | |||
| 443, 448, 452, 457, 461, 465, 470, 474, 478, 483, 487, 491, 495, 499, 503, 507, | |||
| @@ -422,11 +422,11 @@ static void set_frame_rms(frame_t *fr, int new_rms) | |||
| return; | |||
| } | |||
| if (fr->rms == 0) return; // check for divide by zero | |||
| if (fr->rms == 0) return; // check for divide by zero | |||
| x = (new_rms * 64)/fr->rms; | |||
| if (x >= 200) x = 199; | |||
| x = sqrt_tab[x]; // sqrt(new_rms/fr->rms)*0x200; | |||
| x = sqrt_tab[x]; // sqrt(new_rms/fr->rms)*0x200; | |||
| for (ix = 0; ix < 8; ix++) { | |||
| h = fr->fheight[ix] * x; | |||
| @@ -436,7 +436,7 @@ static void set_frame_rms(frame_t *fr, int new_rms) | |||
| static void formants_reduce_hf(frame_t *fr, int level) | |||
| { | |||
| // change height of peaks 2 to 8, percentage | |||
| // change height of peaks 2 to 8, percentage | |||
| int ix; | |||
| int x; | |||
| @@ -451,7 +451,8 @@ static void formants_reduce_hf(frame_t *fr, int level) | |||
| static frame_t *CopyFrame(frame_t *frame1, int copy) | |||
| { | |||
| // create a copy of the specified frame in temporary buffer | |||
| // create a copy of the specified frame in temporary buffer | |||
| frame_t *frame2; | |||
| if ((copy == 0) && (frame1->frflags & FRFLAG_COPIED)) { | |||
| @@ -492,7 +493,7 @@ static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj | |||
| fr->ffreq[3] += f3_adj; | |||
| if (flags & 0x20) | |||
| f3_adj = -f3_adj; // . reverse direction for f4,f5 change | |||
| f3_adj = -f3_adj; // reverse direction for f4,f5 change | |||
| fr->ffreq[4] += f3_adj; | |||
| fr->ffreq[5] += f3_adj; | |||
| @@ -521,7 +522,7 @@ static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj | |||
| static int VowelCloseness(frame_t *fr) | |||
| { | |||
| // return a value 0-3 depending on the vowel's f1 | |||
| // return a value 0-3 depending on the vowel's f1 | |||
| int f1; | |||
| if ((f1 = fr->ffreq[1]) < 300) | |||
| @@ -550,11 +551,11 @@ int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsig | |||
| int flags; | |||
| int vcolour; | |||
| #define N_VCOLOUR 2 | |||
| // percentage change for each formant in 256ths | |||
| #define N_VCOLOUR 2 | |||
| // percentage change for each formant in 256ths | |||
| static short vcolouring[N_VCOLOUR][5] = { | |||
| { 243, 272, 256, 256, 256 }, // palatal consonant follows | |||
| { 256, 256, 240, 240, 240 }, // retroflex | |||
| { 243, 272, 256, 256, 256 }, // palatal consonant follows | |||
| { 256, 256, 240, 240, 240 }, // retroflex | |||
| }; | |||
| frame_t *fr = NULL; | |||
| @@ -578,13 +579,13 @@ int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsig | |||
| flags |= 8; | |||
| if (which == 1) { | |||
| /* entry to vowel */ | |||
| // entry to vowel | |||
| fr = CopyFrame(seq[0].frame, 0); | |||
| seq[0].frame = fr; | |||
| seq[0].length = VOWEL_FRONT_LENGTH; | |||
| if (len > 0) | |||
| seq[0].length = len; | |||
| seq[0].frflags |= FRFLAG_LEN_MOD2; // reduce length modification | |||
| seq[0].frflags |= FRFLAG_LEN_MOD2; // reduce length modification | |||
| fr->frflags |= FRFLAG_LEN_MOD2; | |||
| next_rms = seq[1].frame->rms; | |||
| @@ -649,11 +650,11 @@ int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsig | |||
| if (flags & 4) | |||
| fr->frflags |= FRFLAG_FORMANT_RATE; | |||
| if (flags & 2) | |||
| fr->frflags |= FRFLAG_BREAK; // don't merge with next frame | |||
| fr->frflags |= FRFLAG_BREAK; // don't merge with next frame | |||
| } | |||
| if (flags & 0x40) | |||
| DoPause(20, 0); // add a short pause after the consonant | |||
| DoPause(20, 0); // add a short pause after the consonant | |||
| if (flags & 16) | |||
| return len; | |||
| @@ -705,7 +706,7 @@ static void SmoothSpect(void) | |||
| q[3] = (intptr_t)frame2; | |||
| frame1 = frame2; | |||
| } else | |||
| break; // doesn't follow on from previous frame | |||
| break; // doesn't follow on from previous frame | |||
| frame = frame2 = (frame_t *)q[2]; | |||
| modified = 0; | |||
| @@ -714,7 +715,7 @@ static void SmoothSpect(void) | |||
| break; | |||
| if (frame->frflags & FRFLAG_FORMANT_RATE) | |||
| len = (len * 12)/10; // allow slightly greater rate of change for this frame (was 12/10) | |||
| len = (len * 12)/10; // allow slightly greater rate of change for this frame (was 12/10) | |||
| for (pk = 0; pk < 6; pk++) { | |||
| int f1, f2; | |||
| @@ -778,7 +779,7 @@ static void SmoothSpect(void) | |||
| q[2] = (intptr_t)frame2; | |||
| frame1 = frame2; | |||
| } else | |||
| break; // doesn't follow on from previous frame | |||
| break; // doesn't follow on from previous frame | |||
| } | |||
| frame = frame2 = (frame_t *)q[3]; | |||
| @@ -788,7 +789,7 @@ static void SmoothSpect(void) | |||
| break; | |||
| if (frame1->frflags & FRFLAG_FORMANT_RATE) | |||
| len = (len *6)/5; // allow slightly greater rate of change for this frame | |||
| len = (len *6)/5; // allow slightly greater rate of change for this frame | |||
| for (pk = 0; pk < 6; pk++) { | |||
| int f1, f2; | |||
| @@ -868,10 +869,10 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
| length_mod = plist->length; | |||
| if (length_mod == 0) length_mod = 256; | |||
| length_min = (samplerate/70); // greater than one cycle at low pitch (Hz) | |||
| length_min = (samplerate/70); // greater than one cycle at low pitch (Hz) | |||
| if (which == 2) { | |||
| if ((translator->langopts.param[LOPT_LONG_VOWEL_THRESHOLD] > 0) && ((this_ph->std_length >= translator->langopts.param[LOPT_LONG_VOWEL_THRESHOLD]) || (plist->synthflags & SFLAG_LENGTHEN) || (this_ph->phflags & phLONG))) | |||
| length_min *= 2; // ensure long vowels are longer | |||
| length_min *= 2; // ensure long vowels are longer | |||
| } | |||
| if (which == 1) { | |||
| @@ -885,7 +886,7 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
| modn_flags = 0; | |||
| frames = LookupSpect(this_ph, which, fmt_params, &n_frames, plist); | |||
| if (frames == NULL) | |||
| return 0; // not found | |||
| return 0; // not found | |||
| if (fmt_params->fmt_amp != fmt_amplitude) { | |||
| // an amplitude adjustment is specified for this sequence | |||
| @@ -940,7 +941,7 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
| } | |||
| if ((this_ph->type == phVOWEL) && (which == 2)) { | |||
| SmoothSpect(); // process previous syllable | |||
| SmoothSpect(); // process previous syllable | |||
| // remember the point in the output queue of the centre of the vowel | |||
| syllable_centre = wcmdq_tail; | |||
| @@ -949,11 +950,10 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
| length_sum = 0; | |||
| for (frameix = 1; frameix < n_frames; frameix++) { | |||
| length_factor = length_mod; | |||
| if (frames[frameix-1].frflags & FRFLAG_LEN_MOD) { // reduce effect of length mod | |||
| if (frames[frameix-1].frflags & FRFLAG_LEN_MOD) // reduce effect of length mod | |||
| length_factor = (length_mod*(256-speed.lenmod_factor) + 256*speed.lenmod_factor)/256; | |||
| } else if (frames[frameix-1].frflags & FRFLAG_LEN_MOD2) { // reduce effect of length mod, used for the start of a vowel | |||
| else if (frames[frameix-1].frflags & FRFLAG_LEN_MOD2) // reduce effect of length mod, used for the start of a vowel | |||
| length_factor = (length_mod*(256-speed.lenmod2_factor) + 256*speed.lenmod2_factor)/256; | |||
| } | |||
| frame_length = frames[frameix-1].length; | |||
| len = (frame_length * samplerate)/1000; | |||
| @@ -984,7 +984,7 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
| if (frame1->frflags & FRFLAG_MODULATE) | |||
| modulation = 6; | |||
| if ((frameix == n_frames-1) && (modn_flags & 0xf00)) | |||
| modulation |= modn_flags; // before or after a glottal stop | |||
| modulation |= modn_flags; // before or after a glottal stop | |||
| } | |||
| len = frame_lengths[frameix]; | |||
| @@ -1023,8 +1023,9 @@ int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_L | |||
| void DoMarker(int type, int char_posn, int length, int value) | |||
| { | |||
| // This could be used to return an index to the word currently being spoken | |||
| // Type 1=word, 2=sentence, 3=named marker, 4=play audio, 5=end | |||
| // This could be used to return an index to the word currently being spoken | |||
| // Type 1=word, 2=sentence, 3=named marker, 4=play audio, 5=end | |||
| if (WcmdqFree() > 5) { | |||
| wcmdq[wcmdq_tail][0] = WCMD_MARKER + (type << 8); | |||
| wcmdq[wcmdq_tail][1] = (char_posn & 0xffffff) | (length << 24); | |||
| @@ -1035,15 +1036,16 @@ void DoMarker(int type, int char_posn, int length, int value) | |||
| void DoPhonemeMarker(int type, int char_posn, int length, char *name) | |||
| { | |||
| // This could be used to return an index to the word currently being spoken | |||
| // Type 7=phoneme | |||
| // This could be used to return an index to the word currently being spoken | |||
| // Type 7=phoneme | |||
| int *p; | |||
| if (WcmdqFree() > 5) { | |||
| wcmdq[wcmdq_tail][0] = WCMD_MARKER + (type << 8); | |||
| wcmdq[wcmdq_tail][1] = (char_posn & 0xffffff) | (length << 24); | |||
| p = (int *)name; | |||
| wcmdq[wcmdq_tail][2] = p[0]; // up to 8 bytes of UTF8 characters | |||
| wcmdq[wcmdq_tail][2] = p[0]; // up to 8 bytes of UTF8 characters | |||
| wcmdq[wcmdq_tail][3] = p[1]; | |||
| WcmdqInc(); | |||
| } | |||
| @@ -1052,7 +1054,7 @@ void DoPhonemeMarker(int type, int char_posn, int length, char *name) | |||
| #if HAVE_SONIC_H | |||
| void DoSonicSpeed(int value) | |||
| { | |||
| // value, multiplier * 1024 | |||
| // value, multiplier * 1024 | |||
| wcmdq[wcmdq_tail][0] = WCMD_SONIC_SPEED; | |||
| wcmdq[wcmdq_tail][1] = value; | |||
| WcmdqInc(); | |||
| @@ -1061,7 +1063,7 @@ void DoSonicSpeed(int value) | |||
| void DoVoiceChange(voice_t *v) | |||
| { | |||
| // allocate memory for a copy of the voice data, and free it in wavegenfill() | |||
| // allocate memory for a copy of the voice data, and free it in wavegenfill() | |||
| voice_t *v2; | |||
| v2 = (voice_t *)malloc(sizeof(voice_t)); | |||
| @@ -1074,7 +1076,7 @@ void DoVoiceChange(voice_t *v) | |||
| void DoEmbedded(int *embix, int sourceix) | |||
| { | |||
| // There were embedded commands in the text at this point | |||
| unsigned int word; // bit 7=last command for this word, bits 5,6 sign, bits 0-4 command | |||
| unsigned int word; // bit 7=last command for this word, bits 5,6 sign, bits 0-4 command | |||
| unsigned int value; | |||
| int command; | |||
| @@ -1084,36 +1086,36 @@ void DoEmbedded(int *embix, int sourceix) | |||
| command = word & 0x7f; | |||
| if (command == 0) | |||
| return; // error | |||
| return; // error | |||
| (*embix)++; | |||
| switch (command & 0x1f) | |||
| { | |||
| case EMBED_S: // speed | |||
| SetEmbedded((command & 0x60) + EMBED_S2, value); // adjusts embedded_value[EMBED_S2] | |||
| case EMBED_S: // speed | |||
| SetEmbedded((command & 0x60) + EMBED_S2, value); // adjusts embedded_value[EMBED_S2] | |||
| SetSpeed(2); | |||
| break; | |||
| case EMBED_I: // play dynamically loaded wav data (sound icon) | |||
| case EMBED_I: // play dynamically loaded wav data (sound icon) | |||
| if ((int)value < n_soundicon_tab) { | |||
| if (soundicon_tab[value].length != 0) { | |||
| DoPause(10, 0); // ensure a break in the speech | |||
| DoPause(10, 0); // ensure a break in the speech | |||
| wcmdq[wcmdq_tail][0] = WCMD_WAVE; | |||
| wcmdq[wcmdq_tail][1] = soundicon_tab[value].length; | |||
| wcmdq[wcmdq_tail][2] = (intptr_t)soundicon_tab[value].data + 44; // skip WAV header | |||
| wcmdq[wcmdq_tail][3] = 0x1500; // 16 bit data, amp=21 | |||
| wcmdq[wcmdq_tail][2] = (intptr_t)soundicon_tab[value].data + 44; // skip WAV header | |||
| wcmdq[wcmdq_tail][3] = 0x1500; // 16 bit data, amp=21 | |||
| WcmdqInc(); | |||
| } | |||
| } | |||
| break; | |||
| case EMBED_M: // named marker | |||
| case EMBED_M: // named marker | |||
| DoMarker(espeakEVENT_MARK, (sourceix & 0x7ff) + clause_start_char, 0, value); | |||
| break; | |||
| case EMBED_U: // play sound | |||
| DoMarker(espeakEVENT_PLAY, count_characters+1, 0, value); // always occurs at end of clause | |||
| case EMBED_U: // play sound | |||
| DoMarker(espeakEVENT_PLAY, count_characters+1, 0, value); // always occurs at end of clause | |||
| break; | |||
| default: | |||
| DoPause(10, 0); // ensure a break in the speech | |||
| DoPause(10, 0); // ensure a break in the speech | |||
| wcmdq[wcmdq_tail][0] = WCMD_EMBEDDED; | |||
| wcmdq[wcmdq_tail][1] = command; | |||
| wcmdq[wcmdq_tail][2] = value; | |||
| @@ -1177,7 +1179,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| last_pitch_cmd = -1; | |||
| memset(vowel_transition, 0, sizeof(vowel_transition)); | |||
| memset(&worddata, 0, sizeof(worddata)); | |||
| DoPause(0, 0); // isolate from the previous clause | |||
| DoPause(0, 0); // isolate from the previous clause | |||
| } | |||
| while ((ix < (*n_ph)) && (ix < N_PHONEME_LIST-2)) { | |||
| @@ -1186,12 +1188,12 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| if (p->type == phPAUSE) | |||
| free_min = 10; | |||
| else if (p->type != phVOWEL) | |||
| free_min = 15; // we need less Q space for non-vowels, and we need to generate phonemes after a vowel so that the pitch_length is filled in | |||
| free_min = 15; // we need less Q space for non-vowels, and we need to generate phonemes after a vowel so that the pitch_length is filled in | |||
| else | |||
| free_min = MIN_WCMDQ; // 25 | |||
| free_min = MIN_WCMDQ; | |||
| if (WcmdqFree() <= free_min) | |||
| return 1; // wait | |||
| return 1; // wait | |||
| prev = &phoneme_list[ix-1]; | |||
| next = &phoneme_list[ix+1]; | |||
| @@ -1209,10 +1211,10 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| sourceix = (p->sourceix & 0x7ff) + clause_start_char; | |||
| if (p->newword & 4) | |||
| DoMarker(espeakEVENT_SENTENCE, sourceix, 0, count_sentences); // start of sentence | |||
| DoMarker(espeakEVENT_SENTENCE, sourceix, 0, count_sentences); // start of sentence | |||
| if (p->newword & 1) | |||
| DoMarker(espeakEVENT_WORD, sourceix, p->sourceix >> 11, clause_start_word + word_count++); // NOTE, this count doesn't include multiple-word pronunciations in *_list. eg (of a) | |||
| DoMarker(espeakEVENT_WORD, sourceix, p->sourceix >> 11, clause_start_word + word_count++); // NOTE, this count doesn't include multiple-word pronunciations in *_list. eg (of a) | |||
| } | |||
| EndAmplitude(); | |||
| @@ -1271,7 +1273,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| InterpretPhoneme(NULL, 0, p, &phdata, &worddata); | |||
| if (p->synthflags & SFLAG_LENGTHEN) | |||
| DoSample3(&phdata, p->length, 0); // play it twice for [s:] etc. | |||
| DoSample3(&phdata, p->length, 0); // play it twice for [s:] etc. | |||
| DoSample3(&phdata, p->length, 0); | |||
| break; | |||
| case phVSTOP: | |||
| @@ -1381,7 +1383,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| } else if (prev->type == phVOWEL && (p->synthflags & SFLAG_SEQCONTINUE)) | |||
| DoSpect2(p->ph, 0, &fmtp, p, 0); | |||
| else { | |||
| last_frame = NULL; // only for nasal ? | |||
| last_frame = NULL; // only for nasal ? | |||
| DoSpect2(p->ph, 0, &fmtp, p, 0); | |||
| last_frame = NULL; | |||
| } | |||
| @@ -1461,23 +1463,23 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| modulation = 2; | |||
| if (stress <= 1) | |||
| modulation = 1; // 16ths | |||
| modulation = 1; // 16ths | |||
| else if (stress >= 7) | |||
| modulation = 3; | |||
| if (prev->type == phVSTOP || prev->type == phVFRICATIVE) { | |||
| DoAmplitude(p->amp, amp_env); | |||
| DoPitch(pitch_env, p->pitch1, p->pitch2); // don't use prevocalic rising tone | |||
| DoPitch(pitch_env, p->pitch1, p->pitch2); // don't use prevocalic rising tone | |||
| DoSpect2(ph, 1, &fmtp, p, modulation); | |||
| } else if (prev->type == phLIQUID || prev->type == phNASAL) { | |||
| DoAmplitude(p->amp, amp_env); | |||
| DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone | |||
| DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone | |||
| DoPitch(pitch_env, p->pitch1, p->pitch2); | |||
| } else if (vowelstart_prev) { | |||
| // VowelStart from the previous phoneme, but not phLIQUID or phNASAL | |||
| DoPitch(envelope_data[PITCHrise], p->pitch2 - 15, p->pitch2); | |||
| DoAmplitude(p->amp-1, amp_env); | |||
| DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone | |||
| DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone | |||
| DoPitch(pitch_env, p->pitch1, p->pitch2); | |||
| } else { | |||
| if (!(p->synthflags & SFLAG_SEQCONTINUE)) { | |||
| @@ -1505,12 +1507,11 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| InterpretPhoneme(NULL, 0, next, &phdata_next, NULL); | |||
| fmtp.use_vowelin = 1; | |||
| fmtp.transition0 = phdata_next.vowel_transition[2]; // always do vowel_transition, even if ph_VWLEND ?? consider [N] | |||
| fmtp.transition0 = phdata_next.vowel_transition[2]; // always do vowel_transition, even if ph_VWLEND ?? consider [N] | |||
| fmtp.transition1 = phdata_next.vowel_transition[3]; | |||
| if ((fmtp.fmt2_addr = phdata_next.sound_addr[pd_VWLEND]) != 0) { | |||
| if ((fmtp.fmt2_addr = phdata_next.sound_addr[pd_VWLEND]) != 0) | |||
| fmtp.fmt2_lenadj = phdata_next.sound_param[pd_VWLEND]; | |||
| } | |||
| } | |||
| DoSpect2(ph, 2, &fmtp, p, modulation); | |||
| @@ -1520,11 +1521,11 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
| } | |||
| EndPitch(1); | |||
| if (*n_ph > 0) { | |||
| DoMarker(espeakEVENT_END, count_characters, 0, count_sentences); // end of clause | |||
| DoMarker(espeakEVENT_END, count_characters, 0, count_sentences); // end of clause | |||
| *n_ph = 0; | |||
| } | |||
| return 0; // finished the phoneme list | |||
| return 0; // finished the phoneme list | |||
| } | |||
| static int timer_on = 0; | |||
| @@ -1553,16 +1554,16 @@ int SynthStatus() | |||
| int SpeakNextClause(FILE *f_in, const void *text_in, int control) | |||
| { | |||
| // Speak text from file (f_in) or memory (text_in) | |||
| // control 0: start | |||
| // either f_in or text_in is set, the other must be NULL | |||
| // Speak text from file (f_in) or memory (text_in) | |||
| // control 0: start | |||
| // either f_in or text_in is set, the other must be NULL | |||
| // The other calls have f_in and text_in = NULL | |||
| // control 1: speak next text | |||
| // 2: stop | |||
| // 3: pause (toggle) | |||
| // 4: is file being read (0=no, 1=yes) | |||
| // 5: interrupt and flush current text. | |||
| // The other calls have f_in and text_in = NULL | |||
| // control 1: speak next text | |||
| // 2: stop | |||
| // 3: pause (toggle) | |||
| // 4: is file being read (0=no, 1=yes) | |||
| // 5: interrupt and flush current text. | |||
| int clause_tone; | |||
| char *voice_change; | |||
| @@ -1600,7 +1601,7 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control) | |||
| WavegenOpenSound(); | |||
| timer_on = 1; | |||
| paused = 0; | |||
| Generate(phoneme_list, &n_phoneme_list, 0); // re-start from beginning of clause | |||
| Generate(phoneme_list, &n_phoneme_list, 0); // re-start from beginning of clause | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -1650,7 +1651,6 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control) | |||
| phoneme_callback(phon_out); | |||
| } | |||
| if (skipping_text) { | |||
| n_phoneme_list = 0; | |||
| return 1; | |||
| @@ -22,69 +22,67 @@ extern "C" | |||
| { | |||
| #endif | |||
| #define espeakINITIALIZE_PHONEME_IPA 0x0002 // move this to speak_lib.h, after eSpeak version 1.46.02 | |||
| #define espeakINITIALIZE_PHONEME_IPA 0x0002 // move this to speak_lib.h, after eSpeak version 1.46.02 | |||
| #define N_PHONEME_LIST 1000 // enough for source[N_TR_SOURCE] full of text, else it will truncate | |||
| #define N_PHONEME_LIST 1000 // enough for source[N_TR_SOURCE] full of text, else it will truncate | |||
| #define MAX_HARMONIC 400 // 400 * 50Hz = 20 kHz, more than enough | |||
| #define N_SEQ_FRAMES 25 // max frames in a spectrum sequence (real max is ablut 8) | |||
| #define STEPSIZE 64 // 2.9mS at 22 kHz sample rate | |||
| #define MAX_HARMONIC 400 // 400 * 50Hz = 20 kHz, more than enough | |||
| #define N_SEQ_FRAMES 25 // max frames in a spectrum sequence (real max is ablut 8) | |||
| #define STEPSIZE 64 // 2.9mS at 22 kHz sample rate | |||
| // flags set for frames within a spectrum sequence | |||
| #define FRFLAG_KLATT 0x01 // this frame includes extra data for Klatt synthesizer | |||
| #define FRFLAG_VOWEL_CENTRE 0x02 // centre point of vowel | |||
| #define FRFLAG_LEN_MOD 0x04 // reduce effect of length adjustment | |||
| #define FRFLAG_BREAK_LF 0x08 // but keep f3 upwards | |||
| #define FRFLAG_BREAK 0x10 // don't merge with next frame | |||
| #define FRFLAG_BREAK_2 0x18 // FRFLAG_BREAK_LF or FRFLAG_BREAK | |||
| #define FRFLAG_FORMANT_RATE 0x20 // Flag5 allow increased rate of change of formant freq | |||
| #define FRFLAG_MODULATE 0x40 // Flag6 modulate amplitude of some cycles to give trill | |||
| #define FRFLAG_DEFER_WAV 0x80 // Flag7 defer mixing WAV until the next frame | |||
| #define FRFLAG_LEN_MOD2 0x4000 // reduce effect of length adjustment, used for the start of a vowel | |||
| #define FRFLAG_COPIED 0x8000 // This frame has been copied into temporary rw memory | |||
| #define SFLAG_SEQCONTINUE 0x01 // a liquid or nasal after a vowel, but not followed by a vowel | |||
| #define SFLAG_EMBEDDED 0x02 // there are embedded commands before this phoneme | |||
| #define SFLAG_SYLLABLE 0x04 // vowel or syllabic consonant | |||
| #define SFLAG_LENGTHEN 0x08 // lengthen symbol : included after this phoneme | |||
| #define SFLAG_DICTIONARY 0x10 // the pronunciation of this word was listed in the xx_list dictionary | |||
| #define SFLAG_SWITCHED_LANG 0x20 // this word uses phonemes from a different language | |||
| #define SFLAG_PROMOTE_STRESS 0x40 // this unstressed word can be promoted to stressed | |||
| #define SFLAG_PREV_PAUSE 0x1000 // consider previous phoneme as pause | |||
| #define SFLAG_NEXT_PAUSE 0x2000 // consider next phoneme as pause | |||
| #define FRFLAG_KLATT 0x01 // this frame includes extra data for Klatt synthesizer | |||
| #define FRFLAG_VOWEL_CENTRE 0x02 // centre point of vowel | |||
| #define FRFLAG_LEN_MOD 0x04 // reduce effect of length adjustment | |||
| #define FRFLAG_BREAK_LF 0x08 // but keep f3 upwards | |||
| #define FRFLAG_BREAK 0x10 // don't merge with next frame | |||
| #define FRFLAG_BREAK_2 0x18 // FRFLAG_BREAK_LF or FRFLAG_BREAK | |||
| #define FRFLAG_FORMANT_RATE 0x20 // Flag5 allow increased rate of change of formant freq | |||
| #define FRFLAG_MODULATE 0x40 // Flag6 modulate amplitude of some cycles to give trill | |||
| #define FRFLAG_DEFER_WAV 0x80 // Flag7 defer mixing WAV until the next frame | |||
| #define FRFLAG_LEN_MOD2 0x4000 // reduce effect of length adjustment, used for the start of a vowel | |||
| #define FRFLAG_COPIED 0x8000 // This frame has been copied into temporary rw memory | |||
| #define SFLAG_SEQCONTINUE 0x01 // a liquid or nasal after a vowel, but not followed by a vowel | |||
| #define SFLAG_EMBEDDED 0x02 // there are embedded commands before this phoneme | |||
| #define SFLAG_SYLLABLE 0x04 // vowel or syllabic consonant | |||
| #define SFLAG_LENGTHEN 0x08 // lengthen symbol : included after this phoneme | |||
| #define SFLAG_DICTIONARY 0x10 // the pronunciation of this word was listed in the xx_list dictionary | |||
| #define SFLAG_SWITCHED_LANG 0x20 // this word uses phonemes from a different language | |||
| #define SFLAG_PROMOTE_STRESS 0x40 // this unstressed word can be promoted to stressed | |||
| #define SFLAG_PREV_PAUSE 0x1000 // consider previous phoneme as pause | |||
| #define SFLAG_NEXT_PAUSE 0x2000 // consider next phoneme as pause | |||
| // embedded command numbers | |||
| #define EMBED_P 1 // pitch | |||
| #define EMBED_S 2 // speed (used in setlengths) | |||
| #define EMBED_A 3 // amplitude/volume | |||
| #define EMBED_R 4 // pitch range/expression | |||
| #define EMBED_H 5 // echo/reverberation | |||
| #define EMBED_T 6 // different tone for announcing punctuation (not used) | |||
| #define EMBED_I 7 // sound icon | |||
| #define EMBED_S2 8 // speed (used in synthesize) | |||
| #define EMBED_Y 9 // say-as commands | |||
| #define EMBED_M 10 // mark name | |||
| #define EMBED_U 11 // audio uri | |||
| #define EMBED_B 12 // break | |||
| #define EMBED_F 13 // emphasis | |||
| #define EMBED_C 14 // capital letter indication | |||
| #define EMBED_P 1 // pitch | |||
| #define EMBED_S 2 // speed (used in setlengths) | |||
| #define EMBED_A 3 // amplitude/volume | |||
| #define EMBED_R 4 // pitch range/expression | |||
| #define EMBED_H 5 // echo/reverberation | |||
| #define EMBED_T 6 // different tone for announcing punctuation (not used) | |||
| #define EMBED_I 7 // sound icon | |||
| #define EMBED_S2 8 // speed (used in synthesize) | |||
| #define EMBED_Y 9 // say-as commands | |||
| #define EMBED_M 10 // mark name | |||
| #define EMBED_U 11 // audio uri | |||
| #define EMBED_B 12 // break | |||
| #define EMBED_F 13 // emphasis | |||
| #define EMBED_C 14 // capital letter indication | |||
| #define N_EMBEDDED_VALUES 15 | |||
| extern int embedded_value[N_EMBEDDED_VALUES]; | |||
| extern int embedded_default[N_EMBEDDED_VALUES]; | |||
| #define N_PEAKS 9 | |||
| #define N_PEAKS2 9 // plus Notch and Fill (not yet implemented) | |||
| #define N_PEAKS2 9 // plus Notch and Fill (not yet implemented) | |||
| #define N_MARKERS 8 | |||
| #define N_KLATTP 10 // this affects the phoneme data file format | |||
| #define N_KLATTP2 14 // used in vowel files, with extra parameters for future extensions | |||
| #define N_KLATTP 10 // this affects the phoneme data file format | |||
| #define N_KLATTP2 14 // used in vowel files, with extra parameters for future extensions | |||
| #define KLATT_AV 0 | |||
| #define KLATT_FNZ 1 // nasal zero freq | |||
| #define KLATT_FNZ 1 // nasal zero freq | |||
| #define KLATT_Tilt 2 | |||
| #define KLATT_Aspr 3 | |||
| #define KLATT_Skew 4 | |||
| @@ -95,38 +93,33 @@ extern int embedded_default[N_EMBEDDED_VALUES]; | |||
| #define KLATT_FricBP 8 | |||
| #define KLATT_Turb 9 | |||
| typedef struct { // 64 bytes | |||
| typedef struct { // 64 bytes | |||
| short frflags; | |||
| short ffreq[7]; | |||
| unsigned char length; | |||
| unsigned char rms; | |||
| unsigned char fheight[8]; | |||
| unsigned char fwidth[6]; // width/4 f0-5 | |||
| unsigned char fright[3]; // width/4 f0-2 | |||
| unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 | |||
| unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew | |||
| unsigned char klattp2[5]; // continuation of klattp[], Avp, Fric, FricBP, Turb | |||
| unsigned char klatt_ap[7]; // Klatt parallel amplitude | |||
| unsigned char klatt_bp[7]; // Klatt parallel bandwidth /2 | |||
| unsigned char spare; // pad to multiple of 4 bytes | |||
| } frame_t; // with extra Klatt parameters for parallel resonators | |||
| typedef struct { // 44 bytes | |||
| unsigned char fwidth[6]; // width/4 f0-5 | |||
| unsigned char fright[3]; // width/4 f0-2 | |||
| unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 | |||
| unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew | |||
| unsigned char klattp2[5]; // continuation of klattp[], Avp, Fric, FricBP, Turb | |||
| unsigned char klatt_ap[7]; // Klatt parallel amplitude | |||
| unsigned char klatt_bp[7]; // Klatt parallel bandwidth /2 | |||
| unsigned char spare; // pad to multiple of 4 bytes | |||
| } frame_t; // with extra Klatt parameters for parallel resonators | |||
| typedef struct { // 44 bytes | |||
| short frflags; | |||
| short ffreq[7]; | |||
| unsigned char length; | |||
| unsigned char rms; | |||
| unsigned char fheight[8]; | |||
| unsigned char fwidth[6]; // width/4 f0-5 | |||
| unsigned char fright[3]; // width/4 f0-2 | |||
| unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 | |||
| unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew | |||
| } frame_t2; // without the extra Klatt parameters | |||
| unsigned char fwidth[6]; // width/4 f0-5 | |||
| unsigned char fright[3]; // width/4 f0-2 | |||
| unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 | |||
| unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew | |||
| } frame_t2; // without the extra Klatt parameters | |||
| // formant data used by wavegen | |||
| typedef struct { | |||
| @@ -138,11 +131,11 @@ typedef struct { | |||
| DOUBLEX height1; | |||
| DOUBLEX left1; | |||
| DOUBLEX right1; | |||
| DOUBLEX freq_inc; // increment by this every 64 samples | |||
| DOUBLEX freq_inc; // increment by this every 64 samples | |||
| DOUBLEX height_inc; | |||
| DOUBLEX left_inc; | |||
| DOUBLEX right_inc; | |||
| } wavegen_peaks_t; | |||
| } wavegen_peaks_t; | |||
| typedef struct { | |||
| unsigned char *pitch_env; | |||
| @@ -153,8 +146,8 @@ typedef struct { | |||
| int pitch_range; // Hz*256 range of envelope | |||
| unsigned char *mix_wavefile; // wave file to be added to synthesis | |||
| int n_mix_wavefile; // length in bytes | |||
| int mix_wave_scale; // 0=2 byte samples | |||
| int n_mix_wavefile; // length in bytes | |||
| int mix_wave_scale; // 0=2 byte samples | |||
| int mix_wave_amp; | |||
| int mix_wavefile_ix; | |||
| int mix_wavefile_max; // length of available WAV data (in bytes) | |||
| @@ -165,30 +158,27 @@ typedef struct { | |||
| int amplitude_fmt; // percentage amplitude adjustment for formant synthesis | |||
| } WGEN_DATA; | |||
| typedef struct { | |||
| double a; | |||
| double b; | |||
| double c; | |||
| double x1; | |||
| double x2; | |||
| } RESONATOR; | |||
| } RESONATOR; | |||
| typedef struct { | |||
| short length_total; // not used | |||
| unsigned char n_frames; | |||
| unsigned char sqflags; | |||
| frame_t2 frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence | |||
| } SPECT_SEQ; // sequence of espeak formant frames | |||
| frame_t2 frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence | |||
| } SPECT_SEQ; // sequence of espeak formant frames | |||
| typedef struct { | |||
| short length_total; // not used | |||
| unsigned char n_frames; | |||
| unsigned char sqflags; | |||
| frame_t frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence | |||
| } SPECT_SEQK; // sequence of klatt formants frames | |||
| frame_t frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence | |||
| } SPECT_SEQK; // sequence of klatt formants frames | |||
| typedef struct { | |||
| short length; | |||
| @@ -198,22 +188,21 @@ typedef struct { | |||
| // a clause translated into phoneme codes (first stage) | |||
| typedef struct { | |||
| unsigned short synthflags; // NOTE Put shorts on 32bit boundaries, because of RISC OS compiler bug? | |||
| unsigned short synthflags; // NOTE Put shorts on 32bit boundaries, because of RISC OS compiler bug? | |||
| unsigned char phcode; | |||
| unsigned char stresslevel; | |||
| unsigned short sourceix; // ix into the original source text string, only set at the start of a word | |||
| unsigned char wordstress; // the highest level stress in this word | |||
| unsigned char wordstress; // the highest level stress in this word | |||
| unsigned char tone_ph; // tone phoneme to use with this vowel | |||
| } PHONEME_LIST2; | |||
| typedef struct { | |||
| // The first section is a copy of PHONEME_LIST2 | |||
| // The first section is a copy of PHONEME_LIST2 | |||
| unsigned short synthflags; | |||
| unsigned char phcode; | |||
| unsigned char stresslevel; | |||
| unsigned short sourceix; // ix into the original source text string, only set at the start of a word | |||
| unsigned char wordstress; // the highest level stress in this word | |||
| unsigned char wordstress; // the highest level stress in this word | |||
| unsigned char tone_ph; // tone phoneme to use with this vowel | |||
| PHONEME_TAB *ph; | |||
| @@ -231,7 +220,6 @@ typedef struct { | |||
| int sound_param; | |||
| } PHONEME_LIST; | |||
| #define pd_FMT 0 | |||
| #define pd_WAV 1 | |||
| #define pd_VWLSTART 2 | |||
| @@ -259,7 +247,6 @@ typedef struct { | |||
| char ipa_string[18]; | |||
| } PHONEME_DATA; | |||
| typedef struct { | |||
| int fmt_control; | |||
| int use_vowelin; | |||
| @@ -304,7 +291,6 @@ typedef struct { | |||
| #define i_ADD_LENGTH 0x0c | |||
| // conditions and jumps | |||
| #define i_CONDITION 0x2000 | |||
| #define i_OR 0x1000 // added to i_CONDITION | |||
| @@ -347,23 +333,20 @@ typedef struct { | |||
| #define i_isSeqFlag1 0x8f | |||
| #define i_IsTranslationGiven 0x90 | |||
| // place of articulation | |||
| #define i_isVel 0x28 | |||
| // phflags | |||
| #define i_isSibilant 0x45 // bit 5 in phflags | |||
| #define i_isPalatal 0x49 // bit 9 in phflags | |||
| #define i_isLong 0x55 // bit 21 in phflags | |||
| #define i_isRhotic 0x57 // bit 23 in phflags | |||
| #define i_isSibilant 0x45 // bit 5 in phflags | |||
| #define i_isPalatal 0x49 // bit 9 in phflags | |||
| #define i_isLong 0x55 // bit 21 in phflags | |||
| #define i_isRhotic 0x57 // bit 23 in phflags | |||
| #define i_isFlag1 0x5c | |||
| #define i_isFlag2 0x5d | |||
| #define i_isFlag3 0x5e | |||
| #define i_StressLevel 0x800 | |||
| typedef struct { | |||
| int name; | |||
| int length; | |||
| @@ -376,7 +359,7 @@ typedef struct { | |||
| unsigned int next_phoneme; | |||
| int mbr_name; | |||
| int mbr_name2; | |||
| int percent; // percentage length of first component | |||
| int percent; // percentage length of first component | |||
| int control; | |||
| } MBROLA_TAB; | |||
| @@ -392,7 +375,6 @@ typedef struct { | |||
| int fast_settings[8]; | |||
| } SPEED_FACTORS; | |||
| typedef struct { | |||
| char name[12]; | |||
| unsigned char flags[4]; | |||
| @@ -413,14 +395,14 @@ typedef struct { | |||
| unsigned char head_max_steps; | |||
| unsigned char n_head_extend; | |||
| signed char unstr_start[3]; // for: onset, head, last | |||
| signed char unstr_start[3]; // for: onset, head, last | |||
| signed char unstr_end[3]; | |||
| unsigned char nucleus0_env; // pitch envelope, tonic syllable is at end, no tail | |||
| unsigned char nucleus0_env; // pitch envelope, tonic syllable is at end, no tail | |||
| unsigned char nucleus0_max; | |||
| unsigned char nucleus0_min; | |||
| unsigned char nucleus1_env; // when followed by a tail | |||
| unsigned char nucleus1_env; // when followed by a tail | |||
| unsigned char nucleus1_max; | |||
| unsigned char nucleus1_min; | |||
| unsigned char tail_start; | |||
| @@ -434,7 +416,7 @@ typedef struct { | |||
| unsigned char split_tune; | |||
| unsigned char spare[8]; | |||
| int spare2; // the struct length should be a multiple of 4 bytes | |||
| int spare2; // the struct length should be a multiple of 4 bytes | |||
| } TUNE; | |||
| extern int n_tunes; | |||
| @@ -472,8 +454,6 @@ extern unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1]; | |||
| #define WCMD_FMT_AMPLITUDE 14 | |||
| #define WCMD_SONIC_SPEED 15 | |||
| #define N_WCMDQ 170 | |||
| #define MIN_WCMDQ 25 // need this many free entries before adding new phoneme | |||
| @@ -494,7 +474,6 @@ float polint(float xa[], float ya[], int n, float x); | |||
| int WavegenFill(int fill_zeros); | |||
| void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr); | |||
| extern unsigned char *wavefile_data; | |||
| extern int samplerate; | |||
| extern int samplerate_native; | |||
| @@ -538,10 +517,9 @@ int Read4Bytes(FILE *f); | |||
| int Reverse4Bytes(int word); | |||
| int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name, int flags); | |||
| #define ENV_LEN 128 // length of pitch envelopes | |||
| #define PITCHfall 0 // standard pitch envelopes | |||
| #define PITCHrise 2 | |||
| #define PITCHfall 0 // standard pitch envelopes | |||
| #define PITCHrise 2 | |||
| #define N_ENVELOPE_DATA 20 | |||
| extern unsigned char *envelope_data[N_ENVELOPE_DATA]; | |||
| @@ -22,99 +22,96 @@ extern "C" | |||
| { | |||
| #endif | |||
| #define L(c1, c2) (c1<<8)+c2 // combine two characters into an integer for translator name | |||
| #define L(c1, c2) (c1<<8)+c2 // combine two characters into an integer for translator name | |||
| #define CTRL_EMBEDDED 0x01 // control character at the start of an embedded command | |||
| #define REPLACED_E 'E' // 'e' replaced by silent e | |||
| #define CTRL_EMBEDDED 0x01 // control character at the start of an embedded command | |||
| #define REPLACED_E 'E' // 'e' replaced by silent e | |||
| #define N_WORD_PHONEMES 200 // max phonemes in a word | |||
| #define N_WORD_BYTES 160 // max bytes for the UTF8 characters in a word | |||
| #define N_CLAUSE_WORDS 300 // max words in a clause | |||
| #define N_TR_SOURCE 800 // the source text of a single clause (UTF8 bytes) | |||
| #define N_WORD_PHONEMES 200 // max phonemes in a word | |||
| #define N_WORD_BYTES 160 // max bytes for the UTF8 characters in a word | |||
| #define N_CLAUSE_WORDS 300 // max words in a clause | |||
| #define N_TR_SOURCE 800 // the source text of a single clause (UTF8 bytes) | |||
| #define N_RULE_GROUP2 120 // max num of two-letter rule chains | |||
| #define N_RULE_GROUP2 120 // max num of two-letter rule chains | |||
| #define N_HASH_DICT 1024 | |||
| #define N_CHARSETS 20 | |||
| #define N_LETTER_GROUPS 95 // maximum is 127-32 | |||
| #define N_LETTER_GROUPS 95 // maximum is 127-32 | |||
| /* dictionary flags, word 1 */ | |||
| // dictionary flags, word 1 | |||
| // bits 0-3 stressed syllable, bit 6=unstressed | |||
| #define FLAG_SKIPWORDS 0x80 | |||
| #define FLAG_PREPAUSE 0x100 | |||
| #define FLAG_STRESS_END 0x200 // full stress if at end of clause | |||
| #define FLAG_STRESS_END2 0x400 // full stress if at end of clause, or only followed by unstressed | |||
| #define FLAG_UNSTRESS_END 0x800 // reduce stress at end of clause | |||
| #define FLAG_SPELLWORD 0x1000 // re-translate the word as individual letters, separated by spaces | |||
| #define FLAG_ACCENT_BEFORE 0x1000 // say this accent name before the letter name | |||
| #define FLAG_ABBREV 0x2000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters | |||
| #define FLAG_DOUBLING 0x4000 // doubles the following consonant | |||
| #define BITNUM_FLAG_ALT 14 // bit number of FLAG_ALT_TRANS - 1 | |||
| #define FLAG_ALT_TRANS 0x8000 // language specific | |||
| #define FLAG_ALT2_TRANS 0x10000 // language specific | |||
| #define FLAG_ALT3_TRANS 0x20000 // language specific | |||
| #define FLAG_ALT4_TRANS 0x40000 // language specific | |||
| #define FLAG_ALT5_TRANS 0x80000 // language specific | |||
| #define FLAG_ALT6_TRANS 0x100000 // language specific | |||
| #define FLAG_ALT7_TRANS 0x200000 // language specific | |||
| #define FLAG_COMBINE 0x800000 // combine with the next word | |||
| #define FLAG_ALLOW_DOT 0x01000000 // ignore '.' after word (abbreviation) | |||
| #define FLAG_NEEDS_DOT 0x02000000 // only if the word is followed by a dot | |||
| #define FLAG_STRESS_END 0x200 // full stress if at end of clause | |||
| #define FLAG_STRESS_END2 0x400 // full stress if at end of clause, or only followed by unstressed | |||
| #define FLAG_UNSTRESS_END 0x800 // reduce stress at end of clause | |||
| #define FLAG_SPELLWORD 0x1000 // re-translate the word as individual letters, separated by spaces | |||
| #define FLAG_ACCENT_BEFORE 0x1000 // say this accent name before the letter name | |||
| #define FLAG_ABBREV 0x2000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters | |||
| #define FLAG_DOUBLING 0x4000 // doubles the following consonant | |||
| #define BITNUM_FLAG_ALT 14 // bit number of FLAG_ALT_TRANS - 1 | |||
| #define FLAG_ALT_TRANS 0x8000 // language specific | |||
| #define FLAG_ALT2_TRANS 0x10000 // language specific | |||
| #define FLAG_ALT3_TRANS 0x20000 // language specific | |||
| #define FLAG_ALT4_TRANS 0x40000 // language specific | |||
| #define FLAG_ALT5_TRANS 0x80000 // language specific | |||
| #define FLAG_ALT6_TRANS 0x100000 // language specific | |||
| #define FLAG_ALT7_TRANS 0x200000 // language specific | |||
| #define FLAG_COMBINE 0x800000 // combine with the next word | |||
| #define FLAG_ALLOW_DOT 0x01000000 // ignore '.' after word (abbreviation) | |||
| #define FLAG_NEEDS_DOT 0x02000000 // only if the word is followed by a dot | |||
| #define FLAG_WAS_UNPRONOUNCABLE 0x04000000 // the unpronounceable routine was used | |||
| #define FLAG_MAX3 0x08000000 // limit to 3 repeats | |||
| #define FLAG_PAUSE1 0x10000000 // shorter prepause | |||
| #define FLAG_TEXTMODE 0x20000000 // word translates to replacement text, not phonemes | |||
| #define FLAG_MAX3 0x08000000 // limit to 3 repeats | |||
| #define FLAG_PAUSE1 0x10000000 // shorter prepause | |||
| #define FLAG_TEXTMODE 0x20000000 // word translates to replacement text, not phonemes | |||
| #define BITNUM_FLAG_TEXTMODE 29 | |||
| #define FLAG_FOUND_ATTRIBUTES 0x40000000 // word was found in the dictionary list (has attributes) | |||
| #define FLAG_FOUND 0x80000000 // pronunciation was found in the dictionary list | |||
| #define FLAG_FOUND_ATTRIBUTES 0x40000000 // word was found in the dictionary list (has attributes) | |||
| #define FLAG_FOUND 0x80000000 // pronunciation was found in the dictionary list | |||
| // dictionary flags, word 2 | |||
| #define FLAG_VERBF 0x1 /* verb follows */ | |||
| #define FLAG_VERBSF 0x2 /* verb follows, may have -s suffix */ | |||
| #define FLAG_NOUNF 0x4 /* noun follows */ | |||
| #define FLAG_PASTF 0x8 /* past tense follows */ | |||
| #define FLAG_VERB 0x10 /* pronunciation for verb */ | |||
| #define FLAG_NOUN 0x20 /* pronunciation for noun */ | |||
| #define FLAG_PAST 0x40 /* pronunciation for past tense */ | |||
| #define FLAG_VERB_EXT 0x100 /* extend the 'verb follows' */ | |||
| #define FLAG_CAPITAL 0x200 /* pronunciation if initial letter is upper case */ | |||
| #define FLAG_ALLCAPS 0x400 // only if the word is all capitals | |||
| #define FLAG_ACCENT 0x800 // character name is base-character name + accent name | |||
| #define FLAG_HYPHENATED 0x1000 // multiple-words, but needs hyphen between parts 1 and 2 | |||
| #define FLAG_SENTENCE 0x2000 // only if the clause is a sentence | |||
| #define FLAG_VERBF 0x1 // verb follows | |||
| #define FLAG_VERBSF 0x2 // verb follows, may have -s suffix | |||
| #define FLAG_NOUNF 0x4 // noun follows | |||
| #define FLAG_PASTF 0x8 // past tense follows | |||
| #define FLAG_VERB 0x10 // pronunciation for verb | |||
| #define FLAG_NOUN 0x20 // pronunciation for noun | |||
| #define FLAG_PAST 0x40 // pronunciation for past tense | |||
| #define FLAG_VERB_EXT 0x100 // extend the 'verb follows' | |||
| #define FLAG_CAPITAL 0x200 // pronunciation if initial letter is upper case | |||
| #define FLAG_ALLCAPS 0x400 // only if the word is all capitals | |||
| #define FLAG_ACCENT 0x800 // character name is base-character name + accent name | |||
| #define FLAG_HYPHENATED 0x1000 // multiple-words, but needs hyphen between parts 1 and 2 | |||
| #define FLAG_SENTENCE 0x2000 // only if the clause is a sentence | |||
| #define FLAG_ONLY 0x4000 | |||
| #define FLAG_ONLY_S 0x8000 | |||
| #define FLAG_STEM 0x10000 // must have a suffix | |||
| #define FLAG_ATEND 0x20000 // use this pronunciation if at end of clause | |||
| #define FLAG_ATSTART 0x40000 // use this pronunciation if at start of clause | |||
| #define FLAG_NATIVE 0x80000 // not if we've switched translators | |||
| #define FLAG_LOOKUP_SYMBOL 0x40000000 // to indicate called from Lookup() | |||
| #define BITNUM_FLAG_ALLCAPS 0x2a | |||
| #define BITNUM_FLAG_HYPHENATED 0x2c | |||
| #define BITNUM_FLAG_ONLY 0x2e | |||
| #define BITNUM_FLAG_ONLY_S 0x2f | |||
| #define FLAG_STEM 0x10000 // must have a suffix | |||
| #define FLAG_ATEND 0x20000 // use this pronunciation if at end of clause | |||
| #define FLAG_ATSTART 0x40000 // use this pronunciation if at start of clause | |||
| #define FLAG_NATIVE 0x80000 // not if we've switched translators | |||
| #define FLAG_LOOKUP_SYMBOL 0x40000000 // to indicate called from Lookup() | |||
| #define BITNUM_FLAG_ALLCAPS 0x2a | |||
| #define BITNUM_FLAG_HYPHENATED 0x2c | |||
| #define BITNUM_FLAG_ONLY 0x2e | |||
| #define BITNUM_FLAG_ONLY_S 0x2f | |||
| // wordflags, flags in source word | |||
| #define FLAG_ALL_UPPER 0x1 /* no lower case letters in the word */ | |||
| #define FLAG_FIRST_UPPER 0x2 /* first letter is upper case */ | |||
| #define FLAG_UPPERS 0x3 // FLAG_ALL_UPPER | FLAG_FIRST_UPPER | |||
| #define FLAG_HAS_PLURAL 0x4 /* upper-case word with s or 's lower-case ending */ | |||
| #define FLAG_PHONEMES 0x8 /* word is phonemes */ | |||
| #define FLAG_LAST_WORD 0x10 /* last word in clause */ | |||
| #define FLAG_EMBEDDED 0x40 /* word is preceded by embedded commands */ | |||
| #define FLAG_ALL_UPPER 0x1 // no lower case letters in the word | |||
| #define FLAG_FIRST_UPPER 0x2 // first letter is upper case | |||
| #define FLAG_UPPERS 0x3 // FLAG_ALL_UPPER | FLAG_FIRST_UPPER | |||
| #define FLAG_HAS_PLURAL 0x4 // upper-case word with s or 's lower-case ending | |||
| #define FLAG_PHONEMES 0x8 // word is phonemes | |||
| #define FLAG_LAST_WORD 0x10 // last word in clause | |||
| #define FLAG_EMBEDDED 0x40 // word is preceded by embedded commands | |||
| #define FLAG_HYPHEN 0x80 | |||
| #define FLAG_NOSPACE 0x100 // word is not seperated from previous word by a space | |||
| #define FLAG_FIRST_WORD 0x200 // first word in clause | |||
| #define FLAG_FOCUS 0x400 // the focus word of a clause | |||
| #define FLAG_NOSPACE 0x100 // word is not seperated from previous word by a space | |||
| #define FLAG_FIRST_WORD 0x200 // first word in clause | |||
| #define FLAG_FOCUS 0x400 // the focus word of a clause | |||
| #define FLAG_EMPHASIZED 0x800 | |||
| #define FLAG_EMPHASIZED2 0xc00 // FLAG_FOCUS | FLAG_EMPHASIZED | |||
| #define FLAG_EMPHASIZED2 0xc00 // FLAG_FOCUS | FLAG_EMPHASIZED | |||
| #define FLAG_DONT_SWITCH_TRANSLATOR 0x1000 | |||
| #define FLAG_SUFFIX_REMOVED 0x2000 | |||
| #define FLAG_HYPHEN_AFTER 0x4000 | |||
| @@ -128,11 +125,10 @@ extern "C" | |||
| #define FLAG_TRANSLATOR2 0x400000 // retranslating using a different language | |||
| #define FLAG_PREFIX_REMOVED 0x800000 // a prefix has been removed from this word | |||
| #define FLAG_SUFFIX_VOWEL 0x08000000 // remember an initial vowel from the suffix | |||
| #define FLAG_NO_TRACE 0x10000000 // passed to TranslateRules() to suppress dictionary lookup printout | |||
| #define FLAG_SUFFIX_VOWEL 0x08000000 // remember an initial vowel from the suffix | |||
| #define FLAG_NO_TRACE 0x10000000 // passed to TranslateRules() to suppress dictionary lookup printout | |||
| #define FLAG_NO_PREFIX 0x20000000 | |||
| #define FLAG_UNPRON_TEST 0x80000000 // do unpronounability test on the beginning of the word | |||
| #define FLAG_UNPRON_TEST 0x80000000 // do unpronounability test on the beginning of the word | |||
| // prefix/suffix flags (bits 8 to 14, bits 16 to 22) don't use 0x8000, 0x800000 | |||
| #define SUFX_E 0x0100 // e may have been added | |||
| @@ -149,60 +145,56 @@ extern "C" | |||
| #define SUFX_UNPRON 0x8000 // used to return $unpron flag from *_rules | |||
| #define FLAG_ALLOW_TEXTMODE 0x02 // allow dictionary to translate to text rather than phonemes | |||
| #define FLAG_SUFX 0x04 | |||
| #define FLAG_SUFX_S 0x08 | |||
| #define FLAG_SUFX_E_ADDED 0x10 | |||
| // codes in dictionary rules | |||
| #define RULE_PRE 1 | |||
| #define RULE_POST 2 | |||
| #define RULE_PHONEMES 3 | |||
| #define RULE_PH_COMMON 4 // At start of rule. Its phoneme string is used by subsequent rules | |||
| #define RULE_CONDITION 5 // followed by condition number (byte) | |||
| #define RULE_PRE 1 | |||
| #define RULE_POST 2 | |||
| #define RULE_PHONEMES 3 | |||
| #define RULE_PH_COMMON 4 // At start of rule. Its phoneme string is used by subsequent rules | |||
| #define RULE_CONDITION 5 // followed by condition number (byte) | |||
| #define RULE_GROUP_START 6 | |||
| #define RULE_GROUP_END 7 | |||
| #define RULE_PRE_ATSTART 8 // as RULE_PRE but also match with 'start of word' | |||
| #define RULE_LINENUM 9 // next 2 bytes give a line number, for debugging purposes | |||
| #define RULE_SPACE 32 // ascii space | |||
| #define RULE_SYLLABLE 21 // @ | |||
| #define RULE_STRESSED 10 // & | |||
| #define RULE_DOUBLE 11 // % | |||
| #define RULE_INC_SCORE 12 // + | |||
| #define RULE_DEL_FWD 13 // # | |||
| #define RULE_ENDING 14 // S | |||
| #define RULE_DIGIT 15 // D digit | |||
| #define RULE_NONALPHA 16 // Z non-alpha | |||
| #define RULE_LETTERGP 17 // A B C H F G Y letter group number | |||
| #define RULE_LETTERGP2 18 // L + letter group number | |||
| #define RULE_CAPITAL 19 // ! word starts with a capital letter | |||
| #define RULE_REPLACEMENTS 20 // section for character replacements | |||
| #define RULE_SKIPCHARS 23 // J | |||
| #define RULE_NO_SUFFIX 24 // N | |||
| #define RULE_NOTVOWEL 25 // K | |||
| #define RULE_IFVERB 26 // V | |||
| #define RULE_DOLLAR 28 // $ commands | |||
| #define RULE_NOVOWELS 29 // X no vowels up to word boundary | |||
| #define RULE_SPELLING 31 // W while spelling letter-by-letter | |||
| #define RULE_LAST_RULE 31 | |||
| #define RULE_GROUP_END 7 | |||
| #define RULE_PRE_ATSTART 8 // as RULE_PRE but also match with 'start of word' | |||
| #define RULE_LINENUM 9 // next 2 bytes give a line number, for debugging purposes | |||
| #define RULE_SPACE 32 // ascii space | |||
| #define RULE_SYLLABLE 21 // @ | |||
| #define RULE_STRESSED 10 // & | |||
| #define RULE_DOUBLE 11 // % | |||
| #define RULE_INC_SCORE 12 // + | |||
| #define RULE_DEL_FWD 13 // # | |||
| #define RULE_ENDING 14 // S | |||
| #define RULE_DIGIT 15 // D digit | |||
| #define RULE_NONALPHA 16 // Z non-alpha | |||
| #define RULE_LETTERGP 17 // A B C H F G Y letter group number | |||
| #define RULE_LETTERGP2 18 // L + letter group number | |||
| #define RULE_CAPITAL 19 // ! word starts with a capital letter | |||
| #define RULE_REPLACEMENTS 20 // section for character replacements | |||
| #define RULE_SKIPCHARS 23 // J | |||
| #define RULE_NO_SUFFIX 24 // N | |||
| #define RULE_NOTVOWEL 25 // K | |||
| #define RULE_IFVERB 26 // V | |||
| #define RULE_DOLLAR 28 // $ commands | |||
| #define RULE_NOVOWELS 29 // X no vowels up to word boundary | |||
| #define RULE_SPELLING 31 // W while spelling letter-by-letter | |||
| #define RULE_LAST_RULE 31 | |||
| #define DOLLAR_UNPR 0x01 | |||
| #define DOLLAR_NOPREFIX 0x02 | |||
| #define DOLLAR_LIST 0x03 | |||
| #define LETTERGP_A 0 | |||
| #define LETTERGP_B 1 | |||
| #define LETTERGP_C 2 | |||
| #define LETTERGP_H 3 | |||
| #define LETTERGP_F 4 | |||
| #define LETTERGP_G 5 | |||
| #define LETTERGP_Y 6 | |||
| #define LETTERGP_VOWEL2 7 | |||
| #define LETTERGP_A 0 | |||
| #define LETTERGP_B 1 | |||
| #define LETTERGP_C 2 | |||
| #define LETTERGP_H 3 | |||
| #define LETTERGP_F 4 | |||
| #define LETTERGP_G 5 | |||
| #define LETTERGP_Y 6 | |||
| #define LETTERGP_VOWEL2 7 | |||
| // Punctuation types returned by ReadClause() | |||
| // bits 0-11 pause x 10mS | |||
| @@ -215,14 +207,14 @@ extern "C" | |||
| // bit 22= dot after the last word | |||
| // bit 23= pause is x 320mS (not x 10mS) | |||
| #define CLAUSE_BIT_SENTENCE 0x80000 | |||
| #define CLAUSE_BIT_CLAUSE 0x40000 | |||
| #define CLAUSE_BIT_VOICE 0x20000 | |||
| #define CLAUSE_BITS_INTONATION 0x7000 | |||
| #define PUNCT_IN_WORD 0x100000 | |||
| #define PUNCT_SAY_NAME 0x200000 | |||
| #define CLAUSE_DOT 0x400000 | |||
| #define CLAUSE_PAUSE_LONG 0x800000 | |||
| #define CLAUSE_BIT_SENTENCE 0x80000 | |||
| #define CLAUSE_BIT_CLAUSE 0x40000 | |||
| #define CLAUSE_BIT_VOICE 0x20000 | |||
| #define CLAUSE_BITS_INTONATION 0x7000 | |||
| #define PUNCT_IN_WORD 0x100000 | |||
| #define PUNCT_SAY_NAME 0x200000 | |||
| #define CLAUSE_DOT 0x400000 | |||
| #define CLAUSE_PAUSE_LONG 0x800000 | |||
| #define CLAUSE_NONE ( 0 + 0x04000) | |||
| #define CLAUSE_PARAGRAPH (70 + 0x80000) | |||
| @@ -237,15 +229,15 @@ extern "C" | |||
| #define CLAUSE_COLON (30 + 0x40000) | |||
| #define CLAUSE_SEMICOLON (30 + 0x41000) | |||
| #define SAYAS_CHARS 0x12 | |||
| #define SAYAS_GLYPHS 0x13 | |||
| #define SAYAS_CHARS 0x12 | |||
| #define SAYAS_GLYPHS 0x13 | |||
| #define SAYAS_SINGLE_CHARS 0x14 | |||
| #define SAYAS_KEY 0x24 | |||
| #define SAYAS_DIGITS 0x40 // + number of digits | |||
| #define SAYAS_DIGITS1 0xc1 | |||
| #define SAYAS_KEY 0x24 | |||
| #define SAYAS_DIGITS 0x40 // + number of digits | |||
| #define SAYAS_DIGITS1 0xc1 | |||
| #define CHAR_EMPHASIS 0x0530 // this is an unused character code | |||
| #define CHAR_COMMA_BREAK 0x0557 // unused character code | |||
| #define CHAR_EMPHASIS 0x0530 // this is an unused character code | |||
| #define CHAR_COMMA_BREAK 0x0557 // unused character code | |||
| // Rule: | |||
| // [4] [match] [1 pre] [2 post] [3 phonemes] 0 | |||
| @@ -261,7 +253,6 @@ typedef struct { | |||
| char *del_fwd; | |||
| } MatchRecord; | |||
| // used to mark words with the source[] buffer | |||
| typedef struct { | |||
| unsigned int flags; | |||
| @@ -272,7 +263,6 @@ typedef struct { | |||
| unsigned char length; | |||
| } WORD_TAB; | |||
| typedef struct { | |||
| int type; | |||
| int parameter[N_SPEECH_PARAM]; | |||
| @@ -281,7 +271,6 @@ typedef struct { | |||
| extern PARAM_STACK param_stack[]; | |||
| extern const int param_defaults[N_SPEECH_PARAM]; | |||
| typedef struct { | |||
| const char *name; | |||
| int offset; | |||
| @@ -293,21 +282,20 @@ typedef struct { | |||
| extern ALPHABET alphabets[]; | |||
| extern ALPHABET *current_alphabet; | |||
| // alphabet flags | |||
| #define AL_DONT_NAME 0x01 // don't speak the alphabet name | |||
| #define AL_NOT_LETTERS 0x02 // don't use the language for speaking letters | |||
| #define AL_WORDS 0x04 // use the language to speak words | |||
| #define AL_NOT_CODE 0x08 // don't speak the character code | |||
| #define AL_NO_SYMBOL 0x10 // don't repeat "symbol" or "character" | |||
| #define N_LOPTS 21 | |||
| #define LOPT_DIERESES 1 | |||
| #define AL_DONT_NAME 0x01 // don't speak the alphabet name | |||
| #define AL_NOT_LETTERS 0x02 // don't use the language for speaking letters | |||
| #define AL_WORDS 0x04 // use the language to speak words | |||
| #define AL_NOT_CODE 0x08 // don't speak the character code | |||
| #define AL_NO_SYMBOL 0x10 // don't repeat "symbol" or "character" | |||
| #define N_LOPTS 21 | |||
| #define LOPT_DIERESES 1 | |||
| // 1=remove [:] from unstressed syllables, 2= remove from unstressed or non-penultimate syllables | |||
| // bit 4=0, if stress < 4, bit 4=1, if not the highest stress in the word | |||
| #define LOPT_IT_LENGTHEN 2 | |||
| #define LOPT_IT_LENGTHEN 2 | |||
| // 1=german | |||
| #define LOPT_PREFIXES 3 | |||
| #define LOPT_PREFIXES 3 | |||
| // non-zero, change voiced/unoiced to match last consonant in a cluster | |||
| // bit 0=use regressive voicing | |||
| @@ -316,26 +304,26 @@ extern ALPHABET *current_alphabet; | |||
| // bit 3=LANG=pl, propagate over liquids and nasals | |||
| // bit 4=LANG=cz,sk don't progagate to [v] | |||
| // bit 8=devoice word-final consonants | |||
| #define LOPT_REGRESSIVE_VOICING 4 | |||
| #define LOPT_REGRESSIVE_VOICING 4 | |||
| // 0=default, 1=no check, other allow this character as an extra initial letter (default is 's') | |||
| #define LOPT_UNPRONOUNCABLE 5 | |||
| #define LOPT_UNPRONOUNCABLE 5 | |||
| // select length_mods tables, (length_mod_tab) + (length_mod_tab0 * 100) | |||
| #define LOPT_LENGTH_MODS 6 | |||
| #define LOPT_LENGTH_MODS 6 | |||
| // increase this to prevent sonorants being shortened before shortened (eg. unstressed) vowels | |||
| #define LOPT_SONORANT_MIN 7 | |||
| #define LOPT_SONORANT_MIN 7 | |||
| // bit 0: don't break vowels at word boundary | |||
| #define LOPT_WORD_MERGE 8 | |||
| #define LOPT_WORD_MERGE 8 | |||
| // max. amplitude for vowel at the end of a clause | |||
| #define LOPT_MAXAMP_EOC 9 | |||
| #define LOPT_MAXAMP_EOC 9 | |||
| // bit 0=reduce even if phonemes are specified in the **_list file | |||
| // bit 1=don't reduce the strongest vowel in a word which is marked 'unstressed' | |||
| #define LOPT_REDUCE 10 | |||
| #define LOPT_REDUCE 10 | |||
| // LANG=cs,sk combine some prepositions with the following word, if the combination has N or fewer syllables | |||
| // bits 0-3 N syllables | |||
| @@ -348,15 +336,15 @@ extern ALPHABET *current_alphabet; | |||
| // 1 = allow capitals inside a word | |||
| // 2 = stressed syllable is indicated by capitals | |||
| #define LOPT_CAPS_IN_WORD 13 | |||
| #define LOPT_CAPS_IN_WORD 13 | |||
| // bit 0=Italian "syntactic doubling" of consoants in the word after a word marked with $double attribute | |||
| // bit 1=also after a word which ends with a stressed vowel | |||
| #define LOPT_IT_DOUBLING 14 | |||
| #define LOPT_IT_DOUBLING 14 | |||
| // Call ApplySpecialAttributes() if $alt or $alt2 is set for a word | |||
| // bit 1: stressed syllable: $alt change [e],[o] to [E],[O], $alt2 change [E],[O] to [e],[o] | |||
| #define LOPT_ALT 15 | |||
| #define LOPT_ALT 15 | |||
| // pause for bracket (default=4), pause when annoucing bracket names (default=2) | |||
| #define LOPT_BRACKET_PAUSE 16 | |||
| @@ -368,20 +356,18 @@ extern ALPHABET *current_alphabet; | |||
| #define LOPT_LONG_VOWEL_THRESHOLD 18 | |||
| // bit 0: Don't allow suffices if there is no previous syllable | |||
| #define LOPT_SUFFIX 19 | |||
| #define LOPT_SUFFIX 19 | |||
| // bit 0 Apostrophe at start of word is part of the word | |||
| // bit 1 Apostrophe at end of word is part of the word | |||
| #define LOPT_APOSTROPHE 20 | |||
| #define LOPT_APOSTROPHE 20 | |||
| // stress_rule | |||
| #define STRESSPOSN_1L 0 // 1st syllable | |||
| #define STRESSPOSN_2L 1 // 2nd syllable | |||
| #define STRESSPOSN_2R 2 // penultimate | |||
| #define STRESSPOSN_1R 3 // final syllable | |||
| #define STRESSPOSN_3R 4 // antipenultimate | |||
| #define STRESSPOSN_1L 0 // 1st syllable | |||
| #define STRESSPOSN_2L 1 // 2nd syllable | |||
| #define STRESSPOSN_2R 2 // penultimate | |||
| #define STRESSPOSN_1R 3 // final syllable | |||
| #define STRESSPOSN_3R 4 // antipenultimate | |||
| typedef struct { | |||
| // bits0-2 separate words with (1=pause_vshort, 2=pause_short, 3=pause, 4=pause_long 5=[?] phonemme) | |||
| @@ -445,7 +431,6 @@ typedef struct { | |||
| // bit15= Give stress to the first unstressed syllable | |||
| int stress_flags; | |||
| int unstressed_wd1; // stress for $u word of 1 syllable | |||
| int unstressed_wd2; // stress for $u word of >1 syllable | |||
| @@ -531,7 +516,7 @@ typedef struct { | |||
| #define NUM2_PERCENT_BEFORE 0x10000 | |||
| #define NUM2_OMIT_1_HUNDRED_ONLY 0x20000 | |||
| #define NUM2_ORDINAL_AND_THOUSANDS 0x40000 | |||
| #define NUM2_ORDINAL_DROP_VOWEL 0x80000 // currently only for tens and units | |||
| #define NUM2_ORDINAL_DROP_VOWEL 0x80000 // currently only for tens and units | |||
| #define NUM2_ZERO_TENS 0x100000 | |||
| // bits 1-4 use variant form of numbers before thousands,millions,etc. | |||
| // bits 6-8 use different forms of thousand, million, etc (M MA MB) | |||
| @@ -588,7 +573,6 @@ typedef struct { | |||
| int dict_dialect; // bitmap, use a dialect for foreign words | |||
| } LANGUAGE_OPTIONS; | |||
| // a parameter of ChangePhonemes() | |||
| typedef struct { | |||
| int flags; | |||
| @@ -599,10 +583,7 @@ typedef struct { | |||
| unsigned char vowel_stressed; // syllable number of the highest stressed vowel | |||
| } CHANGEPH; | |||
| typedef struct { | |||
| LANGUAGE_OPTIONS langopts; | |||
| int translator_name; | |||
| int transpose_max; | |||
| @@ -630,8 +611,8 @@ typedef struct { | |||
| const wchar_t *letter_groups[8]; | |||
| /* index1=option, index2 by 0=. 1=, 2=?, 3=! 4=none */ | |||
| #define INTONATION_TYPES 8 | |||
| #define PUNCT_INTONATIONS 6 | |||
| #define INTONATION_TYPES 8 | |||
| #define PUNCT_INTONATIONS 6 | |||
| unsigned char punct_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS]; | |||
| char *data_dictrules; // language_1 translation rules file | |||
| @@ -671,7 +652,6 @@ typedef struct { | |||
| int clause_terminator; | |||
| } Translator; | |||
| extern int option_tone2; | |||
| #define OPTION_EMPHASIZE_ALLCAPS 0x100 | |||
| #define OPTION_EMPHASIZE_PENULTIMATE 0x200 | |||
| @@ -704,8 +684,6 @@ extern int clause_start_word; | |||
| extern char *namedata; | |||
| extern int pre_pause; | |||
| #define N_MARKER_LENGTH 50 // max.length of a mark name | |||
| extern char skip_marker[N_MARKER_LENGTH]; | |||
| @@ -796,9 +774,9 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
| void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata); | |||
| char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags); | |||
| extern FILE *f_trans; // for logging | |||
| extern FILE *f_trans; // for logging | |||
| extern FILE *f_logespeak; | |||
| extern int logging_type; // from config file | |||
| extern int logging_type; // from config file | |||
| #ifdef __cplusplus | |||
| } | |||
| @@ -22,15 +22,13 @@ extern "C" | |||
| { | |||
| #endif | |||
| typedef struct { | |||
| char v_name[40]; | |||
| char language_name[20]; | |||
| int phoneme_tab_ix; // phoneme table number | |||
| int pitch_base; // Hz<<12 | |||
| int pitch_range; // standard = 0x1000 | |||
| int phoneme_tab_ix; // phoneme table number | |||
| int pitch_base; // Hz<<12 | |||
| int pitch_range; // standard = 0x1000 | |||
| int speedf1; | |||
| int speedf2; | |||
| @@ -44,7 +42,7 @@ typedef struct { | |||
| int n_harmonic_peaks; // highest formant which is formed from adding harmonics | |||
| int peak_shape; // alternative shape for formant peaks (0=standard 1=squarer) | |||
| int voicing; // 100% = 64, level of formant-synthesized sound | |||
| int formant_factor; // adjust nominal formant frequencies by this because of the voice's pitch (256ths) | |||
| int formant_factor; // adjust nominal formant frequencies by this because of the voice's pitch (256ths) | |||
| int consonant_amp; // amplitude of unvoiced consonants | |||
| int consonant_ampv; // amplitude of the noise component of voiced consonants | |||
| int samplerate; | |||
| @@ -54,7 +52,7 @@ typedef struct { | |||
| short freq[N_PEAKS]; // 100% = 256 | |||
| short height[N_PEAKS]; // 100% = 256 | |||
| short width[N_PEAKS]; // 100% = 256 | |||
| short freqadd[N_PEAKS]; // Hz | |||
| short freqadd[N_PEAKS]; // Hz | |||
| // copies without temporary adjustments from embedded commands | |||
| short freq2[N_PEAKS]; // 100% = 256 | |||
| @@ -62,7 +60,7 @@ typedef struct { | |||
| short width2[N_PEAKS]; // 100% = 256 | |||
| int breath[N_PEAKS]; // amount of breath for each formant. breath[0] indicates whether any are set. | |||
| int breathw[N_PEAKS]; // width of each breath formant | |||
| int breathw[N_PEAKS]; // width of each breath formant | |||
| // This table provides the opportunity for tone control. | |||
| // Adjustment of harmonic amplitudes, steps of 8Hz | |||
| @@ -56,8 +56,8 @@ MNEM_TAB genders[] = { | |||
| int tone_points[12] = { 600, 170, 1200, 135, 2000, 110, 3000, 110, -1, 0 }; | |||
| // limit the rate of change for each formant number | |||
| static int formant_rate_22050[9] = { 240, 170, 170, 170, 170, 170, 170, 170, 170 }; // values for 22kHz sample rate | |||
| int formant_rate[9]; // values adjusted for actual sample rate | |||
| static int formant_rate_22050[9] = { 240, 170, 170, 170, 170, 170, 170, 170, 170 }; // values for 22kHz sample rate | |||
| int formant_rate[9]; // values adjusted for actual sample rate | |||
| #define DEFAULT_LANGUAGE_PRIORITY 5 | |||
| #define N_VOICES_LIST 250 | |||
| @@ -75,7 +75,7 @@ enum { | |||
| V_PHONEMES, | |||
| V_DICTIONARY, | |||
| // these affect voice quality, are independent of language | |||
| // these affect voice quality, are independent of language | |||
| V_FORMANT, | |||
| V_PITCH, | |||
| V_ECHO, | |||
| @@ -87,7 +87,7 @@ enum { | |||
| V_BREATH, | |||
| V_BREATHW, | |||
| // these override defaults set by the translator | |||
| // these override defaults set by the translator | |||
| V_WORDGAP, | |||
| V_INTONATION, | |||
| V_TUNES, | |||
| @@ -109,72 +109,74 @@ enum { | |||
| V_ALPHABET2, | |||
| V_DICTDIALECT, | |||
| // these need a phoneme table to have been specified | |||
| // these need a phoneme table to have been specified | |||
| V_REPLACE, | |||
| V_CONSONANTS | |||
| }; | |||
| static MNEM_TAB options_tab[] = { | |||
| { "reduce_t", LOPT_REDUCE_T }, | |||
| { "bracket", LOPT_BRACKET_PAUSE }, | |||
| { "reduce_t", LOPT_REDUCE_T }, | |||
| { "bracket", LOPT_BRACKET_PAUSE }, | |||
| { NULL, -1 } | |||
| }; | |||
| static MNEM_TAB keyword_tab[] = { | |||
| { "name", V_NAME }, | |||
| { "language", V_LANGUAGE }, | |||
| { "gender", V_GENDER }, | |||
| { "formant", V_FORMANT }, | |||
| { "pitch", V_PITCH }, | |||
| { "phonemes", V_PHONEMES }, | |||
| { "translator", V_TRANSLATOR }, | |||
| { "dictionary", V_DICTIONARY }, | |||
| { "name", V_NAME }, | |||
| { "language", V_LANGUAGE }, | |||
| { "gender", V_GENDER }, | |||
| { "formant", V_FORMANT }, | |||
| { "pitch", V_PITCH }, | |||
| { "phonemes", V_PHONEMES }, | |||
| { "translator", V_TRANSLATOR }, | |||
| { "dictionary", V_DICTIONARY }, | |||
| { "stressLength", V_STRESSLENGTH }, | |||
| { "stressAmp", V_STRESSAMP }, | |||
| { "stressAdd", V_STRESSADD }, | |||
| { "intonation", V_INTONATION }, | |||
| { "tunes", V_TUNES }, | |||
| { "dictrules", V_DICTRULES }, | |||
| { "stressrule", V_STRESSRULE }, | |||
| { "stressopt", V_STRESSOPT }, | |||
| { "charset", V_CHARSET }, | |||
| { "replace", V_REPLACE }, | |||
| { "words", V_WORDGAP }, | |||
| { "echo", V_ECHO }, | |||
| { "flutter", V_FLUTTER }, | |||
| { "roughness", V_ROUGHNESS }, | |||
| { "clarity", V_CLARITY }, | |||
| { "tone", V_TONE }, | |||
| { "voicing", V_VOICING }, | |||
| { "breath", V_BREATH }, | |||
| { "breathw", V_BREATHW }, | |||
| { "numbers", V_NUMBERS }, | |||
| { "option", V_OPTION }, | |||
| { "mbrola", V_MBROLA }, | |||
| { "consonants", V_CONSONANTS }, | |||
| { "klatt", V_KLATT }, | |||
| { "fast_test2", V_FAST }, | |||
| { "speed", V_SPEED }, | |||
| { "dict_min", V_DICTMIN }, | |||
| { "alphabet2", V_ALPHABET2 }, | |||
| { "dictdialect", V_DICTDIALECT }, | |||
| { "stressAmp", V_STRESSAMP }, | |||
| { "stressAdd", V_STRESSADD }, | |||
| { "intonation", V_INTONATION }, | |||
| { "tunes", V_TUNES }, | |||
| { "dictrules", V_DICTRULES }, | |||
| { "stressrule", V_STRESSRULE }, | |||
| { "stressopt", V_STRESSOPT }, | |||
| { "charset", V_CHARSET }, | |||
| { "replace", V_REPLACE }, | |||
| { "words", V_WORDGAP }, | |||
| { "echo", V_ECHO }, | |||
| { "flutter", V_FLUTTER }, | |||
| { "roughness", V_ROUGHNESS }, | |||
| { "clarity", V_CLARITY }, | |||
| { "tone", V_TONE }, | |||
| { "voicing", V_VOICING }, | |||
| { "breath", V_BREATH }, | |||
| { "breathw", V_BREATHW }, | |||
| { "numbers", V_NUMBERS }, | |||
| { "option", V_OPTION }, | |||
| { "mbrola", V_MBROLA }, | |||
| { "consonants", V_CONSONANTS }, | |||
| { "klatt", V_KLATT }, | |||
| { "fast_test2", V_FAST }, | |||
| { "speed", V_SPEED }, | |||
| { "dict_min", V_DICTMIN }, | |||
| { "alphabet2", V_ALPHABET2 }, | |||
| { "dictdialect", V_DICTDIALECT }, | |||
| // these just set a value in langopts.param[] | |||
| { "l_dieresis", 0x100+LOPT_DIERESES }, | |||
| { "l_prefix", 0x100+LOPT_PREFIXES }, | |||
| { "l_regressive_v", 0x100+LOPT_REGRESSIVE_VOICING }, | |||
| { "l_dieresis", 0x100+LOPT_DIERESES }, | |||
| { "l_prefix", 0x100+LOPT_PREFIXES }, | |||
| { "l_regressive_v", 0x100+LOPT_REGRESSIVE_VOICING }, | |||
| { "l_unpronouncable", 0x100+LOPT_UNPRONOUNCABLE }, | |||
| { "l_sonorant_min", 0x100+LOPT_SONORANT_MIN }, | |||
| { "l_length_mods", 0x100+LOPT_LENGTH_MODS }, | |||
| { "apostrophe", 0x100+LOPT_APOSTROPHE }, | |||
| { NULL, 0 } | |||
| { "l_sonorant_min", 0x100+LOPT_SONORANT_MIN }, | |||
| { "l_length_mods", 0x100+LOPT_LENGTH_MODS }, | |||
| { "apostrophe", 0x100+LOPT_APOSTROPHE }, | |||
| { NULL, 0 } | |||
| }; | |||
| static MNEM_TAB dict_dialects[] = { | |||
| { "en-us", DICTDIALECT_EN_US }, | |||
| { "es-la", DICTDIALECT_ES_LA }, | |||
| { NULL, 0 } | |||
| { "en-us", DICTDIALECT_EN_US }, | |||
| { "es-la", DICTDIALECT_ES_LA }, | |||
| { NULL, 0 } | |||
| }; | |||
| #define N_VOICE_VARIANTS 12 | |||
| @@ -188,7 +190,7 @@ voice_t *voice = &voicedata; | |||
| static char *fgets_strip(char *buf, int size, FILE *f_in) | |||
| { | |||
| // strip trailing spaces, and truncate lines at // comment | |||
| // strip trailing spaces, and truncate lines at // comment | |||
| int len; | |||
| char *p; | |||
| @@ -238,7 +240,7 @@ static void SetToneAdjust(voice_t *voice, int *tone_pts) | |||
| if (pt > 0) | |||
| tone_pts[pt+1] = tone_pts[pt-1]; | |||
| } | |||
| freq2 = tone_pts[pt] / 8; // 8Hz steps | |||
| freq2 = tone_pts[pt] / 8; // 8Hz steps | |||
| height2 = tone_pts[pt+1]; | |||
| if ((freq2 - freq1) > 0) { | |||
| rate = (double)(height2-height1)/(freq2-freq1); | |||
| @@ -257,7 +259,7 @@ static void SetToneAdjust(voice_t *voice, int *tone_pts) | |||
| void ReadTonePoints(char *string, int *tone_pts) | |||
| { | |||
| // tone_pts[] is int[12] | |||
| // tone_pts[] is int[12] | |||
| int ix; | |||
| for (ix = 0; ix < 12; ix++) | |||
| @@ -271,14 +273,14 @@ void ReadTonePoints(char *string, int *tone_pts) | |||
| static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *leafname) | |||
| { | |||
| // Read a Voice file, allocate a VOICE_DATA and set data from the | |||
| // file's language, gender, name lines | |||
| // Read a Voice file, allocate a VOICE_DATA and set data from the | |||
| // file's language, gender, name lines | |||
| char linebuf[120]; | |||
| char vname[80]; | |||
| char vgender[80]; | |||
| char vlanguage[80]; | |||
| char languages[300]; // allow space for several alternate language names and priorities | |||
| char languages[300]; // allow space for several alternate language names and priorities | |||
| unsigned int len; | |||
| int langix = 0; | |||
| @@ -287,7 +289,7 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *le | |||
| espeak_VOICE *voice_data; | |||
| int priority; | |||
| int age; | |||
| int n_variants = 4; // default, number of variants of this voice before using another voice | |||
| int n_variants = 4; // default, number of variants of this voice before using another voice | |||
| int gender; | |||
| #ifdef PLATFORM_WINDOWS | |||
| @@ -336,7 +338,7 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *le | |||
| gender = LookupMnem(genders, vgender); | |||
| if (n_languages == 0) | |||
| return NULL; // no language lines in the voice file | |||
| return NULL; // no language lines in the voice file | |||
| p = (char *)calloc(sizeof(espeak_VOICE) + langix + strlen(fname) + strlen(vname) + 3, 1); | |||
| voice_data = (espeak_VOICE *)p; | |||
| @@ -364,10 +366,10 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *le | |||
| void VoiceReset(int tone_only) | |||
| { | |||
| // Set voice to the default values | |||
| // Set voice to the default values | |||
| int pk; | |||
| static unsigned char default_heights[N_PEAKS] = { 130, 128, 120, 116, 100, 100, 128, 128, 128 }; // changed for v.1.47 | |||
| static unsigned char default_heights[N_PEAKS] = { 130, 128, 120, 116, 100, 100, 128, 128, 128 }; // changed for v.1.47 | |||
| static unsigned char default_widths[N_PEAKS] = { 140, 128, 128, 160, 171, 171, 128, 128, 128 }; | |||
| static int breath_widths[N_PEAKS] = { 0, 200, 200, 400, 400, 400, 600, 600, 600 }; | |||
| @@ -385,7 +387,7 @@ void VoiceReset(int tone_only) | |||
| voice->n_harmonic_peaks = 5; | |||
| voice->peak_shape = 0; | |||
| voice->voicing = 64; | |||
| voice->consonant_amp = 90; // change from 100 to 90 for v.1.47 | |||
| voice->consonant_amp = 90; // change from 100 to 90 for v.1.47 | |||
| voice->consonant_ampv = 100; | |||
| voice->samplerate = samplerate_native; | |||
| memset(voice->klattv, 0, sizeof(voice->klattv)); | |||
| @@ -406,7 +408,7 @@ void VoiceReset(int tone_only) | |||
| voice->height[pk] = default_heights[pk]*2; | |||
| voice->width[pk] = default_widths[pk]*2; | |||
| voice->breath[pk] = 0; | |||
| voice->breathw[pk] = breath_widths[pk]; // default breath formant woidths | |||
| voice->breathw[pk] = breath_widths[pk]; // default breath formant woidths | |||
| voice->freqadd[pk] = 0; | |||
| // adjust formant smoothing depending on sample rate | |||
| @@ -470,7 +472,7 @@ static void PhonemeReplacement(int type, char *p) | |||
| return; | |||
| if ((phon = LookupPhonemeString(phon_string1)) == 0) | |||
| return; // not recognised | |||
| return; // not recognised | |||
| replace_phonemes[n_replace_phonemes].old_ph = phon; | |||
| replace_phonemes[n_replace_phonemes].new_ph = LookupPhonemeString(phon_string2); | |||
| @@ -479,7 +481,7 @@ static void PhonemeReplacement(int type, char *p) | |||
| static int Read8Numbers(char *data_in, int *data) | |||
| { | |||
| // Read 8 integer numbers | |||
| // Read 8 integer numbers | |||
| memset(data, 0, 8+sizeof(int)); | |||
| return sscanf(data_in, "%d %d %d %d %d %d %d %d", | |||
| &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7]); | |||
| @@ -487,7 +489,7 @@ static int Read8Numbers(char *data_in, int *data) | |||
| static unsigned int StringToWord2(const char *string) | |||
| { | |||
| // Convert a language name string to a word such as L('e','n') | |||
| // Convert a language name string to a word such as L('e','n') | |||
| int ix; | |||
| int c; | |||
| unsigned int value = 0; | |||
| @@ -499,10 +501,10 @@ static unsigned int StringToWord2(const char *string) | |||
| voice_t *LoadVoice(const char *vname, int control) | |||
| { | |||
| // control, bit 0 1= no_default | |||
| // bit 1 1 = change tone only, not language | |||
| // bit 2 1 = don't report error on LoadDictionary | |||
| // bit 4 1 = vname = full path | |||
| // control, bit 0 1= no_default | |||
| // bit 1 1 = change tone only, not language | |||
| // bit 2 1 = don't report error on LoadDictionary | |||
| // bit 4 1 = vname = full path | |||
| FILE *f_voice = NULL; | |||
| char *p; | |||
| @@ -545,9 +547,9 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| int pitch1; | |||
| int pitch2; | |||
| static char voice_identifier[40]; // file name for current_voice_selected | |||
| static char voice_name[40]; // voice name for current_voice_selected | |||
| static char voice_languages[100]; // list of languages and priorities for current_voice_selected | |||
| static char voice_identifier[40]; // file name for current_voice_selected | |||
| static char voice_name[40]; // voice name for current_voice_selected | |||
| static char voice_languages[100]; // list of languages and priorities for current_voice_selected | |||
| // which directory to look for a named voice. List of voice names, must end in a space. | |||
| static const char *voices_asia = | |||
| @@ -565,12 +567,12 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| strcpy(voicename, "default"); | |||
| sprintf(path_voices, "%s%cvoices%c", path_home, PATHSEP, PATHSEP); | |||
| sprintf(buf, "%s%s", path_voices, voicename); // first, look in the main voices directory | |||
| sprintf(buf, "%s%s", path_voices, voicename); // first, look in the main voices directory | |||
| if (GetFileLength(buf) <= 0) { | |||
| // then look in the appropriate subdirectory | |||
| if ((voicename[0] == 'm') && (voicename[1] == 'b')) | |||
| voice_dir = "mb"; // mbrola voices | |||
| voice_dir = "mb"; // mbrola voices | |||
| else { | |||
| sprintf(name2, "%s ", voicename); | |||
| if (strstr(voices_europe, voicename) != NULL) | |||
| @@ -592,10 +594,10 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| f_voice = fopen(buf, "r"); | |||
| language_type = "en"; // default | |||
| language_type = "en"; // default | |||
| if (f_voice == NULL) { | |||
| if (control & 3) | |||
| return NULL; // can't open file | |||
| return NULL; // can't open file | |||
| if (SelectPhonemeTableName(voicename) >= 0) | |||
| language_type = voicename; | |||
| @@ -630,7 +632,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| VoiceReset(tone_only); | |||
| if (!tone_only) | |||
| SelectPhonemeTableName(phonemes_name); // set up phoneme_tab | |||
| SelectPhonemeTableName(phonemes_name); // set up phoneme_tab | |||
| while ((f_voice != NULL) && (fgets_strip(buf, sizeof(buf), f_voice) != NULL)) { | |||
| // isolate the attribute name | |||
| @@ -711,10 +713,10 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| new_translator = SelectTranslator(translator_name); | |||
| langopts = &new_translator->langopts; | |||
| break; | |||
| case V_DICTIONARY: // dictionary | |||
| case V_DICTIONARY: // dictionary | |||
| sscanf(p, "%s", new_dictionary); | |||
| break; | |||
| case V_PHONEMES: // phoneme table | |||
| case V_PHONEMES: // phoneme table | |||
| sscanf(p, "%s", phonemes_name); | |||
| break; | |||
| case V_FORMANT: | |||
| @@ -728,19 +730,19 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| voice->pitch_base = (pitch1 - 9) << 12; | |||
| voice->pitch_range = (pitch2 - pitch1) * 108; | |||
| factor = (double)(pitch1 - 82)/82; | |||
| voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch | |||
| voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch | |||
| } | |||
| break; | |||
| case V_STRESSLENGTH: // stressLength | |||
| case V_STRESSLENGTH: // stressLength | |||
| stress_lengths_set = Read8Numbers(p, stress_lengths); | |||
| break; | |||
| case V_STRESSAMP: // stressAmp | |||
| case V_STRESSAMP: // stressAmp | |||
| stress_amps_set = Read8Numbers(p, stress_amps); | |||
| break; | |||
| case V_STRESSADD: // stressAdd | |||
| case V_STRESSADD: // stressAdd | |||
| stress_add_set = Read8Numbers(p, stress_add); | |||
| break; | |||
| case V_INTONATION: // intonation | |||
| case V_INTONATION: // intonation | |||
| sscanf(p, "%d %d", &option_tone_flags, &option_tone2); | |||
| if ((option_tone_flags & 0xff) != 0) | |||
| langopts->intonation_group = option_tone_flags & 0xff; | |||
| @@ -758,7 +760,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| langopts->tunes[ix] = value; | |||
| } | |||
| break; | |||
| case V_DICTRULES: // conditional dictionary rules and list entries | |||
| case V_DICTRULES: // conditional dictionary rules and list entries | |||
| case V_NUMBERS: | |||
| case V_STRESSOPT: | |||
| // expect a list of numbers | |||
| @@ -793,7 +795,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| } | |||
| PhonemeReplacement(key, p); | |||
| break; | |||
| case V_WORDGAP: // words | |||
| case V_WORDGAP: // words | |||
| sscanf(p, "%d %d", &langopts->word_gap, &langopts->vowel_pause); | |||
| break; | |||
| case V_STRESSRULE: | |||
| @@ -821,18 +823,18 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| voice->echo_amp = 0; | |||
| sscanf(p, "%d %d", &voice->echo_delay, &voice->echo_amp); | |||
| break; | |||
| case V_FLUTTER: // flutter | |||
| case V_FLUTTER: // flutter | |||
| if (sscanf(p, "%d", &value) == 1) | |||
| voice->flutter = value * 32; | |||
| break; | |||
| case V_ROUGHNESS: // roughness | |||
| case V_ROUGHNESS: // roughness | |||
| if (sscanf(p, "%d", &value) == 1) | |||
| voice->roughness = value; | |||
| break; | |||
| case V_CLARITY: // formantshape | |||
| case V_CLARITY: // formantshape | |||
| if (sscanf(p, "%d", &value) == 1) { | |||
| if (value > 4) { | |||
| voice->peak_shape = 1; // squarer formant peaks | |||
| voice->peak_shape = 1; // squarer formant peaks | |||
| value = 4; | |||
| } | |||
| voice->n_harmonic_peaks = 1+value; | |||
| @@ -871,14 +873,13 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| name2[0] = 0; | |||
| sscanf(p, "%s %s %d", name1, name2, &srate); | |||
| if (LoadMbrolaTable(name1, name2, &srate) != EE_OK) { | |||
| if (LoadMbrolaTable(name1, name2, &srate) != EE_OK) | |||
| fprintf(stderr, "mbrola voice not found\n"); | |||
| } | |||
| voice->samplerate = srate; | |||
| } | |||
| break; | |||
| case V_KLATT: | |||
| voice->klattv[0] = 1; // default source: IMPULSIVE | |||
| voice->klattv[0] = 1; // default source: IMPULSIVE | |||
| Read8Numbers(p, voice->klattv); | |||
| voice->klattv[KLATT_Kopen] -= 40; | |||
| break; | |||
| @@ -929,7 +930,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| new_translator = SelectTranslator(translator_name); | |||
| } | |||
| SetSpeed(3); // for speed_percent | |||
| SetSpeed(3); // for speed_percent | |||
| for (ix = 0; ix < N_PEAKS; ix++) { | |||
| voice->freq2[ix] = voice->freq[ix]; | |||
| @@ -950,7 +951,7 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| LoadDictionary(new_translator, new_dictionary, control & 4); | |||
| if (dictionary_name[0] == 0) { | |||
| DeleteTranslator(new_translator); | |||
| return NULL; // no dictionary loaded | |||
| return NULL; // no dictionary loaded | |||
| } | |||
| new_translator->dict_condition = conditional_rules; | |||
| @@ -960,7 +961,6 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| langopts = &new_translator->langopts; | |||
| if ((value = langopts->param[LOPT_LENGTH_MODS]) != 0) | |||
| SetLengthMods(new_translator, value); | |||
| @@ -969,7 +969,6 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| if (!tone_only) | |||
| translator = new_translator; | |||
| // relative lengths of different stress syllables | |||
| for (ix = 0; ix < stress_lengths_set; ix++) | |||
| translator->stress_lengths[ix] = stress_lengths[ix]; | |||
| @@ -985,8 +984,8 @@ voice_t *LoadVoice(const char *vname, int control) | |||
| static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | |||
| { | |||
| // Remove any voice variant suffix (name or number) from a voice name | |||
| // Returns the voice variant name | |||
| // Remove any voice variant suffix (name or number) from a voice name | |||
| // Returns the voice variant name | |||
| char *p; | |||
| static char variant_name[40]; | |||
| @@ -1001,9 +1000,9 @@ static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | |||
| if ((p = strchr(vname, '+')) != NULL) { | |||
| // The voice name has a +variant suffix | |||
| variant_num = 0; | |||
| *p++ = 0; // delete the suffix from the voice name | |||
| *p++ = 0; // delete the suffix from the voice name | |||
| if (IsDigit09(*p)) | |||
| variant_num = atoi(p); // variant number | |||
| variant_num = atoi(p); // variant number | |||
| else { | |||
| // voice variant name, not number | |||
| sprintf(variant_name, "%s%s", variant_prefix, p); | |||
| @@ -1013,9 +1012,9 @@ static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | |||
| if (variant_num > 0) { | |||
| if (variant_num < 10) | |||
| sprintf(variant_name, "%sm%d", variant_prefix, variant_num); // male | |||
| sprintf(variant_name, "%sm%d", variant_prefix, variant_num); // male | |||
| else | |||
| sprintf(variant_name, "%sf%d", variant_prefix, variant_num-10); // female | |||
| sprintf(variant_name, "%sf%d", variant_prefix, variant_num-10); // female | |||
| } | |||
| return variant_name; | |||
| @@ -1023,8 +1022,8 @@ static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | |||
| voice_t *LoadVoiceVariant(const char *vname, int variant_num) | |||
| { | |||
| // Load a voice file. | |||
| // Also apply a voice variant if specified by "variant", or by "+number" or "+name" in the "vname" | |||
| // Load a voice file. | |||
| // Also apply a voice variant if specified by "variant", or by "+number" or "+name" in the "vname" | |||
| voice_t *v; | |||
| char *variant_name; | |||
| @@ -1047,9 +1046,9 @@ static int __cdecl VoiceNameSorter(const void *p1, const void *p2) | |||
| espeak_VOICE *v1 = *(espeak_VOICE **)p1; | |||
| espeak_VOICE *v2 = *(espeak_VOICE **)p2; | |||
| if ((ix = strcmp(&v1->languages[1], &v2->languages[1])) != 0) // primary language name | |||
| if ((ix = strcmp(&v1->languages[1], &v2->languages[1])) != 0) // primary language name | |||
| return ix; | |||
| if ((ix = v1->languages[0] - v2->languages[0]) != 0) // priority number | |||
| if ((ix = v1->languages[0] - v2->languages[0]) != 0) // priority number | |||
| return ix; | |||
| return strcmp(v1->name, v2->name); | |||
| } | |||
| @@ -1080,7 +1079,7 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
| int required_age; | |||
| int diff; | |||
| p = voice->languages; // list of languages+dialects for which this voice is suitable | |||
| p = voice->languages; // list of languages+dialects for which this voice is suitable | |||
| if (spec_n_parts < 0) { | |||
| // match on the subdirectory | |||
| @@ -1123,10 +1122,10 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
| break; | |||
| } | |||
| p += (ix+1); | |||
| matching_parts += matching; // number of parts which match | |||
| matching_parts += matching; // number of parts which match | |||
| if (matching_parts == 0) | |||
| continue; // no matching parts for this language | |||
| continue; // no matching parts for this language | |||
| x = 5; | |||
| // reduce the score if not all parts of the required language match | |||
| @@ -1163,7 +1162,7 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
| } | |||
| if ((voice_spec->age <= 12) && (voice->gender == 2) && (voice->age > 12)) | |||
| score += 5; // give some preference for non-child female voice if a child is requested | |||
| score += 5; // give some preference for non-child female voice if a child is requested | |||
| if (voice->age != 0) { | |||
| if (voice_spec->age == 0) | |||
| @@ -1174,14 +1173,14 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
| ratio = (required_age*100)/voice->age; | |||
| if (ratio < 100) | |||
| ratio = 10000/ratio; | |||
| ratio = (ratio - 100)/10; // 0=exact match, 10=out by factor of 2 | |||
| ratio = (ratio - 100)/10; // 0=exact match, 10=out by factor of 2 | |||
| x = 5 - ratio; | |||
| if (x > 0) x = 0; | |||
| score = score + x; | |||
| if (voice_spec->age > 0) | |||
| score += 10; // required age specified, favour voices with a specified age (near it) | |||
| score += 10; // required age specified, favour voices with a specified age (near it) | |||
| } | |||
| if (score < 1) | |||
| score = 1; | |||
| @@ -1190,10 +1189,10 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s | |||
| static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int control) | |||
| { | |||
| // control: bit0=1 include mbrola voices | |||
| // control: bit0=1 include mbrola voices | |||
| int ix; | |||
| int score; | |||
| int nv; // number of candidates | |||
| int nv; // number of candidates | |||
| int n_parts = 0; | |||
| int lang_len = 0; | |||
| espeak_VOICE *vp; | |||
| @@ -1212,7 +1211,7 @@ static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int | |||
| if ((n_parts == 1) && (control & 1)) { | |||
| if (strcmp(language, "mbrola") == 0) { | |||
| language[2] = 0; // truncate to "mb" | |||
| language[2] = 0; // truncate to "mb" | |||
| lang_len = 2; | |||
| } | |||
| @@ -1238,7 +1237,7 @@ static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int | |||
| vp->score = score; | |||
| } | |||
| } | |||
| voices[nv] = NULL; // list terminator | |||
| voices[nv] = NULL; // list terminator | |||
| if (nv == 0) | |||
| return 0; | |||
| @@ -1255,7 +1254,7 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | |||
| int match_fname = -1; | |||
| int match_fname2 = -1; | |||
| int match_name = -1; | |||
| const char *id; // this is the filename within espeak-data/voices | |||
| const char *id; // this is the filename within espeak-data/voices | |||
| char *variant_name; | |||
| int last_part_len; | |||
| char last_part[41]; | |||
| @@ -1263,7 +1262,7 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | |||
| if (voices == NULL) { | |||
| if (n_voices_list == 0) | |||
| espeak_ListVoices(NULL); // create the voices list | |||
| espeak_ListVoices(NULL); // create the voices list | |||
| voices = voices_list; | |||
| } | |||
| @@ -1278,21 +1277,21 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | |||
| for (ix = 0; voices[ix] != NULL; ix++) { | |||
| if (strcmp(name, voices[ix]->name) == 0) { | |||
| match_name = ix; // found matching voice name | |||
| match_name = ix; // found matching voice name | |||
| break; | |||
| } else { | |||
| id = voices[ix]->identifier; | |||
| if (strcmp(name, id) == 0) | |||
| match_fname = ix; // matching identifier, use this if no matching name | |||
| match_fname = ix; // matching identifier, use this if no matching name | |||
| else if (strcmp(last_part, &id[strlen(id)-last_part_len]) == 0) | |||
| match_fname2 = ix; | |||
| } | |||
| } | |||
| if (match_name < 0) { | |||
| match_name = match_fname; // no matching name, try matching filename | |||
| match_name = match_fname; // no matching name, try matching filename | |||
| if (match_name < 0) | |||
| match_name = match_fname2; // try matching just the last part of the filename | |||
| match_name = match_fname2; // try matching just the last part of the filename | |||
| } | |||
| if (match_name < 0) | |||
| @@ -1303,9 +1302,10 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | |||
| char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
| { | |||
| // Returns a path within espeak-voices, with a possible +variant suffix | |||
| // variant is an output-only parameter | |||
| int nv; // number of candidates | |||
| // Returns a path within espeak-voices, with a possible +variant suffix | |||
| // variant is an output-only parameter | |||
| int nv; // number of candidates | |||
| int ix, ix2; | |||
| int j; | |||
| int n_variants; | |||
| @@ -1327,7 +1327,7 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
| memcpy(&voice_select2, voice_select, sizeof(voice_select2)); | |||
| if (n_voices_list == 0) | |||
| espeak_ListVoices(NULL); // create the voices list | |||
| espeak_ListVoices(NULL); // create the voices list | |||
| if ((voice_select2.languages == NULL) || (voice_select2.languages[0] == 0)) { | |||
| // no language is specified. Get language from the named voice | |||
| @@ -1372,13 +1372,13 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
| else if (voice_select2.gender == 1) | |||
| gender = 1; | |||
| #define AGE_OLD 60 | |||
| #define AGE_OLD 60 | |||
| if (voice_select2.age < AGE_OLD) | |||
| aged = 0; | |||
| p = p_start = variant_lists[gender]; | |||
| if (aged == 0) | |||
| p++; // the first voice in the variants list is older | |||
| p++; // the first voice in the variants list is older | |||
| // add variants for the top voices | |||
| n_variants = 0; | |||
| @@ -1401,8 +1401,8 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
| continue; | |||
| } | |||
| vp2 = &voice_variants[n_variants++]; // allocate space for voice variant | |||
| memcpy(vp2, vp, sizeof(espeak_VOICE)); // copy from the original voice | |||
| vp2 = &voice_variants[n_variants++]; // allocate space for voice variant | |||
| memcpy(vp2, vp, sizeof(espeak_VOICE)); // copy from the original voice | |||
| vp2->variant = variant_number; | |||
| voices2[ix2++] = vp2; | |||
| p++; | |||
| @@ -1411,8 +1411,8 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) | |||
| } | |||
| // add any more variants to the end of the list | |||
| while ((vp != NULL) && ((variant_number = *p++) != 0) && (n_variants < N_VOICE_VARIANTS)) { | |||
| vp2 = &voice_variants[n_variants++]; // allocate space for voice variant | |||
| memcpy(vp2, vp, sizeof(espeak_VOICE)); // copy from the original voice | |||
| vp2 = &voice_variants[n_variants++]; // allocate space for voice variant | |||
| memcpy(vp2, vp, sizeof(espeak_VOICE)); // copy from the original voice | |||
| vp2->variant = variant_number; | |||
| voices2[ix2++] = vp2; | |||
| } | |||
| @@ -1456,7 +1456,7 @@ static void GetVoices(const char *path) | |||
| regs.r[6] = 0; | |||
| while (regs.r[3] > 0) { | |||
| error = _kernel_swi(0x0c+0x20000, ®s, ®s); /* OS_GBPB 10, read directory entries */ | |||
| error = _kernel_swi(0x0c+0x20000, ®s, ®s); // OS_GBPB 10, read directory entries | |||
| if ((error != NULL) || (regs.r[3] == 0)) | |||
| break; | |||
| type = (int *)(&buf[16]); | |||
| @@ -1484,7 +1484,7 @@ static void GetVoices(const char *path) | |||
| WIN32_FIND_DATAA FindFileData; | |||
| HANDLE hFind = INVALID_HANDLE_VALUE; | |||
| #undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string | |||
| #undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string | |||
| sprintf(fname, "%s\\*", path); | |||
| hFind = FindFirstFileA(fname, &FindFileData); | |||
| if (hFind == INVALID_HANDLE_VALUE) | |||
| @@ -1492,7 +1492,7 @@ static void GetVoices(const char *path) | |||
| do { | |||
| if (n_voices_list >= (N_VOICES_LIST-2)) | |||
| break; // voices list is full | |||
| break; // voices list is full | |||
| if (FindFileData.cFileName[0] != '.') { | |||
| sprintf(fname, "%s%c%s", path, PATHSEP, FindFileData.cFileName); | |||
| @@ -1520,12 +1520,12 @@ static void GetVoices(const char *path) | |||
| DIR *dir; | |||
| struct dirent *ent; | |||
| if ((dir = opendir((char *)path)) == NULL) // note: (char *) is needed for WINCE | |||
| if ((dir = opendir((char *)path)) == NULL) // note: (char *) is needed for WINCE | |||
| return; | |||
| while ((ent = readdir(dir)) != NULL) { | |||
| if (n_voices_list >= (N_VOICES_LIST-2)) | |||
| break; // voices list is full | |||
| break; // voices list is full | |||
| if (ent->d_name[0] == '.') | |||
| continue; | |||
| @@ -1574,7 +1574,7 @@ espeak_ERROR SetVoiceByName(const char *name) | |||
| } | |||
| memset(&voice_selector, 0, sizeof(voice_selector)); | |||
| voice_selector.name = (char *)name; // include variant name in voice stack ?? | |||
| voice_selector.name = (char *)name; // include variant name in voice stack ?? | |||
| // first check for a voice with this filename | |||
| // This may avoid the need to call espeak_ListVoices(). | |||
| @@ -1590,7 +1590,7 @@ espeak_ERROR SetVoiceByName(const char *name) | |||
| } | |||
| if (n_voices_list == 0) | |||
| espeak_ListVoices(NULL); // create the voices list | |||
| espeak_ListVoices(NULL); // create the voices list | |||
| if ((v = SelectVoiceByName(voices_list, buf)) != NULL) { | |||
| if (LoadVoice(v->identifier, 0) != NULL) { | |||
| @@ -1602,7 +1602,7 @@ espeak_ERROR SetVoiceByName(const char *name) | |||
| return EE_OK; | |||
| } | |||
| } | |||
| return EE_INTERNAL_ERROR; // voice name not found | |||
| return EE_INTERNAL_ERROR; // voice name not found | |||
| } | |||
| espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector) | |||
| @@ -1645,7 +1645,7 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) | |||
| sprintf(path_voices, "%s%cvoices", path_home, PATHSEP); | |||
| len_path_voices = strlen(path_voices)+1; | |||
| GetVoices(path_voices); | |||
| voices_list[n_voices_list] = NULL; // voices list terminator | |||
| voices_list[n_voices_list] = NULL; // voices list terminator | |||
| } | |||
| return (const espeak_VOICE **)voices_list; | |||
| #else | |||
| @@ -1661,7 +1661,7 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) | |||
| len_path_voices = strlen(path_voices)+1; | |||
| GetVoices(path_voices); | |||
| voices_list[n_voices_list] = NULL; // voices list terminator | |||
| voices_list[n_voices_list] = NULL; // voices list terminator | |||
| voices = (espeak_VOICE **)realloc(voices, sizeof(espeak_VOICE *)*(n_voices_list+1)); | |||
| // sort the voices list | |||
| @@ -48,7 +48,7 @@ struct timespec { | |||
| long tv_sec; | |||
| long tv_nsec; | |||
| }; | |||
| #endif /* HAVE_STRUCT_TIMESPEC */ | |||
| #endif | |||
| enum { ONE_BILLION = 1000000000 }; | |||
| @@ -99,7 +99,8 @@ void *wave_pulse_test_get_write_buffer(); | |||
| int wave_pulse_get_remaining_time(uint32_t sample, uint32_t *time); | |||
| // wrappers | |||
| int wave_init(int srate) { | |||
| int wave_init(int srate) | |||
| { | |||
| pulse_running = is_pulse_running(); | |||
| if (pulse_running) | |||
| @@ -108,70 +109,80 @@ int wave_init(int srate) { | |||
| return wave_port_init(srate); | |||
| } | |||
| void *wave_open(const char *the_api) { | |||
| void *wave_open(const char *the_api) | |||
| { | |||
| if (pulse_running) | |||
| return wave_pulse_open(the_api); | |||
| else | |||
| return wave_port_open(the_api); | |||
| } | |||
| size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) { | |||
| size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) | |||
| { | |||
| if (pulse_running) | |||
| return wave_pulse_write(theHandler, theMono16BitsWaveBuffer, theSize); | |||
| else | |||
| return wave_port_write(theHandler, theMono16BitsWaveBuffer, theSize); | |||
| } | |||
| int wave_close(void *theHandler) { | |||
| int wave_close(void *theHandler) | |||
| { | |||
| if (pulse_running) | |||
| return wave_pulse_close(theHandler); | |||
| else | |||
| return wave_port_close(theHandler); | |||
| } | |||
| int wave_is_busy(void *theHandler) { | |||
| int wave_is_busy(void *theHandler) | |||
| { | |||
| if (pulse_running) | |||
| return wave_pulse_is_busy(theHandler); | |||
| else | |||
| return wave_port_is_busy(theHandler); | |||
| } | |||
| void wave_terminate() { | |||
| void wave_terminate() | |||
| { | |||
| if (pulse_running) | |||
| wave_pulse_terminate(); | |||
| else | |||
| wave_port_terminate(); | |||
| } | |||
| uint32_t wave_get_read_position(void *theHandler) { | |||
| uint32_t wave_get_read_position(void *theHandler) | |||
| { | |||
| if (pulse_running) | |||
| return wave_pulse_get_read_position(theHandler); | |||
| else | |||
| return wave_port_get_read_position(theHandler); | |||
| } | |||
| uint32_t wave_get_write_position(void *theHandler) { | |||
| uint32_t wave_get_write_position(void *theHandler) | |||
| { | |||
| if (pulse_running) | |||
| return wave_pulse_get_write_position(theHandler); | |||
| else | |||
| return wave_port_get_write_position(theHandler); | |||
| } | |||
| void wave_flush(void *theHandler) { | |||
| void wave_flush(void *theHandler) | |||
| { | |||
| if (pulse_running) | |||
| wave_pulse_flush(theHandler); | |||
| else | |||
| wave_port_flush(theHandler); | |||
| } | |||
| void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
| void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
| { | |||
| if (pulse_running) | |||
| wave_pulse_set_callback_is_output_enabled(cb); | |||
| else | |||
| wave_port_set_callback_is_output_enabled(cb); | |||
| } | |||
| void *wave_test_get_write_buffer() { | |||
| void *wave_test_get_write_buffer() | |||
| { | |||
| if (pulse_running) | |||
| return wave_pulse_test_get_write_buffer(); | |||
| else | |||
| @@ -200,7 +211,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| #define wave_test_get_write_buffer wave_port_test_get_write_buffer | |||
| #define wave_get_remaining_time wave_port_get_remaining_time | |||
| #endif // USE_PULSEAUDIO | |||
| #endif | |||
| static t_wave_callback *my_callback_is_output_enabled = NULL; | |||
| @@ -320,9 +331,8 @@ static int pa_callback(const void *inputBuffer, void *outputBuffer, | |||
| mInCallbackFinishedState = true; | |||
| size_t aUsedMem = 0; | |||
| aUsedMem = (size_t)(aWrite - myRead); | |||
| if (aUsedMem) { | |||
| if (aUsedMem) | |||
| memcpy(outputBuffer, myRead, aUsedMem); | |||
| } | |||
| char *p = (char *)outputBuffer + aUsedMem; | |||
| memset(p, 0, n - aUsedMem); | |||
| myRead = aWrite; | |||
| @@ -418,17 +428,17 @@ static int wave_open_sound() | |||
| PaDeviceID playbackDevice = Pa_GetDefaultOutputDeviceID(); | |||
| PaError err = Pa_OpenStream(&pa_stream, | |||
| /* capture parameters */ | |||
| // capture parameters | |||
| paNoDevice, | |||
| 0, | |||
| paInt16, | |||
| NULL, | |||
| /* playback parameters */ | |||
| // playback parameters | |||
| playbackDevice, | |||
| out_channels, | |||
| paInt16, | |||
| NULL, | |||
| /* general parameters */ | |||
| // general parameters | |||
| wave_samplerate, FRAMES_PER_BUFFER, 0, | |||
| paNoFlag, | |||
| pa_callback, (void *)userdata); | |||
| @@ -440,17 +450,17 @@ static int wave_open_sound() | |||
| // failed to open with mono, try stereo | |||
| out_channels = 2; | |||
| PaError err = Pa_OpenStream(&pa_stream, | |||
| /* capture parameters */ | |||
| // capture parameters | |||
| paNoDevice, | |||
| 0, | |||
| paInt16, | |||
| NULL, | |||
| /* playback parameters */ | |||
| // playback parameters | |||
| playbackDevice, | |||
| out_channels, | |||
| paInt16, | |||
| NULL, | |||
| /* general parameters */ | |||
| // general parameters | |||
| wave_samplerate, FRAMES_PER_BUFFER, 0, | |||
| paNoFlag, | |||
| pa_callback, (void *)userdata); | |||
| @@ -461,45 +471,40 @@ static int wave_open_sound() | |||
| #else | |||
| myOutputParameters.channelCount = out_channels; | |||
| unsigned long framesPerBuffer = paFramesPerBufferUnspecified; | |||
| err = Pa_OpenStream( | |||
| &pa_stream, | |||
| NULL, /* no input */ | |||
| &myOutputParameters, | |||
| wave_samplerate, | |||
| framesPerBuffer, | |||
| paNoFlag, | |||
| pa_callback, | |||
| (void *)userdata); | |||
| err = Pa_OpenStream(&pa_stream, | |||
| NULL, // no input | |||
| &myOutputParameters, | |||
| wave_samplerate, | |||
| framesPerBuffer, | |||
| paNoFlag, | |||
| pa_callback, | |||
| (void *)userdata); | |||
| if ((err != paNoError) | |||
| && (err != paInvalidChannelCount)) { // err==paUnanticipatedHostError | |||
| && (err != paInvalidChannelCount)) { | |||
| fprintf(stderr, "wave_open_sound > Pa_OpenStream : err=%d (%s)\n", err, Pa_GetErrorText(err)); | |||
| framesPerBuffer = FRAMES_PER_BUFFER; | |||
| err = Pa_OpenStream( | |||
| &pa_stream, | |||
| NULL, /* no input */ | |||
| &myOutputParameters, | |||
| wave_samplerate, | |||
| framesPerBuffer, | |||
| paNoFlag, | |||
| // paClipOff | paDitherOff, | |||
| pa_callback, | |||
| (void *)userdata); | |||
| err = Pa_OpenStream(&pa_stream, | |||
| NULL, // no input | |||
| &myOutputParameters, | |||
| wave_samplerate, | |||
| framesPerBuffer, | |||
| paNoFlag, | |||
| pa_callback, | |||
| (void *)userdata); | |||
| } | |||
| if (err == paInvalidChannelCount) { | |||
| SHOW_TIME("wave_open_sound > try stereo"); | |||
| // failed to open with mono, try stereo | |||
| out_channels = 2; | |||
| myOutputParameters.channelCount = out_channels; | |||
| err = Pa_OpenStream( | |||
| &pa_stream, | |||
| NULL, /* no input */ | |||
| &myOutputParameters, | |||
| wave_samplerate, | |||
| framesPerBuffer, | |||
| paNoFlag, | |||
| // paClipOff | paDitherOff, | |||
| pa_callback, | |||
| (void *)userdata); | |||
| err = Pa_OpenStream(&pa_stream, | |||
| NULL, // no input | |||
| &myOutputParameters, | |||
| wave_samplerate, | |||
| framesPerBuffer, | |||
| paNoFlag, | |||
| pa_callback, | |||
| (void *)userdata); | |||
| } | |||
| mInCallbackFinishedState = false; | |||
| #endif | |||
| @@ -748,7 +753,7 @@ size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSiz | |||
| myWrite = myBuffer; | |||
| myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem/2, theSize - aFreeMem/2); | |||
| } else { // 1 channel (mono) | |||
| // copy with wrap around at the end of ringbuffer | |||
| // copy with wrap around at the end of ringbuffer | |||
| copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem); | |||
| myWrite = myBuffer; | |||
| myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem, theSize - aFreeMem); | |||
| @@ -832,7 +837,6 @@ int wave_close(void *theHandler) | |||
| // DMM: This doesn't seem to be true; it seems to be necessary to | |||
| // call StopStream if the callback brought us here, and AbortStream | |||
| // if the user brought us here. | |||
| // | |||
| #if (USE_PORTAUDIO == 19) | |||
| if (pa_stream) { | |||
| @@ -937,35 +941,57 @@ void *wave_test_get_write_buffer() | |||
| #else | |||
| int wave_init(int srate) { | |||
| int wave_init(int srate) | |||
| { | |||
| return 1; | |||
| } | |||
| void *wave_open(const char *the_api) { | |||
| void *wave_open(const char *the_api) | |||
| { | |||
| return (void *)1; | |||
| } | |||
| size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) { | |||
| size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) | |||
| { | |||
| return theSize; | |||
| } | |||
| int wave_close(void *theHandler) { | |||
| int wave_close(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| int wave_is_busy(void *theHandler) { | |||
| int wave_is_busy(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| void wave_terminate() { | |||
| void wave_terminate() | |||
| { | |||
| } | |||
| uint32_t wave_get_read_position(void *theHandler) { | |||
| uint32_t wave_get_read_position(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| uint32_t wave_get_write_position(void *theHandler) { | |||
| uint32_t wave_get_write_position(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| void wave_flush(void *theHandler) { | |||
| void wave_flush(void *theHandler) | |||
| { | |||
| } | |||
| typedef int (t_wave_callback)(void); | |||
| void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
| void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
| { | |||
| } | |||
| extern void *wave_test_get_write_buffer() { | |||
| extern void *wave_test_get_write_buffer() | |||
| { | |||
| return NULL; | |||
| } | |||
| @@ -976,7 +1002,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| return 0; | |||
| } | |||
| #endif // of USE_PORTAUDIO | |||
| #endif | |||
| void clock_gettime2(struct timespec *ts) | |||
| { | |||
| @@ -1004,4 +1030,4 @@ void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
| ts->tv_nsec = (long int)t_ns; | |||
| } | |||
| #endif // USE_ASYNC | |||
| #endif | |||
| @@ -55,7 +55,6 @@ extern int wave_get_remaining_time(uint32_t sample, uint32_t *time); | |||
| typedef int (t_wave_callback)(void); | |||
| extern void wave_set_callback_is_output_enabled(t_wave_callback *cb); | |||
| // general functions | |||
| extern void clock_gettime2(struct timespec *ts); | |||
| extern void add_time_in_ms(struct timespec *ts, int time_in_ms); | |||
| @@ -102,7 +102,8 @@ int is_pulse_running() | |||
| } else | |||
| return 0; | |||
| } | |||
| #endif // USE_PORTAUDIO | |||
| #endif | |||
| static pthread_mutex_t pulse_mutex; | |||
| @@ -138,7 +139,8 @@ static int wave_samplerate; | |||
| if (!connected) { SHOW("CHECK_CONNECTED_NO_RETVAL: !pulse_connected\n", ""); return; } \ | |||
| } while (0); | |||
| static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { | |||
| static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| assert(c); | |||
| @@ -150,7 +152,8 @@ static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t | |||
| return; | |||
| } | |||
| static void context_state_cb(pa_context *c, void *userdata) { | |||
| static void context_state_cb(pa_context *c, void *userdata) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| assert(c); | |||
| @@ -169,7 +172,8 @@ static void context_state_cb(pa_context *c, void *userdata) { | |||
| } | |||
| } | |||
| static void stream_state_cb(pa_stream *s, void *userdata) { | |||
| static void stream_state_cb(pa_stream *s, void *userdata) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| assert(s); | |||
| @@ -186,7 +190,8 @@ static void stream_state_cb(pa_stream *s, void *userdata) { | |||
| } | |||
| } | |||
| static void stream_success_cb(pa_stream *s, int success, void *userdata) { | |||
| static void stream_success_cb(pa_stream *s, int success, void *userdata) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| assert(s); | |||
| @@ -196,7 +201,8 @@ static void stream_success_cb(pa_stream *s, int success, void *userdata) { | |||
| pa_threaded_mainloop_signal(mainloop, 0); | |||
| } | |||
| static void context_success_cb(pa_context *c, int success, void *userdata) { | |||
| static void context_success_cb(pa_context *c, int success, void *userdata) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| assert(c); | |||
| @@ -206,20 +212,23 @@ static void context_success_cb(pa_context *c, int success, void *userdata) { | |||
| pa_threaded_mainloop_signal(mainloop, 0); | |||
| } | |||
| static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { | |||
| static void stream_request_cb(pa_stream *s, size_t length, void *userdata) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| assert(s); | |||
| pa_threaded_mainloop_signal(mainloop, 0); | |||
| } | |||
| static void stream_latency_update_cb(pa_stream *s, void *userdata) { | |||
| static void stream_latency_update_cb(pa_stream *s, void *userdata) | |||
| { | |||
| assert(s); | |||
| pa_threaded_mainloop_signal(mainloop, 0); | |||
| } | |||
| static int pulse_free(void) { | |||
| static int pulse_free(void) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| size_t l = 0; | |||
| pa_operation *o = NULL; | |||
| @@ -273,7 +282,8 @@ fail: | |||
| return (int)l; | |||
| } | |||
| static int pulse_playing(const pa_timing_info *the_timing_info) { | |||
| static int pulse_playing(const pa_timing_info *the_timing_info) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| int r = 0; | |||
| const pa_timing_info *i; | |||
| @@ -306,7 +316,8 @@ fail: | |||
| return r; | |||
| } | |||
| static void pulse_write(void *ptr, int length) { | |||
| static void pulse_write(void *ptr, int length) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| SHOW("pulse_write > length=%d\n", length); | |||
| @@ -327,7 +338,8 @@ fail: | |||
| pa_threaded_mainloop_unlock(mainloop); | |||
| } | |||
| static int drain(void) { | |||
| static int drain(void) | |||
| { | |||
| pa_operation *o = NULL; | |||
| int success = 0; | |||
| int ret = PULSE_ERROR; | |||
| @@ -367,8 +379,8 @@ fail: | |||
| return ret; | |||
| } | |||
| static void pulse_close(void) { | |||
| static void pulse_close(void) | |||
| { | |||
| ENTER(__FUNCTION__); | |||
| drain(); | |||
| @@ -448,7 +460,7 @@ static int pulse_open() | |||
| goto unlock_and_fail; | |||
| } | |||
| /* Wait until the context is ready */ | |||
| // Wait until the context is ready | |||
| SHOW_TIME("pa_threaded_mainloop_wait"); | |||
| pa_threaded_mainloop_wait(mainloop); | |||
| @@ -484,7 +496,7 @@ static int pulse_open() | |||
| goto unlock_and_fail; | |||
| } | |||
| /* Wait until the stream is ready */ | |||
| // Wait until the stream is ready | |||
| SHOW_TIME("pa_threaded_mainloop_wait"); | |||
| pa_threaded_mainloop_wait(mainloop); | |||
| @@ -493,7 +505,7 @@ static int pulse_open() | |||
| goto unlock_and_fail; | |||
| } | |||
| /* Now subscribe to events */ | |||
| // Now subscribe to events | |||
| SHOW_TIME("pa_context_subscribe"); | |||
| if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) { | |||
| SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); | |||
| @@ -714,9 +726,8 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| // TBD: take in account time suplied by portaudio V18 API | |||
| a_time = sample - a_timing_info.read_index; | |||
| a_time = 0.5 + (a_time * 1000.0) / wave_samplerate; | |||
| } else { | |||
| } else | |||
| a_time = 0; | |||
| } | |||
| SHOW("wave_get_remaining_time > sample=%d, time=%d\n", sample, (uint32_t)a_time); | |||
| @@ -732,34 +743,57 @@ void *wave_test_get_write_buffer() | |||
| #else | |||
| int wave_init(return 1; ) { | |||
| int wave_init(int srate) | |||
| { | |||
| return 1; | |||
| } | |||
| void *wave_open(const char *the_api) { | |||
| void *wave_open(const char *the_api) | |||
| { | |||
| return (void *)1; | |||
| } | |||
| size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) { | |||
| size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) | |||
| { | |||
| return theSize; | |||
| } | |||
| int wave_close(void *theHandler) { | |||
| int wave_close(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| int wave_is_busy(void *theHandler) { | |||
| int wave_is_busy(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| void wave_terminate() { | |||
| void wave_terminate() | |||
| { | |||
| } | |||
| uint32_t wave_get_read_position(void *theHandler) { | |||
| uint32_t wave_get_read_position(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| uint32_t wave_get_write_position(void *theHandler) { | |||
| uint32_t wave_get_write_position(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| void wave_flush(void *theHandler) { | |||
| void wave_flush(void *theHandler) | |||
| { | |||
| } | |||
| typedef int (t_wave_callback)(void); | |||
| void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
| void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
| { | |||
| } | |||
| extern void *wave_test_get_write_buffer() { | |||
| extern void *wave_test_get_write_buffer() | |||
| { | |||
| return NULL; | |||
| } | |||
| @@ -770,7 +804,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| return 0; | |||
| } | |||
| #endif // of USE_PULSEAUDIO | |||
| #endif | |||
| #ifndef USE_PORTAUDIO | |||
| @@ -799,6 +833,6 @@ void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
| } | |||
| ts->tv_nsec = (long int)t_ns; | |||
| } | |||
| #endif // ifndef USE_PORTAUDIO | |||
| #endif // USE_ASYNC | |||
| #endif | |||
| #endif | |||
| @@ -75,7 +75,8 @@ static uint32_t wave_samplerate; | |||
| // sun_audio_fd: modified to hold the file descriptor of the opened | |||
| // audio device. | |||
| // | |||
| int wave_init(int srate) { | |||
| int wave_init(int srate) | |||
| { | |||
| ENTER("wave_init"); | |||
| audio_info_t ainfo; | |||
| @@ -478,9 +479,9 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| // | |||
| actual_index = sample - total_samples_skipped; | |||
| if ((sample < total_samples_skipped) || | |||
| (actual_index <= ainfo.play.samples)) { | |||
| (actual_index <= ainfo.play.samples)) | |||
| *time = 0; | |||
| } else { | |||
| else { | |||
| a_time = ((actual_index - ainfo.play.samples) * 1000) / wave_samplerate; | |||
| *time = (uint32_t)a_time; | |||
| } | |||
| @@ -491,35 +492,57 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| #else | |||
| init wave_init() { | |||
| int wave_init(int srate) | |||
| { | |||
| return 1; | |||
| } | |||
| void *wave_open(const char *the_api) { | |||
| void *wave_open(const char *the_api) | |||
| { | |||
| return (void *)1; | |||
| } | |||
| size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) { | |||
| size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) | |||
| { | |||
| return theSize; | |||
| } | |||
| int wave_close(void *theHandler) { | |||
| int wave_close(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| int wave_is_busy(void *theHandler) { | |||
| int wave_is_busy(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| void wave_terminate() { | |||
| void wave_terminate() | |||
| { | |||
| } | |||
| uint32_t wave_get_read_position(void *theHandler) { | |||
| uint32_t wave_get_read_position(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| uint32_t wave_get_write_position(void *theHandler) { | |||
| uint32_t wave_get_write_position(void *theHandler) | |||
| { | |||
| return 0; | |||
| } | |||
| void wave_flush(void *theHandler) { | |||
| void wave_flush(void *theHandler) | |||
| { | |||
| } | |||
| typedef int (t_wave_callback)(void); | |||
| void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
| void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
| { | |||
| } | |||
| extern void *wave_test_get_write_buffer() { | |||
| extern void *wave_test_get_write_buffer() | |||
| { | |||
| return NULL; | |||
| } | |||
| @@ -530,7 +553,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| return 0; | |||
| } | |||
| #endif // of USE_PORTAUDIO | |||
| #endif | |||
| void clock_gettime2(struct timespec *ts) | |||
| { | |||
| @@ -558,4 +581,4 @@ void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
| ts->tv_nsec = (long int)t_ns; | |||
| } | |||
| #endif // USE_ASYNC | |||
| #endif | |||
| @@ -62,16 +62,16 @@ voice_t *wvoice; | |||
| FILE *f_log = NULL; | |||
| int option_waveout = 0; | |||
| static int option_harmonic1 = 10; // 10 | |||
| static int option_harmonic1 = 10; | |||
| static int flutter_amp = 64; | |||
| static int general_amplitude = 60; | |||
| static int consonant_amp = 26; // 24 | |||
| static int consonant_amp = 26; | |||
| int embedded_value[N_EMBEDDED_VALUES]; | |||
| static int PHASE_INC_FACTOR; | |||
| int samplerate = 0; // this is set by Wavegeninit() | |||
| int samplerate = 0; // this is set by Wavegeninit() | |||
| int samplerate_native = 0; | |||
| extern int option_device_number; | |||
| extern int option_quiet; | |||
| @@ -84,7 +84,7 @@ int echo_head; | |||
| int echo_tail; | |||
| int echo_amp = 0; | |||
| short echo_buf[N_ECHO_BUF]; | |||
| static int echo_length = 0; // period (in sample\) to ensure completion of echo at the end of speech, set in WavegenSetEcho() | |||
| static int echo_length = 0; // period (in sample\) to ensure completion of echo at the end of speech, set in WavegenSetEcho() | |||
| static int voicing; | |||
| static RESONATOR rbreath[N_PEAKS]; | |||
| @@ -92,13 +92,13 @@ static RESONATOR rbreath[N_PEAKS]; | |||
| static int harm_sqrt_n = 0; | |||
| #define N_LOWHARM 30 | |||
| static int harm_inc[N_LOWHARM]; // only for these harmonics do we interpolate amplitude between steps | |||
| static int harm_inc[N_LOWHARM]; // only for these harmonics do we interpolate amplitude between steps | |||
| static int *harmspect; | |||
| static int hswitch = 0; | |||
| static int hspect[2][MAX_HARMONIC]; // 2 copies, we interpolate between then | |||
| static int hspect[2][MAX_HARMONIC]; // 2 copies, we interpolate between then | |||
| static int max_hval = 0; | |||
| static int nsamples = 0; // number to do | |||
| static int nsamples = 0; // number to do | |||
| static int modulation_type = 0; | |||
| static int glottal_flag = 0; | |||
| static int glottal_reduce = 0; | |||
| @@ -109,12 +109,12 @@ static int amp_ix; | |||
| static int amp_inc; | |||
| static unsigned char *amplitude_env = NULL; | |||
| static int samplecount = 0; // number done | |||
| static int samplecount_start = 0; // count at start of this segment | |||
| static int end_wave = 0; // continue to end of wave cycle | |||
| static int samplecount = 0; // number done | |||
| static int samplecount_start = 0; // count at start of this segment | |||
| static int end_wave = 0; // continue to end of wave cycle | |||
| static int wavephase; | |||
| static int phaseinc; | |||
| static int cycle_samples; // number of samples in a cycle at current pitch | |||
| static int cycle_samples; // number of samples in a cycle at current pitch | |||
| static int cbytes; | |||
| static int hf_factor; | |||
| @@ -132,10 +132,10 @@ int wcmdq_head = 0; | |||
| int wcmdq_tail = 0; | |||
| // pitch,speed, | |||
| int embedded_default[N_EMBEDDED_VALUES] = { 0, 50, 175, 100, 50, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0 }; | |||
| static int embedded_max[N_EMBEDDED_VALUES] = { 0, 0x7fff, 750, 300, 99, 99, 99, 0, 750, 0, 0, 0, 0, 4, 0 }; | |||
| int embedded_default[N_EMBEDDED_VALUES] = { 0, 50, 175, 100, 50, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0 }; | |||
| static int embedded_max[N_EMBEDDED_VALUES] = { 0, 0x7fff, 750, 300, 99, 99, 99, 0, 750, 0, 0, 0, 0, 4, 0 }; | |||
| #define N_CALLBACK_IX N_WAV_BUF-2 // adjust this delay to match display with the currently spoken word | |||
| #define N_CALLBACK_IX N_WAV_BUF-2 // adjust this delay to match display with the currently spoken word | |||
| int current_source_index = 0; | |||
| extern FILE *f_wave; | |||
| @@ -232,22 +232,22 @@ static int wavemult_max = 0; | |||
| // the presets are for 22050 Hz sample rate. | |||
| // A different rate will need to recalculate the presets in WavegenInit() | |||
| static unsigned char wavemult[N_WAVEMULT] = { | |||
| 0, 0, 0, 2, 3, 5, 8, 11, 14, 18, 22, 27, 32, 37, 43, 49, | |||
| 55, 62, 69, 76, 83, 90, 98, 105, 113, 121, 128, 136, 144, 152, 159, 166, | |||
| 0, 0, 0, 2, 3, 5, 8, 11, 14, 18, 22, 27, 32, 37, 43, 49, | |||
| 55, 62, 69, 76, 83, 90, 98, 105, 113, 121, 128, 136, 144, 152, 159, 166, | |||
| 174, 181, 188, 194, 201, 207, 213, 218, 224, 228, 233, 237, 240, 244, 246, 249, | |||
| 251, 252, 253, 253, 253, 253, 252, 251, 249, 246, 244, 240, 237, 233, 228, 224, | |||
| 218, 213, 207, 201, 194, 188, 181, 174, 166, 159, 152, 144, 136, 128, 121, 113, | |||
| 105, 98, 90, 83, 76, 69, 62, 55, 49, 43, 37, 32, 27, 22, 18, 14, | |||
| 11, 8, 5, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |||
| 105, 98, 90, 83, 76, 69, 62, 55, 49, 43, 37, 32, 27, 22, 18, 14, | |||
| 11, 8, 5, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |||
| }; | |||
| // set from y = pow(2,x) * 128, x=-1 to 1 | |||
| unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1] = { | |||
| 64, 65, 66, 67, 68, 69, 70, 71, | |||
| 72, 73, 74, 75, 76, 77, 78, 79, | |||
| 80, 81, 82, 83, 84, 86, 87, 88, | |||
| 89, 91, 92, 93, 94, 96, 97, 98, | |||
| 64, 65, 66, 67, 68, 69, 70, 71, | |||
| 72, 73, 74, 75, 76, 77, 78, 79, | |||
| 80, 81, 82, 83, 84, 86, 87, 88, | |||
| 89, 91, 92, 93, 94, 96, 97, 98, | |||
| 100, 101, 103, 104, 105, 107, 108, 110, | |||
| 111, 113, 115, 116, 118, 119, 121, 123, | |||
| 124, 126, 128, 130, 132, 133, 135, 137, | |||
| @@ -310,19 +310,19 @@ unsigned char pk_shape1[PEAKSHAPEW+1] = { | |||
| 245, 244, 242, 241, 239, 238, 236, 234, 233, 231, 229, 227, 225, 223, 220, 218, | |||
| 216, 213, 211, 209, 207, 205, 203, 201, 199, 197, 195, 193, 191, 189, 187, 185, | |||
| 183, 180, 178, 176, 173, 171, 169, 166, 164, 161, 159, 156, 154, 151, 148, 146, | |||
| 143, 140, 138, 135, 132, 129, 126, 123, 120, 118, 115, 112, 108, 105, 102, 99, | |||
| 96, 95, 93, 91, 90, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, | |||
| 72, 70, 69, 68, 67, 66, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, | |||
| 55, 54, 53, 52, 52, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 46, | |||
| 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 44, 43, | |||
| 42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33, | |||
| 32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24, | |||
| 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 18, 17, 17, 16, | |||
| 16, 15, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10, | |||
| 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, | |||
| 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, | |||
| 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0 | |||
| 143, 140, 138, 135, 132, 129, 126, 123, 120, 118, 115, 112, 108, 105, 102, 99, | |||
| 96, 95, 93, 91, 90, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, | |||
| 72, 70, 69, 68, 67, 66, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, | |||
| 55, 54, 53, 52, 52, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 46, | |||
| 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 44, 43, | |||
| 42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33, | |||
| 32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24, | |||
| 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 18, 17, 17, 16, | |||
| 16, 15, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10, | |||
| 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, | |||
| 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, | |||
| 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0 | |||
| }; | |||
| static unsigned char pk_shape2[PEAKSHAPEW+1] = { | |||
| @@ -331,18 +331,18 @@ static unsigned char pk_shape2[PEAKSHAPEW+1] = { | |||
| 243, 243, 242, 241, 239, 237, 235, 233, 231, 229, 227, 225, 223, 221, 218, 216, | |||
| 213, 211, 208, 205, 203, 200, 197, 194, 191, 187, 184, 181, 178, 174, 171, 167, | |||
| 163, 160, 156, 152, 148, 144, 140, 136, 132, 127, 123, 119, 114, 110, 105, 100, | |||
| 96, 94, 91, 88, 86, 83, 81, 78, 76, 74, 71, 69, 66, 64, 62, 60, | |||
| 57, 55, 53, 51, 49, 47, 44, 42, 40, 38, 36, 34, 32, 30, 29, 27, | |||
| 25, 23, 21, 19, 18, 16, 14, 12, 11, 9, 7, 6, 4, 3, 1, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0 | |||
| 96, 94, 91, 88, 86, 83, 81, 78, 76, 74, 71, 69, 66, 64, 62, 60, | |||
| 57, 55, 53, 51, 49, 47, 44, 42, 40, 38, 36, 34, 32, 30, 29, 27, | |||
| 25, 23, 21, 19, 18, 16, 14, 12, 11, 9, 7, 6, 4, 3, 1, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||
| 0 | |||
| }; | |||
| static unsigned char *pk_shape; | |||
| @@ -389,7 +389,7 @@ static int WaveCallback(const void *inputBuffer, void *outputBuffer, | |||
| out_ptr = out_start = outbuffer; | |||
| out_end = out_start + outbuffer_size; | |||
| } | |||
| out_end2 = &outbuffer[pa_size]; // top of data needed for the portaudio buffer | |||
| out_end2 = &outbuffer[pa_size]; // top of data needed for the portaudio buffer | |||
| #ifdef LIBRARY | |||
| event_list_ix = 0; | |||
| @@ -398,19 +398,17 @@ static int WaveCallback(const void *inputBuffer, void *outputBuffer, | |||
| result = WavegenFill(1); | |||
| // copy from the outbut buffer into the portaudio buffer | |||
| if (result && (out_ptr > out_end2)) { | |||
| result = 0; // don't end yet, there is more data in the buffer than can fit in portaudio | |||
| } | |||
| if (result && (out_ptr > out_end2)) | |||
| result = 0; // don't end yet, there is more data in the buffer than can fit in portaudio | |||
| while (out_ptr < out_end2) | |||
| *out_ptr++ = 0; // fill with zeros up to the size of the portaudio buffer | |||
| *out_ptr++ = 0; // fill with zeros up to the size of the portaudio buffer | |||
| memcpy(outputBuffer, outbuffer, pa_size); | |||
| // move the remaining contents of the start of the output buffer | |||
| for (p = out_end2; p < out_end; p++) { | |||
| for (p = out_end2; p < out_end; p++) | |||
| p[-pa_size] = p[0]; | |||
| } | |||
| out_ptr -= pa_size; | |||
| #ifdef LIBRARY | |||
| @@ -421,25 +419,23 @@ static int WaveCallback(const void *inputBuffer, void *outputBuffer, | |||
| event_list[event_list_ix].user_data = 0; | |||
| if (synth_callback(NULL, 0, event_list) == 1) { | |||
| SpeakNextClause(NULL, NULL, 2); // stop speaking | |||
| SpeakNextClause(NULL, NULL, 2); // stop speaking | |||
| result = 1; | |||
| } | |||
| } | |||
| #endif | |||
| #ifdef ARCH_BIG | |||
| { | |||
| // swap the order of bytes in each sound sample in the portaudio buffer | |||
| int c; | |||
| unsigned char *buf_end; | |||
| out_buf = (unsigned char *)outputBuffer; | |||
| buf_end = out_buf + framesPerBuffer*2; | |||
| while (out_buf < buf_end) { | |||
| c = out_buf[0]; | |||
| out_buf[0] = out_buf[1]; | |||
| out_buf[1] = c; | |||
| out_buf += 2; | |||
| } | |||
| // swap the order of bytes in each sound sample in the portaudio buffer | |||
| int c; | |||
| unsigned char *buf_end; | |||
| out_buf = (unsigned char *)outputBuffer; | |||
| buf_end = out_buf + framesPerBuffer*2; | |||
| while (out_buf < buf_end) { | |||
| c = out_buf[0]; | |||
| out_buf[0] = out_buf[1]; | |||
| out_buf[1] = c; | |||
| out_buf += 2; | |||
| } | |||
| #endif | |||
| @@ -591,7 +587,7 @@ int WavegenCloseSound() | |||
| return 1; | |||
| } | |||
| } else | |||
| WavegenOpenSound(); // still items in the queue, shouldn't be closed | |||
| WavegenOpenSound(); // still items in the queue, shouldn't be closed | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -612,19 +608,24 @@ int WavegenInitSound() | |||
| } | |||
| return 0; | |||
| } | |||
| #else | |||
| int WavegenOpenSound() | |||
| { | |||
| return 0; | |||
| } | |||
| int WavegenCloseSound() | |||
| { | |||
| return 0; | |||
| } | |||
| int WavegenInitSound() | |||
| { | |||
| return 0; | |||
| } | |||
| #endif | |||
| void WavegenInit(int rate, int wavemult_fact) | |||
| @@ -633,11 +634,11 @@ void WavegenInit(int rate, int wavemult_fact) | |||
| double x; | |||
| if (wavemult_fact == 0) | |||
| wavemult_fact = 60; // default | |||
| wavemult_fact = 60; // default | |||
| wvoice = NULL; | |||
| samplerate = samplerate_native = rate; | |||
| PHASE_INC_FACTOR = 0x8000000 / samplerate; // assumes pitch is Hz*32 | |||
| PHASE_INC_FACTOR = 0x8000000 / samplerate; // assumes pitch is Hz*32 | |||
| Flutter_inc = (64 * samplerate)/rate; | |||
| samplecount = 0; | |||
| nsamples = 0; | |||
| @@ -666,7 +667,7 @@ void WavegenInit(int rate, int wavemult_fact) | |||
| } | |||
| } | |||
| pk_shape = pk_shape2; // pk_shape2 | |||
| pk_shape = pk_shape2; | |||
| #ifdef INCLUDE_KLATT | |||
| KlattInit(); | |||
| @@ -712,11 +713,11 @@ static void WavegenSetEcho(void) | |||
| amp = 0; | |||
| echo_head = (delay * samplerate)/1000; | |||
| echo_length = echo_head; // ensure completion of echo at the end of speech. Use 1 delay period? | |||
| echo_length = echo_head; // ensure completion of echo at the end of speech. Use 1 delay period? | |||
| if (amp == 0) | |||
| echo_length = 0; | |||
| if (amp > 20) | |||
| echo_length = echo_head * 2; // perhaps allow 2 echo periods if the echo is loud. | |||
| echo_length = echo_head * 2; // perhaps allow 2 echo periods if the echo is loud. | |||
| // echo_amp units are 1/256ths of the amplitude of the original sound. | |||
| echo_amp = amp; | |||
| @@ -727,21 +728,21 @@ static void WavegenSetEcho(void) | |||
| int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | |||
| { | |||
| // Calculate the amplitude of each harmonics from the formants | |||
| // Only for formants 0 to 5 | |||
| // Calculate the amplitude of each harmonics from the formants | |||
| // Only for formants 0 to 5 | |||
| // control 0=initial call, 1=every 64 cycles | |||
| // control 0=initial call, 1=every 64 cycles | |||
| // pitch and freqs are Hz<<16 | |||
| int f; | |||
| wavegen_peaks_t *p; | |||
| int fp; // centre freq of peak | |||
| int fhi; // high freq of peak | |||
| int h; // harmonic number | |||
| int fp; // centre freq of peak | |||
| int fhi; // high freq of peak | |||
| int h; // harmonic number | |||
| int pk; | |||
| int hmax; | |||
| int hmax_samplerate; // highest harmonic allowed for the samplerate | |||
| int hmax_samplerate; // highest harmonic allowed for the samplerate | |||
| int x; | |||
| int ix; | |||
| int h1; | |||
| @@ -759,7 +760,7 @@ int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | |||
| hmax = MAX_HARMONIC-1; | |||
| // restrict highest harmonic to half the samplerate | |||
| hmax_samplerate = (((samplerate * 19)/40) << 16)/pitch; // only 95% of Nyquist freq | |||
| hmax_samplerate = (((samplerate * 19)/40) << 16)/pitch; // only 95% of Nyquist freq | |||
| if (hmax > hmax_samplerate) | |||
| hmax = hmax_samplerate; | |||
| @@ -787,7 +788,7 @@ int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | |||
| int h2; | |||
| // increase bass | |||
| y = peaks[1].height * 10; // addition as a multiple of 1/256s | |||
| h2 = (1000<<16)/pitch; // decrease until 1000Hz | |||
| h2 = (1000<<16)/pitch; // decrease until 1000Hz | |||
| if (h2 > 0) { | |||
| x = y/h2; | |||
| h = 1; | |||
| @@ -819,26 +820,25 @@ int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | |||
| htab[h] = (x * x) >> 8; | |||
| if ((ix = (f >> 19)) < N_TONE_ADJUST) | |||
| htab[h] = (htab[h] * wvoice->tone_adjust[ix]) >> 13; // index tone_adjust with Hz/8 | |||
| htab[h] = (htab[h] * wvoice->tone_adjust[ix]) >> 13; // index tone_adjust with Hz/8 | |||
| } | |||
| // adjust the amplitude of the first harmonic, affects tonal quality | |||
| h1 = htab[1] * option_harmonic1; | |||
| htab[1] = h1/8; | |||
| // calc intermediate increments of LF harmonics | |||
| if (control & 1) { | |||
| for (h = 1; h < N_LOWHARM; h++) | |||
| harm_inc[h] = (htab[h] - harmspect[h]) >> 3; | |||
| } | |||
| return hmax; // highest harmonic number | |||
| return hmax; // highest harmonic number | |||
| } | |||
| static void AdvanceParameters() | |||
| { | |||
| // Called every 64 samples to increment the formant freq, height, and widths | |||
| // Called every 64 samples to increment the formant freq, height, and widths | |||
| int x; | |||
| int ix; | |||
| @@ -859,7 +859,7 @@ static void AdvanceParameters() | |||
| Flutter_ix += Flutter_inc; | |||
| wdata.pitch += x; | |||
| if (wdata.pitch < 102400) | |||
| wdata.pitch = 102400; // min pitch, 25 Hz (25 << 12) | |||
| wdata.pitch = 102400; // min pitch, 25 Hz (25 << 12) | |||
| if (samplecount == samplecount_start) | |||
| return; | |||
| @@ -912,9 +912,9 @@ static double resonator(RESONATOR *r, double input) | |||
| static void setresonator(RESONATOR *rp, int freq, int bwidth, int init) | |||
| { | |||
| // freq Frequency of resonator in Hz | |||
| // bwidth Bandwidth of resonator in Hz | |||
| // init Initialize internal data | |||
| // freq Frequency of resonator in Hz | |||
| // bwidth Bandwidth of resonator in Hz | |||
| // init Initialize internal data | |||
| double x; | |||
| double arg; | |||
| @@ -1007,7 +1007,7 @@ int Wavegen() | |||
| static int agc = 256; | |||
| static int h_switch_sign = 0; | |||
| static int cycle_count = 0; | |||
| static int amplitude2 = 0; // adjusted for pitch | |||
| static int amplitude2 = 0; // adjusted for pitch | |||
| // continue until the output buffer is full, or | |||
| // the required number of samples have been produced | |||
| @@ -1033,7 +1033,7 @@ int Wavegen() | |||
| // pitch is Hz<<12 | |||
| phaseinc = (wdata.pitch>>7) * PHASE_INC_FACTOR; | |||
| cycle_samples = samplerate/(wdata.pitch >> 12); // sr/(pitch*2) | |||
| cycle_samples = samplerate/(wdata.pitch >> 12); // sr/(pitch*2) | |||
| hf_factor = wdata.pitch >> 11; | |||
| maxh = maxh2; | |||
| @@ -1270,7 +1270,7 @@ static int PlayWave(int length, int resume, unsigned char *data, int scale, int | |||
| // 8 bit data, shift by the specified scale factor | |||
| value = (signed char)data[ix++] * scale; | |||
| } | |||
| value *= (consonant_amp * general_amplitude); // reduce strength of consonant | |||
| value *= (consonant_amp * general_amplitude); // reduce strength of consonant | |||
| value = value >> 10; | |||
| value = (value * amp)/32; | |||
| @@ -1353,14 +1353,14 @@ void SetEmbedded(int control, int value) | |||
| switch (command) | |||
| { | |||
| case EMBED_T: | |||
| WavegenSetEcho(); // and drop through to case P | |||
| WavegenSetEcho(); // and drop through to case P | |||
| case EMBED_P: | |||
| SetPitchFormants(); | |||
| break; | |||
| case EMBED_A: // amplitude | |||
| case EMBED_A: // amplitude | |||
| general_amplitude = GetAmplitude(); | |||
| break; | |||
| case EMBED_F: // emphasis | |||
| case EMBED_F: // emphasis | |||
| general_amplitude = GetAmplitude(); | |||
| break; | |||
| case EMBED_H: | |||
| @@ -1383,7 +1383,7 @@ void WavegenSetVoice(voice_t *v) | |||
| consonant_amp = (v->consonant_amp * 26) /100; | |||
| if (samplerate <= 11000) { | |||
| consonant_amp = consonant_amp*2; // emphasize consonants at low sample rates | |||
| consonant_amp = consonant_amp*2; // emphasize consonants at low sample rates | |||
| option_harmonic1 = 6; | |||
| } | |||
| WavegenSetEcho(); | |||
| @@ -1400,7 +1400,7 @@ static void SetAmplitude(int length, unsigned char *amp_env, int value) | |||
| amp_inc = (256 * ENV_LEN * STEPSIZE)/length; | |||
| wdata.amplitude = (value * general_amplitude)/16; | |||
| wdata.amplitude_v = (wdata.amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds | |||
| wdata.amplitude_v = (wdata.amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds | |||
| amplitude_env = amp_env; | |||
| } | |||
| @@ -1413,14 +1413,14 @@ void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pit | |||
| int pitch_value; | |||
| if (pitch1 > pitch2) { | |||
| x = pitch1; // swap values | |||
| x = pitch1; // swap values | |||
| pitch1 = pitch2; | |||
| pitch2 = x; | |||
| } | |||
| if ((pitch_value = embedded_value[EMBED_P]) > MAX_PITCH_VALUE) | |||
| pitch_value = MAX_PITCH_VALUE; | |||
| pitch_value -= embedded_value[EMBED_T]; // adjust tone for announcing punctuation | |||
| pitch_value -= embedded_value[EMBED_T]; // adjust tone for announcing punctuation | |||
| if (pitch_value < 0) | |||
| pitch_value = 0; | |||
| @@ -1436,10 +1436,10 @@ void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pit | |||
| void SetPitch(int length, unsigned char *env, int pitch1, int pitch2) | |||
| { | |||
| // length in samples | |||
| // length in samples | |||
| if ((wdata.pitch_env = env) == NULL) | |||
| wdata.pitch_env = env_fall; // default | |||
| wdata.pitch_env = env_fall; // default | |||
| wdata.pitch_ix = 0; | |||
| if (length == 0) | |||
| @@ -1449,7 +1449,7 @@ void SetPitch(int length, unsigned char *env, int pitch1, int pitch2) | |||
| SetPitch2(wvoice, pitch1, pitch2, &wdata.pitch_base, &wdata.pitch_range); | |||
| // set initial pitch | |||
| wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12 | |||
| wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12 | |||
| flutter_amp = wvoice->flutter; | |||
| } | |||
| @@ -1462,8 +1462,8 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
| int length4; | |||
| int qix; | |||
| int cmd; | |||
| static int glottal_reduce_tab1[4] = { 0x30, 0x30, 0x40, 0x50 }; // vowel before [?], amp * 1/256 | |||
| static int glottal_reduce_tab2[4] = { 0x90, 0xa0, 0xb0, 0xc0 }; // vowel after [?], amp * 1/256 | |||
| static int glottal_reduce_tab1[4] = { 0x30, 0x30, 0x40, 0x50 }; // vowel before [?], amp * 1/256 | |||
| static int glottal_reduce_tab2[4] = { 0x90, 0xa0, 0xb0, 0xc0 }; // vowel after [?], amp * 1/256 | |||
| harm_sqrt_n = 0; | |||
| end_wave = 1; | |||
| @@ -1473,11 +1473,11 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
| glottal_flag = 0; | |||
| if (modn & 0x400) { | |||
| glottal_flag = 3; // before a glottal stop | |||
| glottal_flag = 3; // before a glottal stop | |||
| glottal_reduce = glottal_reduce_tab1[(modn >> 8) & 3]; | |||
| } | |||
| if (modn & 0x800) { | |||
| glottal_flag = 4; // after a glottal stop | |||
| glottal_flag = 4; // after a glottal stop | |||
| glottal_reduce = glottal_reduce_tab2[(modn >> 8) & 3]; | |||
| } | |||
| @@ -1487,11 +1487,11 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
| cmd = wcmdq[qix][0]; | |||
| if (cmd == WCMD_SPECT) { | |||
| end_wave = 0; // next wave generation is from another spectrum | |||
| end_wave = 0; // next wave generation is from another spectrum | |||
| break; | |||
| } | |||
| if ((cmd == WCMD_WAVE) || (cmd == WCMD_PAUSE)) | |||
| break; // next is not from spectrum, so continue until end of wave cycle | |||
| break; // next is not from spectrum, so continue until end of wave cycle | |||
| } | |||
| // round the length to a multiple of the stepsize | |||
| @@ -1513,7 +1513,7 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
| peaks[ix].freq1 = (fr1->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8; | |||
| peaks[ix].freq = (int)peaks[ix].freq1; | |||
| next = (fr2->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8; | |||
| peaks[ix].freq_inc = ((next - peaks[ix].freq1) * (STEPSIZE/4)) / length4; // lower headroom for fixed point math | |||
| peaks[ix].freq_inc = ((next - peaks[ix].freq1) * (STEPSIZE/4)) / length4; // lower headroom for fixed point math | |||
| } | |||
| peaks[ix].height1 = (fr1->fheight[ix] * v->height[ix]) << 6; | |||
| @@ -1532,9 +1532,8 @@ void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | |||
| peaks[ix].right = (int)peaks[ix].right1; | |||
| next = (fr2->fright[ix] * v->width[ix]) << 10; | |||
| peaks[ix].right_inc = ((next - peaks[ix].right1) * STEPSIZE) / length2; | |||
| } else { | |||
| } else | |||
| peaks[ix].right = peaks[ix].left; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1549,7 +1548,7 @@ static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_ | |||
| void Write4Bytes(FILE *f, int value) | |||
| { | |||
| // Write 4 bytes to a file, least significant first | |||
| // Write 4 bytes to a file, least significant first | |||
| int ix; | |||
| for (ix = 0; ix < 4; ix++) { | |||
| @@ -1560,9 +1559,9 @@ void Write4Bytes(FILE *f, int value) | |||
| int WavegenFill2(int fill_zeros) | |||
| { | |||
| // Pick up next wavegen commands from the queue | |||
| // return: 0 output buffer has been filled | |||
| // return: 1 input command queue is now empty | |||
| // Pick up next wavegen commands from the queue | |||
| // return: 0 output buffer has been filled | |||
| // return: 1 input command queue is now empty | |||
| intptr_t *q; | |||
| int length; | |||
| @@ -1577,14 +1576,14 @@ int WavegenFill2(int fill_zeros) | |||
| // continue to play silence until echo is completed | |||
| resume = PlaySilence(echo_complete, resume); | |||
| if (resume == 1) | |||
| return 0; // not yet finished | |||
| return 0; // not yet finished | |||
| } | |||
| if (fill_zeros) { | |||
| while (out_ptr < out_end) | |||
| *out_ptr++ = 0; | |||
| } | |||
| return 1; // queue empty, close sound channel | |||
| return 1; // queue empty, close sound channel | |||
| } | |||
| result = 0; | |||
| @@ -1628,15 +1627,15 @@ int WavegenFill2(int fill_zeros) | |||
| wdata.mix_wavefile_offset = 0; | |||
| wdata.mix_wavefile = (unsigned char *)q[2]; | |||
| break; | |||
| case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file | |||
| wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | |||
| case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file | |||
| wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | |||
| case WCMD_SPECT: | |||
| echo_complete = echo_length; | |||
| result = Wavegen2(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3]); | |||
| break; | |||
| #ifdef INCLUDE_KLATT | |||
| case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file | |||
| wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | |||
| case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file | |||
| wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | |||
| case WCMD_KLATT: | |||
| echo_complete = echo_length; | |||
| result = Wavegen_Klatt2(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3]); | |||
| @@ -1663,7 +1662,7 @@ int WavegenFill2(int fill_zeros) | |||
| break; | |||
| case WCMD_FMT_AMPLITUDE: | |||
| if ((wdata.amplitude_fmt = q[1]) == 0) | |||
| wdata.amplitude_fmt = 100; // percentage, but value=0 means 100% | |||
| wdata.amplitude_fmt = 100; // percentage, but value=0 means 100% | |||
| break; | |||
| #if HAVE_SONIC_H | |||
| case WCMD_SONIC_SPEED: | |||
| @@ -1683,7 +1682,7 @@ int WavegenFill2(int fill_zeros) | |||
| } | |||
| #if HAVE_SONIC_H | |||
| /* Speed up the audio samples with libsonic. */ | |||
| // Speed up the audio samples with libsonic. | |||
| static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text) | |||
| { | |||
| if (length_in > 0) { | |||
| @@ -1704,7 +1703,7 @@ static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text | |||
| } | |||
| #endif | |||
| /* Call WavegenFill2, and then speed up the output samples. */ | |||
| // Call WavegenFill2, and then speed up the output samples. | |||
| int WavegenFill(int fill_zeros) | |||
| { | |||
| int finished; | |||
| @@ -1725,7 +1724,7 @@ int WavegenFill(int fill_zeros) | |||
| out_ptr = p_start + length; | |||
| if (length >= max_length) | |||
| finished = 0; // there may be more data to flush | |||
| finished = 0; // there may be more data to flush | |||
| } | |||
| #endif | |||
| return finished; | |||
| @@ -53,7 +53,7 @@ | |||
| #include "translate.h" | |||
| extern void Write4Bytes(FILE *f, int value); | |||
| char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
| char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
| char filetype[5]; | |||
| char wavefile[200]; | |||
| @@ -204,7 +204,7 @@ static int OpenWaveFile(const char *path, int rate) | |||
| if (path[0] != 0) { | |||
| if (strcmp(path, "stdout") == 0) { | |||
| #ifdef PLATFORM_WINDOWS | |||
| // prevent Windows adding 0x0d before 0x0a bytes | |||
| // prevent Windows adding 0x0d before 0x0a bytes | |||
| _setmode(_fileno(stdout), _O_BINARY); | |||
| #endif | |||
| f_wave = stdout; | |||
| @@ -296,14 +296,14 @@ static void init_path(char *argv0, char *path_specified) | |||
| if (((env = getenv("ESPEAK_DATA_PATH")) != NULL) && ((strlen(env)+12) < sizeof(path_home))) { | |||
| sprintf(path_home, "%s\\espeak-data", env); | |||
| if (GetFileLength(path_home) == -2) | |||
| return; // an espeak-data directory exists in the directory specified by environment variable | |||
| return; // an espeak-data directory exists in the directory specified by environment variable | |||
| } | |||
| strcpy(path_home, argv0); | |||
| if ((p = strrchr(path_home, '\\')) != NULL) { | |||
| strcpy(&p[1], "espeak-data"); | |||
| if (GetFileLength(path_home) == -2) | |||
| return; // an espeak-data directory exists in the same directory as the espeak program | |||
| return; // an espeak-data directory exists in the same directory as the espeak program | |||
| } | |||
| // otherwise, look in the Windows Registry | |||
| @@ -322,7 +322,7 @@ static void init_path(char *argv0, char *path_specified) | |||
| if ((env = getenv("ESPEAK_DATA_PATH")) != NULL) { | |||
| snprintf(path_home, sizeof(path_home), "%s/espeak-data", env); | |||
| if (GetFileLength(path_home) == -2) | |||
| return; // an espeak-data directory exists | |||
| return; // an espeak-data directory exists | |||
| } | |||
| snprintf(path_home, sizeof(path_home), "%s/espeak-data", getenv("HOME")); | |||
| @@ -336,7 +336,7 @@ static int initialise(void) | |||
| { | |||
| int param; | |||
| int result; | |||
| int srate = 22050; // default sample rate | |||
| int srate = 22050; // default sample rate | |||
| // It seems that the wctype functions don't work until the locale has been set | |||
| // to something other than the default "C". Then, not only Latin1 but also the | |||
| @@ -409,7 +409,7 @@ int main(int argc, char **argv) | |||
| FILE *f_text = NULL; | |||
| const char *p_text = NULL; | |||
| char *data_path = NULL; // use default path for espeak-data | |||
| char *data_path = NULL; // use default path for espeak-data | |||
| int option_index = 0; | |||
| int c; | |||
| @@ -417,7 +417,7 @@ int main(int argc, char **argv) | |||
| int speed = 175; | |||
| int ix; | |||
| char *optarg2; | |||
| int amp = 100; // default | |||
| int amp = 100; // default | |||
| int wordgap = 0; | |||
| int flag_stdin = 0; | |||
| int flag_compile = 0; | |||
| @@ -439,7 +439,7 @@ int main(int argc, char **argv) | |||
| option_wordgap = 0; | |||
| option_endpause = 1; | |||
| option_phoneme_input = 1; | |||
| option_multibyte = espeakCHARS_AUTO; // auto | |||
| option_multibyte = espeakCHARS_AUTO; | |||
| f_trans = stdout; | |||
| #ifdef NEED_GETOPT | |||
| @@ -463,7 +463,7 @@ int main(int argc, char **argv) | |||
| if (c == '-') { | |||
| if (p[0] == 0) | |||
| break; // -- means don't interpret further - as commands | |||
| break; // -- means don't interpret further - as commands | |||
| opt_string = ""; | |||
| for (ix = 0;; ix++) { | |||
| @@ -488,10 +488,10 @@ int main(int argc, char **argv) | |||
| } | |||
| #else | |||
| while (true) { | |||
| c = getopt_long(argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value | |||
| c = getopt_long(argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value | |||
| long_options, &option_index); | |||
| /* Detect the end of the options. */ | |||
| // Detect the end of the options. | |||
| if (c == -1) | |||
| break; | |||
| optarg2 = optarg; | |||
| @@ -555,20 +555,20 @@ int main(int argc, char **argv) | |||
| case 'z': | |||
| option_endpause = 0; | |||
| break; | |||
| case 0x100: // --stdin | |||
| case 0x100: // --stdin | |||
| flag_stdin = 1; | |||
| break; | |||
| case 0x105: // --stdout | |||
| case 0x105: // --stdout | |||
| option_waveout = 1; | |||
| strcpy(wavefile, "stdout"); | |||
| break; | |||
| case 0x101: // --compile-debug | |||
| case 0x102: // --compile | |||
| case 0x101: // --compile-debug | |||
| case 0x102: // --compile | |||
| if (optarg2 != NULL) | |||
| strncpy0(voicename, optarg2, sizeof(voicename)); | |||
| flag_compile = c; | |||
| break; | |||
| case 0x103: // --punct | |||
| case 0x103: // --punct | |||
| option_punctuation = 1; | |||
| if (optarg2 != NULL) { | |||
| ix = 0; | |||
| @@ -577,29 +577,29 @@ int main(int argc, char **argv) | |||
| option_punctuation = 2; | |||
| } | |||
| break; | |||
| case 0x104: // --voices | |||
| case 0x104: // --voices | |||
| init_path(argv[0], data_path); | |||
| DisplayVoices(stdout, optarg2); | |||
| exit(0); | |||
| case 0x106: // -- split | |||
| case 0x106: // -- split | |||
| if (optarg2 == NULL) | |||
| samples_split = 30; // default 30 minutes | |||
| samples_split = 30; // default 30 minutes | |||
| else | |||
| samples_split = atoi(optarg2); | |||
| break; | |||
| case 0x107: // --path | |||
| case 0x107: // --path | |||
| data_path = optarg2; | |||
| break; | |||
| case 0x108: // --phonout | |||
| case 0x108: // --phonout | |||
| if ((f_trans = fopen(optarg2, "w")) == NULL) { | |||
| fprintf(stderr, "Can't write to: %s\n", optarg2); | |||
| f_trans = stderr; | |||
| } | |||
| break; | |||
| case 0x109: // --pho | |||
| case 0x109: // --pho | |||
| phoneme_options |= espeakPHONEMES_MBROLA; | |||
| break; | |||
| case 0x10a: // --ipa | |||
| case 0x10a: // --ipa | |||
| phoneme_options |= espeakPHONEMES_IPA; | |||
| if (optarg2 != NULL) { | |||
| // deprecated and obsolete | |||
| @@ -613,33 +613,33 @@ int main(int argc, char **argv) | |||
| phoneme_options |= espeakPHONEMES_TIE; | |||
| break; | |||
| case 3: | |||
| phonemes_separator = 0x200d; // ZWJ | |||
| phonemes_separator = 0x200d; // ZWJ | |||
| phoneme_options |= espeakPHONEMES_TIE; | |||
| break; | |||
| } | |||
| } | |||
| break; | |||
| case 0x10b: // --version | |||
| case 0x10b: // --version | |||
| init_path(argv[0], data_path); | |||
| printf("speak text-to-speech: %s Data at: %s\n", version_string, path_home); | |||
| exit(0); | |||
| case 0x10c: // --sep | |||
| case 0x10c: // --sep | |||
| phoneme_options |= espeakPHONEMES_SHOW; | |||
| if (optarg2 == 0) | |||
| phonemes_separator = ' '; | |||
| else | |||
| utf8_in(&phonemes_separator, optarg2); | |||
| if (phonemes_separator == 'z') | |||
| phonemes_separator = 0x200c; // ZWNJ | |||
| phonemes_separator = 0x200c; // ZWNJ | |||
| break; | |||
| case 0x10d: // --tie | |||
| case 0x10d: // --tie | |||
| phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); | |||
| if (optarg2 == 0) | |||
| phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
| phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
| else | |||
| utf8_in(&phonemes_separator, optarg2); | |||
| if (phonemes_separator == 'z') | |||
| phonemes_separator = 0x200d; // ZWJ | |||
| phonemes_separator = 0x200d; // ZWJ | |||
| break; | |||
| default: | |||
| exit(0); | |||
| @@ -665,14 +665,14 @@ int main(int argc, char **argv) | |||
| #ifdef PLATFORM_DOS | |||
| char path_dsource[sizeof(path_home)+20]; | |||
| strcpy(path_dsource, path_home); | |||
| path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
| path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
| strcat(path_dsource, "dictsource\\"); | |||
| CompileDictionary(path_dsource, dictionary_name, NULL, NULL, flag_compile & 0x1); | |||
| #else | |||
| #ifdef PLATFORM_WINDOWS | |||
| char path_dsource[sizeof(path_home)+20]; | |||
| strcpy(path_dsource, path_home); | |||
| path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
| path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
| strcat(path_dsource, "dictsource\\"); | |||
| CompileDictionary(path_dsource, dictionary_name, NULL, NULL, flag_compile & 0x1); | |||
| #else | |||
| @@ -690,9 +690,8 @@ int main(int argc, char **argv) | |||
| option_phonemes = phoneme_options | (phonemes_separator << 8); | |||
| if (pitch_adjustment != 50) { | |||
| if (pitch_adjustment != 50) | |||
| SetParameter(espeakPITCH, pitch_adjustment, 0); | |||
| } | |||
| DoVoiceChange(voice); | |||
| if (filename[0] == 0) { | |||
| @@ -703,7 +702,7 @@ int main(int argc, char **argv) | |||
| } else { | |||
| f_text = stdin; | |||
| if (flag_stdin == 0) | |||
| option_linelength = -1; // single input lines on stdin | |||
| option_linelength = -1; // single input lines on stdin | |||
| } | |||
| } else | |||
| f_text = fopen(filename, "r"); | |||
| @@ -743,7 +742,7 @@ int main(int argc, char **argv) | |||
| for (;;) { | |||
| if (WavegenFile() != 0) { | |||
| if (ix == 0) | |||
| break; // finished, wavegen command queue is empty | |||
| break; // finished, wavegen command queue is empty | |||
| } | |||
| if (Generate(phoneme_list, &n_phoneme_list, 1) == 0) | |||
| @@ -767,13 +766,13 @@ int main(int argc, char **argv) | |||
| // NOTE: if nanosleep() isn't recognised on your system, try replacing | |||
| // this by sleep(1); | |||
| #ifdef PLATFORM_WINDOWS | |||
| Sleep(300); // 0.3s | |||
| Sleep(300); // 0.3s | |||
| #else | |||
| #ifdef USE_NANOSLEEP | |||
| struct timespec period; | |||
| struct timespec remaining; | |||
| period.tv_sec = 0; | |||
| period.tv_nsec = 300000000; // 0.3 sec | |||
| period.tv_nsec = 300000000; // 0.3 sec | |||
| nanosleep(&period, &remaining); | |||
| #else | |||
| sleep(1); | |||
| @@ -785,6 +784,6 @@ int main(int argc, char **argv) | |||
| } | |||
| if ((f_trans != stdout) && (f_trans != stderr)) | |||
| fclose(f_trans); // needed for WinCe | |||
| fclose(f_trans); | |||
| return 0; | |||
| } | |||