mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-05 14:47:26 +00:00
[1.47.11c]
Change API function: espeak_TextToPhonemes(). Fix bug: number following a non-ascii character could cause crash. git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@361 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
+99
-97
@@ -526,6 +526,10 @@ unsigned short ipa1[96] = {
|
||||
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x303,0x7f
|
||||
};
|
||||
|
||||
#define N_PHON_OUT 500
|
||||
static char *phon_out_buf = NULL;
|
||||
static int phon_out_size = 0;
|
||||
|
||||
|
||||
char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags)
|
||||
{//===================================================================================================
|
||||
@@ -629,8 +633,8 @@ char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int
|
||||
|
||||
|
||||
|
||||
void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int phoneme_mode)
|
||||
{//===============================================================================
|
||||
const char *GetTranslatedPhonemeString(int phoneme_mode)
|
||||
{//=======================================================
|
||||
/* Called after a clause has been translated into phonemes, in order
|
||||
to display the clause in phoneme mnemonic form.
|
||||
|
||||
@@ -640,7 +644,6 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int phoneme_mode
|
||||
|
||||
int ix;
|
||||
unsigned int len;
|
||||
unsigned int max_len;
|
||||
int phon_out_ix=0;
|
||||
int stress;
|
||||
int c;
|
||||
@@ -668,108 +671,107 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int phoneme_mode
|
||||
use_tie = 0;
|
||||
}
|
||||
|
||||
if(phon_out != NULL)
|
||||
for(ix=1; ix<(n_phoneme_list-2); ix++)
|
||||
{
|
||||
for(ix=1; ix<(n_phoneme_list-2); ix++)
|
||||
buf = phon_buf;
|
||||
|
||||
plist = &phoneme_list[ix];
|
||||
|
||||
WritePhMnemonic(phon_buf2, plist->ph, plist, use_ipa, &flags);
|
||||
if(plist->newword)
|
||||
*buf++ = ' ';
|
||||
else
|
||||
{
|
||||
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))
|
||||
{
|
||||
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
|
||||
{
|
||||
utf8_in(&c, phon_buf2);
|
||||
if((c < 0x2b0) || (c > 0x36f)) // not if the phoneme starts with a superscript letter
|
||||
{
|
||||
*buf++ = separate_phonemes;
|
||||
}
|
||||
*buf++ = separate_phonemes;
|
||||
}
|
||||
}
|
||||
|
||||
if(plist->synthflags & SFLAG_SYLLABLE)
|
||||
{
|
||||
if((stress = plist->stresslevel) > 1)
|
||||
{
|
||||
c = 0;
|
||||
if(stress > 5) stress = 5;
|
||||
|
||||
if(use_ipa)
|
||||
{
|
||||
c = 0x2cc; // ipa, secondary stress
|
||||
if(stress > 3)
|
||||
c = 0x02c8; // ipa, primary stress
|
||||
}
|
||||
else
|
||||
{
|
||||
c = stress_chars[stress];
|
||||
}
|
||||
|
||||
if(c != 0)
|
||||
{
|
||||
buf += utf8_out(c, buf);
|
||||
// if(separate_phonemes)
|
||||
// *buf++ = separate_phonemes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
count = 0;
|
||||
for(p=phon_buf2; *p != 0;)
|
||||
{
|
||||
p += utf8_in(&c, p);
|
||||
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)) && iswalpha2(c))
|
||||
{
|
||||
buf += utf8_out(char_tie[use_tie-1], buf);
|
||||
}
|
||||
}
|
||||
buf += utf8_out(c, buf);
|
||||
count++;
|
||||
}
|
||||
|
||||
if(plist->ph->code != phonSWITCH)
|
||||
{
|
||||
if(plist->synthflags & SFLAG_LENGTHEN)
|
||||
{
|
||||
buf = WritePhMnemonic(buf, phoneme_tab[phonLENGTHEN], NULL, use_ipa, NULL);
|
||||
}
|
||||
if((plist->synthflags & SFLAG_SYLLABLE) && (plist->type != phVOWEL))
|
||||
{
|
||||
// syllablic consonant
|
||||
buf = WritePhMnemonic(buf, phoneme_tab[phonSYLLABIC], NULL, use_ipa, NULL);
|
||||
}
|
||||
if(plist->tone_ph > 0)
|
||||
{
|
||||
buf = WritePhMnemonic(buf, phoneme_tab[plist->tone_ph], NULL, use_ipa, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
len = buf - phon_buf;
|
||||
max_len = (n_phon_out - phon_out_ix - 5); // allow for " ..." and zero byte terminator
|
||||
if(len > max_len)
|
||||
{
|
||||
strcpy(&phon_buf[max_len], " ...");
|
||||
len = max_len + 4;
|
||||
}
|
||||
phon_buf[len] = 0;
|
||||
strcpy(&phon_out[phon_out_ix], phon_buf);
|
||||
phon_out_ix += len;
|
||||
|
||||
if(len > max_len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
phon_out[phon_out_ix] = 0;
|
||||
|
||||
if(plist->synthflags & SFLAG_SYLLABLE)
|
||||
{
|
||||
if((stress = plist->stresslevel) > 1)
|
||||
{
|
||||
c = 0;
|
||||
if(stress > 5) stress = 5;
|
||||
|
||||
if(use_ipa)
|
||||
{
|
||||
c = 0x2cc; // ipa, secondary stress
|
||||
if(stress > 3)
|
||||
c = 0x02c8; // ipa, primary stress
|
||||
}
|
||||
else
|
||||
{
|
||||
c = stress_chars[stress];
|
||||
}
|
||||
|
||||
if(c != 0)
|
||||
{
|
||||
buf += utf8_out(c, buf);
|
||||
// if(separate_phonemes)
|
||||
// *buf++ = separate_phonemes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
count = 0;
|
||||
for(p=phon_buf2; *p != 0;)
|
||||
{
|
||||
p += utf8_in(&c, p);
|
||||
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)) && iswalpha2(c))
|
||||
{
|
||||
buf += utf8_out(char_tie[use_tie-1], buf);
|
||||
}
|
||||
}
|
||||
buf += utf8_out(c, buf);
|
||||
count++;
|
||||
}
|
||||
|
||||
if(plist->ph->code != phonSWITCH)
|
||||
{
|
||||
if(plist->synthflags & SFLAG_LENGTHEN)
|
||||
{
|
||||
buf = WritePhMnemonic(buf, phoneme_tab[phonLENGTHEN], NULL, use_ipa, NULL);
|
||||
}
|
||||
if((plist->synthflags & SFLAG_SYLLABLE) && (plist->type != phVOWEL))
|
||||
{
|
||||
// syllablic consonant
|
||||
buf = WritePhMnemonic(buf, phoneme_tab[phonSYLLABIC], NULL, use_ipa, NULL);
|
||||
}
|
||||
if(plist->tone_ph > 0)
|
||||
{
|
||||
buf = WritePhMnemonic(buf, phoneme_tab[plist->tone_ph], NULL, use_ipa, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
len = buf - phon_buf;
|
||||
if((phon_out_ix + len) >= phon_out_size)
|
||||
{
|
||||
// enlarge the phoneme buffer
|
||||
phon_out_size = phon_out_ix + len + N_PHON_OUT;
|
||||
if((phon_out_buf = (char *)realloc(phon_out_buf, phon_out_size)) == NULL)
|
||||
{
|
||||
phon_out_size = 0;
|
||||
return("");
|
||||
}
|
||||
}
|
||||
|
||||
phon_buf[len] = 0;
|
||||
strcpy(&phon_out_buf[phon_out_ix], phon_buf);
|
||||
phon_out_ix += len;
|
||||
}
|
||||
phon_out_buf[phon_out_ix] = 0;
|
||||
|
||||
return(phon_out_buf);
|
||||
} // end of GetTranslatedPhonemeString
|
||||
|
||||
|
||||
|
||||
+15
-11
@@ -1831,17 +1831,24 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null
|
||||
}
|
||||
else
|
||||
{
|
||||
if((!found) && (tensunits == 0))
|
||||
if((hundreds==1) && (tr->langopts.numbers2 & NUM2_OMIT_1_HUNDRED_ONLY) && ((control & 1)==0))
|
||||
{
|
||||
// is there a special pronunciation for exactly n00 ?
|
||||
sprintf(string,"_%dC0",hundreds);
|
||||
found = Lookup(tr, string, ph_digits);
|
||||
// only look for special 100 if there are previous thousands
|
||||
}
|
||||
|
||||
if(!found)
|
||||
else
|
||||
{
|
||||
sprintf(string,"_%dC",hundreds);
|
||||
found = Lookup(tr, string, ph_digits); // is there a specific pronunciation for n-hundred ?
|
||||
if((!found) && (tensunits == 0))
|
||||
{
|
||||
// is there a special pronunciation for exactly n00 ?
|
||||
sprintf(string,"_%dC0",hundreds);
|
||||
found = Lookup(tr, string, ph_digits);
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
sprintf(string,"_%dC",hundreds);
|
||||
found = Lookup(tr, string, ph_digits); // is there a specific pronunciation for n-hundred ?
|
||||
}
|
||||
}
|
||||
|
||||
if(found)
|
||||
@@ -1855,9 +1862,6 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null
|
||||
{
|
||||
if((tr->langopts.numbers & NUM_OMIT_1_HUNDRED) != 0)
|
||||
say_one_hundred = 0;
|
||||
|
||||
if(((tr->langopts.numbers2 & NUM2_OMIT_1_HUNDRED_ONLY) != 0) && ((control & 1)==0))
|
||||
say_one_hundred = 0;
|
||||
}
|
||||
|
||||
if(say_one_hundred != 0)
|
||||
|
||||
+5
-4
@@ -1164,14 +1164,15 @@ 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)
|
||||
{//==============================================================================================================
|
||||
ESPEAK_API const char *espeak_TextToPhonemes(const void **textptr, 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);
|
||||
*textptr = TranslateClause(translator, NULL, *textptr, NULL, NULL);
|
||||
return(GetTranslatedPhonemeString(phonememode));
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-1
@@ -34,7 +34,7 @@
|
||||
#define ESPEAK_API
|
||||
#endif
|
||||
|
||||
#define ESPEAK_API_REVISION 7
|
||||
#define ESPEAK_API_REVISION 9
|
||||
/*
|
||||
Revision 2
|
||||
Added parameter "options" to eSpeakInitialize()
|
||||
@@ -58,6 +58,9 @@ Revision 7 24.Dec.2011
|
||||
Revision 8 26.Apr.2013
|
||||
Added function espeak_TextToPhonemes().
|
||||
|
||||
Revision 9 30.May.2013
|
||||
Changed function espeak_TextToPhonemes().
|
||||
|
||||
*/
|
||||
/********************/
|
||||
/* Initialization */
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.47.11b 28.May.13";
|
||||
const char *version_string = "1.47.11c 31.May.13";
|
||||
const int version_phdata = 0x014709;
|
||||
|
||||
int option_device_number = -1;
|
||||
|
||||
+4
-3
@@ -1865,6 +1865,7 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control)
|
||||
char *voice_change;
|
||||
static FILE *f_text=NULL;
|
||||
static const void *p_text=NULL;
|
||||
const char *phon_out;
|
||||
|
||||
if(control == 4)
|
||||
{
|
||||
@@ -1957,14 +1958,14 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control)
|
||||
if(option_phonemes >= 3)
|
||||
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), phoneme_mode);
|
||||
phon_out = GetTranslatedPhonemeString(phoneme_mode);
|
||||
if(option_phonemes > 0)
|
||||
{
|
||||
fprintf(f_trans,"%s\n",translator->phon_out);
|
||||
fprintf(f_trans,"%s\n",phon_out);
|
||||
}
|
||||
if(phoneme_callback != NULL)
|
||||
{
|
||||
phoneme_callback(translator->phon_out);
|
||||
phoneme_callback(phon_out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1484,7 +1484,7 @@ SetLengthMods(tr,3); // all equal
|
||||
if(name2 == L('m','l'))
|
||||
{
|
||||
tr->letter_bits_offset = OFFSET_MALAYALAM;
|
||||
tr->langopts.numbers = NUM_OMIT_1_THOUSAND;
|
||||
tr->langopts.numbers = NUM_OMIT_1_THOUSAND | NUM_OMIT_1_HUNDRED;
|
||||
tr->langopts.numbers2 = NUM2_OMIT_1_HUNDRED_ONLY;
|
||||
}
|
||||
else
|
||||
|
||||
+2
-2
@@ -3041,7 +3041,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
c = ' ';
|
||||
pre_pause_add = 4;
|
||||
}
|
||||
else if((prev_out == ' ') && IsAlpha(sbuf[ix-2]) && !IsAlpha(prev_in))
|
||||
else if((prev_out == ' ') && IsAlpha(prev_out2) && !IsAlpha(prev_in))
|
||||
{
|
||||
// insert extra space between a word + space + hyphen, to distinguish 'a -2' from 'a-2'
|
||||
sbuf[ix++] = ' ';
|
||||
@@ -3139,7 +3139,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
decimal_sep_count = 1;
|
||||
}
|
||||
}
|
||||
else if((prev_out == ' ') && IsAlpha(sbuf[ix-2]) && !IsAlpha(prev_in))
|
||||
else if((prev_out == ' ') && IsAlpha(prev_out2) && !IsAlpha(prev_in))
|
||||
{
|
||||
// insert extra space between a word and a number, to distinguish 'a 2' from 'a2'
|
||||
sbuf[ix++] = ' ';
|
||||
|
||||
+1
-2
@@ -581,7 +581,6 @@ typedef struct
|
||||
const char *transpose_map;
|
||||
char dictionary_name[40];
|
||||
|
||||
char phon_out[500];
|
||||
char phonemes_repeat[20];
|
||||
int phonemes_repeat_count;
|
||||
int phoneme_tab_ix;
|
||||
@@ -723,7 +722,7 @@ int iswlower2(int c);
|
||||
int iswupper2(int c);
|
||||
int towlower2(unsigned int c);
|
||||
int towupper2(unsigned int c);
|
||||
void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int phoneme_mode);
|
||||
const char *GetTranslatedPhonemeString(int phoneme_mode);
|
||||
const char *WordToString2(unsigned int word);
|
||||
ALPHABET *AlphabetFromChar(int c);
|
||||
ALPHABET *AlphabetFromName(const char *name);
|
||||
|
||||
+4
-3
@@ -406,6 +406,7 @@ void TranslDlg::OnCommand(wxCommandEvent& event)
|
||||
int translate_text = 0;
|
||||
char buf[1000];
|
||||
char phon_out[N_PH_LIST*2];
|
||||
const char *phon_out2;
|
||||
int clause_tone;
|
||||
int clause_count;
|
||||
int use_ipa = 0;
|
||||
@@ -495,11 +496,11 @@ void TranslDlg::OnCommand(wxCommandEvent& event)
|
||||
CalcPitches(translator,clause_tone);
|
||||
CalcLengths(translator);
|
||||
|
||||
GetTranslatedPhonemeString(translator->phon_out, sizeof(translator->phon_out), use_ipa);
|
||||
phon_out2 = GetTranslatedPhonemeString(use_ipa);
|
||||
if(clause_count++ > 0)
|
||||
strcat(phon_out," ||");
|
||||
strcat(phon_out,translator->phon_out);
|
||||
t_phonetic->SetValue(wxString(translator->phon_out,wxConvUTF8));
|
||||
strcat(phon_out, phon_out2);
|
||||
t_phonetic->SetValue(wxString(phon_out2, wxConvUTF8));
|
||||
|
||||
if((n_ph_list + n_phoneme_list) >= N_PH_LIST)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user