mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-07 23:31:26 +00:00
Merge branch 'upstream' into development
Conflicts: dictsource/dict_phonemes phsource/compile_report
This commit is contained in:
+48
-11
@@ -44,6 +44,7 @@
|
||||
|
||||
extern void FindPhonemesUsed(void);
|
||||
extern void DisplayErrorFile(const char *fname);
|
||||
extern int utf8_in(int *c, const char *buf);
|
||||
extern int utf8_out(unsigned int c, char *buf);
|
||||
extern void DrawEnvelopes();
|
||||
extern void ReadPhondataManifest();
|
||||
@@ -157,6 +158,7 @@ static keywtab_t k_properties[] = {
|
||||
|
||||
enum {
|
||||
kPHONEMESTART = 1,
|
||||
kUTF8_BOM,
|
||||
kPROCEDURE,
|
||||
kENDPHONEME,
|
||||
kENDPROCEDURE,
|
||||
@@ -210,6 +212,8 @@ enum {
|
||||
kTUNE_SPLIT,
|
||||
};
|
||||
|
||||
static const char utf8_bom[] = {0xef,0xbb,0xbf,0};
|
||||
|
||||
static keywtab_t k_intonation[] = {
|
||||
{"tune", 0, kTUNE},
|
||||
{"endtune", 0, kENDTUNE},
|
||||
@@ -250,6 +254,7 @@ static keywtab_t keywords[] = {
|
||||
{"phonemenumber",tSTATEMENT, kPHONEMENUMBER},
|
||||
{"phonemetable",tSTATEMENT, kPHONEMETABLE},
|
||||
{"include", tSTATEMENT, kINCLUDE},
|
||||
{utf8_bom, tSTATEMENT, kUTF8_BOM},
|
||||
|
||||
{"phoneme", tSTATEMENT, kPHONEMESTART},
|
||||
{"procedure", tSTATEMENT, kPROCEDURE},
|
||||
@@ -2720,11 +2725,14 @@ int CompilePhoneme(int compile_phoneme)
|
||||
int keyword;
|
||||
int value;
|
||||
int phcode = 0;
|
||||
int flags;
|
||||
int ix;
|
||||
unsigned int c;
|
||||
int start;
|
||||
int count;
|
||||
int c;
|
||||
char *p;
|
||||
char number_buf[12];
|
||||
char ipa_buf[N_ITEM_STRING];
|
||||
char ipa_buf[N_ITEM_STRING+1];
|
||||
PHONEME_TAB phoneme_out2;
|
||||
PHONEME_PROG_LOG phoneme_prog_log;
|
||||
|
||||
@@ -2852,32 +2860,58 @@ int CompilePhoneme(int compile_phoneme)
|
||||
strcpy(item_string," ");
|
||||
|
||||
// copy the string, recognize characters in the form U+9999
|
||||
p = item_string;
|
||||
ix = 0;
|
||||
while((c = *p++) != 0)
|
||||
flags = 0;
|
||||
count = 0;
|
||||
ix = 1;
|
||||
|
||||
for(p=item_string; *p != 0;)
|
||||
{
|
||||
p += utf8_in(&c, p);
|
||||
|
||||
if((c == '|') && (count > 0))
|
||||
{
|
||||
// '|' means don't allow a tie or joiner before this letter
|
||||
flags |= (1 << (count -1));
|
||||
}
|
||||
else
|
||||
if((c=='U') && (p[0]=='+'))
|
||||
{
|
||||
int j;
|
||||
// U+9999
|
||||
memcpy(number_buf,&p[1],4); // U+ should be followed by 4 hex digits
|
||||
p++;
|
||||
memcpy(number_buf,p,4); // U+ should be followed by 4 hex digits
|
||||
number_buf[4] = 0;
|
||||
c = 0;
|
||||
c = '#';
|
||||
sscanf(number_buf,"%x",&c);
|
||||
p += 5;
|
||||
|
||||
// move past the 4 hexdecimal digits
|
||||
for(j=0; j<4; j++)
|
||||
{
|
||||
if(!isalnum(*p))
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
ix += utf8_out(c, &ipa_buf[ix]);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ipa_buf[ix++] = c;
|
||||
ix += utf8_out(c, &ipa_buf[ix]);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
ipa_buf[0] = flags;
|
||||
ipa_buf[ix] = 0;
|
||||
value = strlen(ipa_buf); // number of UTF-8 bytes
|
||||
|
||||
start = 1;
|
||||
if(flags != 0)
|
||||
start = 0; // only include the flags byte if bits are set
|
||||
value = strlen(&ipa_buf[start]); // number of UTF-8 bytes
|
||||
|
||||
*prog_out++ = (i_IPA_NAME << 8) + value;
|
||||
for(ix=0; ix < value; ix += 2)
|
||||
{
|
||||
*prog_out++ = (ipa_buf[ix] << 8) + (ipa_buf[ix+1] & 0xff);
|
||||
*prog_out++ = (ipa_buf[ix+start] << 8) + (ipa_buf[ix+start+1] & 0xff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3400,6 +3434,9 @@ static void CompilePhonemeFiles()
|
||||
|
||||
switch(item)
|
||||
{
|
||||
case kUTF8_BOM:
|
||||
break; // ignore bytes 0xef 0xbb 0xbf
|
||||
|
||||
case kINCLUDE:
|
||||
NextItem(tSTRING);
|
||||
sprintf(buf,"%s%s",path_source,item_string);
|
||||
|
||||
+48
-20
@@ -524,15 +524,14 @@ unsigned short ipa1[96] = {
|
||||
};
|
||||
|
||||
|
||||
char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa)
|
||||
{//=====================================================================================
|
||||
char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags)
|
||||
{//===================================================================================================
|
||||
int c;
|
||||
int mnem;
|
||||
int len;
|
||||
int first;
|
||||
int ix = 0;
|
||||
char *p;
|
||||
unsigned int ipa_control=0; // first byte of ipa string may control the phoneme name interpretation. 0x20 = ignore this phoneme
|
||||
PHONEME_DATA phdata;
|
||||
|
||||
if(ph->code == phonEND_WORD)
|
||||
@@ -564,20 +563,28 @@ char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int
|
||||
InterpretPhoneme(NULL, 0, plist, &phdata, NULL);
|
||||
}
|
||||
|
||||
len = strlen(phdata.ipa_string);
|
||||
p = phdata.ipa_string;
|
||||
if(*p == 0x20)
|
||||
{
|
||||
// indicates no name for this phoneme
|
||||
*phon_out = 0;
|
||||
return(phon_out);
|
||||
}
|
||||
if((*p != 0) && ((*p & 0xff) < 0x20))
|
||||
{
|
||||
// name starts with a flags byte
|
||||
if(flags != NULL)
|
||||
*flags = *p;
|
||||
p++;
|
||||
}
|
||||
|
||||
len = strlen(p);
|
||||
if(len > 0)
|
||||
{
|
||||
if((ipa_control = phdata.ipa_string[0]) > 0x20)
|
||||
{
|
||||
strcpy(&phon_out[ix], phdata.ipa_string);
|
||||
ix += len;
|
||||
}
|
||||
if(ipa_control >= 0x20)
|
||||
{
|
||||
phon_out = &phon_out[ix];
|
||||
*phon_out = 0;
|
||||
return(phon_out); // 0x20 = ignore phoneme
|
||||
}
|
||||
strcpy(phon_out, p);
|
||||
phon_out += len;
|
||||
*phon_out = 0;
|
||||
return(phon_out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,12 +637,17 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa)
|
||||
unsigned int max_len;
|
||||
int phon_out_ix=0;
|
||||
int stress;
|
||||
unsigned int c;
|
||||
int c;
|
||||
char *p;
|
||||
char *buf;
|
||||
int count;
|
||||
int flags;
|
||||
char phon_buf[30];
|
||||
char phon_buf2[30];
|
||||
PHONEME_LIST *plist;
|
||||
|
||||
static const char *stress_chars = "==,,''";
|
||||
static const int char_tie[] = {0x0361, 0x200d}; // combining-double-inverted-breve, zero-width-joiner
|
||||
|
||||
if(phon_out != NULL)
|
||||
{
|
||||
@@ -672,22 +684,38 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa)
|
||||
}
|
||||
}
|
||||
|
||||
buf = WritePhMnemonic(buf, plist->ph, plist, use_ipa);
|
||||
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)
|
||||
{
|
||||
// look for non-inital alphabetic character, but not diacritic, superscript etc.
|
||||
if((count>0) && !(flags & (1 << (count-1))) && ((c < 0x2b0) || (c > 0x36f)) && iswalpha(c))
|
||||
{
|
||||
buf += utf8_out(char_tie[use_ipa-2], 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);
|
||||
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);
|
||||
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);
|
||||
buf = WritePhMnemonic(buf, phoneme_tab[plist->tone_ph], NULL, use_ipa, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-1
@@ -67,6 +67,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"
|
||||
"--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"
|
||||
@@ -362,7 +363,7 @@ int main (int argc, char **argv)
|
||||
{"path", required_argument, 0, 0x107},
|
||||
{"phonout", required_argument, 0, 0x108},
|
||||
{"pho", no_argument, 0, 0x109},
|
||||
{"ipa", no_argument, 0, 0x10a},
|
||||
{"ipa", optional_argument, 0, 0x10a},
|
||||
{"version", no_argument, 0, 0x10b},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
@@ -604,6 +605,17 @@ int main (int argc, char **argv)
|
||||
|
||||
case 0x10a: // --ipa
|
||||
option_phonemes = 3;
|
||||
if(optarg2 != NULL)
|
||||
{
|
||||
value = -1;
|
||||
sscanf(optarg2,"%d",&value);
|
||||
if((value<0) || (value>2))
|
||||
{
|
||||
fprintf(stderr,"Bad value for -ipa=\n");
|
||||
value = 0;
|
||||
}
|
||||
option_phonemes += value;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10b: // -version
|
||||
|
||||
+2
-1
@@ -653,8 +653,9 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
|
||||
alphabet = AlphabetFromChar(letter);
|
||||
if(alphabet != current_alphabet)
|
||||
{
|
||||
// speak the name of the alphabet
|
||||
current_alphabet = alphabet;
|
||||
if((alphabet != NULL) && !(alphabet->flags & AL_DONT_NAME))
|
||||
if((alphabet != NULL) && !(alphabet->flags & AL_DONT_NAME) && (alphabet->offset != translator->letter_bits_offset))
|
||||
{
|
||||
phontab_1 = tr->phoneme_tab_ix;
|
||||
ph_buf2[0] = 0;
|
||||
|
||||
+13
-1
@@ -101,6 +101,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"
|
||||
"--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"
|
||||
@@ -485,7 +486,7 @@ int main (int argc, char **argv)
|
||||
{"path", required_argument, 0, 0x107},
|
||||
{"phonout", required_argument, 0, 0x108},
|
||||
{"pho", no_argument, 0, 0x109},
|
||||
{"ipa", no_argument, 0, 0x10a},
|
||||
{"ipa", optional_argument, 0, 0x10a},
|
||||
{"version", no_argument, 0, 0x10b},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
@@ -723,6 +724,17 @@ int main (int argc, char **argv)
|
||||
|
||||
case 0x10a: // --ipa
|
||||
option_phonemes = 3;
|
||||
if(optarg2 != NULL)
|
||||
{
|
||||
value = -1;
|
||||
sscanf(optarg2,"%d",&value);
|
||||
if((value<0) || (value>2))
|
||||
{
|
||||
fprintf(stderr,"Bad value for -ipa=\n");
|
||||
value = 0;
|
||||
}
|
||||
option_phonemes += value;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10b: // --version
|
||||
|
||||
+62
-62
@@ -82,12 +82,12 @@ void WVoiceChanged(voice_t *wvoice)
|
||||
static int dispatch_audio(short* outbuf, int length, espeak_EVENT* event)
|
||||
{//======================================================================
|
||||
ENTER("dispatch_audio");
|
||||
|
||||
|
||||
int a_wave_can_be_played = fifo_is_command_enabled();
|
||||
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
SHOW("*** dispatch_audio > uid=%d, [write=%p (%d bytes)], sample=%d, a_wave_can_be_played = %d\n",
|
||||
(event) ? event->unique_identifier : 0, wave_test_get_write_buffer(), 2*length,
|
||||
SHOW("*** dispatch_audio > uid=%d, [write=%p (%d bytes)], sample=%d, a_wave_can_be_played = %d\n",
|
||||
(event) ? event->unique_identifier : 0, wave_test_get_write_buffer(), 2*length,
|
||||
(event) ? event->sample : 0,
|
||||
a_wave_can_be_played);
|
||||
#endif
|
||||
@@ -134,8 +134,8 @@ static int dispatch_audio(short* outbuf, int length, espeak_EVENT* event)
|
||||
while(a_wave_can_be_played) {
|
||||
// TBD: some event are filtered here but some insight might be given
|
||||
// TBD: in synthesise.cpp for avoiding to create WORDs with size=0.
|
||||
// TBD: For example sentence "or ALT)." returns three words
|
||||
// "or", "ALT" and "".
|
||||
// TBD: For example sentence "or ALT)." returns three words
|
||||
// "or", "ALT" and "".
|
||||
// TBD: the last one has its size=0.
|
||||
if (event && (event->type == espeakEVENT_WORD) && (event->length==0))
|
||||
{
|
||||
@@ -171,7 +171,7 @@ static int dispatch_audio(short* outbuf, int length, espeak_EVENT* event)
|
||||
}
|
||||
|
||||
SHOW_TIME("LEAVE dispatch_audio\n");
|
||||
|
||||
|
||||
return (a_wave_can_be_played==0); // 1 = stop synthesis, -1 = error
|
||||
}
|
||||
|
||||
@@ -183,12 +183,12 @@ static int create_events(short* outbuf, int length, espeak_EVENT* event, uint32_
|
||||
int i=0;
|
||||
|
||||
// The audio data are written to the output device.
|
||||
// The list of events in event_list (index: event_list_ix) is read:
|
||||
// The list of events in event_list (index: event_list_ix) is read:
|
||||
// Each event is declared to the "event" object which stores them internally.
|
||||
// The event object is responsible of calling the external callback
|
||||
// as soon as the relevant audio sample is played.
|
||||
|
||||
do
|
||||
do
|
||||
{ // for each event
|
||||
espeak_EVENT* event;
|
||||
if (event_list_ix == 0)
|
||||
@@ -231,7 +231,7 @@ int sync_espeak_terminated_msg( uint32_t unique_identifier, void* user_data)
|
||||
|
||||
if (my_mode==AUDIO_OUTPUT_PLAYBACK)
|
||||
{
|
||||
while(1)
|
||||
while(1)
|
||||
{
|
||||
espeak_ERROR a_error = event_declare(event_list);
|
||||
if (a_error != EE_BUFFER_FULL)
|
||||
@@ -290,14 +290,14 @@ static void select_output(espeak_AUDIO_OUTPUT output_type)
|
||||
int GetFileLength(const char *filename)
|
||||
{//====================================
|
||||
struct stat statbuf;
|
||||
|
||||
|
||||
if(stat(filename,&statbuf) != 0)
|
||||
return(0);
|
||||
|
||||
|
||||
if((statbuf.st_mode & S_IFMT) == S_IFDIR)
|
||||
// if(S_ISDIR(statbuf.st_mode))
|
||||
return(-2); // a directory
|
||||
|
||||
|
||||
return(statbuf.st_size);
|
||||
} // end of GetFileLength
|
||||
|
||||
@@ -337,7 +337,7 @@ static void init_path(const char *path)
|
||||
{
|
||||
sprintf(path_home,"%s/espeak-data",env);
|
||||
if(GetFileLength(path_home) == -2)
|
||||
return; // an espeak-data directory exists
|
||||
return; // an espeak-data directory exists
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
@@ -362,7 +362,7 @@ static void init_path(const char *path)
|
||||
{
|
||||
snprintf(path_home,sizeof(path_home),"%s/espeak-data",env);
|
||||
if(GetFileLength(path_home) == -2)
|
||||
return; // an espeak-data directory exists
|
||||
return; // an espeak-data directory exists
|
||||
}
|
||||
|
||||
snprintf(path_home,sizeof(path_home),"%s/espeak-data",getenv("HOME"));
|
||||
@@ -561,21 +561,21 @@ void MarkerEvent(int type, unsigned int char_position, int value, int value2, un
|
||||
ENTER("MarkerEvent");
|
||||
espeak_EVENT *ep;
|
||||
double time;
|
||||
|
||||
|
||||
if((event_list == NULL) || (event_list_ix >= (n_event_list-2)))
|
||||
return;
|
||||
|
||||
|
||||
ep = &event_list[event_list_ix++];
|
||||
ep->type = (espeak_EVENT_TYPE)type;
|
||||
ep->unique_identifier = my_unique_identifier;
|
||||
ep->user_data = my_user_data;
|
||||
ep->text_position = char_position & 0xffffff;
|
||||
ep->length = char_position >> 24;
|
||||
|
||||
|
||||
time = (double(count_samples + mbrola_delay + (out_ptr - out_start)/2)*1000.0)/samplerate;
|
||||
ep->audio_position = int(time);
|
||||
ep->sample = (count_samples + mbrola_delay + (out_ptr - out_start)/2);
|
||||
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
SHOW("MarkerEvent > count_samples=%d, out_ptr=%x, out_start=0x%x\n",count_samples, out_ptr, out_start);
|
||||
SHOW("*** MarkerEvent > type=%s, uid=%d, text_pos=%d, length=%d, audio_position=%d, sample=%d\n",
|
||||
@@ -605,22 +605,22 @@ void MarkerEvent(int type, unsigned int char_position, int value, int value2, un
|
||||
|
||||
|
||||
|
||||
espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size,
|
||||
unsigned int position, espeak_POSITION_TYPE position_type,
|
||||
espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size,
|
||||
unsigned int position, espeak_POSITION_TYPE position_type,
|
||||
unsigned int end_position, unsigned int flags, void* user_data)
|
||||
{//===========================================================================
|
||||
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ENTER("sync_espeak_Synth");
|
||||
SHOW("sync_espeak_Synth > position=%d, position_type=%d, end_position=%d, flags=%d, user_data=0x%x, text=%s\n", position, position_type, end_position, flags, user_data, text);
|
||||
#endif
|
||||
|
||||
espeak_ERROR aStatus;
|
||||
|
||||
|
||||
InitText(flags);
|
||||
my_unique_identifier = unique_identifier;
|
||||
my_user_data = user_data;
|
||||
|
||||
|
||||
for (int i=0; i < N_SPEECH_PARAM; i++)
|
||||
saved_parameters[i] = param_stack[0].parameter[i];
|
||||
|
||||
@@ -629,26 +629,26 @@ espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text,
|
||||
case POS_CHARACTER:
|
||||
skip_characters = position;
|
||||
break;
|
||||
|
||||
|
||||
case POS_WORD:
|
||||
skip_words = position;
|
||||
break;
|
||||
|
||||
|
||||
case POS_SENTENCE:
|
||||
skip_sentences = position;
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
if(skip_characters || skip_words || skip_sentences)
|
||||
skipping_text = 1;
|
||||
|
||||
|
||||
end_character_position = end_position;
|
||||
|
||||
|
||||
aStatus = Synthesize(unique_identifier, text, flags);
|
||||
#ifdef USE_ASYNC
|
||||
wave_flush(my_audio);
|
||||
#endif
|
||||
|
||||
|
||||
SHOW_TIME("LEAVE sync_espeak_Synth");
|
||||
return aStatus;
|
||||
} // end of sync_espeak_Synth
|
||||
@@ -656,29 +656,29 @@ espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text,
|
||||
|
||||
|
||||
|
||||
espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size,
|
||||
const char *index_mark, unsigned int end_position,
|
||||
espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size,
|
||||
const char *index_mark, unsigned int end_position,
|
||||
unsigned int flags, void* user_data)
|
||||
{//=========================================================================
|
||||
espeak_ERROR aStatus;
|
||||
|
||||
|
||||
InitText(flags);
|
||||
|
||||
|
||||
my_unique_identifier = unique_identifier;
|
||||
my_user_data = user_data;
|
||||
|
||||
|
||||
if(index_mark != NULL)
|
||||
{
|
||||
strncpy0(skip_marker, index_mark, sizeof(skip_marker));
|
||||
skipping_text = 1;
|
||||
}
|
||||
|
||||
|
||||
end_character_position = end_position;
|
||||
|
||||
|
||||
|
||||
|
||||
aStatus = Synthesize(unique_identifier, text, flags | espeakSSML);
|
||||
SHOW_TIME("LEAVE sync_espeak_Synth_Mark");
|
||||
|
||||
|
||||
return (aStatus);
|
||||
} // end of sync_espeak_Synth_Mark
|
||||
|
||||
@@ -710,7 +710,7 @@ void sync_espeak_Char(wchar_t character)
|
||||
char buf[80];
|
||||
my_unique_identifier = 0;
|
||||
my_user_data = NULL;
|
||||
|
||||
|
||||
sprintf(buf,"<say-as interpret-as=\"tts:char\">&#%d;</say-as>",character);
|
||||
Synthesize(0, buf,espeakSSML);
|
||||
}
|
||||
@@ -722,7 +722,7 @@ void sync_espeak_SetPunctuationList(const wchar_t *punctlist)
|
||||
// Set the list of punctuation which are spoken for "some".
|
||||
my_unique_identifier = 0;
|
||||
my_user_data = NULL;
|
||||
|
||||
|
||||
wcsncpy(option_punctlist, punctlist, N_PUNCTLIST);
|
||||
option_punctlist[N_PUNCTLIST-1] = 0;
|
||||
} // end of sync_espeak_SetPunctuationList
|
||||
@@ -771,7 +771,7 @@ ENTER("espeak_Initialize");
|
||||
setlocale(LC_CTYPE,"");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
init_path(path);
|
||||
initialise(options);
|
||||
select_output(output_type);
|
||||
@@ -788,30 +788,30 @@ ENTER("espeak_Initialize");
|
||||
outbuf = (unsigned char*)realloc(outbuf,outbuf_size);
|
||||
if((out_start = outbuf) == NULL)
|
||||
return(EE_INTERNAL_ERROR);
|
||||
|
||||
|
||||
// allocate space for event list. Allow 200 events per second.
|
||||
// Add a constant to allow for very small buf_length
|
||||
n_event_list = (buf_length*200)/1000 + 20;
|
||||
if((event_list = (espeak_EVENT *)realloc(event_list,sizeof(espeak_EVENT) * n_event_list)) == NULL)
|
||||
return(EE_INTERNAL_ERROR);
|
||||
|
||||
|
||||
option_phonemes = 0;
|
||||
option_mbrola_phonemes = 0;
|
||||
option_phoneme_events = (options & (espeakINITIALIZE_PHONEME_EVENTS | espeakINITIALIZE_PHONEME_IPA));
|
||||
|
||||
VoiceReset(0);
|
||||
// SetVoiceByName("default");
|
||||
|
||||
|
||||
for(param=0; param<N_SPEECH_PARAM; param++)
|
||||
param_stack[0].parameter[param] = saved_parameters[param] = param_defaults[param];
|
||||
|
||||
|
||||
SetParameter(espeakRATE,175,0);
|
||||
SetParameter(espeakVOLUME,100,0);
|
||||
SetParameter(espeakCAPITALS,option_capitals,0);
|
||||
SetParameter(espeakPUNCTUATION,option_punctuation,0);
|
||||
SetParameter(espeakWORDGAP,0,0);
|
||||
// DoVoiceChange(voice);
|
||||
|
||||
|
||||
#ifdef USE_ASYNC
|
||||
fifo_init();
|
||||
#endif
|
||||
@@ -821,10 +821,10 @@ ENTER("espeak_Initialize");
|
||||
|
||||
|
||||
|
||||
ESPEAK_API espeak_ERROR espeak_Synth(const void *text, size_t size,
|
||||
unsigned int position,
|
||||
ESPEAK_API espeak_ERROR espeak_Synth(const void *text, size_t size,
|
||||
unsigned int position,
|
||||
espeak_POSITION_TYPE position_type,
|
||||
unsigned int end_position, unsigned int flags,
|
||||
unsigned int end_position, unsigned int flags,
|
||||
unsigned int* unique_identifier, void* user_data)
|
||||
{//=====================================================================================
|
||||
#ifdef DEBUG_ENABLED
|
||||
@@ -885,10 +885,10 @@ ESPEAK_API espeak_ERROR espeak_Synth(const void *text, size_t size,
|
||||
|
||||
|
||||
|
||||
ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text, size_t size,
|
||||
const char *index_mark,
|
||||
unsigned int end_position,
|
||||
unsigned int flags,
|
||||
ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text, size_t size,
|
||||
const char *index_mark,
|
||||
unsigned int end_position,
|
||||
unsigned int flags,
|
||||
unsigned int* unique_identifier,
|
||||
void* user_data)
|
||||
{//=========================================================================
|
||||
@@ -919,15 +919,15 @@ ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text, size_t size,
|
||||
|
||||
#ifdef USE_ASYNC
|
||||
// Create the mark command
|
||||
t_espeak_command* c1 = create_espeak_mark(text, size, index_mark, end_position,
|
||||
t_espeak_command* c1 = create_espeak_mark(text, size, index_mark, end_position,
|
||||
flags, user_data);
|
||||
|
||||
|
||||
// Retrieve the unique identifier
|
||||
*unique_identifier = c1->u.my_mark.unique_identifier;
|
||||
|
||||
|
||||
// Create the "terminated msg" command (same uid)
|
||||
t_espeak_command* c2 = create_espeak_terminated_msg(*unique_identifier, user_data);
|
||||
|
||||
|
||||
// Try to add these 2 commands (single transaction)
|
||||
if (c1 && c2)
|
||||
{
|
||||
@@ -1152,15 +1152,15 @@ ESPEAK_API void espeak_SetPhonemeTrace(int value, FILE *stream)
|
||||
value=0 No phoneme output (default)
|
||||
value=1 Output the translated phoneme symbols for the text
|
||||
value=2 as (1), but also output a trace of how the translation was done (matching rules and list entries)
|
||||
value=3 as (1), but produces IPA phoneme names rather than ascii
|
||||
value=3 as (1), but produces IPA phoneme names rather than ascii
|
||||
bit 4: produce mbrola pho data
|
||||
*/
|
||||
option_phonemes = value & 3;
|
||||
option_phonemes = value & 7;
|
||||
option_mbrola_phonemes = value & 16;
|
||||
f_trans = stream;
|
||||
if(stream == NULL)
|
||||
f_trans = stderr;
|
||||
|
||||
|
||||
} // end of espeak_SetPhonemes
|
||||
|
||||
|
||||
@@ -1269,4 +1269,4 @@ ESPEAK_API const char *espeak_Info(const char **ptr)
|
||||
|
||||
#pragma GCC visibility pop
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2007 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 *
|
||||
@@ -490,7 +490,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
|
||||
if(ph->code != phonEND_WORD)
|
||||
{
|
||||
char phoneme_name[16];
|
||||
WritePhMnemonic(phoneme_name, p->ph, p, option_phoneme_events & espeakINITIALIZE_PHONEME_IPA);
|
||||
WritePhMnemonic(phoneme_name, p->ph, p, option_phoneme_events & espeakINITIALIZE_PHONEME_IPA, NULL);
|
||||
DoPhonemeMarker(espeakEVENT_PHONEME, (p->sourceix & 0x7ff) + clause_start_char, 0, phoneme_name);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -35,8 +35,8 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.46.39 01.Mar.13";
|
||||
const int version_phdata = 0x014639;
|
||||
const char *version_string = "1.46.41 03.Mar.13";
|
||||
const int version_phdata = 0x014640;
|
||||
|
||||
int option_device_number = -1;
|
||||
FILE *f_logespeak = NULL;
|
||||
|
||||
+4
-4
@@ -1438,7 +1438,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePhMnemonic(phoneme_name, p->ph, p, use_ipa);
|
||||
WritePhMnemonic(phoneme_name, p->ph, p, use_ipa, NULL);
|
||||
DoPhonemeMarker(espeakEVENT_PHONEME, sourceix, 0, phoneme_name);
|
||||
done_phoneme_marker = 1;
|
||||
}
|
||||
@@ -1751,7 +1751,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
|
||||
if((option_phoneme_events) && (done_phoneme_marker == 0))
|
||||
{
|
||||
WritePhMnemonic(phoneme_name, p->ph, p, use_ipa);
|
||||
WritePhMnemonic(phoneme_name, p->ph, p, use_ipa, NULL);
|
||||
DoPhonemeMarker(espeakEVENT_PHONEME, sourceix, 0, phoneme_name);
|
||||
}
|
||||
|
||||
@@ -1937,8 +1937,8 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control)
|
||||
if((option_phonemes > 0) || (phoneme_callback != NULL))
|
||||
{
|
||||
int use_ipa = 0;
|
||||
if(option_phonemes == 3)
|
||||
use_ipa = 1;
|
||||
if(option_phonemes >= 3)
|
||||
use_ipa = option_phonemes-2; // 1=ipa, 2=ipa with tie, 3=ipa with ZWJ
|
||||
|
||||
GetTranslatedPhonemeString(translator->phon_out, sizeof(translator->phon_out), use_ipa);
|
||||
if(option_phonemes > 0)
|
||||
|
||||
+15
-3
@@ -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 *
|
||||
@@ -163,7 +163,7 @@ static void SetLetterBitsRange(Translator *tr, int group, int first, int last)
|
||||
|
||||
// ignore these characters
|
||||
static const unsigned short chars_ignore_default[] = {
|
||||
0xad, 1, // soft hyphtn
|
||||
0xad, 1, // soft hyphen
|
||||
0x200c, 1, // zero width non-joiner
|
||||
0x200d, 1, // zero width joiner
|
||||
0, 0 };
|
||||
@@ -436,13 +436,16 @@ Translator *SelectTranslator(const char *name)
|
||||
int name2 = 0;
|
||||
Translator *tr;
|
||||
|
||||
static const short stress_lengths_equal[8] = {250, 250, 250, 250, 0, 0, 250, 250};
|
||||
static const unsigned char stress_amps_equal[8] = {18,18, 18,18, 18,18, 18,18 };
|
||||
|
||||
static const short stress_lengths_fr[8] = {190, 170, 190, 200, 0, 0, 190, 240};
|
||||
static const unsigned char stress_amps_fr[8] = {18,16, 18,18, 18,18, 18,18 };
|
||||
|
||||
static const unsigned char stress_amps_sk[8] = {17,16, 20,20, 20,22, 22,21 };
|
||||
static const short stress_lengths_sk[8] = {190,190, 210,210, 0,0, 210,210};
|
||||
|
||||
static const short stress_lengths_ta[8] = {200, 200, 210, 210, 0, 0, 230, 230};
|
||||
static const short stress_lengths_ta[8] = {240, 240, 250, 250, 0, 0, 270, 270};
|
||||
static const unsigned char stress_amps_ta[8] = {18,18, 18,18, 20,20, 22,22 };
|
||||
|
||||
// convert name string into a word of up to 4 characters, for the switch()
|
||||
@@ -836,8 +839,17 @@ Translator *SelectTranslator(const char *name)
|
||||
{
|
||||
tr->letter_bits_offset = OFFSET_GURMUKHI;
|
||||
}
|
||||
else
|
||||
if(name2 == L('g','u'))
|
||||
{
|
||||
SetupTranslator(tr,stress_lengths_equal,stress_amps_equal);
|
||||
tr->letter_bits_offset = OFFSET_GUJARATI;
|
||||
tr->langopts.stress_rule = STRESSPOSN_2R;
|
||||
}
|
||||
else
|
||||
if(name2 == L('n','e'))
|
||||
{
|
||||
SetupTranslator(tr,stress_lengths_equal,stress_amps_equal);
|
||||
tr->langopts.break_numbers = 0x2aaaa8;
|
||||
tr->langopts.max_digits = 22;
|
||||
tr->langopts.numbers2 |= NUM2_ENGLISH_NUMERALS;
|
||||
|
||||
+15
-11
@@ -3309,17 +3309,21 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
*pn++ = tr->langopts.thousands_sep;
|
||||
}
|
||||
*pn++ = ' ';
|
||||
if(tr->langopts.break_numbers & (1 << (nx-1)))
|
||||
{
|
||||
// the next group only has 1 digits (i.e. NUM2_10000), make it three
|
||||
*pn++ = '0';
|
||||
*pn++ = '0';
|
||||
}
|
||||
if(tr->langopts.break_numbers & (1 << (nx-2)))
|
||||
{
|
||||
// the next group only has 2 digits (i.e. NUM2_10000), make it three
|
||||
*pn++ = '0';
|
||||
}
|
||||
|
||||
if((words[ix].flags & FLAG_INDIVIDUAL_DIGITS) == 0)
|
||||
{
|
||||
if(tr->langopts.break_numbers & (1 << (nx-1)))
|
||||
{
|
||||
// the next group only has 1 digits, make it three
|
||||
*pn++ = '0';
|
||||
*pn++ = '0';
|
||||
}
|
||||
if(tr->langopts.break_numbers & (1 << (nx-2)))
|
||||
{
|
||||
// the next group only has 2 digits (eg. Indian languages), make it three
|
||||
*pn++ = '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pw--;
|
||||
|
||||
+1
-1
@@ -721,7 +721,7 @@ int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix
|
||||
void SetVoiceStack(espeak_VOICE *v, const char *variant_name);
|
||||
void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata);
|
||||
void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata);
|
||||
char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa);
|
||||
char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags);
|
||||
|
||||
extern FILE *f_trans; // for logging
|
||||
extern FILE *f_logespeak;
|
||||
|
||||
Reference in New Issue
Block a user