Merge branch 'master' into android

This commit is contained in:
Reece H. Dunn
2013-04-29 10:29:51 +01:00
95 changed files with 4592 additions and 2547 deletions
+6 -1
View File
@@ -2727,7 +2727,6 @@ static void DecThenCount()
static void InstnPlusPhoneme(int instn)
{//====================================
int phcode;
DecThenCount();
phcode = NextItemBrackets(tPHONEMEMNEM,0);
*prog_out++ = instn + phcode;
@@ -2835,16 +2834,19 @@ int CompilePhoneme(int compile_phoneme)
case i_CHANGE_IF+2:
case i_CHANGE_IF+3:
InstnPlusPhoneme(keyword << 8);
DecThenCount();
break;
case i_PAUSE_BEFORE:
value = NextItemMax(255);
*prog_out++ = (i_PAUSE_BEFORE << 8) + value;
DecThenCount();
break;
case i_PAUSE_AFTER:
value = NextItemMax(255);
*prog_out++ = (i_PAUSE_AFTER << 8) + value;
DecThenCount();
break;
case i_SET_LENGTH:
@@ -2936,6 +2938,7 @@ int CompilePhoneme(int compile_phoneme)
{
*prog_out++ = (ipa_buf[ix+start] << 8) + (ipa_buf[ix+start+1] & 0xff);
}
DecThenCount();
break;
}
break;
@@ -3018,6 +3021,7 @@ int CompilePhoneme(int compile_phoneme)
case kCALLPH:
CallPhoneme();
DecThenCount();
break;
case kFMT:
@@ -3049,6 +3053,7 @@ int CompilePhoneme(int compile_phoneme)
break;
case kTONESPEC:
DecThenCount();
endphoneme = CompileToneSpec();
break;
+3 -2
View File
@@ -133,6 +133,7 @@ MNEM_TAB mnem_flags[] = {
{"$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
@@ -700,9 +701,9 @@ static int compile_line(char *linebuf, char *dict_line, int *hash)
ix = utf8_in(&c2,p);
if(c2 == 0)
break;
if(iswupper(c2))
if(iswupper2(c2))
{
utf8_out(towlower(c2),p);
utf8_out(towlower2(c2),p);
}
else
{
+60 -16
View File
@@ -524,7 +524,7 @@ void DecodePhonemes(const char *inptr, char *outptr)
unsigned short ipa1[96] = {
0x20,0x21,0x22,0x2b0,0x24,0x25,0x0e6,0x2c8,0x28,0x27e,0x2a,0x2b,0x2cc,0x2d,0x2e,0x2f,
0x252,0x31,0x32,0x25c,0x34,0x35,0x36,0x37,0x275,0x39,0x2d0,0x2b2,0x3c,0x3d,0x3e,0x294,
0x259,0x251,0x3b2,0xe7,0xf0,0x25b,0x46,0x262,0x127,0x26a,0x25f,0x4b,0x29f,0x271,0x14b,0x254,
0x259,0x251,0x3b2,0xe7,0xf0,0x25b,0x46,0x262,0x127,0x26a,0x25f,0x4b,0x26b,0x271,0x14b,0x254,
0x3a6,0x263,0x280,0x283,0x3b8,0x28a,0x28c,0x153,0x3c7,0xf8,0x292,0x32a,0x5c,0x5d,0x5e,0x5f,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x261,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x303,0x7f
@@ -633,10 +633,13 @@ char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int
void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa)
{//=========================================================================
/* Can be called after a clause has been translated into phonemes, in order
void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int phoneme_mode)
{//===============================================================================
/* Called after a clause has been translated into phonemes, in order
to display the clause in phoneme mnemonic form.
phoneme_mode bits 0-3: 0=only phoneme names, 1=ties, 2=ZWJ, 3=underscore separator
bit 4: 0=eSpeak phoneme names, 1=IPA
*/
int ix;
@@ -649,6 +652,9 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa)
char *buf;
int count;
int flags;
int use_ipa;
int use_tie;
int separate_phonemes = 0;
char phon_buf[30];
char phon_buf2[30];
PHONEME_LIST *plist;
@@ -656,6 +662,16 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa)
static const char *stress_chars = "==,,''";
static const int char_tie[] = {0x0361, 0x200d}; // combining-double-inverted-breve, zero-width-joiner
use_ipa = phoneme_mode & 0x10;
use_tie = phoneme_mode & 0x0f;
if(use_tie >= 3)
{
// separate individual phonemes with underscores
separate_phonemes = '_';
use_tie = 0;
}
if(phon_out != NULL)
{
for(ix=1; ix<(n_phoneme_list-2); ix++)
@@ -663,8 +679,21 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa)
buf = phon_buf;
plist = &phoneme_list[ix];
WritePhMnemonic(phon_buf2, plist->ph, plist, use_ipa, &flags);
if(plist->newword)
*buf++ = ' ';
else
{
if((separate_phonemes != 0) && (ix > 1))
{
utf8_in(&c, phon_buf2);
if((c < 0x2b0) || (c > 0x36f)) // not if the phoneme starts with a superscript letter
{
*buf++ = separate_phonemes;
}
}
}
if(plist->synthflags & SFLAG_SYLLABLE)
{
@@ -687,22 +716,23 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa)
if(c != 0)
{
buf += utf8_out(c, buf);
// if(separate_phonemes)
// *buf++ = separate_phonemes;
}
}
}
flags = 0;
WritePhMnemonic(phon_buf2, plist->ph, plist, use_ipa, &flags);
count = 0;
for(p=phon_buf2; *p != 0;)
{
p += utf8_in(&c, p);
if(use_ipa > 1)
if(use_tie > 0)
{
// look for non-inital alphabetic character, but not diacritic, superscript etc.
if((count>0) && !(flags & (1 << (count-1))) && ((c < 0x2b0) || (c > 0x36f)) && iswalpha(c))
if((count>0) && !(flags & (1 << (count-1))) && ((c < 0x2b0) || (c > 0x36f)) && iswalpha2(c))
{
buf += utf8_out(char_tie[use_ipa-2], buf);
buf += utf8_out(char_tie[use_tie-1], buf);
}
}
buf += utf8_out(c, buf);
@@ -894,7 +924,13 @@ int Unpronouncable(Translator *tr, char *word, int posn)
if(count==0)
c1 = c;
count++;
if((c == '\'') && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 3))
{
// don't count apostrophe
}
else
count++;
if(IsVowel(tr, c))
{
@@ -902,7 +938,7 @@ int Unpronouncable(Translator *tr, char *word, int posn)
break;
}
if((c != '\'') && !iswalpha(c))
if((c != '\'') && !iswalpha2(c))
return(0);
}
@@ -1624,8 +1660,11 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
if(!(control & 1) && ((ph = phoneme_tab[*p]) != NULL))
{
if(ph->type == phSTRESS)
ph = phoneme_tab[p[1]];
while((ph->type == phSTRESS) || (*p == phonEND_WORD))
{
p++;
ph = phoneme_tab[p[0]];
}
#ifdef deleted
int gap = tr->langopts.word_gap & 0x700;
@@ -2078,7 +2117,7 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_
break;
case RULE_NONALPHA:
if(!iswalpha(letter_w))
if(!iswalpha2(letter_w))
{
add_points = (21-distance_right);
post_ptr += letter_xbytes;
@@ -2322,7 +2361,7 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_
break;
case RULE_NONALPHA:
if(!iswalpha(letter_w))
if(!iswalpha2(letter_w))
{
add_points = (21-distance_right);
pre_ptr -= letter_xbytes;
@@ -2639,7 +2678,7 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
if(tr->letter_bits_offset > 0)
{
// not a Latin alphabet, switch to the default Latin alphabet language
if((letter <= 0x241) && iswalpha(letter))
if((letter <= 0x241) && iswalpha2(letter))
{
sprintf(phonemes,"%c%s",phonSWITCH,tr->langopts.ascii_language);
return(0);
@@ -3240,6 +3279,11 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
continue;
}
}
if(dictionary_flags2 & FLAG_NATIVE)
{
if(tr != translator)
continue; // don't use if we've switched translators
}
if(dictionary_flags & FLAG_ALT2_TRANS)
{
// language specific
@@ -3505,9 +3549,9 @@ int LookupFlags(Translator *tr, const char *word)
{//==============================================
char buf[100];
static unsigned int flags[2];
char *word1 = (char *)word;
flags[0] = flags[1] = 0;
char *word1 = (char *)word;
LookupDictList(tr, &word1, buf, flags, 0, NULL);
return(flags[0]);
}
+13 -9
View File
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef NEED_GETOPT
#include <getopt.h>
#endif
@@ -67,7 +68,7 @@ static const char *help_text =
"\t Compile pronunciation rules and dictionary from the current\n"
"\t directory. <voice name> specifies the language\n"
"--ipa Write phonemes to stdout using International Phonetic Alphabet\n"
"\t --ipa=1 Use ties, --ipa=2 Use ZWJ\n"
"\t --ipa=1 Use ties, --ipa=2 Use ZWJ, --ipa=3 Separate with _\n"
"--path=\"<path>\"\n"
"\t Specifies the directory containing the espeak-data directory\n"
"--pho Write mbrola phoneme data (.pho) to stdout or to the file in --phonout\n"
@@ -221,14 +222,17 @@ int OpenWavFile(char *path, int rate)
if(path == NULL)
return(2);
if(path[0] == 0)
return(0);
if(strcmp(path,"stdout")==0)
f_wavfile = stdout;
else
f_wavfile = fopen(path,"wb");
while(isspace(*path)) path++;
f_wavfile = NULL;
if(path[0] != 0)
{
if(strcmp(path,"stdout")==0)
f_wavfile = stdout;
else
f_wavfile = fopen(path,"wb");
}
if(f_wavfile == NULL)
{
fprintf(stderr,"Can't write to: '%s'\n",path);
@@ -620,7 +624,7 @@ int main (int argc, char **argv)
{
value = -1;
sscanf(optarg2,"%d",&value);
if((value<0) || (value>2))
if((value<0) || (value>3))
{
fprintf(stderr,"Bad value for -ipa=\n");
value = 0;
+8 -1
View File
@@ -199,6 +199,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(MENU_OPT_SPEED, MyFrame::OnOptions)
EVT_MENU(MENU_OPT_PUNCT, MyFrame::OnOptions)
EVT_MENU(MENU_OPT_SPELL, MyFrame::OnOptions)
EVT_MENU(MENU_OPT_SPELL2, MyFrame::OnOptions)
EVT_MENU(MENU_PATH0, MyFrame::OnOptions)
EVT_MENU(MENU_PATH1, MyFrame::OnOptions)
EVT_MENU(MENU_PATH2, MyFrame::OnOptions)
@@ -625,6 +626,12 @@ void OnOptions2(int event_id)
break;
case MENU_OPT_SPELL:
transldlg->t_source->SetValue(_T("<say-as interpret-as=\"characters\">\n"));
transldlg->t_source->SetInsertionPointEnd();
notebook->SetSelection(1);
break;
case MENU_OPT_SPELL2:
transldlg->t_source->SetValue(_T("<say-as interpret-as=\"tts:char\">\n"));
transldlg->t_source->SetInsertionPointEnd();
notebook->SetSelection(1);
@@ -632,7 +639,7 @@ void OnOptions2(int event_id)
case MENU_PATH0:
string = wxFileSelector(_T("Master phonemes file"),wxFileName(path_phfile).GetPath(),
_T(""),_T(""),_T("*"),wxOPEN);
_T("phonemes"),_T(""),_T("*"),wxOPEN);
if(!string.IsEmpty())
{
path_phfile = string;
+88 -4
View File
@@ -1564,8 +1564,8 @@ void CountWordFreq(wxString path, wcount **hashtab)
for(k=0; k<ix; )
{
k += utf8_in(&wc,&buf[k]);
wc = towlower(wc); // convert to lower case
if(iswalpha(wc))
wc = towlower2(wc); // convert to lower case
if(iswalpha2(wc))
{
j += utf8_out(wc,&wbuf[j]);
n_chars++;
@@ -2272,6 +2272,82 @@ void Test2()
#endif
#define MAX_WALPHA 0x24f
void Make_walpha_tab()
{//===================
int ix;
int value;
int c;
short exceptions[40];
int ex = 0;
FILE *f;
f = fopen("/home/jsd1/walpha_tab.txt","w");
for(ix=0x80; ix<=MAX_WALPHA; ix++)
{
value = 0;
if(iswalpha(ix))
{
value = 0xfe; // no case
if(iswlower(ix))
{
value = 0xff;
}
else if(iswupper(ix))
{
c = towlower(ix);
if(c > 0)
value = c - ix;
if((value < 0) || (value > 0xfc))
{
exceptions[ex] = ix;
exceptions[ex+1] = c;
ex+=2;
value = 0xfd;
}
}
}
if(value > 0xfc)
fprintf(f," 0x%.2x,", value);
else
fprintf(f," %4d,", value);
if((ix % 16) == 15)
{
fprintf(f," // %.3x\n", ix & 0xfff0);
}
}
fprintf(f, "\nstatic const short wchar_tolower[] = {\n");
for(ix=0; ix<ex; ix+=2)
{
fprintf(f,"\t0x%.3x, 0x%.3x,\n", exceptions[ix], exceptions[ix+1]);
}
fprintf(f, "\t0,0 };\n");
fprintf(f, "\nstatic const short wchar_toupper[] = {\n");
for(ix=0x80; ix<=MAX_WALPHA; ix++)
{
if(iswlower(ix))
{
c = towupper(ix);
value = ix - c;
if((value != 32) && (value != 1))
{
fprintf(f,"\t0x%.3x, 0x%.3x,\n", ix, c);
}
}
}
fprintf(f, "\t0,0 };\n");
fclose(f);
}
const char* text1 = "Hello world. Testing.";
@@ -2290,6 +2366,7 @@ void TestTest(int control)
//CharsetToUnicode("ISO-8859-4");
//CharsetToUnicode("ISCII");
if(control==2)
{
return;
@@ -2319,9 +2396,16 @@ if(control==2)
espeak_SetSynthCallback(TestSynthCallback);
espeak_SetUriCallback(TestUriCallback);
espeak_SetVoiceByName("en");
voice.languages = "fr";
espeak_SetVoiceByProperties(&voice);
// espeak_SetVoiceByName("fr");
espeak_Synth("1", 5, 0, POS_CHARACTER, 0, espeakSSML|espeakCHARS_UTF8, &unique_identifier, (void *)user_data);
// voice.languages = "en";
// espeak_SetVoiceByProperties(&voice);
espeak_SetVoiceByName("de");
espeak_Synth(textbuf, strlen(textbuf)+1, 0, POS_CHARACTER, 0, espeakSSML|espeakCHARS_UTF8, &unique_identifier, (void *)user_data);
// espeak_Synth(text1, strlen(text1)+1, 0, POS_CHARACTER, 0, espeakSSML|espeakCHARS_UTF8, &unique_identifier, (void *)(user_data+1));
// espeak_Synth(text1, strlen(text1)+1, 0, POS_CHARACTER, 0, espeakSSML|espeakCHARS_UTF8, &unique_identifier, (void *)(user_data+1));
espeak_SetParameter(espeakPUNCTUATION, 1, 0);
espeak_Synchronize();
+1
View File
@@ -127,6 +127,7 @@ enum {
MENU_OPT_SPEED,
MENU_OPT_PUNCT,
MENU_OPT_SPELL,
MENU_OPT_SPELL2,
MENU_PATHS,
MENU_PATH0,
MENU_PATH1,
+4 -2
View File
@@ -119,8 +119,10 @@ wxMenuBar *MakeMenu(int type, const char *dict_name)
option_menu = new wxMenu;
option_menu->Append(MENU_PATHS, _("Set &paths"), paths_menu);
option_menu->Append(MENU_OPT_SPEED, _("Speed..."));
option_menu->Append(MENU_OPT_PUNCT, _("Speak punctiation"));
option_menu->Append(MENU_OPT_SPELL, _("Speak character names"));
option_menu->AppendSeparator();
option_menu->Append(MENU_OPT_PUNCT, _("Speak punctuation"));
option_menu->Append(MENU_OPT_SPELL, _("Speak characters"));
option_menu->Append(MENU_OPT_SPELL2, _("Speak character name"));
// TOOLS
vowelchart_menu = new wxMenu;
+148 -9
View File
@@ -582,7 +582,103 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b
} // end of LookupLetter
static const char *hex_letters[] = {"'e:j","b'i:","s'i:","d'i:","'i:","'Ef"}; // using phonemes available to all languages
// unicode ranges for non-ascii digits 0-9
static const int number_ranges[] = {
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)
const int *p;
int base;
for(p=number_ranges; (base = *p) != 0; p++)
{
if(letter < base)
break; // not found
if(letter < (base+10))
return(letter-base+'0');
}
return(-1);
}
#define L_SUB 0x4000 // subscript
#define L_SUP 0x8000 // superscript
static const char *modifiers[] = {NULL, "_sub", "_sup", NULL};
// this list must be in ascending order
static unsigned short derived_letters[] = {
0x00aa, 'a'+L_SUP,
0x00b2, '2'+L_SUP,
0x00b3, '3'+L_SUP,
0x00b9, '1'+L_SUP,
0x00ba, 'o'+L_SUP,
0x02b0, 'h'+L_SUP,
0x02b1, 0x266+L_SUP,
0x02b2, 'j'+L_SUP,
0x02b3, 'r'+L_SUP,
0x02b4, 0x279+L_SUP,
0x02b5, 0x27b+L_SUP,
0x02b6, 0x281+L_SUP,
0x02b7, 'w'+L_SUP,
0x02b8, 'y'+L_SUP,
0x02c0, 0x294+L_SUP,
0x02c1, 0x295+L_SUP,
0x02e0, 0x263+L_SUP,
0x02e1, 'l'+L_SUP,
0x02e2, 's'+L_SUP,
0x02e3, 'x'+L_SUP,
0x2070, '0'+L_SUP,
0x2071, 'i'+L_SUP,
0x2074, '4'+L_SUP,
0x2075, '5'+L_SUP,
0x2076, '6'+L_SUP,
0x2077, '7'+L_SUP,
0x2078, '8'+L_SUP,
0x2079, '9'+L_SUP,
0x207a, '+'+L_SUP,
0x207b, '-'+L_SUP,
0x207c, '='+L_SUP,
0x207d, '('+L_SUP,
0x207e, ')'+L_SUP,
0x207f, 'n'+L_SUP,
0x2080, '0'+L_SUB,
0x2081, '1'+L_SUB,
0x2082, '2'+L_SUB,
0x2083, '3'+L_SUB,
0x2084, '4'+L_SUB,
0x2085, '5'+L_SUB,
0x2086, '6'+L_SUB,
0x2087, '7'+L_SUB,
0x2088, '8'+L_SUB,
0x2089, '9'+L_SUB,
0x208a, '+'+L_SUB,
0x208b, '-'+L_SUB,
0x208c, '='+L_SUB,
0x208d, '('+L_SUB,
0x208e, ')'+L_SUB,
0x2090, 'a'+L_SUB,
0x2091, 'e'+L_SUB,
0x2092, 'o'+L_SUB,
0x2093, 'x'+L_SUB,
0x2094, 0x259+L_SUB,
0x2095, 'h'+L_SUB,
0x2096, 'k'+L_SUB,
0x2097, 'l'+L_SUB,
0x2098, 'm'+L_SUB,
0x2099, 'n'+L_SUB,
0x209a, 'p'+L_SUB,
0x209b, 's'+L_SUB,
0x209c, 't'+L_SUB,
0,0};
static const char *hex_letters[] = {"'e:j","b'i:","s'i:","d'i:","'i:","'ef"}; // names, using phonemes available to all languages
int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
{//=========================================================================
@@ -596,15 +692,18 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
int letter;
int len;
int ix;
int c;
char *p2;
char *pbuf;
const char *modifier;
ALPHABET *alphabet;
int al_offset;
int al_flags;
int language;
int number;
int phontab_1;
int speak_letter_number;
char capital[20];
char capital[30];
char ph_buf[80];
char ph_buf2[80];
char ph_alphabet[80];
@@ -626,21 +725,61 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
if(control & 2)
{
// include CAPITAL information
if(iswupper(letter))
if(iswupper2(letter))
{
Lookup(tr, "_cap", capital);
}
}
letter = towlower2(letter);
LookupLetter(tr, letter, word[n_bytes], ph_buf, control & 1);
if(ph_buf[0] == 0)
{
// is this a subscript or superscript letter ?
for(ix=0; (c = derived_letters[ix]) != 0; ix+=2)
{
if(c > letter)
break;
if(c == letter)
{
c = derived_letters[ix+1];
letter = c & 0x3fff;
if((modifier = modifiers[c >> 14]) != NULL)
{
Lookup(tr, modifier, capital);
if(capital[0] == 0)
{
capital[2] = SetTranslator2("en"); // overwrites previous contents of translator2
Lookup(translator2, modifier, &capital[3]);
if(capital[3] != 0)
{
capital[0] = phonPAUSE;
capital[1] = phonSWITCH;
len = strlen(&capital[3]);
capital[len+3] = phonSWITCH;
capital[len+4] = phontab_1;
capital[len+5] = 0;
}
}
}
}
}
LookupLetter(tr, letter, word[n_bytes], ph_buf, control & 1);
}
if(ph_buf[0] == phonSWITCH)
{
strcpy(phonemes,ph_buf);
return(0);
}
if((ph_buf[0] == 0) && ((number = NonAsciiNumber(letter)) > 0))
{
// convert a non-ascii number to 0-9
LookupLetter(tr, number, 0, ph_buf, control & 1);
}
al_offset = 0;
al_flags = 0;
if((alphabet = AlphabetFromChar(letter)) != NULL)
@@ -766,7 +905,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
speak_letter_number = 1;
if(!(al_flags & AL_NO_SYMBOL))
{
if(iswalpha(letter))
if(iswalpha2(letter))
Lookup(translator, "_?A", ph_buf);
if((ph_buf[0]==0) && !iswspace(letter))
@@ -784,8 +923,8 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
speak_letter_number = 0;
}
if((ph_alphabet[0] != 0) && speak_letter_number)
ph_buf[0] = 0; // don't speak "letter" if we speak alphabet name
// if((ph_alphabet[0] != 0) && speak_letter_number)
// ph_buf[0] = 0; // don't speak "letter" if we speak alphabet name
if(speak_letter_number)
{
@@ -2216,8 +2355,8 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
if((tr->langopts.numbers & NUM_NOPAUSE) && (next_char == ' '))
utf8_in(&next_char,p);
if(!iswalpha(next_char) && (thousands_exact==0))
// if(!iswalpha(next_char) && !((wtab[thousandplex].flags & FLAG_HYPHEN_AFTER) && (thousands_exact != 0)))
if(!iswalpha2(next_char) && (thousands_exact==0))
// if(!iswalpha2(next_char) && !((wtab[thousandplex].flags & FLAG_HYPHEN_AFTER) && (thousands_exact != 0)))
strcat(ph_out,str_pause); // don't add pause for 100s, 6th, etc.
}
+194 -59
View File
@@ -76,6 +76,8 @@ static int ssml_ignore_l_angle = 0;
// punctuations symbols that can end a clause
static const unsigned short punct_chars[] = {',','.','?','!',':',';',
0x00a1, // inverted exclamation
0x00bf, // inverted question
0x2013, // en-dash
0x2014, // em-dash
0x2026, // elipsis
@@ -124,6 +126,8 @@ static const unsigned short punct_chars[] = {',','.','?','!',':',';',
// bits 0-7 pause x 10mS, bits 12-14 intonation type, bit 15 don't need following space or bracket
static const unsigned int punct_attributes [] = { 0,
CLAUSE_COMMA, CLAUSE_PERIOD, CLAUSE_QUESTION, CLAUSE_EXCLAMATION, CLAUSE_COLON, CLAUSE_SEMICOLON,
CLAUSE_SEMICOLON | 0x8000, // inverted exclamation
CLAUSE_SEMICOLON | 0x8000, // inverted question
CLAUSE_SEMICOLON, // en-dash
CLAUSE_SEMICOLON, // em-dash
CLAUSE_SEMICOLON | PUNCT_SAY_NAME | 0x8000, // elipsis
@@ -214,50 +218,91 @@ const int param_defaults[N_SPEECH_PARAM] = {
0, // voice type
};
#ifdef NEED_WCHAR_FUNCTIONS
// additional Latin characters beyond the Latin1 character set
#define MAX_WALPHA 0x233
// indexed by character - 0x100
// 0=not alphabetic, 0xff=lower case, 0xfe=special case
// additional Latin characters beyond the ascii character set
#define MAX_WALPHA 0x24f
// indexed by character - 0x80
// 0=not alphabetic, 0xff=lower case, 0xfe=no case, 0xfd=use wchar_tolower
// other=value to add to upper case to convert to lower case
static unsigned char walpha_tab[MAX_WALPHA-0xff] = {
1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 100
1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 110
1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 120
0xfe,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, 1, // 130
0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, // 140
1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 150
1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 160
1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, // 170
0xff, 210, 1,0xff, 1,0xff, 206, 1,0xff, 205, 205, 1,0xff,0xff, 79, 202, // 180
203, 1,0xff, 205, 207,0xff, 211, 209, 1,0xff,0xff,0xff, 211, 213,0xff, 214, // 190
1,0xff, 1,0xff, 1,0xff, 218, 1,0xff, 218,0xff,0xff, 1,0xff, 218, 1, // 1a0
0xff, 217, 217, 1,0xff, 1,0xff, 219, 1,0xff,0xff,0xff, 1,0xff,0xff,0xff, // 1b0
0xff,0xff,0xff,0xff, 2, 1,0xff, 2, 1,0xff, 2, 1,0xff, 1,0xff, 1, // 1c0
0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, // 1d0
1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 1e0
0xff, 2, 1,0xff, 1,0xff,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 1f0
1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 200
1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 210
0xff, 0, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 220
1,0xff, 1,0xff }; // 230
static unsigned char walpha_tab[MAX_WALPHA-0x7f] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 080
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 090
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfe, 0, 0, 0, 0, 0, // 0a0
0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0xfe, 0, 0, 0, 0, 0, // 0b0
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 0c0
32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0xff, // 0d0
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 0e0
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 0f0
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 100
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 110
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 120
0xfd, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 0xfe, 1, 0xff, 1, 0xff, 1, 0xff, 1, // 130
0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 0xfe, 1, 0xff, 1, 0xff, 1, 0xff, // 140
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 150
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 160
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 0xfd, 1, 0xff, 1, 0xff, 1, 0xff, 0xff, // 170
0xff, 210, 1, 0xff, 1, 0xff, 206, 1, 0xff, 205, 205, 1, 0xff, 0xfe, 79, 202, // 180
203, 1, 0xff, 205, 207, 0xff, 211, 209, 1, 0xff, 0xff, 0xfe, 211, 213, 0xff, 214, // 190
1, 0xff, 1, 0xff, 1, 0xff, 218, 1, 0xff, 218, 0xfe, 0xfe, 1, 0xff, 218, 1, // 1a0
0xff, 217, 217, 1, 0xff, 1, 0xff, 219, 1, 0xff, 0xfe, 0xfe, 1, 0xff, 0xfe, 0xff, // 1b0
0xfe, 0xfe, 0xfe, 0xfe, 2, 0xff, 0xff, 2, 0xff, 0xff, 2, 0xff, 0xff, 1, 0xff, 1, // 1c0
0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 0xff, 1, 0xff, // 1d0
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 1e0
0xfe, 2, 0xff, 0xff, 1, 0xff, 0xfd, 0xfd, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 1f0
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 200
1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 210
0xfd, 0xfe, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, // 220
1, 0xff, 1, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 1, 0xff, 0xfd, 0xfd, 0xfe, // 230
0xfe, 1, 0xff, 0xfd, 69, 71, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff, 1, 0xff}; // 240
static const short wchar_tolower[] = {
0x130, 0x069,
0x178, 0x0ff,
0x1f6, 0x195,
0x1f7, 0x1bf,
0x220, 0x19e,
0x23a, 0x2c65,
0x23d, 0x19a,
0x23e, 0x2c66,
0x243, 0x180,
0,0 };
static const short wchar_toupper[] = {
0x0b5, 0x39c,
0x0df, 0x0df,
0x0ff, 0x178,
0x131, 0x049,
0x17f, 0x053,
0x180, 0x243,
0x195, 0x1f6,
0x19a, 0x23d,
0x19e, 0x220,
0x1bf, 0x1f7,
0x1c6, 0x1c4,
0x1c9, 0x1c7,
0x1cc, 0x1ca,
0x1dd, 0x18e,
0x1f3, 0x1f1,
0,0 };
#ifdef NEED_WCHAR_FUNCTIONS
// use ctype.h functions for Latin1 (character < 0x100)
int iswalpha(int c)
{
if(c < 0x100)
if(c < 0x80)
return(isalpha(c));
if((c > 0x3040) && (c <= 0xa700))
return(1); // japanese, chinese characters
if(c > MAX_WALPHA)
return(0);
return(walpha_tab[c-0x100]);
return(walpha_tab[c-0x80]);
}
int iswdigit(int c)
{
if(c < 0x100)
if(c < 0x80)
return(isdigit(c));
return(0);
}
@@ -272,50 +317,67 @@ int iswalnum(int c)
int towlower(int c)
{
int x;
if(c < 0x100)
int ix;
if(c < 0x80)
return(tolower(c));
if((c > MAX_WALPHA) || ((x = walpha_tab[c-0x100])==0xff))
return(c); // already lower case
if(x == 0xfe)
if((c > MAX_WALPHA) || ((x = walpha_tab[c-0x80]) >= 0xfe))
return(c);
if(x == 0xfd)
{
// special cases
if(c == 0x130) // uppercase i-dot
return('i');
// special cases, lookup translation table
for(ix=0; wchar_tolower[ix] != 0; ix+=2)
{
if(wchar_tolower[ix] == c)
return(wchar_tolower[ix+1]);
}
}
return(c + x); // convert to lower case
}
int towupper(int c)
{
// check whether the previous character code is the upper-case equivalent of this character
if(tolower(c-1) == c)
return(c-1); // yes, use it
int ix;
// check whether a previous character code is the upper-case equivalent of this character
if(towlower(c-32) == c)
return(c-32); // yes, use it
if(towlower(c-1) == c)
return(c-1);
for(ix=0; wchar_toupper[ix] != 0; ix+=2)
{
if(wchar_toupper[ix] == c)
return(wchar_toupper[ix+1]);
}
return(c); // no
}
int iswupper(int c)
{
int x;
if(c < 0x100)
if(c < 0x80)
return(isupper(c));
if(((c > MAX_WALPHA) || (x = walpha_tab[c-0x100])==0) || (x == 0xff))
if(((c > MAX_WALPHA) || (x = walpha_tab[c-0x80])==0) || (x == 0xff))
return(0);
return(1);
}
int iswlower(int c)
{
if(c < 0x100)
if(c < 0x80)
return(islower(c));
if((c > MAX_WALPHA) || (walpha_tab[c-0x100] != 0xff))
if((c > MAX_WALPHA) || (walpha_tab[c-0x80] != 0xff))
return(0);
return(1);
}
int iswspace(int c)
{
if(c < 0x100)
if(c < 0x80)
return(isspace(c));
if(c == 0xa0)
return(1);
return(0);
}
@@ -367,23 +429,96 @@ float wcstod(const wchar_t *str, wchar_t **tailptr)
}
#endif
// use internal data for iswalpha up to U+024F
// iswalpha() on Windows is unreliable (U+AA, U+BA).
int iswalpha2(int c)
{
if(c < 0x80)
return(isalpha(c));
if((c > 0x3040) && (c <= 0xa700))
return(1); // japanese, chinese characters
if(c > MAX_WALPHA)
return(iswalpha(c));
return(walpha_tab[c-0x80]);
}
int iswlower2(int c)
{
if(c < 0x80)
return(islower(c));
if(c > MAX_WALPHA)
return(iswlower(c));
if(walpha_tab[c-0x80] == 0xff)
return(1);
return(0);
}
int iswupper2(int c)
{
int x;
if(c < 0x80)
return(isupper(c));
if(c > MAX_WALPHA)
return(iswupper(c));
if(((x = walpha_tab[c-0x80]) > 0) && (x < 0xfe))
return(1);
return(0);
}
int towlower2(unsigned int c)
{
int x;
int ix;
// check for non-standard upper to lower case conversions
if(c == 'I')
{
if(translator->translator_name == L('t','r'))
if(translator->langopts.dotless_i)
{
c = 0x131; // I -> ı
}
}
#ifdef __WIN32__
if(c == 0x130) // uppercase i-dot
return('i');
#endif
return(towlower(c));
if(c < 0x80)
return(tolower(c));
if(c > MAX_WALPHA)
return(towlower(c));
if((x = walpha_tab[c-0x80]) >= 0xfe)
return(c); // this is not an upper case letter
if(x == 0xfd)
{
// special cases, lookup translation table
for(ix=0; wchar_tolower[ix] != 0; ix+=2)
{
if(wchar_tolower[ix] == (int)c)
return(wchar_tolower[ix+1]);
}
}
return(c + x); // convert to lower case
}
int towupper2(unsigned int c)
{
int ix;
if(c > MAX_WALPHA)
return(towupper(c));
// check whether a previous character code is the upper-case equivalent of this character
if(towlower2(c-32) == (int)c)
return(c-32); // yes, use it
if(towlower2(c-1) == (int)c)
return(c-1);
for(ix=0; wchar_toupper[ix] != 0; ix+=2)
{
if(wchar_toupper[ix] == (int)c)
return(wchar_toupper[ix+1]);
}
return(c); // no
}
static int IsRomanU(unsigned int c)
{//================================
@@ -2261,7 +2396,7 @@ f_input = f_in; // for GetC etc
c2 = ' ';
}
else
if((c2 == '/') || iswalpha(c2))
if((c2 == '/') || iswalpha2(c2))
{
// check for space in the output buffer for embedded commands produced by the SSML tag
if(ix > (n_buf - 20))
@@ -2444,10 +2579,10 @@ f_input = f_in; // for GetC etc
}
}
if(iswupper(c1))
if(iswupper2(c1))
{
tr->clause_upper_count++;
if((option_capitals == 2) && (sayas_mode == 0) && !iswupper(cprev))
if((option_capitals == 2) && (sayas_mode == 0) && !iswupper2(cprev))
{
char text_buf[40];
char text_buf2[30];
@@ -2464,7 +2599,7 @@ f_input = f_in; // for GetC etc
}
}
else
if(iswalpha(c1))
if(iswalpha2(c1))
tr->clause_lower_count++;
if(option_phoneme_input)
@@ -2533,8 +2668,8 @@ if(option_ssml) parag=1;
if(!iswspace(c1))
{
if(!IsAlpha(c1) || !iswlower(c1))
// if(iswdigit(c1) || (IsAlpha(c1) && !iswlower(c1)))
if(!IsAlpha(c1) || !iswlower2(c1))
// if(iswdigit(c1) || (IsAlpha(c1) && !iswlower2(c1)))
{
UngetC(c2);
ungot_char2 = c1;
@@ -2633,7 +2768,7 @@ if(option_ssml) parag=1;
if(nl_count==0)
{
if((c1 == ',') && (cprev == '.') && (tr->translator_name == L('h','u')) && iswdigit(cprev2) && (iswdigit(c_next) || (iswlower(c_next))))
if((c1 == ',') && (cprev == '.') && (tr->translator_name == L('h','u')) && iswdigit(cprev2) && (iswdigit(c_next) || (iswlower2(c_next))))
{
// lang=hu, fix for ordinal numbers, eg: "december 2., szerda", ignore ',' after ordinal number
c1 = CHAR_COMMA_BREAK;
@@ -2652,7 +2787,7 @@ if(option_ssml) parag=1;
}
else
{
if (iswlower(c_next) || (c_next=='-')) // hyphen is needed for lang-hu (eg. 2.-kal)
if (iswlower2(c_next) || (c_next=='-')) // hyphen is needed for lang-hu (eg. 2.-kal)
is_end_clause = 0; // only if followed by lower-case, (or if there is a XML tag)
}
}
@@ -2661,7 +2796,7 @@ if(option_ssml) parag=1;
{
is_end_clause = 0; // eg. u.s.a.'s
}
if(iswlower(c_next))
if(iswlower2(c_next))
{
// next word has no capital letter, this dot is probably from an abbreviation
// c1 = ' ';
+14 -7
View File
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef PLATFORM_DOS
#ifdef PLATFORM_WINDOWS
@@ -101,7 +102,7 @@ static const char *help_text =
"\t Compile pronunciation rules and dictionary from the current\n"
"\t directory. <voice name> specifies the language\n"
"--ipa Write phonemes to stdout using International Phonetic Alphabet\n"
"\t --ipa=1 Use ties, --ipa=2 Use ZWJ\n"
"\t --ipa=1 Use ties, --ipa=2 Use ZWJ, --ipa=3 Separate with _\n"
"--path=\"<path>\"\n"
"\t Specifies the directory containing the espeak-data directory\n"
"--pho Write mbrola phoneme data (.pho) to stdout or to the file in --phonout\n"
@@ -243,16 +244,22 @@ static int OpenWaveFile(const char *path, int rate)
if(path == NULL)
return(2);
if(strcmp(path,"stdout")==0)
while(isspace(*path)) path++;
f_wave = NULL;
if(path[0] != 0)
{
if(strcmp(path,"stdout")==0)
{
#ifdef PLATFORM_WINDOWS
// prevent Windows adding 0x0d before 0x0a bytes
_setmode(_fileno(stdout), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
#endif
f_wave = stdout;
f_wave = stdout;
}
else
f_wave = fopen(path,"wb");
}
else
f_wave = fopen(path,"wb");
if(f_wave != NULL)
{
@@ -739,7 +746,7 @@ int main (int argc, char **argv)
{
value = -1;
sscanf(optarg2,"%d",&value);
if((value<0) || (value>2))
if((value<0) || (value>3))
{
fprintf(stderr,"Bad value for -ipa=\n");
value = 0;
+11
View File
@@ -1164,6 +1164,17 @@ ESPEAK_API void espeak_SetPhonemeTrace(int value, FILE *stream)
} // end of espeak_SetPhonemes
ESPEAK_API void espeak_TextToPhonemes(const void *text, char *buffer, int size, int textmode, int phonememode)
{//==============================================================================================================
/* phoneme_mode bits 0-3: 0=only phoneme names, 1=ties, 2=ZWJ, 3=underscore separator
bits 4-7: 0=eSpeak phoneme names, 1=IPA
*/
option_multibyte = textmode & 7;
TranslateClause(translator, NULL, text, NULL, NULL);
GetTranslatedPhonemeString(buffer, size, phonememode);
}
ESPEAK_API void espeak_CompileDictionary(const char *path, FILE *log, int flags)
{//=============================================================================
ENTER("espeak_CompileDictionary");
+62 -29
View File
@@ -55,6 +55,9 @@ Revision 7 24.Dec.2011
Changed espeak_EVENT structure to add id.string[] for phoneme mnemonics.
Added espeakINITIALIZE_PHONEME_IPA option for espeak_Initialize() to report phonemes as IPA names.
Revision 8 26.Apr.2013
Added function espeak_TextToPhonemes().
*/
/********************/
/* Initialization */
@@ -94,7 +97,7 @@ typedef struct {
char string[8]; // used for phoneme names (UTF8). Terminated by a zero byte unless the name needs the full 8 bytes.
} id;
} espeak_EVENT;
/*
/*
When a message is supplied to espeak_synth, the request is buffered and espeak_synth returns. When the message is really processed, the callback function will be repetedly called.
@@ -102,16 +105,16 @@ typedef struct {
In PLAYBACK mode, the callback function is called as soon as an event happens.
For example suppose that the following message is supplied to espeak_Synth:
For example suppose that the following message is supplied to espeak_Synth:
"hello, hello."
* Once processed in RETRIEVAL mode, it could lead to 3 calls of the callback function :
** Block 1:
<audio data> +
<audio data> +
List of events: SENTENCE + WORD + LIST_TERMINATED
** Block 2:
<audio data> +
List of events: WORD + END + LIST_TERMINATED
@@ -148,11 +151,11 @@ typedef enum {
typedef enum {
/* PLAYBACK mode: plays the audio data, supplies events to the calling program*/
AUDIO_OUTPUT_PLAYBACK,
AUDIO_OUTPUT_PLAYBACK,
/* RETRIEVAL mode: supplies audio data and events to the calling program */
AUDIO_OUTPUT_RETRIEVAL,
/* SYNCHRONOUS mode: as RETRIEVAL but doesn't return until synthesis is completed */
AUDIO_OUTPUT_SYNCHRONOUS,
@@ -199,7 +202,7 @@ extern "C"
ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback* SynthCallback);
/* Must be called before any synthesis functions are called.
This specifies a function in the calling program which is called when a buffer of
speech sound data has been produced.
speech sound data has been produced.
The callback function is of the form:
@@ -288,7 +291,7 @@ ESPEAK_API espeak_ERROR espeak_Synth(const void *text,
start of the text.
position_type: Determines whether "position" is a number of characters, words, or sentences.
Values:
Values:
end_position: If set, this gives a character position at which speaking will stop. A value
of zero indicates no end position.
@@ -299,6 +302,7 @@ ESPEAK_API espeak_ERROR espeak_Synth(const void *text,
espeakCHARS_8BIT The 8 bit ISO-8859 character set for the particular language.
espeakCHARS_AUTO 8 bit or UTF8 (this is the default)
espeakCHARS_WCHAR Wide characters (wchar_t)
espeakCHARS_16BIT 16 bit characters.
espeakSSML Elements within < > are treated as SSML elements, or if not recognised are ignored.
@@ -307,13 +311,13 @@ ESPEAK_API espeak_ERROR espeak_Synth(const void *text,
espeakENDPAUSE If set then a sentence pause is added at the end of the text. If not set then
this pause is suppressed.
unique_identifier: message identifier; helpful for identifying later
unique_identifier: message identifier; helpful for identifying later
data supplied to the callback.
user_data: pointer which will be passed to the callback function.
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR.
*/
@@ -336,8 +340,8 @@ ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text,
For the other parameters, see espeak_Synth()
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR.
*/
@@ -350,8 +354,8 @@ ESPEAK_API espeak_ERROR espeak_Key(const char *key_name);
If key_name is a single character, it speaks the name of the character.
Otherwise, it speaks key_name as a text string.
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR.
*/
@@ -360,10 +364,10 @@ ESPEAK_API espeak_ERROR espeak_Key(const char *key_name);
extern "C"
#endif
ESPEAK_API espeak_ERROR espeak_Char(wchar_t character);
/* Speak the name of the given character
/* Speak the name of the given character
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR.
*/
@@ -420,7 +424,7 @@ ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int valu
espeakRANGE: pitch range, range 0-100. 0-monotone, 50=normal
espeakPUNCTUATION: which punctuation characters to announce:
value in espeak_PUNCT_TYPE (none, all, some),
value in espeak_PUNCT_TYPE (none, all, some),
see espeak_GetParameter() to specify which characters are announced.
espeakCAPITALS: announce capital letters by:
@@ -432,8 +436,8 @@ ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int valu
espeakWORDGAP: pause between words, units of 10mS (at the default speed)
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR.
*/
@@ -455,8 +459,8 @@ ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist);
punctlist: A list of character codes, terminated by a zero character.
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR.
*/
@@ -474,6 +478,35 @@ ESPEAK_API void espeak_SetPhonemeTrace(int value, FILE *stream);
stream output stream for the phoneme symbols (and trace). If stream=NULL then it uses stdout.
*/
#ifdef __cplusplus
extern "C"
#endif
ESPEAK_API void espeak_TextToPhonemes(const void *text, char *buffer, int size, int textmode, int phonememode);
/* Translates text into phonemes. Call espeak_SetVoiceByName() first, to select a language.
text: The text to translate, terminated by a zero character.
buffer: Output buffer for the phoneme translation.
size: Size of the output buffer in bytes.
textmode: Type of character codes, one of:
espeakCHARS_UTF8 UTF8 encoding
espeakCHARS_8BIT The 8 bit ISO-8859 character set for the particular language.
espeakCHARS_AUTO 8 bit or UTF8 (this is the default)
espeakCHARS_WCHAR Wide characters (wchar_t)
espeakCHARS_16BIT 16 bit characters.
phonememode: bits0-3:
0= just phonemes.
1= include ties (U+361) for phoneme names of more than one letter.
2= include zero-width-joiner for phoneme names of more than one letter.
3= separate phonemes with underscore characters.
bits 4-7:
0= eSpeak's ascii phoneme names.
1= International Phonetic Alphabet (as UTF-8 characters).
*/
#ifdef __cplusplus
extern "C"
#endif
@@ -501,7 +534,7 @@ typedef struct {
unsigned char gender; // 0=none 1=male, 2=female,
unsigned char age; // 0=not specified, or age in years
unsigned char variant; // only used when passed as a parameter to espeak_SetVoiceByProperties
unsigned char xx1; // for internal use
unsigned char xx1; // for internal use
int score; // for internal use
void *spare; // for internal use
} espeak_VOICE;
@@ -546,8 +579,8 @@ ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name);
/* Searches for a voice with a matching "name" field. Language is not considered.
"name" is a UTF8 string.
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR.
*/
@@ -588,7 +621,7 @@ ESPEAK_API espeak_ERROR espeak_Cancel(void);
function returns, the audio output is fully stopped and the synthesizer is ready to
synthesize a new message.
Return: EE_OK: operation achieved
Return: EE_OK: operation achieved
EE_INTERNAL_ERROR.
*/
@@ -605,7 +638,7 @@ extern "C"
#endif
ESPEAK_API espeak_ERROR espeak_Synchronize(void);
/* This function returns when all data have been spoken.
Return: EE_OK: operation achieved
Return: EE_OK: operation achieved
EE_INTERNAL_ERROR.
*/
@@ -614,7 +647,7 @@ extern "C"
#endif
ESPEAK_API espeak_ERROR espeak_Terminate(void);
/* last function to be called.
Return: EE_OK: operation achieved
Return: EE_OK: operation achieved
EE_INTERNAL_ERROR.
*/
+1 -1
View File
@@ -35,7 +35,7 @@
#include "translate.h"
#include "wave.h"
const char *version_string = "1.47.04 02.Apr.13";
const char *version_string = "1.47.08 26.Apr.13";
const int version_phdata = 0x014701;
int option_device_number = -1;
+3 -9
View File
@@ -1953,20 +1953,14 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control)
if((option_phonemes > 0) || (phoneme_callback != NULL))
{
int use_ipa = 0;
int phoneme_mode = 0;
if(option_phonemes >= 3)
use_ipa = option_phonemes-2; // 1=ipa, 2=ipa with tie, 3=ipa with ZWJ
phoneme_mode = 0x10 + option_phonemes-3; // 0x10=ipa, 0x11=ipa with tie, 0x12=ipa with ZWJ, 0x13=ipa with separators
GetTranslatedPhonemeString(translator->phon_out, sizeof(translator->phon_out), use_ipa);
GetTranslatedPhonemeString(translator->phon_out, sizeof(translator->phon_out), phoneme_mode);
if(option_phonemes > 0)
{
fprintf(f_trans,"%s\n",translator->phon_out);
if(!iswalpha(0x010d))
{
// check that c-caron is recognized as an alphabetic character
fprintf(stderr,"Warning: Accented letters are not recognized, eg: U+010D\nSet LC_CTYPE to a UTF-8 locale\n");
}
}
if(phoneme_callback != NULL)
{
+5 -5
View File
@@ -192,23 +192,23 @@ 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 char phcode;
unsigned char stresslevel;
unsigned char wordstress;
unsigned char tone_ph; // tone phoneme to use with this vowel
unsigned short synthflags;
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 tone_ph; // tone phoneme to use with this vowel
} PHONEME_LIST2;
typedef struct {
// 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 tone_ph; // tone phoneme to use with this vowel
unsigned short synthflags;
unsigned short sourceix; // ix into the original source text string, only set at the start of a word
PHONEME_TAB *ph;
short length; // length_mod
+4 -1
View File
@@ -844,6 +844,7 @@ Translator *SelectTranslator(const char *name)
tr->langopts.stress_rule = STRESSPOSN_1L;
tr->langopts.numbers = 1;
tr->langopts.accents = 2; // 'capital' after letter name
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 3; // don't count apostrophe
}
break;
@@ -971,7 +972,7 @@ SetLengthMods(tr,3); // all equal
SetLetterBits(tr,LETTERGP_VOWEL2,hy_vowels);
SetLetterBits(tr,LETTERGP_C,hy_consonants);
tr->langopts.max_initial_consonants = 6;
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED;
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED;
// tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
}
break;
@@ -1289,6 +1290,7 @@ SetLengthMods(tr,3); // all equal
ResetLetterBits(tr,0x2);
SetLetterBits(tr,1,"bcdfgjkmnpqstvxz"); // B hard consonants, excluding h,l,r,w,y
tr->langopts.param[LOPT_ALT] = 2; // call ApplySpecialAttributes2() if a word has $alt or $alt2
tr->langopts.accents = 2; // 'capital' after letter name
}
break;
@@ -1520,6 +1522,7 @@ SetLengthMods(tr,3); // all equal
tr->langopts.stress_rule = 7; // stress on the last syllable, before any explicitly unstressed syllable
tr->langopts.stress_flags = S_NO_AUTO_2; //no automatic secondary stress
tr->langopts.dotless_i = 1;
tr->langopts.param[LOPT_SUFFIX] = 1;
if(name2 == L('a','z'))
+20 -17
View File
@@ -388,9 +388,12 @@ int IsAlpha(unsigned int c)
0
};
if(iswalpha(c))
if(iswalpha2(c))
return(1);
if(c < 0x300)
return(0);
if((c >= 0x901) && (c <= 0xdf7))
{
// Indic scripts: Devanagari, Tamil, etc
@@ -625,7 +628,7 @@ int IsAllUpper(const char *word)
while((*word != 0) && !isspace2(*word))
{
word += utf8_in(&c, word);
if(!iswupper(c))
if(!iswupper2(c))
return(0);
}
return(1);
@@ -1054,7 +1057,7 @@ int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wt
}
}
if((wflags & FLAG_ALL_UPPER) && (word_length > 1)&& iswalpha(first_char))
if((wflags & FLAG_ALL_UPPER) && (word_length > 1)&& iswalpha2(first_char))
{
if((option_tone_flags & OPTION_EMPHASIZE_ALLCAPS) && !(dictionary_flags[0] & FLAG_ABBREV))
{
@@ -1633,7 +1636,7 @@ if(end_type & SUFX_UNPRON)
tr->expect_past--;
}
if((word_length == 1) && (tr->translator_name == L('e','n')) && iswalpha(first_char) && (first_char != 'i'))
if((word_length == 1) && (tr->translator_name == L('e','n')) && iswalpha2(first_char) && (first_char != 'i'))
{
// English Specific !!!!
// any single letter before a dot is an abbreviation, except 'I'
@@ -1909,7 +1912,7 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
while(*p2 != ' ') p2++;
utf8_in(&c_word2, p2+1); // first character of the next word;
if(!iswalpha(c_word2))
if(!iswalpha2(c_word2))
{
ok =0;
}
@@ -2377,9 +2380,9 @@ static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in,
// there is a list of character codes to be substituted with alternative codes
if(iswupper(c_lower = c))
if(iswupper2(c_lower = c))
{
c_lower = towlower(c);
c_lower = towlower2(c);
upper_case = 1;
}
@@ -2393,7 +2396,7 @@ static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in,
new_c = replace_chars[ix+1];
break;
}
if((word >> 16) == (unsigned int)towlower(next_in))
if((word >> 16) == (unsigned int)towlower2(next_in))
{
new_c = replace_chars[ix+1];
ignore_next = 1;
@@ -2410,14 +2413,14 @@ static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in,
// there is a second character to be inserted
// don't convert the case of the second character unless the next letter is also upper case
c2 = new_c >> 16;
if(upper_case && iswupper(next_in))
c2 = towupper(c2);
if(upper_case && iswupper2(next_in))
c2 = towupper2(c2);
*insert = c2;
new_c &= 0xffff;
}
if(upper_case)
new_c = towupper(new_c);
new_c = towupper2(new_c);
*wordflags |= FLAG_CHAR_REPLACED;
return(new_c);
@@ -2481,7 +2484,7 @@ static int TranslateChar(Translator *tr, char *ptr, int prev_in, unsigned int c,
// look for 'n and replace by a special character (unicode: schwa)
if(!iswalpha(prev_in))
if(!iswalpha2(prev_in))
{
utf8_in(&next2, &ptr[1]);
@@ -2911,7 +2914,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
}
else
{
if(iswupper(c))
if(iswupper2(c))
word_flags |= FLAG_FIRST_UPPER;
if((prev_out == ' ') && iswdigit(sbuf[ix-2]) && !iswdigit(prev_in))
@@ -2940,7 +2943,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
}
}
if(iswupper(c))
if(iswupper2(c))
{
c = towlower2(c);
@@ -2955,13 +2958,13 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
}
else
{
if((iswlower(prev_in)) && (prev_in != 0xba)) // Windows thinks masc.ordinal (0xba) is lower-case
if(iswlower2(prev_in))
{
// lower case followed by upper case in a word
if(UpperCaseInWord(tr, &sbuf[ix], c) == 1)
{
// convert to lower case and continue
c = towlower(c);
c = towlower2(c);
}
else
{
@@ -2971,7 +2974,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
// next_word_flags |= FLAG_NOSPACE; // problem: prevents FLAG_HAS_DOT being set
}
}
else if((c != ' ') && iswupper(prev_in) && iswlower(next_in))
else if((c != ' ') && iswupper2(prev_in) && iswlower2(next_in))
{
int next2_in;
utf8_in(&next2_in,&source[source_index + next_in_nbytes]);
+9 -3
View File
@@ -81,8 +81,9 @@
#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_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
@@ -247,9 +248,9 @@ typedef struct {
typedef struct{
unsigned int flags;
unsigned short start;
unsigned short sourceix;
unsigned char pre_pause;
unsigned char wmark;
unsigned short sourceix;
unsigned char length;
} WORD_TAB;
@@ -542,6 +543,7 @@ typedef struct {
char tone_numbers;
char ideographs; // treat as separate words
char textmode; // the meaning of FLAG_TEXTMODE is reversed (to save data when *_list file is compiled)
char dotless_i; // uses letter U+0131
int testing; // testing options: bit 1= specify stressed syllable in the form: "outdoor/2"
int listx; // compile *_listx after *list
const unsigned int *replace_chars; // characters to be substitutes
@@ -713,9 +715,13 @@ int IsDigit(unsigned int c);
int IsDigit09(unsigned int c);
int IsAlpha(unsigned int c);
int IsVowel(Translator *tr, int c);
int iswalpha2(int c);
int isspace2(unsigned int c);
int iswlower2(int c);
int iswupper2(int c);
int towlower2(unsigned int c);
void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa);
int towupper2(unsigned int c);
void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int phoneme_mode);
const char *WordToString2(unsigned int word);
ALPHABET *AlphabetFromChar(int c);
ALPHABET *AlphabetFromName(const char *name);
+1 -1
View File
@@ -460,7 +460,7 @@ void TranslDlg::OnCommand(wxCommandEvent& event)
t_phonetic->SetDefaultStyle(style_phonetic_large);
translate_text = 3;
use_ipa = 1;
use_ipa = 0x10;
break;
case T_PROCESS:
+1
View File
@@ -21,6 +21,7 @@
typedef struct {
char v_name[40];
char language_name[20];
int phoneme_tab_ix; // phoneme table number
int pitch_base; // Hz<<12
+8 -5
View File
@@ -422,7 +422,7 @@ void VoiceReset(int tone_only)
voice->n_harmonic_peaks = 5;
voice->peak_shape = 0;
voice->voicing = 64;
voice->consonant_amp = 90; // change to 85 for v.1.47 was 100
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));
@@ -540,7 +540,7 @@ static unsigned int StringToWord2(const char *string)
int c;
unsigned int value = 0;
for(ix=0; (ix<4) & ((c = string[ix]) != 0); ix++)
for(ix=0; (ix<4) && ((c = string[ix]) != 0); ix++)
{
value = (value << 8) | (c & 0xff);
}
@@ -602,7 +602,7 @@ voice_t *LoadVoice(const char *vname, int control)
// which directory to look for a named voice. List of voice names, must end in a space.
static const char *voices_asia =
"bn fa fa-pin hi hy hy-west id ka kn ku ml ms ne pa ta te tr vi vi-hue zh zh-yue ";
"az bn fa fa-pin hi hy hy-west id ka kn ku ml ms ne pa ta te tr vi vi-hue vi-sgn zh zh-yue ";
static const char *voices_europe =
"an bg bs ca cs cy da de el en en-us es et fi fr fr-be ga hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";
@@ -751,6 +751,7 @@ voice_t *LoadVoice(const char *vname, int control)
new_translator = SelectTranslator(translator_name);
langopts = &new_translator->langopts;
strncpy0(voice->language_name, language_name, sizeof(voice->language_name));
}
}
break;
@@ -1829,6 +1830,7 @@ espeak_ERROR SetVoiceByName(const char *name)
}
DoVoiceChange(voice);
voice_selector.languages = voice->language_name;
SetVoiceStack(&voice_selector, variant_name);
return(EE_OK);
}
@@ -1845,6 +1847,7 @@ espeak_ERROR SetVoiceByName(const char *name)
LoadVoice(variant_name,2);
}
DoVoiceChange(voice);
voice_selector.languages = voice->language_name;
SetVoiceStack(&voice_selector, variant_name);
return(EE_OK);
}
@@ -1895,8 +1898,8 @@ void FreeVoiceList()
ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec)
{//========================================================================
char path_voices[sizeof(path_home)+12];
#ifdef PLATFORM_RISCOS
if(n_voices_list == 0)
{