mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-14 09:37:47 +00:00
Merge branch 'master' into android
This commit is contained in:
+9
-1
@@ -122,6 +122,7 @@ static keywtab_t k_properties[] = {
|
||||
{"isNasal", 0, phNASAL},
|
||||
{"isLiquid", 0, phLIQUID},
|
||||
{"isUStop", 0, phSTOP},
|
||||
{"isVStop", 0, phVSTOP},
|
||||
{"isVFricative", 0, phVFRICATIVE},
|
||||
|
||||
{"isPalatal", 0, i_isPalatal},
|
||||
@@ -294,7 +295,7 @@ static keywtab_t keywords[] = {
|
||||
{"Continue", tSTATEMENT, kCONTINUE},
|
||||
|
||||
{"ChangePhoneme", tINSTRN1, i_CHANGE_PHONEME},
|
||||
{"ReplaceNextPhoneme", tINSTRN1, i_REPLACE_NEXT_PHONEME},
|
||||
{"ChangeNextPhoneme", tINSTRN1, i_REPLACE_NEXT_PHONEME},
|
||||
{"InsertPhoneme", tINSTRN1, i_INSERT_PHONEME},
|
||||
{"AppendPhoneme", tINSTRN1, i_APPEND_PHONEME},
|
||||
{"IfNextVowelAppend", tINSTRN1, i_APPEND_IFNEXTVOWEL},
|
||||
@@ -1133,6 +1134,9 @@ static unsigned int StringToWord(const char *string)
|
||||
unsigned char c;
|
||||
unsigned int word;
|
||||
|
||||
if(string==NULL)
|
||||
return(0);
|
||||
|
||||
word = 0;
|
||||
for(ix=0; ix<4; ix++)
|
||||
{
|
||||
@@ -3496,6 +3500,10 @@ static void CompilePhonemeFiles()
|
||||
strncpy0(current_fname,item_string,sizeof(current_fname));
|
||||
linenum = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Missing file: %s", item_string);
|
||||
}
|
||||
break;
|
||||
|
||||
case kPHONEMETABLE:
|
||||
|
||||
+21
-6
@@ -50,8 +50,9 @@ static char *hash_chains[N_HASH_DICT];
|
||||
static char letterGroupsDefined[N_LETTER_GROUPS];
|
||||
|
||||
MNEM_TAB mnem_rules[] = {
|
||||
{"unpr", 0x01},
|
||||
{"noprefix", 0x02}, // rule fails if a prefix has been removed
|
||||
{"unpr", DOLLAR_UNPR},
|
||||
{"noprefix", DOLLAR_NOPREFIX}, // rule fails if a prefix has been removed
|
||||
{"list", DOLLAR_LIST}, // a pronunciation is given in the *_list file
|
||||
|
||||
{"w_alt1", 0x11},
|
||||
{"w_alt2", 0x12},
|
||||
@@ -95,6 +96,7 @@ MNEM_TAB mnem_flags[] = {
|
||||
{"$strend", 9}, // full stress if at end of clause
|
||||
{"$strend2", 10}, // full stress if at end of clause, or only followed by unstressed
|
||||
{"$unstressend",11}, // reduce stress at end of clause
|
||||
{"$accent_before",12}, // used with accent names, say this accent name before the letter name
|
||||
{"$abbrev", 13}, // use this pronuciation rather than split into letters
|
||||
|
||||
// language specific
|
||||
@@ -314,6 +316,7 @@ char *DecodeRule(const char *group_chars, int group_length, char *rule, int cont
|
||||
value = *rule++ & 0xff;
|
||||
if((value != 0x01) || (control & FLAG_UNPRON_TEST))
|
||||
{
|
||||
// TODO write the string backwards if in RULE_PRE
|
||||
p[0] = '$';
|
||||
name = LookupMnemName(mnem_rules, value);
|
||||
strcpy(&p[1],name);
|
||||
@@ -1102,21 +1105,33 @@ static void copy_rule_string(char *string, int *state_out)
|
||||
break;
|
||||
|
||||
case '$':
|
||||
output[ix++] = RULE_DOLLAR;
|
||||
c = 0;
|
||||
value = 0;
|
||||
mr = mnem_rules;
|
||||
while(mr->mnem != NULL)
|
||||
{
|
||||
len = strlen(mr->mnem);
|
||||
if(memcmp(p, mr->mnem, len) == 0)
|
||||
{
|
||||
c = mr->value;
|
||||
value = mr->value;
|
||||
p += len;
|
||||
break;
|
||||
}
|
||||
mr++;
|
||||
}
|
||||
if(c == 0)
|
||||
|
||||
if(state == 1)
|
||||
{
|
||||
// pre-rule, put the number before the RULE_DOLLAR
|
||||
output[ix++] = value;
|
||||
c = RULE_DOLLAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
output[ix++] = RULE_DOLLAR;
|
||||
c = value;
|
||||
}
|
||||
|
||||
if(value == 0)
|
||||
{
|
||||
fprintf(f_log,"%5d: $ command not recognized\n",linenum);
|
||||
error_count++;
|
||||
|
||||
+46
-13
@@ -1933,6 +1933,7 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_
|
||||
int add_points;
|
||||
int command;
|
||||
int check_atstart;
|
||||
unsigned int *flags;
|
||||
|
||||
MatchRecord match;
|
||||
static MatchRecord best;
|
||||
@@ -2170,11 +2171,11 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_
|
||||
|
||||
case RULE_DOLLAR:
|
||||
command = *rule++;
|
||||
if(command == 0x01)
|
||||
if(command == DOLLAR_UNPR)
|
||||
{
|
||||
match.end_type = SUFX_UNPRON; // $unpron
|
||||
}
|
||||
else if(command == 0x02) // $noprefix
|
||||
else if(command == DOLLAR_NOPREFIX) // $noprefix
|
||||
{
|
||||
if(word_flags & FLAG_PREFIX_REMOVED)
|
||||
failed = 1; // a prefix has been removed
|
||||
@@ -2189,16 +2190,20 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_
|
||||
else
|
||||
failed = 1;
|
||||
}
|
||||
else if((command & 0xf0) == 0x20)
|
||||
else if(((command & 0xf0) == 0x20) || (command == DOLLAR_LIST))
|
||||
{
|
||||
// $p_alt
|
||||
// $list or $p_alt
|
||||
// make a copy of the word up to the post-match characters
|
||||
ix = *word - word_start + consumed + group_length + 1;
|
||||
memcpy(word_buf, word_start-1, ix);
|
||||
word_buf[ix] = ' ';
|
||||
word_buf[ix+1] = 0;
|
||||
LookupFlags(tr, &word_buf[1], &flags);
|
||||
|
||||
if(LookupFlags(tr, &word_buf[1]) & (1 << (BITNUM_FLAG_ALT + (command & 0xf))))
|
||||
if((command == DOLLAR_LIST) && (flags[0] & FLAG_FOUND) && !(flags[1] & FLAG_ONLY))
|
||||
add_points = 23;
|
||||
else
|
||||
if(flags[0] & (1 << (BITNUM_FLAG_ALT + (command & 0xf))))
|
||||
add_points = 23;
|
||||
else
|
||||
failed = 1;
|
||||
@@ -2412,6 +2417,28 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_
|
||||
failed = 1;
|
||||
break;
|
||||
|
||||
case RULE_DOLLAR:
|
||||
command = *rule++;
|
||||
if((command==DOLLAR_LIST) || ((command & 0xf0) == 0x20))
|
||||
{
|
||||
// $list or $p_alt
|
||||
// make a copy of the word up to the current character
|
||||
ix = *word - word_start + 1;
|
||||
memcpy(word_buf, word_start-1, ix);
|
||||
word_buf[ix] = ' ';
|
||||
word_buf[ix+1] = 0;
|
||||
LookupFlags(tr, &word_buf[1], &flags);
|
||||
|
||||
if((command==DOLLAR_LIST) && (flags[0] & FLAG_FOUND) && !(flags[1] & FLAG_ONLY))
|
||||
add_points = 23;
|
||||
else
|
||||
if(flags[0] & (1 << (BITNUM_FLAG_ALT + (command & 0xf))))
|
||||
add_points = 23;
|
||||
else
|
||||
failed = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case RULE_SYLLABLE:
|
||||
/* more than specified number of vowels to the left */
|
||||
syllable_count = 1;
|
||||
@@ -3565,8 +3592,10 @@ int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *f
|
||||
extern char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes
|
||||
|
||||
int Lookup(Translator *tr, const char *word, char *ph_out)
|
||||
{//===================================================
|
||||
int found;
|
||||
{//=========================================================
|
||||
// Look up in *_list, returns dictionary flags[0] and phonemes
|
||||
|
||||
int flags0;
|
||||
unsigned int flags[2];
|
||||
int say_as;
|
||||
char *word1 = (char *)word;
|
||||
@@ -3574,7 +3603,10 @@ int Lookup(Translator *tr, const char *word, char *ph_out)
|
||||
|
||||
flags[0] = 0;
|
||||
flags[1] = FLAG_LOOKUP_SYMBOL;
|
||||
found = LookupDictList(tr, &word1, ph_out, flags, FLAG_ALLOW_TEXTMODE, NULL);
|
||||
if((flags0 = LookupDictList(tr, &word1, ph_out, flags, FLAG_ALLOW_TEXTMODE, NULL)) != 0)
|
||||
{
|
||||
flags0 = flags[0];
|
||||
}
|
||||
|
||||
if(flags[0] & FLAG_TEXTMODE)
|
||||
{
|
||||
@@ -3582,22 +3614,23 @@ int Lookup(Translator *tr, const char *word, char *ph_out)
|
||||
option_sayas = 0; // don't speak replacement word as letter names
|
||||
text[0] = 0;
|
||||
strncpy0(&text[1], word1, sizeof(text));
|
||||
found = TranslateWord(tr, &text[1], 0, NULL, NULL);
|
||||
flags0 = TranslateWord(tr, &text[1], 0, NULL, NULL);
|
||||
strcpy(ph_out, word_phonemes);
|
||||
option_sayas = say_as;
|
||||
}
|
||||
return(found);
|
||||
return(flags0);
|
||||
}
|
||||
|
||||
|
||||
int LookupFlags(Translator *tr, const char *word)
|
||||
{//==============================================
|
||||
int LookupFlags(Translator *tr, const char *word, unsigned int **flags_out)
|
||||
{//===========================================================================
|
||||
char buf[100];
|
||||
static unsigned int flags[2];
|
||||
char *word1 = (char *)word;
|
||||
|
||||
flags[0] = flags[1] = 0;
|
||||
LookupDictList(tr, &word1, buf, flags, 0, NULL);
|
||||
*flags_out = flags;
|
||||
return(flags[0]);
|
||||
}
|
||||
|
||||
@@ -3658,7 +3691,7 @@ int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy)
|
||||
}
|
||||
|
||||
// remove bytes from the end of the word and replace them by spaces
|
||||
for(i=0; (i<len_ending) && (i < sizeof(ending)-1); i++)
|
||||
for(i=0; (i<len_ending) && (i < (int)sizeof(ending)-1); i++)
|
||||
{
|
||||
ending[i] = word_end[i];
|
||||
word_end[i] = ' ';
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
|
||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington *
|
||||
* email: jonsd@users.sourceforge.net *
|
||||
* Copyright (C) 2013 by Reece H. Dunn *
|
||||
* *
|
||||
@@ -139,6 +139,12 @@ if(argc > 1)
|
||||
if(strcmp(param,"--compile")==0)
|
||||
{
|
||||
samplerate_native = samplerate = 22050;
|
||||
LoadPhData(NULL);
|
||||
if(LoadVoice("", 0) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Failed to load default voice\n");
|
||||
exit(1);
|
||||
}
|
||||
CompilePhonemeData();
|
||||
CompileIntonation();
|
||||
}
|
||||
|
||||
+21
-9
@@ -77,15 +77,15 @@ static int number_control;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int flags;
|
||||
int accent_flags; // bit 0, say before the letter name
|
||||
} ACCENTS;
|
||||
|
||||
// these are tokens to look up in the *_list file.
|
||||
static ACCENTS accents_tab[] = {
|
||||
{"_lig", 1},
|
||||
{"_smc", 1}, // smallcap
|
||||
{"_tur", 1}, // turned
|
||||
{"_rev", 1}, // reversed
|
||||
{"_smc", 0}, // smallcap
|
||||
{"_tur", 0}, // turned
|
||||
{"_rev", 0}, // reversed
|
||||
{"_crl", 0}, // curl
|
||||
|
||||
{"_acu", 0}, // acute
|
||||
@@ -423,6 +423,7 @@ void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf)
|
||||
int accent_data = 0;
|
||||
int accent1 = 0;
|
||||
int accent2 = 0;
|
||||
int flags1, flags2;
|
||||
int basic_letter;
|
||||
int letter2=0;
|
||||
char ph_letter1[30];
|
||||
@@ -460,19 +461,19 @@ void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf)
|
||||
}
|
||||
|
||||
|
||||
if(Lookup(tr, accents_tab[accent1].name, ph_accent1) != 0)
|
||||
if((flags1 = Lookup(tr, accents_tab[accent1].name, ph_accent1)) != 0)
|
||||
{
|
||||
|
||||
if(LookupLetter2(tr, basic_letter, ph_letter1) != 0)
|
||||
{
|
||||
if(accent2 != 0)
|
||||
{
|
||||
if(Lookup(tr, accents_tab[accent2].name, ph_accent2) == 0)
|
||||
if((flags2 = Lookup(tr, accents_tab[accent2].name, ph_accent2)) == 0)
|
||||
{
|
||||
// break;
|
||||
}
|
||||
|
||||
if(accents_tab[accent2].flags & 1)
|
||||
if(flags2 & FLAG_ACCENT_BEFORE)
|
||||
{
|
||||
strcpy(ph_buf,ph_accent2);
|
||||
ph_buf += strlen(ph_buf);
|
||||
@@ -489,7 +490,7 @@ void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf)
|
||||
{
|
||||
if(accent1 == 0)
|
||||
strcpy(ph_buf, ph_letter1);
|
||||
else if((tr->langopts.accents & 1) || (accents_tab[accent1].flags & 1))
|
||||
else if((tr->langopts.accents & 1) || (flags1 & FLAG_ACCENT_BEFORE) || (accents_tab[accent1].accent_flags & 1))
|
||||
sprintf(ph_buf,"%s%c%c%s", ph_accent1, phonPAUSE_VSHORT, phonSTRESS_P, ph_letter1);
|
||||
else
|
||||
sprintf(ph_buf,"%c%s%c%s%c", phonSTRESS_2, ph_letter1, phonPAUSE_VSHORT, ph_accent1, phonPAUSE_VSHORT);
|
||||
@@ -1688,7 +1689,18 @@ static int LookupNum2(Translator *tr, int value, int thousandplex, const int con
|
||||
ph_tens[ix] = 0;
|
||||
}
|
||||
}
|
||||
sprintf(ph_out,"%s%s%s",ph_tens, ph_digits, ph_ordinal);
|
||||
|
||||
if((tr->langopts.numbers2 & NUM2_ORDINAL_DROP_VOWEL) && (ph_ordinal[0] != 0))
|
||||
{
|
||||
ix = sprintf(ph_out,"%s%s", ph_tens, ph_digits);
|
||||
if((ix > 0) && (phoneme_tab[(unsigned char)(ph_out[ix-1])]->type == phVOWEL))
|
||||
ix--;
|
||||
sprintf(&ph_out[ix], "%s", ph_ordinal);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(ph_out,"%s%s%s",ph_tens, ph_digits, ph_ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -399,6 +399,14 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
|
||||
InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata);
|
||||
|
||||
if((alternative = phdata.pd_param[pd_CHANGE_NEXTPHONEME]) > 0)
|
||||
{
|
||||
ph_list3[j+1].ph = phoneme_tab[alternative];
|
||||
ph_list3[j+1].phcode = alternative;
|
||||
ph_list3[j+1].type = phoneme_tab[alternative]->type;
|
||||
next = phoneme_tab[alternative];
|
||||
}
|
||||
|
||||
if(((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == 0))
|
||||
{
|
||||
// PROBLEM: if we insert a phoneme before a vowel then we loose the stress.
|
||||
|
||||
+13
-10
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
|
||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington *
|
||||
* email: jonsd@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -343,19 +343,22 @@ void ProsodyDisplay::OnMouse(wxMouseEvent& event)
|
||||
|
||||
line = pt.y / FRAMEHEIGHT;
|
||||
|
||||
// find which phoneme is selected on this line
|
||||
for(ix=linetab[line]; (ix<linetab[line+1]) && (ix<numph); ix++)
|
||||
if(line < num_lines)
|
||||
{
|
||||
xpos += GetWidth(&phlist[ix]);
|
||||
if(xpos > pt.x)
|
||||
// find which phoneme is selected on this line
|
||||
for(ix=linetab[line]; (ix<linetab[line+1]) && (ix<numph); ix++)
|
||||
{
|
||||
selected_ph = ix;
|
||||
SelectPh(selected_ph);
|
||||
break;
|
||||
xpos += GetWidth(&phlist[ix]);
|
||||
if(xpos > pt.x)
|
||||
{
|
||||
selected_ph = ix;
|
||||
SelectPh(selected_ph);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RefreshLine(line);
|
||||
RefreshLine(line);
|
||||
}
|
||||
|
||||
if(event.RightDown())
|
||||
{
|
||||
|
||||
+15
-3
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
|
||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington *
|
||||
* email: jonsd@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -2097,7 +2097,13 @@ static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outb
|
||||
}
|
||||
if((attr2 = GetSsmlAttribute(px,"time")) != NULL)
|
||||
{
|
||||
value = (attrnumber(attr2,0,1) * 25) / speed.pause_factor; // compensate for speaking speed to keep constant pause length
|
||||
value2 = attrnumber(attr2,0,1); // pause in mS
|
||||
|
||||
// compensate for speaking speed to keep constant pause length, see function PauseLength()
|
||||
// 'value' here is x 10mS
|
||||
value = (value2 * 256) / (speed.clause_pause_factor * 10);
|
||||
if(value < 200)
|
||||
value = (value2 * 256) / (speed.pause_factor * 10);
|
||||
|
||||
if(terminator == 0)
|
||||
terminator = CLAUSE_NONE;
|
||||
@@ -2105,7 +2111,13 @@ static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outb
|
||||
if(terminator)
|
||||
{
|
||||
if(value > 0xfff)
|
||||
value = 0xfff;
|
||||
{
|
||||
// scale down the value and set a scaling indicator bit
|
||||
value = value / 32;
|
||||
if(value > 0xfff)
|
||||
value = 0xfff;
|
||||
terminator |= CLAUSE_PAUSE_LONG;
|
||||
}
|
||||
return(terminator + value);
|
||||
}
|
||||
break;
|
||||
|
||||
+2
-1
@@ -766,6 +766,7 @@ static int adjustPitch(
|
||||
}
|
||||
|
||||
/* Skip over a pitch period, and copy period/speed samples to the output */
|
||||
/* NOTE: Only called if speed > 1.0f */
|
||||
static int skipPitchPeriod(
|
||||
sonicStream stream,
|
||||
short *samples,
|
||||
@@ -777,7 +778,7 @@ static int skipPitchPeriod(
|
||||
|
||||
if(speed >= 2.0f) {
|
||||
newSamples = period/(speed - 1.0f);
|
||||
} else if(speed > 1.0f) {
|
||||
} else {
|
||||
newSamples = period;
|
||||
stream->remainingInputToCopy = period*(2.0f - speed)/(speed - 1.0f);
|
||||
}
|
||||
|
||||
+3
-15
@@ -455,17 +455,6 @@ static int initialise(void)
|
||||
}
|
||||
|
||||
|
||||
static void StopSpeak(int unused)
|
||||
{//==============================
|
||||
signal(SIGINT,SIG_IGN);
|
||||
// DEBUG
|
||||
// printf("\n*** Interrupting speech output (use Ctrl-D to actually quit).\n");
|
||||
fflush(stdout);
|
||||
SpeakNextClause(NULL,NULL,5);
|
||||
signal(SIGINT,StopSpeak);
|
||||
} // end of StopSpeak()
|
||||
|
||||
|
||||
|
||||
#ifdef NEED_GETOPT
|
||||
struct option {
|
||||
@@ -524,13 +513,15 @@ int main (int argc, char **argv)
|
||||
char *optarg2;
|
||||
int amp = 100; // default
|
||||
int wordgap = 0;
|
||||
int speaking = 0;
|
||||
int flag_stdin = 0;
|
||||
int flag_compile = 0;
|
||||
int pitch_adjustment = 50;
|
||||
espeak_VOICE voice_select;
|
||||
char filename[200];
|
||||
char voicename[40];
|
||||
#ifdef USE_PORTAUDIO
|
||||
int speaking = 0;
|
||||
#endif
|
||||
|
||||
voicename[0] = 0;
|
||||
mbrola_name[0] = 0;
|
||||
@@ -898,9 +889,6 @@ int main (int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Silence on ^C or SIGINT
|
||||
// signal(SIGINT,StopSpeak);
|
||||
|
||||
// output sound using portaudio
|
||||
WavegenInitSound();
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
|
||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington *
|
||||
* email: jonsd@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.48.02 02.Feb.14";
|
||||
const char *version_string = "1.48.05 23.May.14";
|
||||
const int version_phdata = 0x014801;
|
||||
|
||||
int option_device_number = -1;
|
||||
|
||||
+20
-4
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
|
||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington *
|
||||
* email: jonsd@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -188,7 +188,7 @@ static void DoPitch(unsigned char *env, int pitch1, int pitch2)
|
||||
|
||||
int PauseLength(int pause, int control)
|
||||
{//====================================
|
||||
int len;
|
||||
unsigned int len;
|
||||
|
||||
if(control == 0)
|
||||
{
|
||||
@@ -210,8 +210,10 @@ int PauseLength(int pause, int control)
|
||||
|
||||
static void DoPause(int length, int control)
|
||||
{//=========================================
|
||||
// length in nominal mS
|
||||
// control = 1, less shortening at fast speeds
|
||||
int len;
|
||||
unsigned int len;
|
||||
int srate2;
|
||||
|
||||
if(length == 0)
|
||||
len = 0;
|
||||
@@ -219,7 +221,15 @@ static void DoPause(int length, int control)
|
||||
{
|
||||
len = PauseLength(length, control);
|
||||
|
||||
len = (len * samplerate) / 1000; // convert from mS to number of samples
|
||||
if(len < 90000)
|
||||
{
|
||||
len = (len * samplerate) / 1000; // convert from mS to number of samples
|
||||
}
|
||||
else
|
||||
{
|
||||
srate2 = samplerate / 25; // avoid overflow
|
||||
len = (len * srate2) / 40;
|
||||
}
|
||||
}
|
||||
|
||||
EndPitch(1);
|
||||
@@ -1335,6 +1345,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
int modulation;
|
||||
int pre_voiced;
|
||||
int free_min;
|
||||
int value;
|
||||
unsigned char *pitch_env=NULL;
|
||||
unsigned char *amp_env;
|
||||
PHONEME_TAB *ph;
|
||||
@@ -1677,6 +1688,11 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
StartSyllable();
|
||||
}
|
||||
InterpretPhoneme(NULL, 0, p, &phdata, &worddata);
|
||||
|
||||
if((value = (phdata.pd_param[i_PAUSE_BEFORE] - p->prepause)) > 0)
|
||||
{
|
||||
DoPause(value, 1);
|
||||
}
|
||||
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
|
||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington *
|
||||
* email: jonsd@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -212,7 +212,7 @@ typedef struct {
|
||||
unsigned char tone_ph; // tone phoneme to use with this vowel
|
||||
|
||||
PHONEME_TAB *ph;
|
||||
short length; // length_mod
|
||||
unsigned int length; // length_mod
|
||||
unsigned char env; // pitch envelope number
|
||||
unsigned char type;
|
||||
unsigned char prepause;
|
||||
@@ -239,6 +239,7 @@ typedef struct {
|
||||
#define pd_INSERTPHONEME i_INSERT_PHONEME
|
||||
#define pd_APPENDPHONEME i_APPEND_PHONEME
|
||||
#define pd_CHANGEPHONEME i_CHANGE_PHONEME
|
||||
#define pd_CHANGE_NEXTPHONEME i_REPLACE_NEXT_PHONEME
|
||||
#define pd_LENGTHMOD i_SET_LENGTH
|
||||
|
||||
#define pd_FORNEXTPH 0x2
|
||||
@@ -379,7 +380,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
int pause_factor;
|
||||
int clause_pause_factor;
|
||||
int min_pause;
|
||||
unsigned int min_pause;
|
||||
int wav_factor;
|
||||
int lenmod_factor;
|
||||
int lenmod2_factor;
|
||||
|
||||
+11
-2
@@ -51,6 +51,7 @@
|
||||
#define OFFSET_ARMENIAN 0x530
|
||||
#define OFFSET_HEBREW 0x590
|
||||
#define OFFSET_ARABIC 0x600
|
||||
#define OFFSET_SYRIAC 0x700
|
||||
#define OFFSET_THAANA 0x780 // Divehi/Maldives
|
||||
#define OFFSET_DEVANAGARI 0x900
|
||||
#define OFFSET_BENGALI 0x980
|
||||
@@ -78,6 +79,7 @@ ALPHABET alphabets [] = {
|
||||
{"_hy", OFFSET_ARMENIAN, 0x530, 0x58f, L('h','y'), AL_WORDS},
|
||||
{"_he", OFFSET_HEBREW, 0x590, 0x5ff, 0, 0},
|
||||
{"_ar", OFFSET_ARABIC, 0x600, 0x6ff, 0, 0},
|
||||
{"_syc", OFFSET_SYRIAC, 0x700, 0x74f, 0, 0},
|
||||
{"_dv", OFFSET_THAANA, 0x780, 0x7bf, 0, 0},
|
||||
{"_hi", OFFSET_DEVANAGARI, 0x900, 0x97f,L('h','i'), AL_WORDS},
|
||||
{"_bn", OFFSET_BENGALI, 0x0980, 0x9ff, L('b','n'), AL_WORDS},
|
||||
@@ -518,6 +520,9 @@ Translator *SelectTranslator(const char *name)
|
||||
|
||||
|
||||
case L('a','r'): // Arabic
|
||||
tr->transpose_min = 0x620; // for ar_list, use 6-bit character codes
|
||||
tr->transpose_max = 0x65f;
|
||||
tr->transpose_map = NULL;
|
||||
tr->letter_bits_offset = OFFSET_ARABIC;
|
||||
tr->langopts.numbers = NUM_SWAP_TENS | NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_AND_HUNDRED | NUM_THOUSAND_AND | NUM_OMIT_1_THOUSAND;
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
|
||||
@@ -543,6 +548,7 @@ Translator *SelectTranslator(const char *name)
|
||||
{
|
||||
static const short stress_lengths_bn[8] = {180, 180, 210, 210, 0, 0, 230, 240};
|
||||
static const unsigned char stress_amps_bn[8] = {18,18, 18,18, 20,20, 22,22 };
|
||||
static const char bn_consonants2[3] = {0x70, 0x71, 0};
|
||||
|
||||
SetupTranslator(tr,stress_lengths_bn,stress_amps_bn);
|
||||
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
|
||||
@@ -553,6 +559,7 @@ Translator *SelectTranslator(const char *name)
|
||||
SetIndicLetters(tr); // call this after setting OFFSET_BENGALI
|
||||
SetLetterBitsRange(tr,LETTERGP_B,0x01,0x01); // candranindu
|
||||
SetLetterBitsRange(tr,LETTERGP_F,0x3e,0x4c); // vowel signs, but not virama
|
||||
SetLetterBits(tr,LETTERGP_C,bn_consonants2);
|
||||
|
||||
tr->langopts.numbers = NUM_SWAP_TENS;
|
||||
tr->langopts.break_numbers = 0x24924aa8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi
|
||||
@@ -781,7 +788,8 @@ Translator *SelectTranslator(const char *name)
|
||||
static const unsigned char stress_amps_eu[8] = {16,16, 18,18, 18,18, 18,18 };
|
||||
SetupTranslator(tr,stress_lengths_eu,stress_amps_eu);
|
||||
tr->langopts.stress_rule = STRESSPOSN_2L; // ?? second syllable ??
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_VIGESIMAL;
|
||||
tr->langopts.param[LOPT_SUFFIX] = 1;
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_VIGESIMAL;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1421,7 +1429,7 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 0x76; // [v] don't count this character at start of word
|
||||
tr->langopts.param[LOPT_ALT] = 2; // call ApplySpecialAttributes2() if a word has $alt or $alt2
|
||||
tr->langopts.param[LOPT_IT_LENGTHEN] = 1; // remove lengthen indicator from unstressed syllables
|
||||
tr->letter_bits['r'] |= 0x80; // add 'r' to letter group 7, vowels for Unpronouncable test
|
||||
tr->letter_bits[(int)'r'] |= 0x80; // add 'r' to letter group 7, vowels for Unpronouncable test
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_SWAP_TENS | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_2 | NUM_ORDINAL_DOT | NUM_ROMAN;
|
||||
tr->langopts.numbers2 = 0x100; // plural forms of millions etc
|
||||
tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator
|
||||
@@ -1525,6 +1533,7 @@ SetLengthMods(tr,3); // all equal
|
||||
{
|
||||
tr->letter_bits_offset = OFFSET_TELUGU;
|
||||
tr->langopts.numbers = 0x1;
|
||||
tr->langopts.numbers2 = NUM2_ORDINAL_DROP_VOWEL;
|
||||
}
|
||||
SetIndicLetters(tr); // call this after setting OFFSET_
|
||||
SetLetterBitsRange(tr,LETTERGP_B,0x4e,0x4e); // chillu-virama (unofficial)
|
||||
|
||||
+5
-3
@@ -108,7 +108,6 @@ static int embedded_read;
|
||||
unsigned int embedded_list[N_EMBEDDED_LIST];
|
||||
|
||||
// the source text of a single clause (UTF8 bytes)
|
||||
#define N_TR_SOURCE 800
|
||||
static char source[N_TR_SOURCE+40]; // extra space for embedded command & voice change info at end
|
||||
|
||||
int n_replace_phonemes;
|
||||
@@ -954,7 +953,7 @@ int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wt
|
||||
found = LookupDictList(tr, &word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word
|
||||
|
||||
|
||||
if((dictionary_flags[0] & (FLAG_ALLOW_DOT || FLAG_NEEDS_DOT)) && (wordx[1] == '.'))
|
||||
if((dictionary_flags[0] & (FLAG_ALLOW_DOT | FLAG_NEEDS_DOT)) && (wordx[1] == '.'))
|
||||
{
|
||||
wordx[1] = ' '; // remove a Dot after this word
|
||||
}
|
||||
@@ -2075,7 +2074,7 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
|
||||
if(pre_pause < 1)
|
||||
pre_pause = 1;
|
||||
}
|
||||
if((flags & FLAG_PREPAUSE) && !(word_flags && (FLAG_LAST_WORD | FLAG_FIRST_WORD)) && !(wtab[-1].flags & FLAG_FIRST_WORD) && (tr->prepause_timeout == 0))
|
||||
if((flags & FLAG_PREPAUSE) && !(word_flags & (FLAG_LAST_WORD | FLAG_FIRST_WORD)) && !(wtab[-1].flags & FLAG_FIRST_WORD) && (tr->prepause_timeout == 0))
|
||||
{
|
||||
// the word is marked in the dictionary list with $pause
|
||||
if(pre_pause < 4) pre_pause = 4;
|
||||
@@ -2659,6 +2658,9 @@ void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *t
|
||||
charix[charix_top+3] = 0;
|
||||
|
||||
clause_pause = (terminator & 0xfff) * 10; // mS
|
||||
if(terminator & CLAUSE_PAUSE_LONG)
|
||||
clause_pause = clause_pause * 32 ; // pause value is *320mS not *10mS
|
||||
|
||||
tone = (terminator >> 12) & 0x7;
|
||||
if(tone2 != 0)
|
||||
{
|
||||
|
||||
+16
-2
@@ -26,6 +26,9 @@
|
||||
#define N_WORD_PHONEMES 200 // max phonemes in a word
|
||||
#define N_WORD_BYTES 160 // max bytes for the UTF8 characters in a word
|
||||
#define N_CLAUSE_WORDS 300 // max words in a clause
|
||||
#define N_TR_SOURCE 800 // the source text of a single clause (UTF8 bytes)
|
||||
|
||||
|
||||
#define N_RULE_GROUP2 120 // max num of two-letter rule chains
|
||||
#define N_HASH_DICT 1024
|
||||
#define N_CHARSETS 20
|
||||
@@ -41,6 +44,7 @@
|
||||
#define FLAG_STRESS_END2 0x400 // full stress if at end of clause, or only followed by unstressed
|
||||
#define FLAG_UNSTRESS_END 0x800 // reduce stress at end of clause
|
||||
#define FLAG_SPELLWORD 0x1000 // re-translate the word as individual letters, separated by spaces
|
||||
#define FLAG_ACCENT_BEFORE 0x1000 // say this accent name before the letter name
|
||||
#define FLAG_ABBREV 0x2000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters
|
||||
#define FLAG_DOUBLING 0x4000 // doubles the following consonant
|
||||
|
||||
@@ -180,6 +184,11 @@
|
||||
#define RULE_SPELLING 31 // W while spelling letter-by-letter
|
||||
#define RULE_LAST_RULE 31
|
||||
|
||||
#define DOLLAR_UNPR 0x01
|
||||
#define DOLLAR_NOPREFIX 0x02
|
||||
#define DOLLAR_LIST 0x03
|
||||
|
||||
|
||||
#define LETTERGP_A 0
|
||||
#define LETTERGP_B 1
|
||||
#define LETTERGP_C 2
|
||||
@@ -191,7 +200,7 @@
|
||||
|
||||
|
||||
// Punctuation types returned by ReadClause()
|
||||
// bits 0-7 pause x 10mS, bits 12-14 intonation type,
|
||||
// bits 0-11 pause x 10mS
|
||||
// bits12-14 intonation type
|
||||
// bit 15- don't need space after the punctuation
|
||||
// bit 19=sentence, bit 18=clause, bits 17=voice change
|
||||
@@ -199,6 +208,8 @@
|
||||
// bit 20= punctuation character can be inside a word (Armenian)
|
||||
// bit 21= speak the name of the punctuation character
|
||||
// bit 22= dot after the last word
|
||||
// bit 23= pause is x 320mS (not x 10mS)
|
||||
|
||||
#define CLAUSE_BIT_SENTENCE 0x80000
|
||||
#define CLAUSE_BIT_CLAUSE 0x40000
|
||||
#define CLAUSE_BIT_VOICE 0x20000
|
||||
@@ -206,6 +217,7 @@
|
||||
#define PUNCT_IN_WORD 0x100000
|
||||
#define PUNCT_SAY_NAME 0x200000
|
||||
#define CLAUSE_DOT 0x400000
|
||||
#define CLAUSE_PAUSE_LONG 0x800000
|
||||
|
||||
#define CLAUSE_NONE ( 0 + 0x04000)
|
||||
#define CLAUSE_PARAGRAPH (70 + 0x80000)
|
||||
@@ -513,6 +525,7 @@ typedef struct {
|
||||
#define NUM2_PERCENT_BEFORE 0x10000
|
||||
#define NUM2_OMIT_1_HUNDRED_ONLY 0x20000
|
||||
#define NUM2_ORDINAL_AND_THOUSANDS 0x40000
|
||||
#define NUM2_ORDINAL_DROP_VOWEL 0x80000
|
||||
// bits 1-4 use variant form of numbers before thousands,millions,etc.
|
||||
// bits 6-8 use different forms of thousand, million, etc (M MA MB)
|
||||
// bit9=(LANG=rw) say "thousand" and "million" before its number, not after
|
||||
@@ -524,6 +537,7 @@ typedef struct {
|
||||
// bit16=(LANG=si) say "%" before the number
|
||||
// bit17=(LANG=ml) omit "one" before hundred only if there are no previous digits
|
||||
// bit18=(LANG=ta) same variant for ordinals and thousands (#o = #a)
|
||||
// bit19=(LANG=te) drop final vowel from cardial number before adding ordinal suffix
|
||||
int numbers2;
|
||||
|
||||
#define BREAK_THOUSANDS 0x49249248
|
||||
@@ -741,7 +755,7 @@ int SetTranslator2(const char *name);
|
||||
void DeleteTranslator(Translator *tr);
|
||||
void ProcessLanguageOptions(LANGUAGE_OPTIONS *langopts);
|
||||
int Lookup(Translator *tr, const char *word, char *ph_out);
|
||||
int LookupFlags(Translator *tr, const char *word);
|
||||
int LookupFlags(Translator *tr, const char *word, unsigned int **flags_out);
|
||||
|
||||
int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control);
|
||||
int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
|
||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington *
|
||||
* email: jonsd@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -611,7 +611,7 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
|
||||
// which directory to look for a named voice. List of voice names, must end in a space.
|
||||
static const char *voices_asia =
|
||||
"az bn fa fa-pin hi hy hy-west id ka kn ku ml ms ne pa ta te tr vi vi-hue vi-sgn zh zh-yue ";
|
||||
"az bn fa fa-pin gu hi hy hy-west id ka kn ku ml ms ne pa ta te tr vi vi-hue vi-sgn zh zh-yue ";
|
||||
static const char *voices_europe =
|
||||
"an bg bs ca cs cy da de el en en-us es et fi fr fr-be ga hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user