[1.46.38]

Speak names of characters in non-native alphabets (eg. non-Latin).
Language changes: en, nl, pt.


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@304 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
jonsd
2013-02-27 13:34:02 +00:00
parent 182d88f81e
commit 6ee501b5bb
23 changed files with 562 additions and 149 deletions
+21 -3
View File
@@ -1390,6 +1390,24 @@ static int NextItem(int type)
static int NextItemMax(int max)
{//==============================
// Get a number, but restrict value to max
int value;
char msg[80];
value = NextItem(tNUMBER);
if(value > max)
{
sprintf(msg, "Value %d is greater than maximum %d", value, max);
error(msg, NULL);
value = max;
}
return(value);
}
static int NextItemBrackets(int type, int control)
{//===============================================
// Expect a parameter inside parantheses
@@ -2794,17 +2812,17 @@ int CompilePhoneme(int compile_phoneme)
break;
case i_PAUSE_BEFORE:
value = NextItem(tNUMBER);
value = NextItemMax(255);
*prog_out++ = (i_PAUSE_BEFORE << 8) + value;
break;
case i_PAUSE_AFTER:
value = NextItem(tNUMBER);
value = NextItemMax(255);
*prog_out++ = (i_PAUSE_AFTER << 8) + value;
break;
case i_SET_LENGTH:
value = NextItem(tNUMBER);
value = NextItemMax(511);
if(after_if == 0)
{
phoneme_out->std_length = value/2;
+8
View File
@@ -2489,6 +2489,7 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
int ix;
unsigned int digit_count=0;
char *p;
ALPHABET *alphabet;
int dict_flags0=0;
MatchRecord match1;
MatchRecord match2;
@@ -2685,6 +2686,13 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
match1.points = 1;
p += (wc_bytes-1);
}
if(((alphabet = AlphabetFromChar(letter)) != NULL) && (alphabet->language != 0) && (alphabet->offset != tr->letter_bits_offset))
{
// switch to the nominated language for this alphabet
sprintf(phonemes,"%c%s",phonSWITCH, WordToString2(alphabet->language));
return(0);
}
}
}
+76 -9
View File
@@ -591,15 +591,19 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
int letter;
int len;
int ix;
int save_option_phonemes;
char *p2;
char *pbuf;
ALPHABET *alphabet;
int language;
int phontab_1;
char capital[20];
char ph_buf[80];
char ph_buf2[80];
char ph_alphabet[80];
char hexbuf[6];
ph_buf[0] = 0;
ph_alphabet[0] = 0;
capital[0] = 0;
n_bytes = utf8_in(&letter,word);
@@ -627,6 +631,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
return(0);
}
#ifdef deleted
if((ph_buf[0] == 0) && (tr->translator_name != L('e','n')))
{
// speak as English, check whether there is a translation for this character
@@ -643,6 +648,67 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
return(0);
}
}
#endif
alphabet = AlphabetFromChar(letter);
if(alphabet != current_alphabet)
{
current_alphabet = alphabet;
if((alphabet != NULL) && !(alphabet->flags & AL_DONT_NAME))
{
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
phontab_1 = tr->phoneme_tab_ix;
ph_alphabet[2] = SetTranslator2("en"); // overwrites previous contents of translator2
if(Lookup(translator2, alphabet->name, &ph_alphabet[3]) != 0)
{
ph_alphabet[0] = phonPAUSE;
ph_alphabet[1] = phonSWITCH;
len = strlen(&ph_alphabet[3]) + 3;
ph_alphabet[len] = phonSWITCH; // switch back
ph_alphabet[len+1] = phontab_1;
ph_alphabet[len+2] = 0;
}
}
}
}
// caution: SetWordStress() etc don't expect phonSWITCH + phoneme table number
if(ph_buf[0] == 0)
{
if((alphabet != NULL) && (alphabet->language != 0) && !(alphabet->flags & AL_NOT_LETTERS))
language = alphabet->language;
else
language = L('e','n');
if(language != tr->translator_name)
{
// speak in the language for this alphabet (or English)
ph_buf[2] = SetTranslator2(WordToString2(language));
LookupLetter(translator2, letter, word[n_bytes], &ph_buf[3], control & 1);
if(ph_buf[3] == phonSWITCH)
{
// another level of language change
ph_buf[2] = SetTranslator2(&ph_buf[4]);
LookupLetter(translator2, letter, word[n_bytes], &ph_buf[3], control & 1);
}
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+1] = tr->phoneme_tab_ix;
ph_buf[len+2] = 0;
}
}
}
if(ph_buf[0] == 0)
{
@@ -695,10 +761,11 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
}
len = strlen(phonemes);
if(tr->langopts.accents & 2)
sprintf(ph_buf2,"%c%s%s",0xff,ph_buf,capital);
sprintf(ph_buf2,"%c%s%s%s",0xff,ph_alphabet,ph_buf,capital);
else
sprintf(ph_buf2,"%c%s%s",0xff,capital,ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress()
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);
@@ -714,23 +781,25 @@ void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars)
int ix;
unsigned int c;
int n_stress=0;
int prev = 0;
int count;
unsigned char buf[N_WORD_PHONEMES];
for(ix=0; (c = phonemes[ix]) != 0; ix++)
{
if(c == phonSTRESS_P)
if((c == phonSTRESS_P) && (prev != phonSWITCH))
{
n_stress++;
}
buf[ix] = c;
buf[ix] = prev = c;
}
buf[ix] = 0;
count = 0;
prev = 0;
for(ix=0; (c = buf[ix]) != 0; ix++)
{
if((c == phonSTRESS_P) && (n_chars > 1))
if((c == phonSTRESS_P) && (n_chars > 1) && (prev != phonSWITCH))
{
count++;
@@ -761,10 +830,8 @@ void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars)
c = phonPAUSE_NOLINK; // pause following a primary stress
else
c = phonPAUSE_VSHORT;
// else
// continue; // remove marker
}
*phonemes++ = c;
*phonemes++ = prev = c;
}
if(control >= 2)
*phonemes++ = phonPAUSE_NOLINK;
+25 -25
View File
@@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2005 to 2011 by Jonathan Duddington *
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
* email: jonsd@users.sourceforge.net *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -58,7 +58,7 @@ static const char *ungot_word = NULL;
static int end_of_input;
static int ignore_text=0; // set during <sub> ... </sub> to ignore text which has been replaced by an alias
static int audio_text=0; // set during <audio> ... </audio>
static int audio_text=0; // set during <audio> ... </audio>
static int clear_skipping_text = 0; // next clause should clear the skipping_text flag
int count_characters = 0;
static int sayas_mode;
@@ -110,7 +110,7 @@ static const unsigned short punct_chars[] = {',','.','?','!',':',';',
0xff1a, // fullwidth colon
0xff1b, // fullwidth semicolon
0xff1f, // fullwidth question mark
0};
@@ -448,7 +448,7 @@ static int GetC_get(void)
end_of_input = 1;
return(0);
}
if(!end_of_input)
{
if(option_multibyte == espeakCHARS_16BIT)
@@ -563,8 +563,8 @@ static void UngetC(int c)
}
static const char *WordToString2(unsigned int word)
{//================================================
const char *WordToString2(unsigned int word)
{//============================================
// Convert a language mnemonic word into a string
int ix;
static char buf[5];
@@ -961,7 +961,7 @@ static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output
if(attributes & CLAUSE_BIT_SENTENCE)
return(attributes);
return(short_pause);
} // end of AnnouncePunctuation
@@ -1078,7 +1078,7 @@ static const char *VoiceFromStack()
}
p += (strlen(p) + 1);
}
if(voice_name_specified == 0)
voice_name[0] = 0; // forget a previous voice name if a language is specified
}
@@ -1248,7 +1248,7 @@ static wchar_t *GetSsmlAttribute(wchar_t *pw, const char *name)
static int attrcmp(const wchar_t *string1, const char *string2)
{//============================================================
int ix;
if(string1 == NULL)
return(1);
@@ -1334,7 +1334,7 @@ static int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out)
}
if(*pw == '-')
{
pw++;
pw++;
sign = -1;
}
value = (double)wcstod(pw,&tail);
@@ -1485,10 +1485,10 @@ static int GetVoiceAttributes(wchar_t *pw, int tag_type)
age = GetSsmlAttribute(pw,"age");
gender = GetSsmlAttribute(pw,"gender");
}
if((tag_type != SSML_VOICE) && (lang==NULL))
return(0); // <s> or <p> without language spec, nothing to do
ssml_sp = &ssml_stack[n_ssml_stack++];
attrcopy_utf8(ssml_sp->language,lang,sizeof(ssml_sp->language));
@@ -1592,7 +1592,7 @@ static int ReplaceKeyName(char *outbuf, int index, int &outix)
{"underscore ", 0xe05f},
{"double-quote ", '"'},
{NULL, 0}};
int ix;
int letter;
char *p;
@@ -1624,7 +1624,7 @@ static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int &outix, int n_outb
int voice_change_flag;
wchar_t *px;
wchar_t *attr1;
wchar_t *attr2;
wchar_t *attr2;
wchar_t *attr3;
int terminator;
char *uri;
@@ -1688,7 +1688,7 @@ static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int &outix, int n_outb
tag_name[ix] = 0;
px = &xml_buf[ix]; // the tag's attributes
if(tag_name[0] == '/')
{
// closing tag
@@ -2268,7 +2268,7 @@ f_input = f_in; // for GetC etc
}
xml_buf[n_xml_buf] = 0;
c2 = ' ';
self_closing = 0;
if(xml_buf[n_xml_buf-1] == '/')
{
@@ -2276,9 +2276,9 @@ f_input = f_in; // for GetC etc
xml_buf[n_xml_buf-1] = ' ';
self_closing = 1;
}
terminator = ProcessSsmlTag(xml_buf,buf,ix,n_buf,self_closing);
if(terminator != 0)
{
if(end_clause_after_tag)
@@ -2286,7 +2286,7 @@ f_input = f_in; // for GetC etc
buf[ix] = ' ';
buf[ix++] = 0;
if(terminator & CLAUSE_BIT_VOICE)
{
strcpy(voice_change, current_voice_id);
@@ -2397,7 +2397,7 @@ f_input = f_in; // for GetC etc
if(iswspace(c1))
{
char *p_word;
if(tr->translator_name == 0x6a626f)
{
// language jbo : lojban
@@ -2514,7 +2514,7 @@ if(option_ssml) parag=1;
// Because of an xml tag, we are waiting for the
// next non-blank character to decide whether to end the clause
// i.e. is dot followed by an upper-case letter?
if(!iswspace(c1))
{
if(!IsAlpha(c1) || !iswlower(c1))
@@ -2548,7 +2548,7 @@ if(option_ssml) parag=1;
if((punct = lookupwchar(punct_chars,c1)) != 0)
{
punct_data = punct_attributes[punct];
if(punct_data & PUNCT_IN_WORD)
{
// Armenian punctuation inside a word
@@ -2579,7 +2579,7 @@ if(option_ssml) parag=1;
announced_punctuation = c1;
}
}
if((punct_data & PUNCT_SAY_NAME) && (announced_punctuation == 0))
{
// used for elipsis (and 3 dots) if a pronunciation for elipsis is given in *_list
@@ -2626,7 +2626,7 @@ if(option_ssml) parag=1;
if(c1 == '.')
{
if((tr->langopts.numbers & NUM_ORDINAL_DOT) &&
if((tr->langopts.numbers & NUM_ORDINAL_DOT) &&
(iswdigit(cprev) || (IsRomanU(cprev) && (IsRomanU(cprev2) || iswspace(cprev2))))) // lang=hu
{
// dot after a number indicates an ordinal number
@@ -2643,7 +2643,7 @@ if(option_ssml) parag=1;
else
if(c_next == '\'')
{
is_end_clause = 0; // eg. u.s.a.'s
is_end_clause = 0; // eg. u.s.a.'s
}
if(iswlower(c_next))
{
+1 -1
View File
@@ -35,7 +35,7 @@
#include "translate.h"
#include "wave.h"
const char *version_string = "1.46.37 20.Feb.13";
const char *version_string = "1.46.38 27.Feb.13";
const int version_phdata = 0x014636;
int option_device_number = -1;
+79 -29
View File
@@ -48,6 +48,7 @@
#define OFFSET_GREEK 0x380
#define OFFSET_CYRILLIC 0x420
#define OFFSET_ARMENIAN 0x530
#define OFFSET_HEBREW 0x590
#define OFFSET_ARABIC 0x600
#define OFFSET_THAANA 0x780 // Divehi/Maldives
#define OFFSET_DEVANAGARI 0x900
@@ -60,12 +61,61 @@
#define OFFSET_KANNADA 0xc80
#define OFFSET_MALAYALAM 0xd00
#define OFFSET_SINHALA 0x0d80
#define OFFSET_THAI 0x0e00
#define OFFSET_LAO 0x0e80
#define OFFSET_TIBET 0x0f00
#define OFFSET_GEORGIAN 0x1080
#define OFFSET_MYANMAR 0x1000
#define OFFSET_GEORGIAN 0x10a0
#define OFFSET_KOREAN 0x1100
#define OFFSET_ETHIOPIC 0x1200
ALPHABET alphabets [] = {
{"_el", OFFSET_GREEK, 0x380, 0x3ff, L('e','l'), AL_DONT_NAME | AL_NOT_LETTERS},
{"_cyr", OFFSET_CYRILLIC, 0x400, 0x52f, 0, 0},
{"_hy", OFFSET_ARMENIAN, 0x530, 0x58f, L('h','y'), 0},
{"_he", OFFSET_HEBREW, 0x590, 0x5ff, 0, 0},
{"_ar", OFFSET_ARABIC, 0x600, 0x6ff, 0, 0},
{"_dv", OFFSET_THAANA, 0x780, 0x7bf, 0, 0},
{"_hi", OFFSET_DEVANAGARI, 0x900, 0x97f,L('h','i'), 0},
{"_bn", OFFSET_BENGALI, 0x0980, 0x9ff, 0, 0},
{"_gur", OFFSET_GURMUKHI, 0xa00, 0xa7f, 0, 0},
{"_gu", OFFSET_GUJARATI, 0xa80, 0xaff, 0, 0},
{"_or", OFFSET_ORIYA, 0xb00, 0xb7f, 0, 0},
{"_ta", OFFSET_TAMIL, 0xb80, 0xbff, L('t','a'), 0},
{"_te", OFFSET_TELUGU, 0xc00, 0xc7f, 0, 0},
{"_kn", OFFSET_KANNADA, 0xc80, 0xcff, L('k','n'), 0},
{"_ml", OFFSET_MALAYALAM,0xd00, 0xd7f, L('m','l'), 0},
{"_si", OFFSET_SINHALA, 0xd80, 0xdff, 0, 0},
{"_th", OFFSET_THAI, 0xe00, 0xe7f, 0, 0},
{"_lo", OFFSET_LAO, 0xe80, 0xeff, 0, 0},
{"_ti", OFFSET_TIBET, 0xf00, 0xfff, 0, 0},
{"_my", OFFSET_MYANMAR, 0x1000,0x109f, 0, 0},
{"_ka", OFFSET_GEORGIAN, 0x10a0,0x10ff, L('k','a'), 0},
{"_ko", OFFSET_KOREAN, 0x1100,0x11ff, 0, 0},
{"_eth", OFFSET_ETHIOPIC, 0x1200,0x139f, 0, 0},
{NULL, 0, 0, 0, 0, 0}
};
ALPHABET *AlphabetFromChar(int c)
{//===============================
// Find the alphabet from a character.
ALPHABET *alphabet = alphabets;
while(alphabet->name != NULL)
{
if((c >= alphabet->range_min) && (c <= alphabet->range_max))
{
return(alphabet);
}
alphabet++;
}
return(NULL);
}
static void Translator_Russian(Translator *tr);
@@ -93,7 +143,7 @@ static void SetLetterBits(Translator *tr, int group, const char *string)
{//=====================================================================
int bits;
unsigned char c;
bits = (1L << group);
while((c = *string++) != 0)
tr->letter_bits[c] |= bits;
@@ -242,7 +292,7 @@ static const char transpose_map_latin[] = {
// common letter pairs, encode these as a single byte
// 2 bytes, using the transposed character codes
static const short pairs_ru[] = {
static const short pairs_ru[] = {
0x010c, // ла 21052 0x23
0x010e, // на 18400
0x0113, // та 14254
@@ -279,7 +329,7 @@ static const short pairs_ru[] = {
static const unsigned int replace_cyrillic_latin[] =
static const unsigned int replace_cyrillic_latin[] =
{0x430,'a',
0x431,'b',
0x446,'c',
@@ -413,7 +463,7 @@ Translator *SelectTranslator(const char *name)
tr->langopts.param[LOPT_DIERESES] = 1;
tr->langopts.param[LOPT_PREFIXES] = 1;
SetLetterVowel(tr,'y'); // add 'y' to vowels
tr->langopts.numbers = NUM_SWAP_TENS | NUM_HUNDRED_AND | NUM_SINGLE_AND | NUM_ROMAN | NUM_1900;
tr->langopts.accents = 1;
}
@@ -496,7 +546,7 @@ Translator *SelectTranslator(const char *name)
// tr->langopts.intonation_group = 4;
// 'diminished' is an unstressed final syllable
tr->langopts.stress_flags = 0x6 | 0x10;
tr->langopts.stress_flags = 0x6 | 0x10;
tr->langopts.unstressed_wd1 = 0;
tr->langopts.unstressed_wd2 = 2;
tr->langopts.param[LOPT_SONORANT_MIN] = 120; // limit the shortening of sonorants before short vowels
@@ -532,7 +582,7 @@ Translator *SelectTranslator(const char *name)
tr->langopts.param[LOPT_PREFIXES] = 1;
tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x100; // devoice at end of word
tr->langopts.param[LOPT_LONG_VOWEL_THRESHOLD] = 175/2;
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SWAP_TENS | NUM_ALLOW_SPACE | NUM_ORDINAL_DOT | NUM_ROMAN;
// tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SWAP_TENS | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_ALLOW_SPACE | NUM_ORDINAL_DOT | NUM_ROMAN;
SetLetterVowel(tr,'y');
@@ -549,7 +599,7 @@ Translator *SelectTranslator(const char *name)
tr->langopts.stress_rule = STRESSPOSN_1L;
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
SetLetterBitsRange(tr,LETTERGP_B,0x26,0x30); // vowel signs, and virama
tr->langopts.break_numbers = 0x14a8; // 1000, 100,000 10,000,000
tr->langopts.break_numbers = 0x14a8; // 1000, 100,000 10,000,000
tr->langopts.numbers = 1;
}
break;
@@ -578,7 +628,7 @@ Translator *SelectTranslator(const char *name)
// character codes offset by 0x380
static const char el_vowels[] = {0x10,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x35,0x37,0x39,0x3f,0x45,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0};
static const char el_fvowels[] = {0x2d,0x2e,0x2f,0x35,0x37,0x39,0x45,0x4d,0}; // ε η ι υ έ ή ί ύ
static const char el_voiceless[]= {0x38,0x3a,0x3e,0x40,0x42,0x43,0x44,0x46,0x47,0}; // θ κ ξ π ς σ τ φ χ
static const char el_voiceless[]= {0x38,0x3a,0x3e,0x40,0x42,0x43,0x44,0x46,0x47,0}; // θ κ ξ π ς σ τ φ χ
static const char el_consonants[]={0x32,0x33,0x34,0x36,0x38,0x3a,0x3b,0x3c,0x3d,0x3e,0x40,0x41,0x42,0x43,0x44,0x46,0x47,0x48,0};
static const wchar_t el_char_apostrophe[] = {0x3c3,0}; // σ
@@ -602,7 +652,7 @@ Translator *SelectTranslator(const char *name)
tr->langopts.unstressed_wd2 = 2;
tr->langopts.param[LOPT_SONORANT_MIN] = 130; // limit the shortening of sonorants before short vowels
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA;
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA;
tr->langopts.numbers2 = 0x2 | NUM2_MULTIPLE_ORDINAL; // variant form of numbers before thousands
if(name2 == L_grc)
@@ -618,7 +668,7 @@ Translator *SelectTranslator(const char *name)
static const short stress_lengths_eo[8] = {150, 150, 230, 180, 0, 0, 300, 320};
static const unsigned char stress_amps_eo[] = {16,14, 20,20, 20,22, 22,21 };
static const wchar_t eo_char_apostrophe[2] = {'l',0};
SetupTranslator(tr,stress_lengths_eo,stress_amps_eo);
tr->charset_a0 = charsets[3]; // ISO-8859-3
@@ -627,7 +677,7 @@ Translator *SelectTranslator(const char *name)
// tr->langopts.word_gap = 1;
tr->langopts.vowel_pause = 2;
tr->langopts.stress_rule = STRESSPOSN_2R;
tr->langopts.stress_flags = 0x6 | 0x10;
tr->langopts.stress_flags = 0x6 | 0x10;
// tr->langopts.unstressed_wd1 = 3;
tr->langopts.unstressed_wd2 = 2;
@@ -651,13 +701,13 @@ Translator *SelectTranslator(const char *name)
// stress last syllable if it doesn't end in vowel or "s" or "n"
// 'diminished' is an unstressed final syllable
tr->langopts.stress_flags = 0x200 | 0x6 | 0x10;
tr->langopts.stress_flags = 0x200 | 0x6 | 0x10;
tr->langopts.unstressed_wd1 = 0;
tr->langopts.unstressed_wd2 = 2;
tr->langopts.param[LOPT_SONORANT_MIN] = 120; // limit the shortening of sonorants before short vowels
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_ROMAN | NUM_ROMAN_AFTER;
tr->langopts.numbers2 = NUM2_MULTIPLE_ORDINAL;
tr->langopts.numbers2 = NUM2_MULTIPLE_ORDINAL;
if(name2 == L('c','a'))
{
@@ -667,7 +717,7 @@ Translator *SelectTranslator(const char *name)
else
if(name2 == L('a','n'))
{
tr->langopts.stress_flags = 0x200 | 0x6 | 0x10;
tr->langopts.stress_flags = 0x200 | 0x6 | 0x10;
}
else
if(name2 == L_pap)
@@ -805,7 +855,7 @@ Translator *SelectTranslator(const char *name)
tr->charset_a0 = charsets[2]; // ISO-8859-2
tr->langopts.stress_rule = STRESSPOSN_1L;
tr->langopts.stress_flags = 0x10;
tr->langopts.stress_flags = 0x10;
tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x3;
tr->langopts.max_initial_consonants = 5;
tr->langopts.spelling_stress = 1;
@@ -884,7 +934,7 @@ SetLengthMods(tr,3); // all equal
SetupTranslator(tr,stress_lengths_id,stress_amps_id);
tr->langopts.stress_rule = STRESSPOSN_2R;
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_ROMAN;
tr->langopts.stress_flags = 0x6 | 0x10;
tr->langopts.stress_flags = 0x6 | 0x10;
tr->langopts.accents = 2; // "capital" after letter name
}
break;
@@ -919,7 +969,7 @@ SetLengthMods(tr,3); // all equal
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
tr->langopts.stress_rule = STRESSPOSN_2R;
tr->langopts.stress_flags = 0x10 | 0x20000;
tr->langopts.stress_flags = 0x10 | 0x20000;
tr->langopts.vowel_pause = 1;
tr->langopts.unstressed_wd1 = 2;
tr->langopts.unstressed_wd2 = 2;
@@ -974,7 +1024,7 @@ SetLengthMods(tr,3); // all equal
{
static const unsigned char stress_amps_tr[8] = {18,16, 20,21, 20,21, 21,20 };
static const short stress_lengths_tr[8] = {190,180, 230,230, 0,0, 250,250};
tr->letter_bits_offset = OFFSET_CYRILLIC;
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
SetLetterBits(tr,LETTERGP_A,(char *)ru_vowels);
@@ -1173,9 +1223,9 @@ SetLengthMods(tr,3); // all equal
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
tr->langopts.stress_rule = STRESSPOSN_1R; // stress on final syllable
tr->langopts.stress_flags = 0x6 | 0x10 | 0x2000 | 0x20000;
tr->langopts.stress_flags = 0x6 | 0x10 | 0x2000 | 0x20000;
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_DFRACTION_2 | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_ROMAN;
tr->langopts.numbers2 = NUM2_MULTIPLE_ORDINAL | NUM2_NO_TEEN_ORDINALS;
tr->langopts.numbers2 = NUM2_MULTIPLE_ORDINAL | NUM2_NO_TEEN_ORDINALS;
SetLetterVowel(tr,'y');
ResetLetterBits(tr,0x2);
SetLetterBits(tr,1,"bcdfgjkmnpqstvxz"); // B hard consonants, excluding h,l,r,w,y
@@ -1223,7 +1273,7 @@ SetLengthMods(tr,3); // all equal
tr->charset_a0 = charsets[2]; // ISO-8859-2
tr->langopts.stress_rule = STRESSPOSN_1L;
tr->langopts.stress_flags = 0x16;
tr->langopts.stress_flags = 0x16;
tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x3;
tr->langopts.max_initial_consonants = 5;
tr->langopts.spelling_stress = 1;
@@ -1259,11 +1309,11 @@ SetLengthMods(tr,3); // all equal
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
SetLetterBitsRange(tr,LETTERGP_A,0x05,0x16); // vowel letters
SetLetterBitsRange(tr,LETTERGP_A,0x4a,0x73); // + vowel signs, and virama
SetLetterBitsRange(tr,LETTERGP_B,0x4a,0x73); // vowel signs, and virama
SetLetterBitsRange(tr,LETTERGP_C,0x1a,0x46); // the main consonant range
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
tr->langopts.suffix_add_e = tr->letter_bits_offset + 0x4a; //virama
tr->langopts.numbers = NUM_OMIT_1_THOUSAND | NUM_SINGLE_STRESS_L | NUM_DFRACTION_7;
@@ -1292,7 +1342,7 @@ SetLengthMods(tr,3); // all equal
SetupTranslator(tr,stress_lengths_sq,stress_amps_sq);
tr->langopts.stress_rule = STRESSPOSN_2R;
tr->langopts.stress_flags = 0x16 + 0x100;
tr->langopts.stress_flags = 0x16 + 0x100;
SetLetterVowel(tr,'y');
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_DFRACTION_4;
tr->langopts.accents = 2; // "capital" after letter name
@@ -1324,7 +1374,7 @@ SetLengthMods(tr,3); // all equal
tr->langopts.vowel_pause = 1;
tr->langopts.stress_rule = STRESSPOSN_2R;
tr->langopts.stress_flags = 0x6 | 0x10;
tr->langopts.stress_flags = 0x6 | 0x10;
tr->langopts.numbers = NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_SINGLE_AND | NUM_OMIT_1_HUNDRED;
tr->langopts.break_numbers = 0x49249268; // for languages which have numbers for 100,000 and 1,000,000
@@ -1343,7 +1393,7 @@ SetLengthMods(tr,3); // all equal
tr->langopts.stress_rule = STRESSPOSN_1L;
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
tr->langopts.spelling_stress = 1;
tr->langopts.break_numbers = 0x14a8; // 1000, 100,000 10,000,000
tr->langopts.break_numbers = 0x14a8; // 1000, 100,000 10,000,000
if(name2 == L('t','a'))
{
@@ -1604,7 +1654,7 @@ PH('V','#'),PH('I','3'),PH('I','2'),PH('E','3')};
/*2*/ {'o', '8', '8', 'o', '8', '8'}, // O
/*3*/ {'i', 'I', 'i', 'a', 'I', 'a'}, // I Uses 3,4,5 columns.
/*4*/ {'i', PH('I','#'), 'i', 'i', PH('I','#'), 'i'}, // I#
/*5*/ {'E', PH('E','#'), 'E', 'e', PH('E','#'), 'e'}, // E#
/*5*/ {'E', PH('E','#'), 'E', 'e', PH('E','#'), 'e'}, // E#
/*6*/ {'E', PH('E','2'), 'E', 'e', PH('E','2'), 'e'}, // E2 Uses 3,4,5 columns.
/*7*/ {PH('j','a'), 'V', PH('j','a'), 'A', 'V', 'A'}, // V#
/*8*/ {PH('j','a'), 'I', PH('j','a'), 'e', 'I', 'e'}, // I3 Uses 3,4,5 columns.
+30 -5
View File
@@ -77,6 +77,7 @@ static int prev_clause_pause=0;
static int max_clause_pause = 0;
static int any_stressed_words;
int pre_pause;
ALPHABET *current_alphabet;
// these were previously in translator class
@@ -874,6 +875,7 @@ int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wt
unpron_phonemes[0] = 0;
prefix_phonemes[0] = 0;
end_phonemes[0] = 0;
current_alphabet = NULL;
if(tr->data_dictlist == NULL)
{
@@ -902,6 +904,12 @@ int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wt
spell_word = 0;
if((word_length == 1) && (wflags & FLAG_TRANSLATOR2))
{
// retranslating a 1-character word using a different language, say its name
spell_word = 1;
}
if(option_sayas == SAYAS_KEY)
{
if(word_length == 1)
@@ -1061,6 +1069,8 @@ if((wmark > 0) && (wmark < 8))
return(FLAG_SPELLWORD); // a mixture of languages, retranslate as individual letters, separated by spaces
return(0);
}
strcpy(word_phonemes, phonemes);
return(0); // ??
}
else
if(found == 0)
@@ -1098,7 +1108,7 @@ if((wmark > 0) && (wmark < 8))
if(strcmp(&unpron_phonemes[1],"en")==0)
return(FLAG_SPELLWORD); // _^_en must have been set in TranslateLetter(), not *_rules
return(0);
}
}
#ifdef deleted
p = &wordx[word_length-3]; // this looks wrong. Doesn't consider multi-byte chars.
@@ -1158,6 +1168,8 @@ if(end_type & SUFX_UNPRON)
{
return(0);
}
strcpy(word_phonemes, phonemes);
return(0);
}
}
@@ -1713,6 +1725,7 @@ int SetTranslator2(const char *new_language)
new_phoneme_tab = -1;
translator2_language[0] = 0;
}
translator2->phoneme_tab_ix = new_phoneme_tab;
}
}
return(new_phoneme_tab);
@@ -1953,12 +1966,14 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
if(switch_phonemes >= 0)
{
// re-translate the word using the new translator
wtab[0].flags |= FLAG_TRANSLATOR2;
flags = TranslateWord(translator2, word, next_pause, wtab);
// strcpy((char *)p,translator2->word_phonemes);
if(p[0] == phonSWITCH)
{
// the second translator doesn't want to process this word
switch_phonemes = -1;
// switch_phonemes = -1;
return(FLAG_SPELLWORD);
}
}
if(switch_phonemes < 0)
@@ -2050,8 +2065,16 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
if(switch_phonemes >= 0)
{
// this word uses a different phoneme table
SetPlist2(&ph_list2[n_ph_list2],phonSWITCH);
ph_list2[n_ph_list2++].tone_ph = switch_phonemes; // temporary phoneme table number
if(ph_list2[n_ph_list2-1].phcode == phonSWITCH)
{
//previous phoneme is also a phonSWITCH, just change its phoneme table number
n_ph_list2--;
}
else
{
SetPlist2(&ph_list2[n_ph_list2],phonSWITCH);
}
ph_list2[n_ph_list2++].tone_ph = switch_phonemes; // temporary phoneme table number
}
// remove initial pause from a word if it follows a hyphen
@@ -2078,7 +2101,9 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
ph_list2[n_ph_list2].phcode = ph_code;
ph_list2[n_ph_list2].sourceix = 0;
ph_list2[n_ph_list2].synthflags = embedded_flag;
ph_list2[n_ph_list2++].tone_ph = *p++;
ph_list2[n_ph_list2++].tone_ph = *p;
SelectPhonemeTable(*p);
p++;
}
else
if(ph->type == phSTRESS)
+18
View File
@@ -111,6 +111,7 @@
#define FLAG_INDIVIDUAL_DIGITS 0x80000 // speak number as individual digits
#define FLAG_DELETE_WORD 0x100000 // don't speak this word, it has been spoken as part of the previous word
#define FLAG_CHAR_REPLACED 0x200000 // characters have been replaced by .replace in the *_rules
#define FLAG_TRANSLATOR2 0x400000 // retranslating using a different language
#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
@@ -258,6 +259,21 @@ extern PARAM_STACK param_stack[];
extern const int param_defaults[N_SPEECH_PARAM];
typedef struct {
const char *name;
int offset;
unsigned short range_min, range_max;
int language;
int flags;
} ALPHABET;
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_NOT_WORDS 0x04 // don't use the language to speak words
#define N_LOPTS 21
#define LOPT_DIERESES 1
@@ -664,6 +680,8 @@ int IsAlpha(unsigned int c);
int isspace2(unsigned int c);
int towlower2(unsigned int c);
void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa);
const char *WordToString2(unsigned int word);
ALPHABET *AlphabetFromChar(int c);
Translator *SelectTranslator(const char *name);
int SetTranslator2(const char *name);