diff --git a/Makefile.am b/Makefile.am index 462220d5..73f66f3a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -165,6 +165,7 @@ src_libespeak_ng_la_SOURCES = \ src/libespeak-ng/espeak_api.c \ src/libespeak-ng/ieee80.c \ src/libespeak-ng/intonation.c \ + src/libespeak-ng/langopts.c \ src/libespeak-ng/mnemonics.c \ src/libespeak-ng/numbers.c \ src/libespeak-ng/readclause.c \ @@ -195,6 +196,7 @@ noinst_HEADERS = \ src/libespeak-ng/ieee80.h \ src/libespeak-ng/intonation.h \ src/libespeak-ng/klatt.h \ + src/libespeak-ng/langopts.h \ src/libespeak-ng/mbrola.h \ src/libespeak-ng/mbrowrap.h \ src/libespeak-ng/mnemonics.h \ diff --git a/android/jni/Android.mk b/android/jni/Android.mk index c88f52f7..209641d1 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -30,6 +30,7 @@ ESPEAK_SOURCES := \ src/libespeak-ng/ieee80.c \ src/libespeak-ng/intonation.c \ src/libespeak-ng/klatt.c \ + src/libespeak-ng/langopts.c \ src/libespeak-ng/mnemonics.c \ src/libespeak-ng/numbers.c \ src/libespeak-ng/phoneme.c \ diff --git a/src/libespeak-ng/intonation.c b/src/libespeak-ng/intonation.c index d5e9092d..c1664218 100644 --- a/src/libespeak-ng/intonation.c +++ b/src/libespeak-ng/intonation.c @@ -287,9 +287,6 @@ static TONE_NUCLEUS tone_nucleus_table[N_TONE_NUCLEUS_TABLE] = { { PITCHfall, 70, 18, PITCHfall, 70, 24, NULL, 32, 20, 0 }, // 12 test }; -int n_tunes = 0; -TUNE *tunes = NULL; - #define SECONDARY 3 #define PRIMARY 4 #define PRIMARY_STRESSED 6 diff --git a/src/libespeak-ng/langopts.c b/src/libespeak-ng/langopts.c new file mode 100644 index 00000000..320e7288 --- /dev/null +++ b/src/libespeak-ng/langopts.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2005 to 2015 by Jonathan Duddington + * email: jonsd@users.sourceforge.net + * Copyright (C) 2015-2017 Reece H. Dunn + * Copyright (C) 2022 Juho Hiltunen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see: . + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "langopts.h" +#include "mnemonics.h" // for MNEM_TAB +#include "translate.h" // for Translator +#include "synthdata.h" // for n_tunes, tunes +#include "voice.h" // for ReadNumbers, Read8Numbers, ... + +static int CheckTranslator(Translator *tr, const MNEM_TAB *keyword_tab, int key); +static int LookupTune(const char *name); + +extern const MNEM_TAB langopts_tab[]; + +void LoadLanguageOptions(Translator *translator, int key, char *keyValue ) { +if (CheckTranslator(translator, langopts_tab, key) != 0) { + return; + } + + int ix; + int n; + + switch (key) { + case V_DICTMIN: { + + + if (sscanf(keyValue, "%d", &n) == 1) + translator->dict_min_size = n; + + break; + } + + case V_DICTRULES: { // conditional dictionary rules and list entries + ReadNumbers(keyValue, &translator->dict_condition, 32, langopts_tab, key); + break; + } + case V_INTONATION: { + sscanf(keyValue, "%d", &option_tone_flags); + if ((option_tone_flags & 0xff) != 0) { + translator->langopts.intonation_group = option_tone_flags & 0xff; + } + break; + } + case V_NUMBERS: { + // expect a list of numbers + while (*keyValue != 0) { + while (isspace(*keyValue)) keyValue++; + if ((n = atoi(keyValue)) > 0) { + keyValue++; + if (n < 32) { + translator->langopts.numbers |= (1 << n); + } else { + if (n < 64) + translator->langopts.numbers2 |= (1 << (n-32)); + else + fprintf(stderr, "numbers: Bad option number %d\n", n); } + } + while (isalnum(*keyValue)) keyValue++; + } + ProcessLanguageOptions(&(translator->langopts)); + + break; + } + case V_LOWERCASE_SENTENCE: { + translator->langopts.lowercase_sentence = true; + break; + } + case V_STRESSADD: { // stressAdd + int stress_add_set = 0; + int stress_add[8]; + + stress_add_set = Read8Numbers(keyValue, stress_add); + + for (ix = 0; ix < stress_add_set; ix++) { + translator->stress_lengths[ix] += stress_add[ix]; + } + + break; + } + case V_STRESSAMP: { + + int stress_amps_set = 0; + int stress_amps[8]; + + stress_amps_set = Read8Numbers(keyValue, stress_amps); + + for (ix = 0; ix < stress_amps_set; ix++) { + translator->stress_amps[ix] = stress_amps[ix]; + } + + break; + } + case V_STRESSLENGTH: { + //printf("parsing: %s", keyValue); + int stress_lengths_set = 0; + int stress_lengths[8]; + stress_lengths_set = Read8Numbers(keyValue, stress_lengths); + + for (ix = 0; ix < stress_lengths_set; ix++) { + translator->stress_lengths[ix] = stress_lengths[ix]; + } + break; + } + case V_STRESSOPT: { + ReadNumbers(keyValue, &translator->langopts.stress_flags, 32, langopts_tab, key); + break; + } + case V_STRESSRULE: { + sscanf(keyValue, "%d %d %d", &translator->langopts.stress_rule, + &translator->langopts.unstressed_wd1, + &translator->langopts.unstressed_wd2); + + break; + } + case V_TUNES: { + char names[6][40] = { 0, 0, 0, 0, 0, 0 }; + n = sscanf(keyValue, "%s %s %s %s %s %s", names[0], names[1], names[2], names[3], names[4], names[5]); + translator->langopts.intonation_group = 0; + + for (ix = 0; ix < n; ix++) { + if (strcmp(names[ix], "NULL") == 0) + continue; + + if ((n = LookupTune(names[ix])) < 0) + fprintf(stderr, "Unknown tune '%s'\n", names[ix]); + else + translator->langopts.tunes[ix] = n; + } + break; + } + case V_WORDGAP: { + sscanf(keyValue, "%d %d", &translator->langopts.word_gap, &translator->langopts.vowel_pause); + break; + } + + + case V_MAINTAINER: + case V_STATUS: + break; + default: { + if ((key & 0xff00) == 0x100) { + sscanf(keyValue, "%d", &translator->langopts.param[key &0xff]); + } + break; + } + } +} + +static int LookupTune(const char *name) { + int ix; + + for (ix = 0; ix < n_tunes; ix++) { + if (strcmp(name, tunes[ix].name) == 0) + return ix; + } + return -1; +} + +int CheckTranslator(Translator *tr, const MNEM_TAB *keyword_tab, int key) +{ + // Return 0 if translator is set. + // Return 1 and print an error message for specified key if not + // used for parsing language options + if (tr) + return 0; + + fprintf(stderr, "Cannot set %s: language not set, or is invalid.\n", LookupMnemName(keyword_tab, key)); + return 1; +} \ No newline at end of file diff --git a/src/libespeak-ng/langopts.h b/src/libespeak-ng/langopts.h new file mode 100644 index 00000000..4f3d3c5e --- /dev/null +++ b/src/libespeak-ng/langopts.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005 to 2007 by Jonathan Duddington + * email: jonsd@users.sourceforge.net + * Copyright (C) 2015 Reece H. Dunn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see: . + */ + +#ifndef ESPEAK_NG_LANGOPTS_H +#define ESPEAK_NG_LANGOPTS_H + +#include +#include "translate.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +void LoadLanguageOptions(Translator *translator, int key, char *keyValue); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libespeak-ng/synthdata.c b/src/libespeak-ng/synthdata.c index a2d7ae10..7510cc2a 100644 --- a/src/libespeak-ng/synthdata.c +++ b/src/libespeak-ng/synthdata.c @@ -42,6 +42,9 @@ #include "translate.h" // for Translator, LANGUAGE_OPTIONS #include "voice.h" // for ReadTonePoints, tone_points, voice +int n_tunes = 0; +TUNE *tunes = NULL; + const int version_phdata = 0x014801; // copy the current phoneme table into here diff --git a/src/libespeak-ng/synthdata.h b/src/libespeak-ng/synthdata.h index 5607f056..3548e3c5 100644 --- a/src/libespeak-ng/synthdata.h +++ b/src/libespeak-ng/synthdata.h @@ -56,6 +56,9 @@ int PhonemeCode(unsigned int mnem); void SelectPhonemeTable(int number); int SelectPhonemeTableName(const char *name); +extern int n_tunes; +extern TUNE *tunes; + #ifdef __cplusplus } #endif diff --git a/src/libespeak-ng/synthesize.h b/src/libespeak-ng/synthesize.h index d78e35e1..f8b71a02 100644 --- a/src/libespeak-ng/synthesize.h +++ b/src/libespeak-ng/synthesize.h @@ -382,8 +382,7 @@ typedef struct { int spare2; // the struct length should be a multiple of 4 bytes } TUNE; -extern int n_tunes; -extern TUNE *tunes; + // phoneme table extern PHONEME_TAB *phoneme_tab[N_PHONEME_TAB]; diff --git a/src/libespeak-ng/tr_languages.c b/src/libespeak-ng/tr_languages.c index c278bb66..c05f79b0 100644 --- a/src/libespeak-ng/tr_languages.c +++ b/src/libespeak-ng/tr_languages.c @@ -808,7 +808,7 @@ Translator *SelectTranslator(const char *name) tr->langopts.param[LOPT_IT_DOUBLING] = 1; tr->langopts.long_stop = 130; - tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_DFRACTION_2 | NUM_ORDINAL_DOT; + // tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_DFRACTION_2 | NUM_ORDINAL_DOT; SetLetterVowel(tr, 'y'); tr->langopts.spelling_stress = 1; tr->langopts.intonation_group = 3; // less intonation, don't raise pitch at comma diff --git a/src/libespeak-ng/voice.h b/src/libespeak-ng/voice.h index 04f1e9e4..a0d93ec5 100644 --- a/src/libespeak-ng/voice.h +++ b/src/libespeak-ng/voice.h @@ -22,6 +22,9 @@ #include +#include "mnemonics.h" +#include "translate.h" + #ifdef __cplusplus extern "C" { @@ -81,12 +84,118 @@ extern espeak_VOICE current_voice_selected; extern voice_t *voice; extern int tone_points[12]; +typedef enum { + V_NAME = 1, + V_LANGUAGE, + V_GENDER, + V_PHONEMES, + V_DICTIONARY, + V_VARIANTS, + + V_MAINTAINER, + V_STATUS, + + // these affect voice quality, are independent of language + V_FORMANT, + V_PITCH, + V_ECHO, + V_FLUTTER, + V_ROUGHNESS, + V_CLARITY, + V_TONE, + V_VOICING, + V_BREATH, + V_BREATHW, + + // these override defaults set by the translator + V_LOWERCASE_SENTENCE, + V_WORDGAP, + V_INTONATION, + V_TUNES, + V_STRESSLENGTH, + V_STRESSAMP, + V_STRESSADD, + V_DICTRULES, + V_STRESSRULE, + V_STRESSOPT, + V_NUMBERS, + + V_MBROLA, + V_KLATT, + V_FAST, + V_SPEED, + V_DICTMIN, + + // these need a phoneme table to have been specified + V_REPLACE, + V_CONSONANTS +} VOICELANGATTRIBUTES; + +static const MNEM_TAB langopts_tab[] = { + { "dictrules", V_DICTRULES }, + { "intonation", V_INTONATION }, + { "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 }, + { "lowercaseSentence", V_LOWERCASE_SENTENCE }, + { "numbers", V_NUMBERS }, + { "stressAdd", V_STRESSADD }, + { "stressAmp", V_STRESSAMP }, + { "stressLength", V_STRESSLENGTH }, + { "stressOpt", V_STRESSOPT }, + { "stressRule", V_STRESSRULE }, + { "tunes", V_TUNES }, + { "words", V_WORDGAP }, + + { "maintainer", V_MAINTAINER }, + { "status", V_STATUS }, + + { NULL, 0 } +}; + +static const MNEM_TAB keyword_tab[] = { + { "name", V_NAME }, + { "language", V_LANGUAGE }, + { "gender", V_GENDER }, + { "variants", V_VARIANTS }, + { "formant", V_FORMANT }, + { "pitch", V_PITCH }, + { "phonemes", V_PHONEMES }, + { "dictionary", V_DICTIONARY }, + { "replace", V_REPLACE }, + { "echo", V_ECHO }, + { "flutter", V_FLUTTER }, + { "roughness", V_ROUGHNESS }, + { "clarity", V_CLARITY }, + { "tone", V_TONE }, + { "voicing", V_VOICING }, + { "breath", V_BREATH }, + { "breathw", V_BREATHW }, + { "mbrola", V_MBROLA }, + { "consonants", V_CONSONANTS }, + { "klatt", V_KLATT }, + { "fast_test2", V_FAST }, + { "speed", V_SPEED }, + { "dict_min", V_DICTMIN }, + + + { "apostrophe", 0x100+LOPT_APOSTROPHE }, + { "brackets", 0x100+LOPT_BRACKET_PAUSE }, + { "bracketsAnnounced", 0x100+LOPT_BRACKET_PAUSE_ANNOUNCED }, + + { NULL, 0 } +}; + const char *SelectVoice(espeak_VOICE *voice_select, int *found); espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name); voice_t *LoadVoice(const char *voice_name, int control); voice_t *LoadVoiceVariant(const char *voice_name, int variant); espeak_ng_STATUS DoVoiceChange(voice_t *v); void WavegenSetVoice(voice_t *v); +void ReadNumbers(char *p, int *flags, int maxValue, const MNEM_TAB *keyword_tab, int key); +int Read8Numbers(char *data_in, int data[8]); void ReadTonePoints(char *string, int *tone_pts); void VoiceReset(int control); void FreeVoiceList(void); diff --git a/src/libespeak-ng/voices.c b/src/libespeak-ng/voices.c index fd2ad538..60d8f23a 100644 --- a/src/libespeak-ng/voices.c +++ b/src/libespeak-ng/voices.c @@ -1,3 +1,4 @@ + /* * Copyright (C) 2005 to 2015 by Jonathan Duddington * email: jonsd@users.sourceforge.net @@ -41,6 +42,7 @@ #include "voice.h" // for voice_t, DoVoiceChange, N_PEAKS #include "common.h" // for GetFileLength, strncpy0 #include "dictionary.h" // for LoadDictionary +#include "langopts.h" // for LoadLanguageOptions #include "mnemonics.h" // for LookupMnemName, MNEM_TAB #include "phoneme.h" // for REPLACE_PHONEMES, n_replace_pho... #include "speech.h" // for PATHSEP @@ -50,6 +52,8 @@ #include "translate.h" // for LANGUAGE_OPTIONS, DeleteTranslator #include "wavegen.h" // for InitBreath + + static const MNEM_TAB genders[] = { { "male", ENGENDER_MALE }, { "female", ENGENDER_FEMALE }, @@ -69,107 +73,6 @@ static espeak_VOICE *voices_list[N_VOICES_LIST]; espeak_VOICE current_voice_selected; -enum { - V_NAME = 1, - V_LANGUAGE, - V_GENDER, - V_PHONEMES, - V_DICTIONARY, - V_VARIANTS, - - V_MAINTAINER, - V_STATUS, - - // these affect voice quality, are independent of language - V_FORMANT, - V_PITCH, - V_ECHO, - V_FLUTTER, - V_ROUGHNESS, - V_CLARITY, - V_TONE, - V_VOICING, - V_BREATH, - V_BREATHW, - - // these override defaults set by the translator - V_LOWERCASE_SENTENCE, - V_WORDGAP, - V_INTONATION, - V_TUNES, - V_STRESSLENGTH, - V_STRESSAMP, - V_STRESSADD, - V_DICTRULES, - V_STRESSRULE, - V_STRESSOPT, - V_NUMBERS, - - V_MBROLA, - V_KLATT, - V_FAST, - V_SPEED, - V_DICTMIN, - - // these need a phoneme table to have been specified - V_REPLACE, - V_CONSONANTS -}; - -static const MNEM_TAB keyword_tab[] = { - { "name", V_NAME }, - { "language", V_LANGUAGE }, - { "gender", V_GENDER }, - - { "maintainer", V_MAINTAINER }, - { "status", V_STATUS }, - - - { "lowercaseSentence", V_LOWERCASE_SENTENCE }, - { "variants", V_VARIANTS }, - { "formant", V_FORMANT }, - { "pitch", V_PITCH }, - { "phonemes", V_PHONEMES }, - { "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 }, - { "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 }, - { "mbrola", V_MBROLA }, - { "consonants", V_CONSONANTS }, - { "klatt", V_KLATT }, - { "fast_test2", V_FAST }, - { "speed", V_SPEED }, - { "dict_min", V_DICTMIN }, - - // 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_unpronouncable", 0x100+LOPT_UNPRONOUNCABLE }, - { "l_sonorant_min", 0x100+LOPT_SONORANT_MIN }, - { "apostrophe", 0x100+LOPT_APOSTROPHE }, - { "brackets", 0x100+LOPT_BRACKET_PAUSE }, - { "bracketsAnnounced", 0x100+LOPT_BRACKET_PAUSE_ANNOUNCED }, - - { NULL, 0 } -}; - #define N_VOICE_VARIANTS 12 const char variants_either[N_VOICE_VARIANTS] = { 1, 2, 12, 3, 13, 4, 14, 5, 11, 0 }; const char variants_male[N_VOICE_VARIANTS] = { 1, 2, 3, 4, 5, 6, 0 }; @@ -203,17 +106,6 @@ static char *fgets_strip(char *buf, int size, FILE *f_in) return buf; } -static int LookupTune(const char *name) -{ - int ix; - - for (ix = 0; ix < n_tunes; ix++) { - if (strcmp(name, tunes[ix].name) == 0) - return ix; - } - return -1; -} - static void SetToneAdjust(voice_t *voice, int *tone_pts) { int ix; @@ -473,7 +365,7 @@ static void PhonemeReplacement(char *p) replace_phonemes[n_replace_phonemes++].type = flags; } -static int Read8Numbers(char *data_in, int data[8]) +int Read8Numbers(char *data_in, int data[8]) { // Read 8 integer numbers memset(data, 0, 8*sizeof(int)); @@ -481,7 +373,7 @@ static int Read8Numbers(char *data_in, int data[8]) &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7]); } -static void ReadNumbers(char *p, int *flags, int maxValue, const MNEM_TAB *keyword_tab, int key) { +void ReadNumbers(char *p, int *flags, int maxValue, const MNEM_TAB *keyword_tab, int key) { // read a list of numbers from string p // store them as flags in *flags // the meaning of the numbers is bit ordinals, not integer values @@ -501,18 +393,6 @@ static void ReadNumbers(char *p, int *flags, int maxValue, const MNEM_TAB *keyw } } -static int CheckTranslator(Translator *tr, const MNEM_TAB *keyword_tab, int key) -{ - // Return 0 if translator is set. - // Return 1 and print an error message for specified key if not - // used for parsing language options - if (tr) - return 0; - - fprintf(stderr, "Cannot set %s: language not set, or is invalid.\n", LookupMnemName(keyword_tab, key)); - return 1; -} - voice_t *LoadVoice(const char *vname, int control) { // control, bit 0 1= no_default @@ -527,7 +407,6 @@ voice_t *LoadVoice(const char *vname, int control) char *p; int key; int ix; - int n; int value; int langix = 0; int tone_only = control & 2; @@ -543,8 +422,7 @@ voice_t *LoadVoice(const char *vname, int control) char buf[sizeof(path_home)+30]; char path_voices[sizeof(path_home)+12]; - int stress_add[8]; - char names[8][40]; + char name1[40]; char name2[80]; @@ -627,312 +505,184 @@ voice_t *LoadVoice(const char *vname, int control) if (buf[0] == 0) continue; - key = LookupMnem(keyword_tab, buf); + key = LookupMnem(langopts_tab, buf); - switch (key) - { - case V_LANGUAGE: - { - unsigned int len; - int priority; + if (key != 0) { + LoadLanguageOptions(translator, key, p); + } else { + key = LookupMnem(keyword_tab, buf); + switch (key) + { + case V_LANGUAGE: + { + unsigned int len; + int priority; - if (tone_only) - break; + if (tone_only) + break; - priority = DEFAULT_LANGUAGE_PRIORITY; - language_name[0] = 0; + priority = DEFAULT_LANGUAGE_PRIORITY; + language_name[0] = 0; - sscanf(p, "%s %d", language_name, &priority); - if (strcmp(language_name, "variant") == 0) - break; + sscanf(p, "%s %d", language_name, &priority); + if (strcmp(language_name, "variant") == 0) + break; - len = strlen(language_name) + 2; - // check for space in languages[] - if (len < (sizeof(voice_languages)-langix-1)) { - voice_languages[langix] = priority; + len = strlen(language_name) + 2; + // check for space in languages[] + if (len < (sizeof(voice_languages)-langix-1)) { + voice_languages[langix] = priority; - strcpy(&voice_languages[langix+1], language_name); - langix += len; - } + strcpy(&voice_languages[langix+1], language_name); + langix += len; + } - // only act on the first language line - if (language_set == false) { - language_type = strtok(language_name, "-"); - language_set = true; - strcpy(translator_name, language_type); - strcpy(new_dictionary, language_type); - strcpy(phonemes_name, language_type); - SelectPhonemeTableName(phonemes_name); + // only act on the first language line + if (language_set == false) { + language_type = strtok(language_name, "-"); + language_set = true; + strcpy(translator_name, language_type); + strcpy(new_dictionary, language_type); + strcpy(phonemes_name, language_type); + SelectPhonemeTableName(phonemes_name); - translator = SelectTranslator(translator_name); - strncpy0(voice->language_name, language_name, sizeof(voice->language_name)); - } - } - break; - case V_NAME: - if (tone_only == 0) { - while (isspace(*p)) p++; - strncpy0(voice_name, p, sizeof(voice_name)); - } - break; - case V_GENDER: - { - int age = 0; - char vgender[80]; - sscanf(p, "%s %d", vgender, &age); - current_voice_selected.gender = LookupMnem(genders, vgender); - current_voice_selected.age = age; - } - break; - case V_DICTIONARY: // dictionary - sscanf(p, "%s", new_dictionary); - break; - case V_PHONEMES: // phoneme table - sscanf(p, "%s", phonemes_name); - break; - case V_FORMANT: - VoiceFormant(p); - break; - case V_LOWERCASE_SENTENCE: { - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; + translator = SelectTranslator(translator_name); + strncpy0(voice->language_name, language_name, sizeof(voice->language_name)); + } + } + break; + case V_NAME: + if (tone_only == 0) { + while (isspace(*p)) p++; + strncpy0(voice_name, p, sizeof(voice_name)); + } + break; + case V_GENDER: + { + int age = 0; + char vgender[80]; + sscanf(p, "%s %d", vgender, &age); + current_voice_selected.gender = LookupMnem(genders, vgender); + current_voice_selected.age = age; + } + break; + case V_DICTIONARY: // dictionary + sscanf(p, "%s", new_dictionary); + break; + case V_PHONEMES: // phoneme table + sscanf(p, "%s", phonemes_name); + break; + case V_FORMANT: + VoiceFormant(p); + break; + case V_PITCH: + // default is pitch 82 118 + if (sscanf(p, "%d %d", &pitch1, &pitch2) == 2) { + voice->pitch_base = (pitch1 - 9) << 12; + voice->pitch_range = (pitch2 - pitch1) * 108; + double factor = (double)(pitch1 - 82)/82; + voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch + } + break; - translator->langopts.lowercase_sentence = true; - break; - } - case V_PITCH: - // default is pitch 82 118 - if (sscanf(p, "%d %d", &pitch1, &pitch2) == 2) { - voice->pitch_base = (pitch1 - 9) << 12; - voice->pitch_range = (pitch2 - pitch1) * 108; - double factor = (double)(pitch1 - 82)/82; - voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch - } - break; - case V_STRESSLENGTH: {// stressLength - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - int stress_lengths_set = 0; - int stress_lengths[8]; - stress_lengths_set = Read8Numbers(p, stress_lengths); - for (ix = 0; ix < stress_lengths_set; ix++) { - translator->stress_lengths[ix] = stress_lengths[ix]; - } - break; - } - case V_STRESSAMP: { // stressAmp - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; + case V_REPLACE: + if (phonemes_set == false) { + // must set up a phoneme table before we can lookup phoneme mnemonics + SelectPhonemeTableName(phonemes_name); + phonemes_set = true; + } + PhonemeReplacement(p); + break; - int stress_amps_set = 0; - int stress_amps[8]; - stress_amps_set = Read8Numbers(p, stress_amps); - for (ix = 0; ix < stress_amps_set; ix++) { - translator->stress_amps[ix] = stress_amps[ix]; - } + case V_ECHO: + // echo. suggest: 135mS 11% + value = 0; + voice->echo_amp = 0; + sscanf(p, "%d %d", &voice->echo_delay, &voice->echo_amp); + break; + case V_FLUTTER: // flutter + if (sscanf(p, "%d", &value) == 1) + voice->flutter = value * 32; + break; + case V_ROUGHNESS: // roughness + if (sscanf(p, "%d", &value) == 1) + voice->roughness = value; + break; + case V_CLARITY: // formantshape + if (sscanf(p, "%d", &value) == 1) { + if (value > 4) { + voice->peak_shape = 1; // squarer formant peaks + value = 4; + } + voice->n_harmonic_peaks = 1+value; + } + break; + case V_TONE: + { + int tone_data[12]; + ReadTonePoints(p, tone_data); + SetToneAdjust(voice, tone_data); + } + break; + case V_VOICING: + if (sscanf(p, "%d", &value) == 1) + voice->voicing = (value * 64)/100; + break; + case V_BREATH: + voice->breath[0] = Read8Numbers(p, &voice->breath[1]); + for (ix = 1; ix < 8; ix++) { + if (ix % 2) + voice->breath[ix] = -voice->breath[ix]; + } + break; + case V_BREATHW: + voice->breathw[0] = Read8Numbers(p, &voice->breathw[1]); + break; + case V_CONSONANTS: + value = sscanf(p, "%d %d", &voice->consonant_amp, &voice->consonant_ampv); + break; + case V_SPEED: + sscanf(p, "%d", &voice->speed_percent); + SetSpeed(3); + break; + case V_MBROLA: + { + int srate = 16000; - break; - } - case V_STRESSADD: { // stressAdd - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; + name2[0] = 0; + sscanf(p, "%s %s %d", name1, name2, &srate); + espeak_ng_STATUS status = LoadMbrolaTable(name1, name2, &srate); + if (status != ENS_OK) { + espeak_ng_PrintStatusCodeMessage(status, stderr, NULL); + fclose(f_voice); + return NULL; + } + else + voice->samplerate = srate; + } + break; + case V_KLATT: + voice->klattv[0] = 1; // default source: IMPULSIVE + Read8Numbers(p, voice->klattv); + voice->klattv[KLATT_Kopen] -= 40; + break; + case V_FAST: + sscanf(p, "%d", &speed.fast_settings); + SetSpeed(3); + break; - int stress_add_set = 0; - stress_add_set = Read8Numbers(p, stress_add); - - for (ix = 0; ix < stress_add_set; ix++) { - translator->stress_lengths[ix] += stress_add[ix]; - } - - break; - } - case V_INTONATION: // intonation - sscanf(p, "%d", &option_tone_flags); - if ((option_tone_flags & 0xff) != 0) { - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - - translator->langopts.intonation_group = option_tone_flags & 0xff; - } - break; - case V_TUNES: - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - - n = sscanf(p, "%s %s %s %s %s %s", names[0], names[1], names[2], names[3], names[4], names[5]); - translator->langopts.intonation_group = 0; - - for (ix = 0; ix < n; ix++) { - if (strcmp(names[ix], "NULL") == 0) - continue; - - if ((value = LookupTune(names[ix])) < 0) - fprintf(stderr, "Unknown tune '%s'\n", names[ix]); - else - translator->langopts.tunes[ix] = value; - } - break; - - case V_DICTRULES: // conditional dictionary rules and list entries - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - - ReadNumbers(p, &translator->dict_condition, 32, keyword_tab, key); - break; - case V_STRESSOPT: - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - - ReadNumbers(p, &translator->langopts.stress_flags, 32, keyword_tab, key); - break; - - case V_NUMBERS: - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - - // expect a list of numbers - while (*p != 0) { - while (isspace(*p)) p++; - if ((n = atoi(p)) > 0) { - p++; - if (n < 32) { - translator->langopts.numbers |= (1 << n); - } else { - if (n < 64) - translator->langopts.numbers2 |= (1 << (n-32)); - else - fprintf(stderr, "numbers: Bad option number %d\n", n); } - } - while (isalnum(*p)) p++; - } - ProcessLanguageOptions(&(translator->langopts)); - - break; - case V_REPLACE: - if (phonemes_set == false) { - // must set up a phoneme table before we can lookup phoneme mnemonics - SelectPhonemeTableName(phonemes_name); - phonemes_set = true; - } - PhonemeReplacement(p); - break; - case V_WORDGAP: // words - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - - sscanf(p, "%d %d", &translator->langopts.word_gap, &translator->langopts.vowel_pause); - break; - case V_STRESSRULE: - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - - sscanf(p, "%d %d %d", &translator->langopts.stress_rule, - &translator->langopts.unstressed_wd1, - &translator->langopts.unstressed_wd2); - - break; - case V_ECHO: - // echo. suggest: 135mS 11% - value = 0; - voice->echo_amp = 0; - sscanf(p, "%d %d", &voice->echo_delay, &voice->echo_amp); - break; - case V_FLUTTER: // flutter - if (sscanf(p, "%d", &value) == 1) - voice->flutter = value * 32; - break; - case V_ROUGHNESS: // roughness - if (sscanf(p, "%d", &value) == 1) - voice->roughness = value; - break; - case V_CLARITY: // formantshape - if (sscanf(p, "%d", &value) == 1) { - if (value > 4) { - voice->peak_shape = 1; // squarer formant peaks - value = 4; - } - voice->n_harmonic_peaks = 1+value; - } - break; - case V_TONE: - { - int tone_data[12]; - ReadTonePoints(p, tone_data); - SetToneAdjust(voice, tone_data); - } - break; - case V_VOICING: - if (sscanf(p, "%d", &value) == 1) - voice->voicing = (value * 64)/100; - break; - case V_BREATH: - voice->breath[0] = Read8Numbers(p, &voice->breath[1]); - for (ix = 1; ix < 8; ix++) { - if (ix % 2) - voice->breath[ix] = -voice->breath[ix]; - } - break; - case V_BREATHW: - voice->breathw[0] = Read8Numbers(p, &voice->breathw[1]); - break; - case V_CONSONANTS: - value = sscanf(p, "%d %d", &voice->consonant_amp, &voice->consonant_ampv); - break; - case V_SPEED: - sscanf(p, "%d", &voice->speed_percent); - SetSpeed(3); - break; - case V_MBROLA: - { - int srate = 16000; - - name2[0] = 0; - sscanf(p, "%s %s %d", name1, name2, &srate); - espeak_ng_STATUS status = LoadMbrolaTable(name1, name2, &srate); - if (status != ENS_OK) { - espeak_ng_PrintStatusCodeMessage(status, stderr, NULL); - fclose(f_voice); - return NULL; - } - else - voice->samplerate = srate; - } - break; - case V_KLATT: - voice->klattv[0] = 1; // default source: IMPULSIVE - Read8Numbers(p, voice->klattv); - voice->klattv[KLATT_Kopen] -= 40; - break; - case V_FAST: - sscanf(p, "%d", &speed.fast_settings); - SetSpeed(3); - break; - case V_DICTMIN: { - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - - if (sscanf(p, "%d", &value) == 1) - translator->dict_min_size = value; - break; - } - - break; - case V_MAINTAINER: - case V_STATUS: - break; - default: - if ((key & 0xff00) == 0x100) { - if (CheckTranslator(translator, keyword_tab, key) != 0) - break; - sscanf(p, "%d", &translator->langopts.param[key &0xff]); - } else - fprintf(stderr, "Bad voice attribute: %s\n", buf); - break; - } + case V_MAINTAINER: + case V_STATUS: + break; + default: + fprintf(stderr, "Bad voice attribute: %s\n", buf); + break; + } + } } if (f_voice != NULL) fclose(f_voice); diff --git a/src/windows/libespeak-ng.vcxproj b/src/windows/libespeak-ng.vcxproj index 8812d016..1ea3935d 100644 --- a/src/windows/libespeak-ng.vcxproj +++ b/src/windows/libespeak-ng.vcxproj @@ -177,6 +177,7 @@ + @@ -210,6 +211,7 @@ + @@ -232,4 +234,4 @@ - \ No newline at end of file + diff --git a/src/windows/libespeak-ng.vcxproj.filters b/src/windows/libespeak-ng.vcxproj.filters index 74b04244..b60291ae 100644 --- a/src/windows/libespeak-ng.vcxproj.filters +++ b/src/windows/libespeak-ng.vcxproj.filters @@ -90,6 +90,9 @@ Source Files + + Source Files + Source Files @@ -197,6 +200,9 @@ Header Files + + Header Files + Header Files @@ -227,4 +233,4 @@ Source Files - \ No newline at end of file +