mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-14 17:47:19 +00:00
[1.46.45]
Indian languages, rename aspirated phonemes with # instead of h (eg. [t#] not [th]). git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@311 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
+96
-106
@@ -67,7 +67,8 @@ MNEM_TAB mnem_rules[] = {
|
||||
{"p_alt5", 0x25},
|
||||
{"p_alt6", 0x26},
|
||||
{"p_alt", 0x21},
|
||||
{NULL, -1} };
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
MNEM_TAB mnem_flags[] = {
|
||||
// these in the first group put a value in bits0-3 of dictionary_flags
|
||||
@@ -182,13 +183,13 @@ const char *LookupMnemName(MNEM_TAB *table, const int value)
|
||||
//==========================================================
|
||||
/* Lookup a mnemonic string in a table, return its name */
|
||||
{
|
||||
while(table->mnem != NULL)
|
||||
{
|
||||
if(table->value==value)
|
||||
return(table->mnem);
|
||||
table++;
|
||||
}
|
||||
return(""); /* not found */
|
||||
while(table->mnem != NULL)
|
||||
{
|
||||
if(table->value==value)
|
||||
return(table->mnem);
|
||||
table++;
|
||||
}
|
||||
return(""); /* not found */
|
||||
} /* end of LookupMnemValue */
|
||||
|
||||
|
||||
@@ -200,27 +201,27 @@ void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len)
|
||||
int len;
|
||||
int total = 0;
|
||||
|
||||
buf[0] = 0;
|
||||
buf[0] = 0;
|
||||
if((stress = flags[0] & 0xf) != 0)
|
||||
{
|
||||
sprintf(buf, "%s", LookupMnemName(mnem_flags, stress + 0x40));
|
||||
total = strlen(buf);
|
||||
buf += total;
|
||||
sprintf(buf, "%s", LookupMnemName(mnem_flags, stress + 0x40));
|
||||
total = strlen(buf);
|
||||
buf += total;
|
||||
}
|
||||
|
||||
for(ix=8; ix<64; ix++)
|
||||
{
|
||||
if(((ix < 30) && (flags[0] & (1 << ix))) || ((ix >= 0x20) && (flags[1] & (1 << (ix-0x20)))))
|
||||
{
|
||||
name = LookupMnemName(mnem_flags, ix);
|
||||
len = strlen(name) + 1;
|
||||
total += len;
|
||||
if(total >= buf_len)
|
||||
continue;
|
||||
sprintf(buf, " %s", name);
|
||||
buf += len;
|
||||
}
|
||||
}
|
||||
for(ix=8; ix<64; ix++)
|
||||
{
|
||||
if(((ix < 30) && (flags[0] & (1 << ix))) || ((ix >= 0x20) && (flags[1] & (1 << (ix-0x20)))))
|
||||
{
|
||||
name = LookupMnemName(mnem_flags, ix);
|
||||
len = strlen(name) + 1;
|
||||
total += len;
|
||||
if(total >= buf_len)
|
||||
continue;
|
||||
sprintf(buf, " %s", name);
|
||||
buf += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -228,12 +229,12 @@ void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len)
|
||||
|
||||
char *DecodeRule(const char *group_chars, int group_length, char *rule, int control)
|
||||
{//=================================================================================
|
||||
/* Convert compiled match template to ascii */
|
||||
/* Convert compiled match template to ascii */
|
||||
|
||||
unsigned char rb;
|
||||
unsigned char rb;
|
||||
unsigned char c;
|
||||
char *p;
|
||||
int ix;
|
||||
int ix;
|
||||
int match_type;
|
||||
int finished=0;
|
||||
int value;
|
||||
@@ -243,18 +244,20 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
|
||||
int condition_num=0;
|
||||
int at_start = 0;
|
||||
const char *name;
|
||||
char buf[60];
|
||||
char buf_pre[60];
|
||||
char buf[60];
|
||||
char buf_pre[60];
|
||||
char suffix[20];
|
||||
static char output[60];
|
||||
|
||||
static char symbols[] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
|
||||
'&','%','+','#','S','D','Z','A','L','!',' ','@','?','J','N','K','V','?','T','X','?','W'};
|
||||
static char symbols[] =
|
||||
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
|
||||
'&','%','+','#','S','D','Z','A','L','!',' ','@','?','J','N','K','V','?','T','X','?','W'
|
||||
};
|
||||
|
||||
static char symbols_lg[] = {'A','B','C','H','F','G','Y'};
|
||||
|
||||
match_type = 0;
|
||||
buf_pre[0] = 0;
|
||||
buf_pre[0] = 0;
|
||||
|
||||
for(ix=0; ix<group_length; ix++)
|
||||
{
|
||||
@@ -263,8 +266,8 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
|
||||
buf[ix] = 0;
|
||||
|
||||
p = &buf[strlen(buf)];
|
||||
while(!finished)
|
||||
{
|
||||
while(!finished)
|
||||
{
|
||||
rb = *rule++;
|
||||
|
||||
if(rb <= RULE_LINENUM)
|
||||
@@ -315,8 +318,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
|
||||
}
|
||||
c = ' ';
|
||||
}
|
||||
else
|
||||
if(rb == RULE_ENDING)
|
||||
else if(rb == RULE_ENDING)
|
||||
{
|
||||
static const char *flag_chars = "eipvdfq tba ";
|
||||
flags = ((rule[0] & 0x7f)<< 8) + (rule[1] & 0x7f);
|
||||
@@ -325,7 +327,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
|
||||
suffix_char = 'P';
|
||||
sprintf(suffix,"%c%d",suffix_char,rule[2] & 0x7f);
|
||||
rule += 3;
|
||||
for(ix=0;ix<9;ix++)
|
||||
for(ix=0; ix<9; ix++)
|
||||
{
|
||||
if(flags & 1)
|
||||
sprintf(&suffix[strlen(suffix)],"%c",flag_chars[ix]);
|
||||
@@ -335,13 +337,11 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
|
||||
p += strlen(suffix);
|
||||
c = ' ';
|
||||
}
|
||||
else
|
||||
if(rb == RULE_LETTERGP)
|
||||
else if(rb == RULE_LETTERGP)
|
||||
{
|
||||
c = symbols_lg[*rule++ - 'A'];
|
||||
}
|
||||
else
|
||||
if(rb == RULE_LETTERGP2)
|
||||
else if(rb == RULE_LETTERGP2)
|
||||
{
|
||||
value = *rule++ - 'A';
|
||||
p[0] = 'L';
|
||||
@@ -355,11 +355,9 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
|
||||
}
|
||||
p+=2;
|
||||
}
|
||||
else
|
||||
if(rb <= RULE_LAST_RULE)
|
||||
else if(rb <= RULE_LAST_RULE)
|
||||
c = symbols[rb];
|
||||
else
|
||||
if(rb == RULE_SPACE)
|
||||
else if(rb == RULE_SPACE)
|
||||
c = '_';
|
||||
else
|
||||
c = rb;
|
||||
@@ -393,7 +391,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
|
||||
while(ix < 8)
|
||||
output[ix++]=' ';
|
||||
output[ix]=0;
|
||||
return(output);
|
||||
return(output);
|
||||
} /* end of DecodeRule */
|
||||
|
||||
|
||||
@@ -427,7 +425,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash)
|
||||
unsigned char flag_codes[100];
|
||||
char encoded_ph[200];
|
||||
unsigned char bad_phoneme[4];
|
||||
static char nullstring[] = {0};
|
||||
static char nullstring[] = {0};
|
||||
|
||||
text_not_phonemes = 0;
|
||||
phonetic = word = nullstring;
|
||||
@@ -500,13 +498,11 @@ static char nullstring[] = {0};
|
||||
{
|
||||
text_mode = 1;
|
||||
}
|
||||
else
|
||||
if(flagnum == 201)
|
||||
else if(flagnum == 201)
|
||||
{
|
||||
text_mode = 0;
|
||||
}
|
||||
else
|
||||
if(flagnum == BITNUM_FLAG_TEXTMODE)
|
||||
else if(flagnum == BITNUM_FLAG_TEXTMODE)
|
||||
{
|
||||
text_not_phonemes = 1;
|
||||
}
|
||||
@@ -536,8 +532,7 @@ static char nullstring[] = {0};
|
||||
word = p+1;
|
||||
step = 1;
|
||||
}
|
||||
else
|
||||
if(!isspace2(c))
|
||||
else if(!isspace2(c))
|
||||
{
|
||||
word = p;
|
||||
step = 1;
|
||||
@@ -571,8 +566,7 @@ static char nullstring[] = {0};
|
||||
step = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(c == ')')
|
||||
else if(c == ')')
|
||||
{
|
||||
if(multiple_words)
|
||||
{
|
||||
@@ -580,8 +574,7 @@ static char nullstring[] = {0};
|
||||
multiple_words = 0;
|
||||
step = 3;
|
||||
}
|
||||
else
|
||||
if(word[0] != '_')
|
||||
else if(word[0] != '_')
|
||||
{
|
||||
fprintf(f_log, "%5d: Missing '('\n", linenum);
|
||||
error_count++;
|
||||
@@ -595,8 +588,7 @@ static char nullstring[] = {0};
|
||||
{
|
||||
multiple_words++;
|
||||
}
|
||||
else
|
||||
if(c == ')')
|
||||
else if(c == ')')
|
||||
{
|
||||
p[0] = ' '; // terminate extra string
|
||||
multiple_string_end = p+1;
|
||||
@@ -641,8 +633,8 @@ static char nullstring[] = {0};
|
||||
// This is a special word, used by eSpeak. Translate this into phonemes now
|
||||
strcat(phonetic, " "); // need a space to indicate word-boundary
|
||||
|
||||
// PROBLEM vowel reductions are not applied to the translated phonemes
|
||||
// condition rules are not applied
|
||||
// PROBLEM vowel reductions are not applied to the translated phonemes
|
||||
// condition rules are not applied
|
||||
TranslateWord(translator,phonetic,0,NULL,NULL);
|
||||
text_not_phonemes = 0;
|
||||
strncpy0(encoded_ph, word_phonemes, N_WORD_BYTES-4);
|
||||
@@ -653,11 +645,11 @@ static char nullstring[] = {0};
|
||||
error_need_dictionary++;
|
||||
fprintf(f_log,"%5d: Need to compile dictionary again\n",linenum);
|
||||
}
|
||||
{
|
||||
{
|
||||
//char decoded_phonemes[128];
|
||||
//DecodePhonemes(word_phonemes,decoded_phonemes);
|
||||
//printf("Translator %x %s [%s] [%s]\n",translator->translator_name,word,phonetic,decoded_phonemes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -694,8 +686,7 @@ static char nullstring[] = {0};
|
||||
ix = utf8_out(wc, word);
|
||||
word[ix] = 0;
|
||||
}
|
||||
else
|
||||
if(word[0] != '_')
|
||||
else if(word[0] != '_')
|
||||
{
|
||||
// convert to lower case, and note if the word is all-capitals
|
||||
int c2;
|
||||
@@ -1082,8 +1073,7 @@ static void copy_rule_string(char *string, int &state)
|
||||
fprintf(f_log,"%5d: Expected 2 digits after 'L'\n",linenum);
|
||||
error_count++;
|
||||
}
|
||||
else
|
||||
if((c <= 0) || (c >= N_LETTER_GROUPS) || (letterGroupsDefined[(int)c] == 0))
|
||||
else if((c <= 0) || (c >= N_LETTER_GROUPS) || (letterGroupsDefined[(int)c] == 0))
|
||||
{
|
||||
fprintf(f_log,"%5d: Letter group L%.2d not defined\n",linenum,c);
|
||||
error_count++;
|
||||
@@ -1162,9 +1152,9 @@ static void copy_rule_string(char *string, int &state)
|
||||
case 'a':
|
||||
sxflags |= SUFX_A;
|
||||
break;
|
||||
case 'm':
|
||||
sxflags |= SUFX_M;
|
||||
break;
|
||||
case 'm':
|
||||
sxflags |= SUFX_M;
|
||||
break;
|
||||
default:
|
||||
if(isdigit(c))
|
||||
value = (value*10) + (c - '0');
|
||||
@@ -1376,11 +1366,11 @@ int __cdecl string_sorter(char **a, char **b)
|
||||
char *pa, *pb;
|
||||
int ix;
|
||||
|
||||
if((ix = strcmp(pa = *a,pb = *b)) != 0)
|
||||
return(ix);
|
||||
if((ix = strcmp(pa = *a,pb = *b)) != 0)
|
||||
return(ix);
|
||||
pa += (strlen(pa)+1);
|
||||
pb += (strlen(pb)+1);
|
||||
return(strcmp(pa,pb));
|
||||
return(strcmp(pa,pb));
|
||||
} /* end of string_sorter */
|
||||
|
||||
|
||||
@@ -1471,12 +1461,12 @@ static void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name)
|
||||
if(rule_pre[0] != 0)
|
||||
{
|
||||
p = buf;
|
||||
for(ix=strlen(rule_pre)-1;ix>=0;ix--)
|
||||
for(ix=strlen(rule_pre)-1; ix>=0; ix--)
|
||||
*p++ = rule_pre[ix];
|
||||
sprintf(p,") ");
|
||||
spaces -= strlen(buf);
|
||||
for(ix=0; ix<spaces; ix++)
|
||||
fputc(' ',f_out);
|
||||
fputc(' ',f_out);
|
||||
fprintf(f_out,"%s",buf);
|
||||
spaces = 0;
|
||||
}
|
||||
@@ -1580,7 +1570,7 @@ static int compile_lettergroup(char *input, FILE *f_out)
|
||||
int length;
|
||||
int max_length = 0;
|
||||
|
||||
#define N_LETTERGP_ITEMS 200
|
||||
#define N_LETTERGP_ITEMS 200
|
||||
char *items[N_LETTERGP_ITEMS];
|
||||
char item_length[N_LETTERGP_ITEMS];
|
||||
|
||||
@@ -1797,37 +1787,37 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
|
||||
break;
|
||||
|
||||
case 2: // .replace
|
||||
{
|
||||
int replace1;
|
||||
int replace2;
|
||||
char *p;
|
||||
{
|
||||
int replace1;
|
||||
int replace2;
|
||||
char *p;
|
||||
|
||||
p = buf;
|
||||
replace1 = 0;
|
||||
replace2 = 0;
|
||||
while(isspace2(*p)) p++;
|
||||
ix = 0;
|
||||
while((unsigned char)(*p) > 0x20) // not space or zero-byte
|
||||
{
|
||||
p += utf8_in(&c,p);
|
||||
replace1 += (c << ix);
|
||||
ix += 16;
|
||||
}
|
||||
while(isspace2(*p)) p++;
|
||||
ix = 0;
|
||||
while((unsigned char)(*p) > 0x20)
|
||||
{
|
||||
p += utf8_in(&c,p);
|
||||
replace2 += (c << ix);
|
||||
ix += 16;
|
||||
}
|
||||
if(replace1 != 0)
|
||||
{
|
||||
Write4Bytes(f_out,replace1); // write as little-endian
|
||||
Write4Bytes(f_out,replace2); // if big-endian, reverse the bytes in LoadDictionary()
|
||||
}
|
||||
p = buf;
|
||||
replace1 = 0;
|
||||
replace2 = 0;
|
||||
while(isspace2(*p)) p++;
|
||||
ix = 0;
|
||||
while((unsigned char)(*p) > 0x20) // not space or zero-byte
|
||||
{
|
||||
p += utf8_in(&c,p);
|
||||
replace1 += (c << ix);
|
||||
ix += 16;
|
||||
}
|
||||
break;
|
||||
while(isspace2(*p)) p++;
|
||||
ix = 0;
|
||||
while((unsigned char)(*p) > 0x20)
|
||||
{
|
||||
p += utf8_in(&c,p);
|
||||
replace2 += (c << ix);
|
||||
ix += 16;
|
||||
}
|
||||
if(replace1 != 0)
|
||||
{
|
||||
Write4Bytes(f_out,replace1); // write as little-endian
|
||||
Write4Bytes(f_out,replace2); // if big-endian, reverse the bytes in LoadDictionary()
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f_temp);
|
||||
|
||||
+272
-301
File diff suppressed because it is too large
Load Diff
+403
-405
File diff suppressed because it is too large
Load Diff
+13
-13
@@ -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 *
|
||||
@@ -133,7 +133,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
PHONEME_LIST2 *plist2;
|
||||
WORD_PH_DATA worddata;
|
||||
|
||||
memset(&worddata, 0, sizeof(worddata));
|
||||
memset(&worddata, 0, sizeof(worddata));
|
||||
plist2 = ph_list2;
|
||||
phlist = phoneme_list;
|
||||
end_sourceix = plist2[n_ph_list2-1].sourceix;
|
||||
@@ -142,7 +142,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
max_stress = 0;
|
||||
for(j = n_ph_list2-3; j>=0; j--)
|
||||
{
|
||||
// start with the last phoneme (before the terminating pauses) and move forwards
|
||||
// start with the last phoneme (before the terminating pauses) and move backwards
|
||||
if((plist2[j].stresslevel & 0x7f) > max_stress)
|
||||
max_stress = plist2[j].stresslevel & 0x7f;
|
||||
if(plist2[j].sourceix != 0)
|
||||
@@ -204,21 +204,18 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
{
|
||||
voicing = 1;
|
||||
}
|
||||
else
|
||||
if((voicing==2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants
|
||||
else if((voicing==2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants
|
||||
{
|
||||
plist2[j].phcode = ph->end_type; // change to voiced equivalent
|
||||
}
|
||||
}
|
||||
else
|
||||
if((type==phVSTOP) || type==(phVFRICATIVE))
|
||||
else if((type==phVSTOP) || type==(phVFRICATIVE))
|
||||
{
|
||||
if((voicing==0) && (regression & 0xf))
|
||||
{
|
||||
voicing = 2;
|
||||
}
|
||||
else
|
||||
if((voicing==1) && (ph->end_type != 0))
|
||||
else if((voicing==1) && (ph->end_type != 0))
|
||||
{
|
||||
plist2[j].phcode = ph->end_type; // change to unvoiced equivalent
|
||||
}
|
||||
@@ -331,6 +328,9 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
|
||||
if(plist3->phcode == phonSWITCH)
|
||||
{
|
||||
if((plist3[1].phcode == phonSWITCH) || ((plist3[1].type == phPAUSE) && (plist3[2].phcode == phonSWITCH)))
|
||||
continue; // next phoneme is also a phonSWITCH, so ignore
|
||||
|
||||
// change phoneme table
|
||||
SelectPhonemeTable(plist3->tone_ph);
|
||||
switched_language ^= SFLAG_SWITCHED_LANG;
|
||||
@@ -580,18 +580,18 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
phlist[ix].newword = 2; // end of clause
|
||||
|
||||
phlist[ix].phcode = phonPAUSE;
|
||||
phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes
|
||||
phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes
|
||||
phlist[ix].length = post_pause; // length of the pause, depends on the punctuation
|
||||
phlist[ix].sourceix = end_sourceix;
|
||||
phlist[ix].synthflags = 0;
|
||||
phlist[ix++].ph = phoneme_tab[phonPAUSE];
|
||||
phlist[ix++].ph = phoneme_tab[phonPAUSE];
|
||||
|
||||
phlist[ix].phcode = phonPAUSE;
|
||||
phlist[ix].type = phPAUSE;
|
||||
phlist[ix].type = phPAUSE;
|
||||
phlist[ix].length = 0;
|
||||
phlist[ix].sourceix=0;
|
||||
phlist[ix].synthflags = 0;
|
||||
phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT];
|
||||
phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT];
|
||||
|
||||
n_phoneme_list = ix;
|
||||
} // end of MakePhonemeList
|
||||
|
||||
+18
-9
@@ -842,14 +842,13 @@ static int LoadSoundFile2(const char *fname)
|
||||
|
||||
|
||||
static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output, int *bufix, int end_clause)
|
||||
{//==========================================================================================================
|
||||
{//=============================================================================================================
|
||||
// announce punctuation names
|
||||
// c1: the punctuation character
|
||||
// c2: the following character
|
||||
|
||||
int punct_count;
|
||||
const char *punctname;
|
||||
int found = 0;
|
||||
const char *punctname = NULL;
|
||||
int soundicon;
|
||||
int attributes;
|
||||
int short_pause;
|
||||
@@ -858,6 +857,7 @@ static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output
|
||||
int bufix1;
|
||||
char buf[200];
|
||||
char buf2[80];
|
||||
char ph_buf[30];
|
||||
|
||||
c2 = *c2_ptr;
|
||||
buf[0] = 0;
|
||||
@@ -867,12 +867,24 @@ static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output
|
||||
// add an embedded command to play the soundicon
|
||||
sprintf(buf,"\001%dI ",soundicon);
|
||||
UngetC(c2);
|
||||
found = 1;
|
||||
}
|
||||
else
|
||||
if((punctname = LookupCharName(tr, c1, 0)) != NULL)
|
||||
{
|
||||
found = 1;
|
||||
if((c1 == '.') && (end_clause) && (c2 != '.'))
|
||||
{
|
||||
if(LookupSpecial(tr, "_.p", ph_buf))
|
||||
{
|
||||
punctname = ph_buf; // use word for 'period' instead of 'dot'
|
||||
}
|
||||
}
|
||||
if(punctname == NULL)
|
||||
{
|
||||
punctname = LookupCharName(tr, c1, 0);
|
||||
}
|
||||
|
||||
if(punctname == NULL)
|
||||
return(-1);
|
||||
|
||||
if((*bufix==0) || (end_clause ==0) || (tr->langopts.param[LOPT_ANNOUNCE_PUNCT] & 2))
|
||||
{
|
||||
punct_count=1;
|
||||
@@ -932,9 +944,6 @@ static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output
|
||||
}
|
||||
}
|
||||
|
||||
if(found == 0)
|
||||
return(-1);
|
||||
|
||||
bufix1 = *bufix;
|
||||
len = strlen(buf);
|
||||
strcpy(&output[*bufix],buf);
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.46.44 08.Mar.13";
|
||||
const char *version_string = "1.46.45 10.Mar.13";
|
||||
const int version_phdata = 0x014640;
|
||||
|
||||
int option_device_number = -1;
|
||||
|
||||
+47
-40
@@ -79,7 +79,7 @@ ALPHABET alphabets [] = {
|
||||
{"_dv", OFFSET_THAANA, 0x780, 0x7bf, 0, 0},
|
||||
{"_hi", OFFSET_DEVANAGARI, 0x900, 0x97f,L('h','i'), AL_WORDS},
|
||||
{"_bn", OFFSET_BENGALI, 0x0980, 0x9ff, 0, 0},
|
||||
{"_gur", OFFSET_GURMUKHI, 0xa00, 0xa7f, 0, 0},
|
||||
{"_gur", OFFSET_GURMUKHI, 0xa00, 0xa7f, L('p','a'), AL_WORDS},
|
||||
{"_gu", OFFSET_GUJARATI, 0xa80, 0xaff, 0, 0},
|
||||
{"_or", OFFSET_ORIYA, 0xb00, 0xb7f, 0, 0},
|
||||
{"_ta", OFFSET_TAMIL, 0xb80, 0xbff, L('t','a'), AL_WORDS},
|
||||
@@ -94,24 +94,26 @@ ALPHABET alphabets [] = {
|
||||
{"_ka", OFFSET_GEORGIAN, 0x10a0,0x10ff, L('k','a'), AL_WORDS},
|
||||
{"_ko", OFFSET_KOREAN, 0x1100,0x11ff, 0, 0},
|
||||
{"_eth", OFFSET_ETHIOPIC, 0x1200,0x139f, 0, 0},
|
||||
{"_ja", 0x3040, 0x3040,0x30ff, 0, AL_NOT_CODE},
|
||||
{"_zh", 0x3100, 0x3100,0x9fff, 0, AL_NOT_CODE},
|
||||
{NULL, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
ALPHABET *AlphabetFromChar(int c)
|
||||
{//===============================
|
||||
// Find the alphabet from a character.
|
||||
ALPHABET *alphabet = alphabets;
|
||||
// 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);
|
||||
while(alphabet->name != NULL)
|
||||
{
|
||||
if((c >= alphabet->range_min) && (c <= alphabet->range_max))
|
||||
{
|
||||
return(alphabet);
|
||||
}
|
||||
alphabet++;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -514,7 +516,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
|
||||
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
|
||||
tr->langopts.stress_flags = S_MID_DIM | S_FINAL_DIM; // use 'diminished' for unstressed final syllable
|
||||
tr->letter_bits_offset = OFFSET_BENGALI;
|
||||
SetIndicLetters(tr); // call this after setting OFFSET_BENGALI
|
||||
SetLetterBitsRange(tr,LETTERGP_F,0x3e,0x4c); // vowel signs, but not virama
|
||||
@@ -601,7 +603,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
|
||||
tr->letter_bits_offset = OFFSET_THAANA;
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
|
||||
tr->langopts.stress_flags = S_MID_DIM | S_FINAL_DIM; // 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.numbers = 1;
|
||||
@@ -705,7 +707,7 @@ 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 = S_FINAL_SPANISH | S_FINAL_DIM_ONLY | S_FINAL_NO_2;
|
||||
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
|
||||
@@ -715,18 +717,20 @@ Translator *SelectTranslator(const char *name)
|
||||
|
||||
if(name2 == L('c','a'))
|
||||
{
|
||||
// stress last syllable unless word ends with a vowel
|
||||
tr->punct_within_word = ca_punct_within_word;
|
||||
tr->langopts.stress_flags = 0x200 | 0x6 | 0x30; // stress last syllable unless word ends with a vowel
|
||||
tr->langopts.stress_flags = S_FINAL_SPANISH | S_FINAL_DIM_ONLY | S_FINAL_NO_2 | S_NO_AUTO_2;
|
||||
}
|
||||
else
|
||||
if(name2 == L('a','n'))
|
||||
{
|
||||
tr->langopts.stress_flags = 0x200 | 0x6 | 0x10;
|
||||
tr->langopts.stress_flags = S_FINAL_SPANISH | S_FINAL_DIM_ONLY | S_FINAL_NO_2;
|
||||
}
|
||||
else
|
||||
if(name2 == L_pap)
|
||||
{
|
||||
tr->langopts.stress_flags = 0x100 | 0x6 | 0x30; // stress last syllable unless word ends with a vowel
|
||||
// stress last syllable unless word ends with a vowel
|
||||
tr->langopts.stress_flags = S_FINAL_STRESS_C | S_FINAL_DIM_ONLY | S_FINAL_NO_2 | S_NO_AUTO_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -786,7 +790,7 @@ Translator *SelectTranslator(const char *name)
|
||||
SetupTranslator(tr,stress_lengths_fi,stress_amps_fi);
|
||||
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.stress_flags = 0x56; // move secondary stress from light to a following heavy syllable
|
||||
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2 | S_2_TO_HEAVY; // move secondary stress from light to a following heavy syllable
|
||||
tr->langopts.param[LOPT_IT_DOUBLING] = 1;
|
||||
tr->langopts.long_stop = 130;
|
||||
|
||||
@@ -802,7 +806,7 @@ Translator *SelectTranslator(const char *name)
|
||||
{
|
||||
SetupTranslator(tr,stress_lengths_fr,stress_amps_fr);
|
||||
tr->langopts.stress_rule = STRESSPOSN_1R; // stress on final syllable
|
||||
tr->langopts.stress_flags = 0x0024; // don't use secondary stress
|
||||
tr->langopts.stress_flags = S_NO_AUTO_2 | S_FINAL_DIM; // don't use secondary stress
|
||||
tr->langopts.param[LOPT_IT_LENGTHEN] = 1; // remove lengthen indicator from unstressed syllables
|
||||
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
|
||||
tr->langopts.accents = 2; // Say "Capital" after the letter.
|
||||
@@ -812,12 +816,12 @@ Translator *SelectTranslator(const char *name)
|
||||
}
|
||||
break;
|
||||
|
||||
case L('g','a'): // irish
|
||||
{
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.numbers = 1;
|
||||
}
|
||||
break;
|
||||
case L('g','a'): // irish
|
||||
{
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.numbers = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case L('h','i'): // Hindi
|
||||
case L('n','e'): // Nepali
|
||||
@@ -831,7 +835,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
|
||||
|
||||
tr->langopts.stress_rule = 6; // stress on last heaviest syllable, excluding final syllable
|
||||
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
|
||||
tr->langopts.stress_flags = S_MID_DIM | S_FINAL_DIM; // use 'diminished' for unstressed final syllable
|
||||
tr->langopts.numbers = NUM_SWAP_TENS;
|
||||
tr->langopts.break_numbers = 0x14aa8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi
|
||||
tr->letter_bits_offset = OFFSET_DEVANAGARI;
|
||||
@@ -875,7 +879,7 @@ SetupTranslator(tr,stress_lengths_equal,stress_amps_equal);
|
||||
tr->charset_a0 = charsets[2]; // ISO-8859-2
|
||||
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.stress_flags = 0x10;
|
||||
tr->langopts.stress_flags = S_FINAL_NO_2;
|
||||
tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x3;
|
||||
tr->langopts.max_initial_consonants = 5;
|
||||
tr->langopts.spelling_stress = 1;
|
||||
@@ -894,7 +898,7 @@ SetupTranslator(tr,stress_lengths_equal,stress_amps_equal);
|
||||
case L('h','t'): // Haitian Creole
|
||||
// memcpy(tr->stress_lengths,stress_lengths_fr,sizeof(tr->stress_lengths));
|
||||
tr->langopts.stress_rule = STRESSPOSN_1R; // stress on final syllable
|
||||
tr->langopts.stress_flags = 0x0024; // don't use secondary stress
|
||||
tr->langopts.stress_flags = S_NO_AUTO_2 | S_FINAL_DIM; // don't use secondary stress
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_VIGESIMAL | NUM_DFRACTION_4;
|
||||
break;
|
||||
|
||||
@@ -909,7 +913,7 @@ SetupTranslator(tr,stress_lengths_equal,stress_amps_equal);
|
||||
|
||||
tr->langopts.vowel_pause = 0x20;
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.stress_flags = 0x8036 | S_HYPEN_UNSTRESS;
|
||||
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2 | S_NO_AUTO_2 | 0x8000 | S_HYPEN_UNSTRESS;
|
||||
tr->langopts.unstressed_wd1 = 2;
|
||||
tr->langopts.param[LOPT_IT_DOUBLING] = 1;
|
||||
tr->langopts.param[LOPT_ANNOUNCE_PUNCT] = 2; // don't break clause before announcing . ? !
|
||||
@@ -942,7 +946,7 @@ SetLengthMods(tr,3); // all equal
|
||||
SetLetterBits(tr,LETTERGP_C,hy_consonants);
|
||||
tr->langopts.max_initial_consonants = 6;
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED;
|
||||
// tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
|
||||
// tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -954,7 +958,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 = S_FINAL_DIM_ONLY | S_FINAL_NO_2;
|
||||
tr->langopts.accents = 2; // "capital" after letter name
|
||||
}
|
||||
break;
|
||||
@@ -966,7 +970,7 @@ SetLengthMods(tr,3); // all equal
|
||||
|
||||
SetupTranslator(tr,stress_lengths_is,NULL);
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.stress_flags = 0x10;
|
||||
tr->langopts.stress_flags = S_FINAL_NO_2;
|
||||
tr->langopts.param[LOPT_IT_LENGTHEN] = 0x11; // remove lengthen indicator from unstressed vowels
|
||||
tr->langopts.param[LOPT_REDUCE] = 2;
|
||||
|
||||
@@ -989,7 +993,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 | S_PRIORITY_STRESS;
|
||||
tr->langopts.stress_flags = S_FINAL_NO_2 | S_PRIORITY_STRESS;
|
||||
tr->langopts.vowel_pause = 1;
|
||||
tr->langopts.unstressed_wd1 = 2;
|
||||
tr->langopts.unstressed_wd2 = 2;
|
||||
@@ -1024,8 +1028,9 @@ SetLengthMods(tr,3); // all equal
|
||||
{
|
||||
// character codes offset by 0x1080
|
||||
static const char ka_vowels[] = {0x30,0x34,0x38,0x3d,0x43,0x55,0x57,0};
|
||||
static const char ka_consonants[] = {0x31,0x32,0x33,0x35,0x36,0x37,0x39,0x3a,0x3b,0x3c,0x3e,0x3f,
|
||||
0x40,0x41,0x42,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x56,0};
|
||||
static const char ka_consonants[] =
|
||||
{0x31,0x32,0x33,0x35,0x36,0x37,0x39,0x3a,0x3b,0x3c,0x3e,0x3f,0x40,0x41,0x42,0x44,
|
||||
0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x56,0};
|
||||
SetupTranslator(tr,stress_lengths_ta,stress_amps_ta);
|
||||
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
|
||||
SetLetterBits(tr,LETTERGP_A,ka_vowels);
|
||||
@@ -1149,7 +1154,7 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.spelling_stress = 1;
|
||||
tr->charset_a0 = charsets[4]; // ISO-8859-4
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_4 | NUM_ORDINAL_DOT;
|
||||
tr->langopts.stress_flags = 0x16 + 0x40000;
|
||||
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2 | S_EO_CLAUSE1;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1496,14 +1501,14 @@ SetLengthMods(tr,3); // all equal
|
||||
break;
|
||||
|
||||
case L('t','t'): // Tatar
|
||||
{
|
||||
{
|
||||
SetCyrillicLetters(tr);
|
||||
SetupTranslator(tr,stress_lengths_fr,stress_amps_fr);
|
||||
tr->langopts.stress_rule = STRESSPOSN_1R; // stress on final syllable
|
||||
tr->langopts.stress_flags = S_NO_AUTO_2; //no automatic secondary stress
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case L('u','k'): // Ukrainian
|
||||
{
|
||||
@@ -1513,10 +1518,12 @@ SetLengthMods(tr,3); // all equal
|
||||
break;
|
||||
|
||||
case L('u','r'): // Urdu
|
||||
{
|
||||
tr->letter_bits_offset = OFFSET_ARABIC;
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
|
||||
tr->langopts.numbers = NUM_SWAP_TENS;
|
||||
tr->langopts.break_numbers = 0x52a8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi
|
||||
}
|
||||
break;
|
||||
|
||||
case L('v','i'): // Vietnamese
|
||||
|
||||
+450
-474
File diff suppressed because it is too large
Load Diff
+9
-3
@@ -275,7 +275,8 @@ extern ALPHABET *current_alphabet;
|
||||
// alphabet flags
|
||||
#define AL_DONT_NAME 0x01 // don't speak the alphabet name
|
||||
#define AL_NOT_LETTERS 0x02 // don't use the language for speaking letters
|
||||
#define AL_WORDS 0x04 // use the language to speak words
|
||||
#define AL_WORDS 0x04 // use the language to speak words
|
||||
#define AL_NOT_CODE 0x08 // don't speak the character code
|
||||
|
||||
|
||||
#define N_LOPTS 21
|
||||
@@ -402,12 +403,18 @@ typedef struct {
|
||||
#define S_INITIAL_2 0x2000
|
||||
// bit13= If there is only one syllable before the primary stress, give it a secondary stress
|
||||
|
||||
#define S_MID_DIM 0x10000
|
||||
// bit 16= Set (not first or last) syllables to diminished stress
|
||||
|
||||
#define S_PRIORITY_STRESS 0x20000
|
||||
// bit17= "priority" stress reduces other primary stress to "unstressed" not "secondary"
|
||||
|
||||
#define S_EO_CLAUSE1 0x40000
|
||||
// bit18= don't lengthen short vowels more than long vowels at end-of-clause
|
||||
|
||||
#define S_FINAL_LONG 0x80000
|
||||
// bit19=stress on final syllable if it has a long vowel, but previous syllable has a short vowel
|
||||
|
||||
|
||||
#define S_HYPEN_UNSTRESS 0x100000
|
||||
// bit20= hyphenated words, 2nd part is unstressed
|
||||
@@ -416,7 +423,6 @@ typedef struct {
|
||||
// bit21= don't lengthen vowels at end-of-clause
|
||||
|
||||
// bit15= Give stress to the first unstressed syllable
|
||||
// bit19=stress on final syllable if it has a long vowel, but previous syllable has a short vowel
|
||||
|
||||
|
||||
int stress_flags;
|
||||
@@ -566,7 +572,7 @@ typedef struct
|
||||
const char *transpose_map;
|
||||
char dictionary_name[40];
|
||||
|
||||
char phon_out[400];
|
||||
char phon_out[500];
|
||||
char phonemes_repeat[20];
|
||||
int phonemes_repeat_count;
|
||||
int phoneme_tab_ix;
|
||||
|
||||
+184
-181
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2010 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 *
|
||||
@@ -47,7 +47,8 @@ MNEM_TAB genders [] = {
|
||||
{"unknown", 0},
|
||||
{"male", 1},
|
||||
{"female", 2},
|
||||
{NULL, 0 }};
|
||||
{NULL, 0 }
|
||||
};
|
||||
|
||||
int tone_points[12] = {600,170, 1200,135, 2000,110, 3000,110, -1,0};
|
||||
//int tone_points[12] = {250,200, 400,170, 600,170, 1200,135, 2000,110, -1,0};
|
||||
@@ -98,6 +99,7 @@ enum {
|
||||
V_STRESSADD,
|
||||
V_DICTRULES,
|
||||
V_STRESSRULE,
|
||||
V_STRESSOPT,
|
||||
V_CHARSET,
|
||||
V_NUMBERS,
|
||||
V_OPTION,
|
||||
@@ -118,7 +120,8 @@ enum {
|
||||
static MNEM_TAB options_tab[] = {
|
||||
{"reduce_t", LOPT_REDUCE_T},
|
||||
{"bracket", LOPT_BRACKET_PAUSE},
|
||||
{NULL, -1} };
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
static MNEM_TAB keyword_tab[] = {
|
||||
{"name", V_NAME},
|
||||
@@ -128,7 +131,7 @@ static MNEM_TAB keyword_tab[] = {
|
||||
{"formant", V_FORMANT},
|
||||
{"pitch", V_PITCH},
|
||||
{"phonemes", V_PHONEMES},
|
||||
{"translator", V_TRANSLATOR},
|
||||
{"translator", V_TRANSLATOR},
|
||||
{"dictionary", V_DICTIONARY},
|
||||
{"stressLength", V_STRESSLENGTH},
|
||||
{"stressAmp", V_STRESSAMP},
|
||||
@@ -137,6 +140,7 @@ static MNEM_TAB keyword_tab[] = {
|
||||
{"tunes", V_TUNES},
|
||||
{"dictrules", V_DICTRULES},
|
||||
{"stressrule", V_STRESSRULE},
|
||||
{"stressopt", V_STRESSOPT},
|
||||
{"charset", V_CHARSET},
|
||||
{"replace", V_REPLACE},
|
||||
{"words", V_WORDGAP},
|
||||
@@ -166,7 +170,8 @@ static MNEM_TAB keyword_tab[] = {
|
||||
{"l_sonorant_min", 0x100+LOPT_SONORANT_MIN},
|
||||
{"l_length_mods", 0x100+LOPT_LENGTH_MODS},
|
||||
{"apostrophe", 0x100+LOPT_APOSTROPHE},
|
||||
{NULL, 0} };
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
#define N_VOICE_VARIANTS 12
|
||||
const char variants_either[N_VOICE_VARIANTS] = {1,2,12,3,13,4,14,5,11,0};
|
||||
@@ -260,9 +265,9 @@ void ReadTonePoints(char *string, int *tone_pts)
|
||||
tone_pts[ix] = -1;
|
||||
|
||||
sscanf(string,"%d %d %d %d %d %d %d %d %d %d",
|
||||
&tone_pts[0],&tone_pts[1],&tone_pts[2],&tone_pts[3],
|
||||
&tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7],
|
||||
&tone_pts[8],&tone_pts[9]);
|
||||
&tone_pts[0],&tone_pts[1],&tone_pts[2],&tone_pts[3],
|
||||
&tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7],
|
||||
&tone_pts[8],&tone_pts[9]);
|
||||
}
|
||||
|
||||
|
||||
@@ -316,8 +321,7 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*lea
|
||||
while(isspace(*p)) p++;
|
||||
strncpy0(vname,p,sizeof(vname));
|
||||
}
|
||||
else
|
||||
if(memcmp(linebuf,"language",8)==0)
|
||||
else if(memcmp(linebuf,"language",8)==0)
|
||||
{
|
||||
priority = DEFAULT_LANGUAGE_PRIORITY;
|
||||
vlanguage[0] = 0;
|
||||
@@ -334,13 +338,11 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*lea
|
||||
n_languages++;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(memcmp(linebuf,"gender",6)==0)
|
||||
else if(memcmp(linebuf,"gender",6)==0)
|
||||
{
|
||||
sscanf(&linebuf[6],"%s %d",vgender,&age);
|
||||
}
|
||||
else
|
||||
if(memcmp(linebuf,"variants",8)==0)
|
||||
else if(memcmp(linebuf,"variants",8)==0)
|
||||
{
|
||||
sscanf(&linebuf[8],"%d",&n_variants);
|
||||
}
|
||||
@@ -443,7 +445,7 @@ void VoiceReset(int tone_only)
|
||||
// Adjustment of harmonic amplitudes, steps of 8Hz
|
||||
// value of 128 means no change
|
||||
// memset(voice->tone_adjust,128,sizeof(voice->tone_adjust));
|
||||
SetToneAdjust(voice,tone_points);
|
||||
SetToneAdjust(voice,tone_points);
|
||||
|
||||
// default values of speed factors
|
||||
voice->speedf1 = 256;
|
||||
@@ -517,7 +519,7 @@ static int Read8Numbers(char *data_in,int *data)
|
||||
// Read 8 integer numbers
|
||||
memset(data, 0, 8+sizeof(int));
|
||||
return(sscanf(data_in,"%d %d %d %d %d %d %d %d",
|
||||
&data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7]));
|
||||
&data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7]));
|
||||
}
|
||||
|
||||
|
||||
@@ -557,7 +559,7 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
char buf[sizeof(path_home)+30];
|
||||
char path_voices[sizeof(path_home)+12];
|
||||
|
||||
int dict_min = 0;
|
||||
int dict_min = 0;
|
||||
int stress_amps[8];
|
||||
int stress_lengths[8];
|
||||
int stress_add[8];
|
||||
@@ -572,11 +574,11 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
static char voice_name[40]; // voice name for current_voice_selected
|
||||
static char voice_languages[100]; // list of languages and priorities for current_voice_selected
|
||||
|
||||
// which directory to look for a named voice
|
||||
static const char *voices_asia =
|
||||
"fa fa-pin hi hy hy-west id ka kn ku ml ne pa ta tr vi vi-hue zh zh-yue ";
|
||||
static const char *voices_europe =
|
||||
"bg bs ca cs cy da el es et fi fr-be hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";
|
||||
// which directory to look for a named voice
|
||||
static const char *voices_asia =
|
||||
"fa fa-pin hi hy hy-west id ka kn ku ml ne pa ta tr vi vi-hue zh zh-yue ";
|
||||
static const char *voices_europe =
|
||||
"bg bs ca cs cy da el es et fi fr-be hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";
|
||||
|
||||
|
||||
strncpy0(voicename, vname, sizeof(voicename));
|
||||
@@ -588,38 +590,37 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(voicename[0]==0)
|
||||
strcpy(voicename,"default");
|
||||
if(voicename[0]==0)
|
||||
strcpy(voicename,"default");
|
||||
|
||||
sprintf(path_voices,"%s%cvoices%c",path_home,PATHSEP,PATHSEP);
|
||||
sprintf(buf,"%s%s",path_voices,voicename); // first, look in the main voices directory
|
||||
|
||||
if(GetFileLength(buf) <= 0)
|
||||
{
|
||||
// then look in the appropriate subdirectory
|
||||
if((voicename[0]=='m') && (voicename[1]=='b'))
|
||||
{
|
||||
voice_dir = "mb"; // mbrola voices
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(name2, "%s ", voicename);
|
||||
if(strstr(voices_europe, voicename) != NULL)
|
||||
voice_dir = "europe";
|
||||
else
|
||||
if(strstr(voices_asia, voicename) != NULL)
|
||||
voice_dir = "asia";
|
||||
else
|
||||
voice_dir = "other";
|
||||
// then look in the appropriate subdirectory
|
||||
if((voicename[0]=='m') && (voicename[1]=='b'))
|
||||
{
|
||||
voice_dir = "mb"; // mbrola voices
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(name2, "%s ", voicename);
|
||||
if(strstr(voices_europe, voicename) != NULL)
|
||||
voice_dir = "europe";
|
||||
else if(strstr(voices_asia, voicename) != NULL)
|
||||
voice_dir = "asia";
|
||||
else
|
||||
voice_dir = "other";
|
||||
|
||||
sprintf(buf,"%s%s%c%s", path_voices,voice_dir,PATHSEP,voicename);
|
||||
sprintf(buf,"%s%s%c%s", path_voices,voice_dir,PATHSEP,voicename);
|
||||
|
||||
if(GetFileLength(buf) <= 0)
|
||||
{
|
||||
// if not found, look in "test" sub-directory
|
||||
sprintf(buf,"%stest%c%s",path_voices,PATHSEP,voicename);
|
||||
}
|
||||
}
|
||||
if(GetFileLength(buf) <= 0)
|
||||
{
|
||||
// if not found, look in "test" sub-directory
|
||||
sprintf(buf,"%stest%c%s",path_voices,PATHSEP,voicename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,48 +686,48 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
switch(key)
|
||||
{
|
||||
case V_LANGUAGE:
|
||||
{
|
||||
unsigned int len;
|
||||
int priority;
|
||||
|
||||
if(tone_only)
|
||||
break;
|
||||
|
||||
priority = DEFAULT_LANGUAGE_PRIORITY;
|
||||
language_name[0] = 0;
|
||||
|
||||
sscanf(p,"%s %d",language_name,&priority);
|
||||
if(strcmp(language_name,"variant") == 0)
|
||||
break;
|
||||
|
||||
len = strlen(language_name) + 2;
|
||||
// check for space in languages[]
|
||||
if(len < (sizeof(voice_languages)-langix-1))
|
||||
{
|
||||
unsigned int len;
|
||||
int priority;
|
||||
voice_languages[langix] = priority;
|
||||
|
||||
if(tone_only)
|
||||
break;
|
||||
|
||||
priority = DEFAULT_LANGUAGE_PRIORITY;
|
||||
language_name[0] = 0;
|
||||
|
||||
sscanf(p,"%s %d",language_name,&priority);
|
||||
if(strcmp(language_name,"variant") == 0)
|
||||
break;
|
||||
|
||||
len = strlen(language_name) + 2;
|
||||
// check for space in languages[]
|
||||
if(len < (sizeof(voice_languages)-langix-1))
|
||||
{
|
||||
voice_languages[langix] = priority;
|
||||
|
||||
strcpy(&voice_languages[langix+1],language_name);
|
||||
langix += len;
|
||||
}
|
||||
|
||||
// only act on the first language line
|
||||
if(language_set == 0)
|
||||
{
|
||||
language_type = strtok(language_name,"-");
|
||||
language_set = 1;
|
||||
strcpy(translator_name,language_type);
|
||||
strcpy(new_dictionary,language_type);
|
||||
strcpy(phonemes_name,language_type);
|
||||
SelectPhonemeTableName(phonemes_name);
|
||||
|
||||
if(new_translator != NULL)
|
||||
DeleteTranslator(new_translator);
|
||||
|
||||
new_translator = SelectTranslator(translator_name);
|
||||
langopts = &new_translator->langopts;
|
||||
}
|
||||
strcpy(&voice_languages[langix+1],language_name);
|
||||
langix += len;
|
||||
}
|
||||
break;
|
||||
|
||||
// only act on the first language line
|
||||
if(language_set == 0)
|
||||
{
|
||||
language_type = strtok(language_name,"-");
|
||||
language_set = 1;
|
||||
strcpy(translator_name,language_type);
|
||||
strcpy(new_dictionary,language_type);
|
||||
strcpy(phonemes_name,language_type);
|
||||
SelectPhonemeTableName(phonemes_name);
|
||||
|
||||
if(new_translator != NULL)
|
||||
DeleteTranslator(new_translator);
|
||||
|
||||
new_translator = SelectTranslator(translator_name);
|
||||
langopts = &new_translator->langopts;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case V_NAME:
|
||||
if(tone_only == 0)
|
||||
@@ -737,14 +738,14 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_GENDER:
|
||||
{
|
||||
int age = 0;
|
||||
char vgender[80];
|
||||
sscanf(p,"%s %d",vgender,&age);
|
||||
current_voice_selected.gender = LookupMnem(genders,vgender);
|
||||
current_voice_selected.age = age;
|
||||
}
|
||||
break;
|
||||
{
|
||||
int age = 0;
|
||||
char vgender[80];
|
||||
sscanf(p,"%s %d",vgender,&age);
|
||||
current_voice_selected.gender = LookupMnem(genders,vgender);
|
||||
current_voice_selected.age = age;
|
||||
}
|
||||
break;
|
||||
|
||||
case V_TRANSLATOR:
|
||||
if(tone_only) break;
|
||||
@@ -752,7 +753,7 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
sscanf(p,"%s",translator_name);
|
||||
|
||||
if(new_translator != NULL)
|
||||
DeleteTranslator(new_translator);
|
||||
DeleteTranslator(new_translator);
|
||||
|
||||
new_translator = SelectTranslator(translator_name);
|
||||
langopts = &new_translator->langopts;
|
||||
@@ -771,16 +772,16 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_PITCH:
|
||||
{
|
||||
double factor;
|
||||
// default is pitch 82 118
|
||||
n = sscanf(p,"%d %d",&pitch1,&pitch2);
|
||||
voice->pitch_base = (pitch1 - 9) << 12;
|
||||
voice->pitch_range = (pitch2 - pitch1) * 108;
|
||||
factor = double(pitch1 - 82)/82;
|
||||
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch
|
||||
}
|
||||
break;
|
||||
{
|
||||
double factor;
|
||||
// default is pitch 82 118
|
||||
n = sscanf(p,"%d %d",&pitch1,&pitch2);
|
||||
voice->pitch_base = (pitch1 - 9) << 12;
|
||||
voice->pitch_range = (pitch2 - pitch1) * 108;
|
||||
factor = double(pitch1 - 82)/82;
|
||||
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch
|
||||
}
|
||||
break;
|
||||
|
||||
case V_STRESSLENGTH: // stressLength
|
||||
stress_lengths_set = Read8Numbers(p,stress_lengths);
|
||||
@@ -817,7 +818,8 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
|
||||
case V_DICTRULES: // conditional dictionary rules and list entries
|
||||
case V_NUMBERS:
|
||||
// expect a list of numbers
|
||||
case V_STRESSOPT:
|
||||
// expect a list of numbers
|
||||
while(*p != 0)
|
||||
{
|
||||
while(isspace(*p)) p++;
|
||||
@@ -825,16 +827,22 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
if((n = atoi(p)) > 0)
|
||||
{
|
||||
p++;
|
||||
if((key==V_DICTRULES) && (n < 32))
|
||||
conditional_rules |= (1 << n);
|
||||
if(n < 32)
|
||||
{
|
||||
if(key==V_DICTRULES)
|
||||
conditional_rules |= (1 << n);
|
||||
else if(key==V_NUMBERS)
|
||||
langopts->numbers |= (1 << n);
|
||||
else if(key==V_STRESSOPT)
|
||||
langopts->stress_flags |= (1 << n);
|
||||
}
|
||||
else
|
||||
if((key==V_NUMBERS) && (n < 32))
|
||||
langopts->numbers |= (1 << n);
|
||||
else
|
||||
if((key==V_NUMBERS) && (n < 64))
|
||||
langopts->numbers |= (1 << (n-32));
|
||||
else
|
||||
fprintf(stderr,"Bad option number %d\n", n);
|
||||
{
|
||||
if((key==V_NUMBERS) && (n < 64))
|
||||
langopts->numbers |= (1 << (n-32));
|
||||
else
|
||||
fprintf(stderr,"Bad option number %d\n", n);
|
||||
}
|
||||
}
|
||||
while(isalnum(*p)) p++;
|
||||
}
|
||||
@@ -856,9 +864,9 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
|
||||
case V_STRESSRULE:
|
||||
sscanf(p,"%d %d %d %d",&langopts->stress_rule,
|
||||
&langopts->stress_flags,
|
||||
&langopts->unstressed_wd1,
|
||||
&langopts->unstressed_wd2);
|
||||
&langopts->stress_flags,
|
||||
&langopts->unstressed_wd1,
|
||||
&langopts->unstressed_wd2);
|
||||
break;
|
||||
|
||||
case V_CHARSET:
|
||||
@@ -909,12 +917,12 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_TONE:
|
||||
{
|
||||
int tone_data[12];
|
||||
ReadTonePoints(p,tone_data);
|
||||
SetToneAdjust(voice,tone_data);
|
||||
}
|
||||
break;
|
||||
{
|
||||
int tone_data[12];
|
||||
ReadTonePoints(p,tone_data);
|
||||
SetToneAdjust(voice,tone_data);
|
||||
}
|
||||
break;
|
||||
|
||||
case V_VOICING:
|
||||
if(sscanf(p,"%d",&value)==1)
|
||||
@@ -922,16 +930,16 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_BREATH:
|
||||
voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
|
||||
for(ix=1; ix<8; ix++)
|
||||
{
|
||||
if(ix % 2)
|
||||
voice->breath[ix] = -voice->breath[ix];
|
||||
}
|
||||
voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
|
||||
for(ix=1; ix<8; ix++)
|
||||
{
|
||||
if(ix % 2)
|
||||
voice->breath[ix] = -voice->breath[ix];
|
||||
}
|
||||
break;
|
||||
|
||||
case V_BREATHW:
|
||||
voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
|
||||
voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
|
||||
break;
|
||||
|
||||
case V_CONSONANTS:
|
||||
@@ -943,20 +951,20 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_MBROLA:
|
||||
{
|
||||
int srate = 16000;
|
||||
char name[40];
|
||||
char phtrans[40];
|
||||
{
|
||||
int srate = 16000;
|
||||
char name[40];
|
||||
char phtrans[40];
|
||||
|
||||
phtrans[0] = 0;
|
||||
sscanf(p,"%s %s %d",name,phtrans,&srate);
|
||||
if(LoadMbrolaTable(name,phtrans,srate) != EE_OK)
|
||||
{
|
||||
fprintf(stderr,"mbrola voice not found\n");
|
||||
}
|
||||
voice->samplerate = srate;
|
||||
phtrans[0] = 0;
|
||||
sscanf(p,"%s %s %d",name,phtrans,&srate);
|
||||
if(LoadMbrolaTable(name,phtrans,srate) != EE_OK)
|
||||
{
|
||||
fprintf(stderr,"mbrola voice not found\n");
|
||||
}
|
||||
break;
|
||||
voice->samplerate = srate;
|
||||
}
|
||||
break;
|
||||
|
||||
case V_KLATT:
|
||||
voice->klattv[0] = 1; // default source: IMPULSIVE
|
||||
@@ -969,9 +977,9 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
SetSpeed(3);
|
||||
break;
|
||||
|
||||
case V_DICTMIN:
|
||||
case V_DICTMIN:
|
||||
sscanf(p,"%d",&dict_min);
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
if((key & 0xff00) == 0x100)
|
||||
@@ -1015,7 +1023,7 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
}
|
||||
voice->phoneme_tab_ix = ix;
|
||||
new_translator->phoneme_tab_ix = ix;
|
||||
new_translator->dict_min_size = dict_min;
|
||||
new_translator->dict_min_size = dict_min;
|
||||
LoadDictionary(new_translator, new_dictionary, control & 4);
|
||||
if(dictionary_name[0]==0)
|
||||
return(NULL); // no dictionary loaded
|
||||
@@ -1255,15 +1263,14 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s
|
||||
// match on voice name
|
||||
score += 500;
|
||||
}
|
||||
else
|
||||
if(strcmp(voice_spec->name,voice->identifier)==0)
|
||||
else if(strcmp(voice_spec->name,voice->identifier)==0)
|
||||
{
|
||||
score += 400;
|
||||
}
|
||||
}
|
||||
|
||||
if(((voice_spec->gender == 1) || (voice_spec->gender == 2)) &&
|
||||
((voice->gender == 1) || (voice->gender == 2)))
|
||||
((voice->gender == 1) || (voice->gender == 2)))
|
||||
{
|
||||
if(voice_spec->gender == voice->gender)
|
||||
score += 50;
|
||||
@@ -1395,8 +1402,7 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2)
|
||||
{
|
||||
match_fname = ix; // matching identifier, use this if no matching name
|
||||
}
|
||||
else
|
||||
if(strcmp(last_part,&id[strlen(id)-last_part_len])==0)
|
||||
else if(strcmp(last_part,&id[strlen(id)-last_part_len])==0)
|
||||
{
|
||||
match_fname2 = ix;
|
||||
}
|
||||
@@ -1493,8 +1499,7 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found)
|
||||
gender = 0;
|
||||
if((voice_select2.gender == 2) || ((voice_select2.age > 0) && (voice_select2.age < 13)))
|
||||
gender = 2;
|
||||
else
|
||||
if(voice_select2.gender == 1)
|
||||
else if(voice_select2.gender == 1)
|
||||
gender = 1;
|
||||
|
||||
#define AGE_OLD 60
|
||||
@@ -1625,8 +1630,8 @@ static void GetVoices(const char *path)
|
||||
}
|
||||
#else
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
WIN32_FIND_DATAA FindFileData;
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
WIN32_FIND_DATAA FindFileData;
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
|
||||
#undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string
|
||||
sprintf(fname,"%s\\*",path);
|
||||
@@ -1640,30 +1645,29 @@ static void GetVoices(const char *path)
|
||||
|
||||
if(FindFileData.cFileName[0] != '.')
|
||||
{
|
||||
sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
|
||||
ftype = GetFileLength(fname);
|
||||
sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
|
||||
ftype = GetFileLength(fname);
|
||||
|
||||
if(ftype == -2)
|
||||
{
|
||||
// a sub-sirectory
|
||||
GetVoices(fname);
|
||||
}
|
||||
else
|
||||
if(ftype > 0)
|
||||
{
|
||||
// a regular line, add it to the voices list
|
||||
if((f_voice = fopen(fname,"r")) == NULL)
|
||||
continue;
|
||||
if(ftype == -2)
|
||||
{
|
||||
// a sub-sirectory
|
||||
GetVoices(fname);
|
||||
}
|
||||
else if(ftype > 0)
|
||||
{
|
||||
// a regular line, add it to the voices list
|
||||
if((f_voice = fopen(fname,"r")) == NULL)
|
||||
continue;
|
||||
|
||||
// pass voice file name within the voices directory
|
||||
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName);
|
||||
fclose(f_voice);
|
||||
// pass voice file name within the voices directory
|
||||
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName);
|
||||
fclose(f_voice);
|
||||
|
||||
if(voice_data != NULL)
|
||||
{
|
||||
voices_list[n_voices_list++] = voice_data;
|
||||
}
|
||||
}
|
||||
if(voice_data != NULL)
|
||||
{
|
||||
voices_list[n_voices_list++] = voice_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(FindNextFileA(hFind, &FindFileData) != 0);
|
||||
FindClose(hFind);
|
||||
@@ -1680,8 +1684,8 @@ static void GetVoices(const char *path)
|
||||
if(n_voices_list >= (N_VOICES_LIST-2))
|
||||
break; // voices list is full
|
||||
|
||||
if(ent->d_name[0] == '.')
|
||||
continue;
|
||||
if(ent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
sprintf(fname,"%s%c%s",path,PATHSEP,ent->d_name);
|
||||
|
||||
@@ -1692,8 +1696,7 @@ static void GetVoices(const char *path)
|
||||
// a sub-sirectory
|
||||
GetVoices(fname);
|
||||
}
|
||||
else
|
||||
if(ftype > 0)
|
||||
else if(ftype > 0)
|
||||
{
|
||||
// a regular line, add it to the voices list
|
||||
if((f_voice = fopen(fname,"r")) == NULL)
|
||||
@@ -1728,7 +1731,7 @@ espeak_ERROR SetVoiceByName(const char *name)
|
||||
|
||||
variant_name = ExtractVoiceVariantName(buf, 0, 1);
|
||||
|
||||
for(ix=0; ;ix++)
|
||||
for(ix=0; ; ix++)
|
||||
{
|
||||
// convert voice name to lower case (ascii)
|
||||
if((buf[ix] = tolower(buf[ix])) == 0)
|
||||
@@ -1833,7 +1836,7 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec)
|
||||
|
||||
// sort the voices list
|
||||
qsort(voices_list,n_voices_list,sizeof(espeak_VOICE *),
|
||||
(int (__cdecl *)(const void *,const void *))VoiceNameSorter);
|
||||
(int (__cdecl *)(const void *,const void *))VoiceNameSorter);
|
||||
|
||||
|
||||
if(voice_spec)
|
||||
|
||||
Reference in New Issue
Block a user