mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-12 00:46:50 +00:00
[1.31.20]
Speak accented letter names as base-letter name plus accent name, using a table of Unicode characters up to U+17F. Added $accent attribute for *_list files, meaning "speak as base-letter name plus accent name". Added accent names to several languages *_list files. Added language option to allow vowels to merge between words (used for lang=TA). git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@153 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
@@ -103,6 +103,7 @@ MNEM_TAB mnem_flags[] = {
|
||||
{"$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
|
||||
|
||||
// doesn't set dictionary_flags
|
||||
{"$?", 100}, // conditional rule, followed by byte giving the condition number
|
||||
|
||||
+14
-3
@@ -2390,15 +2390,15 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char
|
||||
// no group for this letter, use default group
|
||||
MatchRule(&p, "", groups1[0], &match1, word_flags, dict_flags);
|
||||
|
||||
if(match1.points == 0)
|
||||
if((match1.points == 0) && ((option_sayas & 0x10) == 0))
|
||||
{
|
||||
// no match, try removing the accent and re-translating the word
|
||||
n = utf8_in(&letter,p-1,0)-1;
|
||||
if((letter >= 0xc0) && (letter <= 0x241))
|
||||
if((letter >= 0xc0) && (letter <= 0x241) && ((ix = remove_accent[letter-0xc0]) != 0))
|
||||
{
|
||||
// within range of the remove_accent table
|
||||
p2 = p-1;
|
||||
p[-1] = remove_accent[letter-0xc0];
|
||||
p[-1] = ix;
|
||||
while((p[0] = p[n]) != ' ') p++;
|
||||
while(n-- > 0) *p++ = ' '; // replacement character must be no longer than original
|
||||
|
||||
@@ -3020,6 +3020,16 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags
|
||||
|
||||
found = LookupDict2(word, word1, ph_out, flags, end_flags, wtab);
|
||||
|
||||
if((found == 0) && (flags[1] & FLAG_ACCENT))
|
||||
{
|
||||
int letter;
|
||||
word2 = word;
|
||||
if(*word2 == '_') word2++;
|
||||
len = utf8_in(&letter, word2, 0);
|
||||
LookupAccentedLetter(letter, ph_out);
|
||||
found = word2 + len;
|
||||
}
|
||||
|
||||
if(found == 0)
|
||||
{
|
||||
ph_out[0] = 0;
|
||||
@@ -3086,6 +3096,7 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags
|
||||
int Translator::Lookup(const char *word, char *ph_out)
|
||||
{//===================================================
|
||||
unsigned int flags[2];
|
||||
flags[0] = flags[1] = 0;
|
||||
char *word1 = (char *)word;
|
||||
return(LookupDictList(&word1, ph_out, flags, 0, NULL));
|
||||
}
|
||||
|
||||
+298
-1
@@ -36,6 +36,290 @@
|
||||
|
||||
|
||||
|
||||
#define M_NAME 0
|
||||
#define M_ACUTE 1
|
||||
#define M_BREVE 2
|
||||
#define M_CARON 3
|
||||
#define M_CEDILLA 4
|
||||
#define M_CIRCUMFLEX 5
|
||||
#define M_DIAERESIS 6
|
||||
#define M_DOUBLE_ACUTE 7
|
||||
#define M_DOT_ABOVE 8
|
||||
#define M_GRAVE 9
|
||||
#define M_MACRON 10
|
||||
#define M_OGONEK 11
|
||||
#define M_RING 12
|
||||
#define M_STROKE 13
|
||||
#define M_TILDE 14
|
||||
|
||||
#define M_MIDDLE_DOT 8 // duplicate of M_DOT_ABOVE
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int flags;
|
||||
} ACCENTS;
|
||||
|
||||
// these are tokens to look up in the *_list file.
|
||||
ACCENTS accents_tab[] = {
|
||||
{"_lig", 1},
|
||||
{"_acu", 0}, // acute
|
||||
{"_brv", 0}, // breve
|
||||
{"_hac", 0}, // caron/hacek
|
||||
{"_ced", 0}, // cedilla
|
||||
{"_cir", 0}, // circumflex
|
||||
{"_dia", 0}, // diaeresis
|
||||
{"_ac2", 0}, // double acute
|
||||
{"_dot", 0}, // dot
|
||||
{"_grv", 0}, // grave
|
||||
{"_mcn", 0}, // macron
|
||||
{"_ogo", 0}, // ogonek
|
||||
{"_rng", 0}, // ring
|
||||
{"_stk", 0}, // stroke
|
||||
{"_tld", 0}, // tilde
|
||||
};
|
||||
|
||||
|
||||
#define CAPITAL 0
|
||||
#define LETTER(ch,mod1,mod2) ch+(mod1 << 8)
|
||||
#define LIGATURE(ch1,ch2,mod1) ch1+(ch2 << 8)+0x8000
|
||||
|
||||
// characters U+00e0 to U+017f
|
||||
const short letter_accents_0e0[] = {
|
||||
LETTER('a',M_GRAVE,0), // U+00e0
|
||||
LETTER('a',M_ACUTE,0),
|
||||
LETTER('a',M_CIRCUMFLEX,0),
|
||||
LETTER('a',M_TILDE,0),
|
||||
LETTER('a',M_DIAERESIS,0),
|
||||
LETTER('a',M_RING,0),
|
||||
LIGATURE('a','e',0),
|
||||
LETTER('c',M_CEDILLA,0),
|
||||
LETTER('e',M_GRAVE,0),
|
||||
LETTER('e',M_ACUTE,0),
|
||||
LETTER('e',M_CIRCUMFLEX,0),
|
||||
LETTER('e',M_DIAERESIS,0),
|
||||
LETTER('i',M_GRAVE,0),
|
||||
LETTER('i',M_ACUTE,0),
|
||||
LETTER('i',M_CIRCUMFLEX,0),
|
||||
LETTER('i',M_DIAERESIS,0),
|
||||
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
|
||||
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('y',M_DIAERESIS,0),
|
||||
CAPITAL, // U+0100
|
||||
LETTER('a',M_MACRON,0),
|
||||
CAPITAL,
|
||||
LETTER('a',M_BREVE,0),
|
||||
CAPITAL,
|
||||
LETTER('a',M_OGONEK,0),
|
||||
CAPITAL,
|
||||
LETTER('c',M_ACUTE,0),
|
||||
CAPITAL,
|
||||
LETTER('c',M_CIRCUMFLEX,0),
|
||||
CAPITAL,
|
||||
LETTER('c',M_DOT_ABOVE,0),
|
||||
CAPITAL,
|
||||
LETTER('c',M_CARON,0),
|
||||
CAPITAL,
|
||||
LETTER('d',M_CARON,0),
|
||||
CAPITAL, // U+0110
|
||||
LETTER('d',M_STROKE,0),
|
||||
CAPITAL,
|
||||
LETTER('e',M_MACRON,0),
|
||||
CAPITAL,
|
||||
LETTER('e',M_BREVE,0),
|
||||
CAPITAL,
|
||||
LETTER('e',M_DOT_ABOVE,0),
|
||||
CAPITAL,
|
||||
LETTER('e',M_OGONEK,0),
|
||||
CAPITAL,
|
||||
LETTER('e',M_CARON,0),
|
||||
CAPITAL,
|
||||
LETTER('g',M_CIRCUMFLEX,0),
|
||||
CAPITAL,
|
||||
LETTER('g',M_BREVE,0),
|
||||
CAPITAL, // U+0120
|
||||
LETTER('g',M_DOT_ABOVE,0),
|
||||
CAPITAL,
|
||||
LETTER('g',M_CEDILLA,0),
|
||||
CAPITAL,
|
||||
LETTER('h',M_CIRCUMFLEX,0),
|
||||
CAPITAL,
|
||||
LETTER('h',M_STROKE,0),
|
||||
CAPITAL,
|
||||
LETTER('i',M_TILDE,0),
|
||||
CAPITAL,
|
||||
LETTER('i',M_MACRON,0),
|
||||
CAPITAL,
|
||||
LETTER('i',M_BREVE,0),
|
||||
CAPITAL,
|
||||
LETTER('i',M_OGONEK,0),
|
||||
CAPITAL, // U+0130
|
||||
LETTER('i',M_NAME,0), // dotless i
|
||||
CAPITAL,
|
||||
LIGATURE('i','j',0),
|
||||
CAPITAL,
|
||||
LETTER('j',M_CIRCUMFLEX,0),
|
||||
CAPITAL,
|
||||
LETTER('k',M_CEDILLA,0),
|
||||
LETTER('k',M_NAME,0), // kra
|
||||
CAPITAL,
|
||||
LETTER('l',M_ACUTE,0),
|
||||
CAPITAL,
|
||||
LETTER('l',M_CEDILLA,0),
|
||||
CAPITAL,
|
||||
LETTER('1',M_CARON,0),
|
||||
CAPITAL,
|
||||
LETTER('1',M_MIDDLE_DOT,0), // U+0140
|
||||
CAPITAL,
|
||||
LETTER('1',M_STROKE,0),
|
||||
CAPITAL,
|
||||
LETTER('n',M_ACUTE,0),
|
||||
CAPITAL,
|
||||
LETTER('n',M_CEDILLA,0),
|
||||
CAPITAL,
|
||||
LETTER('n',M_CARON,0),
|
||||
LETTER('n',M_NAME,0), // apostrophe n
|
||||
CAPITAL,
|
||||
LETTER('n',M_NAME,0), // eng
|
||||
CAPITAL,
|
||||
LETTER('o',M_MACRON,0),
|
||||
CAPITAL,
|
||||
LETTER('o',M_BREVE,0),
|
||||
CAPITAL, // U+0150
|
||||
LETTER('o',M_DOUBLE_ACUTE,0),
|
||||
CAPITAL,
|
||||
LIGATURE('o','e',0),
|
||||
CAPITAL,
|
||||
LETTER('r',M_ACUTE,0),
|
||||
CAPITAL,
|
||||
LETTER('r',M_CEDILLA,0),
|
||||
CAPITAL,
|
||||
LETTER('r',M_CARON,0),
|
||||
CAPITAL,
|
||||
LETTER('s',M_ACUTE,0),
|
||||
CAPITAL,
|
||||
LETTER('s',M_CIRCUMFLEX,0),
|
||||
CAPITAL,
|
||||
LETTER('s',M_CEDILLA,0),
|
||||
CAPITAL, // U+0160
|
||||
LETTER('s',M_CARON,0),
|
||||
CAPITAL,
|
||||
LETTER('t',M_CEDILLA,0),
|
||||
CAPITAL,
|
||||
LETTER('t',M_CARON,0),
|
||||
CAPITAL,
|
||||
LETTER('t',M_STROKE,0),
|
||||
CAPITAL,
|
||||
LETTER('u',M_TILDE,0),
|
||||
CAPITAL,
|
||||
LETTER('u',M_MACRON,0),
|
||||
CAPITAL,
|
||||
LETTER('u',M_BREVE,0),
|
||||
CAPITAL,
|
||||
LETTER('u',M_RING,0),
|
||||
CAPITAL, // U+0170
|
||||
LETTER('u',M_DOUBLE_ACUTE,0),
|
||||
CAPITAL,
|
||||
LETTER('u',M_OGONEK,0),
|
||||
CAPITAL,
|
||||
LETTER('w',M_CIRCUMFLEX,0),
|
||||
CAPITAL,
|
||||
LETTER('y',M_CIRCUMFLEX,0),
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
|
||||
int Translator::LookupLetter2(unsigned int letter, char *ph_buf)
|
||||
{//=============================================================
|
||||
int len;
|
||||
char single_letter[10];
|
||||
|
||||
single_letter[0] = 0;
|
||||
single_letter[1] = '_';
|
||||
len = utf8_out(letter, &single_letter[2]);
|
||||
single_letter[2+len] = 0;
|
||||
|
||||
if(Lookup(&single_letter[1],ph_buf) == 0)
|
||||
{
|
||||
single_letter[1] = ' ';
|
||||
if(Lookup(&single_letter[2],ph_buf) == 0)
|
||||
{
|
||||
TranslateRules(&single_letter[2], ph_buf, 20, NULL,0,0);
|
||||
}
|
||||
}
|
||||
return(ph_buf[0]);
|
||||
}
|
||||
|
||||
|
||||
void Translator::LookupAccentedLetter(unsigned int letter, char *ph_buf)
|
||||
{//=====================================================================
|
||||
// lookup the character in the accents table
|
||||
int accent_data;
|
||||
int accent1;
|
||||
int basic_letter;
|
||||
int letter2=0;
|
||||
char ph_letter1[30];
|
||||
char ph_letter2[30];
|
||||
char ph_accent1[30];
|
||||
|
||||
if((letter >= 0xe0) && (letter < 0x17f))
|
||||
{
|
||||
accent_data = letter_accents_0e0[letter - 0xe0];
|
||||
|
||||
basic_letter = accent_data & 0x7f;
|
||||
if((accent1 = (accent_data >> 8) & 0x7f) != 0)
|
||||
{
|
||||
if(accent_data & 0x8000)
|
||||
{
|
||||
letter2 = accent1;
|
||||
accent1 = 0;
|
||||
}
|
||||
|
||||
if(Lookup(accents_tab[accent1].name, ph_accent1) != 0)
|
||||
{
|
||||
|
||||
if(LookupLetter2(basic_letter, ph_letter1) != 0)
|
||||
{
|
||||
if(accent1 == 0)
|
||||
{
|
||||
//ligature
|
||||
LookupLetter2(letter2, ph_letter2);
|
||||
sprintf(ph_buf,"%s%c%s%s",ph_accent1, phonPAUSE_VSHORT, ph_letter1, ph_letter2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(langopts.accents & 1)
|
||||
sprintf(ph_buf,"%s%c%s", ph_accent1, phonPAUSE_VSHORT, ph_letter1);
|
||||
else
|
||||
sprintf(ph_buf,"%s%c%s%c", ph_letter1, phonPAUSE_VSHORT, ph_accent1, phonPAUSE_VSHORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end of LookupAccentedLetter
|
||||
|
||||
|
||||
|
||||
void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1)
|
||||
{//=============================================================================
|
||||
@@ -43,7 +327,9 @@ void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1)
|
||||
unsigned char *p;
|
||||
static char single_letter[10] = {0,0};
|
||||
char ph_stress[2];
|
||||
char ph_buf3[30];
|
||||
unsigned int dict_flags[2];
|
||||
char ph_buf3[40];
|
||||
char *ptr;
|
||||
|
||||
ph_buf1[0] = 0;
|
||||
len = utf8_out(letter,&single_letter[2]);
|
||||
@@ -83,6 +369,11 @@ void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1)
|
||||
single_letter[3+len] = next_byte; // follow by space-space if the end of the word, or space-0x31
|
||||
|
||||
single_letter[1] = '_';
|
||||
|
||||
// if the $accent flag is set for this letter, use the accents table (below)
|
||||
dict_flags[1] = 0;
|
||||
ptr = &single_letter[1];
|
||||
|
||||
if(Lookup(&single_letter[1],ph_buf3) == 0)
|
||||
{
|
||||
single_letter[1] = ' ';
|
||||
@@ -92,6 +383,11 @@ void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1)
|
||||
}
|
||||
}
|
||||
|
||||
if(ph_buf3[0] == 0)
|
||||
{
|
||||
LookupAccentedLetter(letter, ph_buf3);
|
||||
}
|
||||
|
||||
if(ph_buf3[0] == 0)
|
||||
{
|
||||
ph_buf1[0] = 0;
|
||||
@@ -185,6 +481,7 @@ int Translator::TranslateLetter(char *word, char *phonemes, int control, int wor
|
||||
for(p2 = hexbuf; *p2 != 0; p2++)
|
||||
{
|
||||
pbuf += strlen(pbuf);
|
||||
*pbuf++ = phonPAUSE_VSHORT;
|
||||
LookupLetter(*p2, 0, pbuf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,6 +517,7 @@ const char *Translator::LookupSpecial(const char *string, char* text_out)
|
||||
const char *Translator::LookupCharName(int c)
|
||||
{//==========================================
|
||||
// Find the phoneme string (in ascii) to speak the name of character c
|
||||
// Used for punctuation characters and symbols
|
||||
|
||||
int ix;
|
||||
unsigned int flags[2];
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.31.19 28.Feb.08";
|
||||
const char *version_string = "1.31.20 01.Mar.08";
|
||||
const int version_phdata = 0x013105;
|
||||
|
||||
int option_device_number = -1;
|
||||
|
||||
+3
-1
@@ -1146,7 +1146,9 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
|
||||
if(p->newword)
|
||||
{
|
||||
last_frame = NULL;
|
||||
if(translator->langopts.param[LOPT_WORD_MERGE] == 0)
|
||||
last_frame = NULL;
|
||||
|
||||
sourceix = (p->sourceix & 0x7ff) + clause_start_char;
|
||||
|
||||
if(p->newword & 4)
|
||||
|
||||
@@ -663,6 +663,7 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.stress_rule = 1;
|
||||
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
|
||||
tr->letter_bits_offset = OFFSET_TAMIL;
|
||||
tr->langopts.param[LOPT_WORD_MERGE] = 1; // don't break vowels betwen words
|
||||
|
||||
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
|
||||
SetLetterBitsRange(tr,LETTERGP_A,0x05,0x14); // vowel letters
|
||||
@@ -1055,6 +1056,7 @@ Translator_Afrikaans::Translator_Afrikaans() : Translator()
|
||||
SetLetterVowel(this,'y'); // add 'y' to vowels
|
||||
|
||||
langopts.numbers = 0x8d1 + NUM_ROMAN;
|
||||
langopts.accents = 1;
|
||||
memcpy(stress_lengths,stress_lengths2,sizeof(stress_lengths));
|
||||
}
|
||||
|
||||
|
||||
+15
-4
@@ -74,6 +74,7 @@
|
||||
#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
|
||||
|
||||
|
||||
|
||||
@@ -230,7 +231,7 @@ extern const int param_defaults[N_SPEECH_PARAM];
|
||||
|
||||
|
||||
|
||||
#define N_LOPTS 14
|
||||
#define N_LOPTS 15
|
||||
#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
|
||||
@@ -254,9 +255,8 @@ extern const int param_defaults[N_SPEECH_PARAM];
|
||||
// increase this to prevent sonorants being shortened before shortened (eg. unstressed) vowels
|
||||
#define LOPT_SONORANT_MIN 7
|
||||
|
||||
// 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 8
|
||||
// don't break vowels at word boundary
|
||||
#define LOPT_WORD_MERGE 8
|
||||
|
||||
// max. amplitude for vowel at the end of a clause
|
||||
#define LOPT_MAXAMP_EOC 9
|
||||
@@ -277,6 +277,11 @@ extern const int param_defaults[N_SPEECH_PARAM];
|
||||
// stressed syllable is indicated by capitals
|
||||
#define LOPT_SYLLABLE_CAPS 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
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
// bits0-2 separate words with (1=pause_vshort, 2=pause_short, 3=pause, 4=pause_long 5=[?] phonemme)
|
||||
@@ -341,6 +346,10 @@ typedef struct {
|
||||
int max_roman;
|
||||
int thousands_sep;
|
||||
int decimal_sep;
|
||||
|
||||
// bit 0, accent name before the letter name
|
||||
int accents;
|
||||
|
||||
int tone_language; // 1=tone language
|
||||
int intonation_group;
|
||||
int long_stop; // extra mS pause for a lengthened stop
|
||||
@@ -430,6 +439,8 @@ private:
|
||||
const char *LookupSpecial(const char *string, char *text_out);
|
||||
const char *LookupCharName(int c);
|
||||
void LookupLetter(unsigned int letter, int next_byte, char *ph_buf);
|
||||
int LookupLetter2(unsigned int letter, char *ph_buf);
|
||||
void LookupAccentedLetter(unsigned int letter, char *ph_buf);
|
||||
int LookupNum2(int value, int control, char *ph_out);
|
||||
int LookupNum3(int value, char *ph_out, int suppress_null, int thousandplex, int prev_thousands);
|
||||
int LookupThousands(int value, int thousandplex, char *ph_out);
|
||||
|
||||
Reference in New Issue
Block a user