Browse Source

[1.30.01] Fixed SSML <break time="">


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@115 d46cf337-b52f-0410-862d-fd96e6ae7743
master
jonsd 17 years ago
parent
commit
27b622538b
5 changed files with 93 additions and 65 deletions
  1. 69
    43
      src/readclause.cpp
  2. 1
    1
      src/synthdata.cpp
  3. 2
    2
      src/translate.cpp
  4. 18
    18
      src/translate.h
  5. 3
    1
      src/voices.cpp

+ 69
- 43
src/readclause.cpp View File





// indexed by (entry num. in punct_chars) + 1 // indexed by (entry num. in punct_chars) + 1
// bits 0-7 pause x 10mS, bits 8-10 intonation type, bit 11 don't need following space or bracket
// bits 0-7 pause x 10mS, bits 12-14 intonation type, bit 15 don't need following space or bracket
static const unsigned short punct_attributes [] = { 0, static const unsigned short punct_attributes [] = { 0,
CLAUSE_COMMA, CLAUSE_PERIOD, CLAUSE_QUESTION, CLAUSE_EXCLAMATION, CLAUSE_COLON, CLAUSE_SEMICOLON, CLAUSE_COMMA, CLAUSE_PERIOD, CLAUSE_QUESTION, CLAUSE_EXCLAMATION, CLAUSE_COLON, CLAUSE_SEMICOLON,
CLAUSE_SEMICOLON, // en-dash CLAUSE_SEMICOLON, // en-dash


CLAUSE_QUESTION, // Greek question mark CLAUSE_QUESTION, // Greek question mark
CLAUSE_SEMICOLON, // Greek semicolon CLAUSE_SEMICOLON, // Greek semicolon
CLAUSE_PERIOD+0x800, // Devanagari Danda (fullstop)
CLAUSE_COMMA+0x800, // ideograph comma
CLAUSE_PERIOD+0x800, // ideograph period
CLAUSE_PERIOD+0x8000, // Devanagari Danda (fullstop)
CLAUSE_COMMA+0x8000, // ideograph comma
CLAUSE_PERIOD+0x8000, // ideograph period


CLAUSE_EXCLAMATION+0x800, // fullwidth
CLAUSE_COMMA+0x800,
CLAUSE_PERIOD+0x800,
CLAUSE_COLON+0x800,
CLAUSE_SEMICOLON+0x800,
CLAUSE_QUESTION+0x800,
CLAUSE_EXCLAMATION+0x8000, // fullwidth
CLAUSE_COMMA+0x8000,
CLAUSE_PERIOD+0x8000,
CLAUSE_COLON+0x8000,
CLAUSE_SEMICOLON+0x8000,
CLAUSE_QUESTION+0x8000,


CLAUSE_SEMICOLON, // spare CLAUSE_SEMICOLON, // spare
0 }; 0 };
char command[sizeof(fname2)+sizeof(fname2)+30]; char command[sizeof(fname2)+sizeof(fname2)+30];


if(fname == NULL) if(fname == NULL)
{
// filename is already in the table
fname = soundicon_tab[index].filename; fname = soundicon_tab[index].filename;
}


if((fname==NULL) || (GetFileLength(fname) <= 0))
if(fname==NULL)
return(1); return(1);

if(fname[0] != '/') if(fname[0] != '/')
{ {
// a relative path, look in espeak-data/soundicons // a relative path, look in espeak-data/soundicons
sprintf(fname2,"%s%csoundicons%c%s",path_home,PATHSEP,PATHSEP,fname); sprintf(fname2,"%s%csoundicons%c%s",path_home,PATHSEP,PATHSEP,fname);
fname = fname2; fname = fname2;
} }
sprintf(fname_temp,"%s.wav",tmpnam(NULL));
sprintf(command,"sox \"%s\" -r %d -w %s polyphase\n",fname,samplerate,fname_temp);
if(system(command) != 0)
{
// resample has failed, use the original file
fprintf(stderr,"Failed to resample: %s\n",command);
}
else

f = NULL;
#ifdef PLATFORM_POSIX
if((f = fopen(fname,"rb")) != NULL)
{ {
fname = fname_temp;
int header[11];
fread(header, 1, 44, f);

if(header[6] != samplerate)
{
fclose(f);
f = NULL;

sprintf(fname_temp,"%s.wav",tmpnam(NULL));
sprintf(command,"sox \"%s\" -r %d -w %s polyphase\n",fname,samplerate,fname_temp);
if(system(command) == 0)
{
fname = fname_temp;
}
}
} }
#endif


length = GetFileLength(fname);
f = fopen(fname,"rb");
if(f == NULL) if(f == NULL)
{ {
fprintf(stderr,"Can't read temp file: %s",fname);
return(3);
f = fopen(fname,"rb");
if(f == NULL)
{
fprintf(stderr,"Can't read temp file: %s\n",fname);
return(3);
}
} }


length = GetFileLength(fname);
fseek(f,0,SEEK_SET); fseek(f,0,SEEK_SET);
p = Alloc(length); p = Alloc(length);
fread(p,length,1,f); fread(p,length,1,f);
} // end of LoadSoundFile } // end of LoadSoundFile





static int LookupSoundicon(int c) static int LookupSoundicon(int c)
{//============================== {//==============================
// Find the sound icon number for a punctuation chatacter // Find the sound icon number for a punctuation chatacter
} }





int Translator::AnnouncePunctuation(int c1, int c2, char *buf, int bufix) int Translator::AnnouncePunctuation(int c1, int c2, char *buf, int bufix)
{//====================================================================== {//======================================================================
// announce punctuation names // announce punctuation names
#define SSML_CLOSE 0x10 // for a closing tag, OR this with the tag type #define SSML_CLOSE 0x10 // for a closing tag, OR this with the tag type


// these tags have no effect if they are self-closing, eg. <voice /> // these tags have no effect if they are self-closing, eg. <voice />
static char ignore_if_self_closing[] = {0,1,1,1,1,0,0,0,0,1,1,0,1,0};
static char ignore_if_self_closing[] = {0,1,1,1,1,0,0,0,0,1,1,0,1,0,0,0,0};




MNEM_TAB ssmltags[] = { MNEM_TAB ssmltags[] = {
break; break;


case SSML_AUDIO: case SSML_AUDIO:
if(uri_callback == NULL)
break;
sp = PushParamStack(tag_type); sp = PushParamStack(tag_type);


if((attr1 = GetSsmlAttribute(px,"src")) != NULL) if((attr1 = GetSsmlAttribute(px,"src")) != NULL)
{ {
attrcopy_utf8(buf,attr1,sizeof(buf)); attrcopy_utf8(buf,attr1,sizeof(buf));
if((index = AddNameData(buf,0)) >= 0)

if(uri_callback == NULL)
{
// we could load the audio file as a sound icon (assuming it's a local WAV file)
// But when to free() the data?
}
else
{ {
uri = &namedata[index];
if(uri_callback(1,uri,xmlbase) == 0)
if((index = AddNameData(buf,0)) >= 0)
{ {
sprintf(buf,"%c%dU",CTRL_EMBEDDED,index);
strcpy(&outbuf[outix],buf);
outix += strlen(buf);
sp->parameter[espeakSILENCE] = 1;
uri = &namedata[index];
if(uri_callback(1,uri,xmlbase) == 0)
{
sprintf(buf,"%c%dU",CTRL_EMBEDDED,index);
strcpy(&outbuf[outix],buf);
outix += strlen(buf);
sp->parameter[espeakSILENCE] = 1;
}
} }
} }
} }
return(CLAUSE_NONE); return(CLAUSE_NONE);


case SSML_AUDIO + SSML_CLOSE: case SSML_AUDIO + SSML_CLOSE:
if(uri_callback == NULL)
break;
PopParamStack(tag_type, outbuf, outix); PopParamStack(tag_type, outbuf, outix);
return(CLAUSE_NONE); return(CLAUSE_NONE);


case SSML_BREAK: case SSML_BREAK:
value = 50;
value = 21;
terminator = CLAUSE_NONE; terminator = CLAUSE_NONE;


if((attr1 = GetSsmlAttribute(px,"strength")) != NULL) if((attr1 = GetSsmlAttribute(px,"strength")) != NULL)
outix += 3; outix += 3;
terminator = 0; terminator = 0;
} }
// if(value > 3)
// terminator = CLAUSE_COMMA & 0xff00;
value = break_value[value]; value = break_value[value];
} }
if((attr2 = GetSsmlAttribute(px,"time")) != NULL) if((attr2 = GetSsmlAttribute(px,"time")) != NULL)
{ {
value2 = attrnumber(px,0,1) / 10;
value = (attrnumber(attr2,0,1) * 25) / speed_factor1; // compensate for speaking speed to keep constant pause length

if(terminator == 0) if(terminator == 0)
terminator = CLAUSE_NONE; terminator = CLAUSE_NONE;
} }
if(terminator) if(terminator)
{
if(value > 0xfff)
value = 0xfff;
return(terminator + value); return(terminator + value);
}
break; break;


case SSML_SPEAK: case SSML_SPEAK:
char buf2[40]; char buf2[40];
wchar_t xml_buf[N_XML_BUF+1]; wchar_t xml_buf[N_XML_BUF+1];



if(clear_skipping_text) if(clear_skipping_text)
{ {
skipping_text = 0; skipping_text = 0;
if(xml_buf[n_xml_buf-1] == '/') if(xml_buf[n_xml_buf-1] == '/')
{ {
// a self-closing tag // a self-closing tag
xml_buf[n_xml_buf-1] = ' ';
self_closing = 1; self_closing = 1;
} }


if((phoneme_mode==0) && (sayas_mode==0) && ((punct = lookupwchar(punct_chars,c1)) != 0)) if((phoneme_mode==0) && (sayas_mode==0) && ((punct = lookupwchar(punct_chars,c1)) != 0))
{ {
if((iswspace(c2) || (punct_attributes[punct] & 0x800) || IsBracket(c2) || (c2=='?') || (c2=='-') || Eof()))
if((iswspace(c2) || (punct_attributes[punct] & 0x8000) || IsBracket(c2) || (c2=='?') || (c2=='-') || Eof()))
{ {
// note: (c2='?') is for when a smart-quote has been replaced by '?' // note: (c2='?') is for when a smart-quote has been replaced by '?'
buf[ix] = ' '; buf[ix] = ' ';

+ 1
- 1
src/synthdata.cpp View File

#include "translate.h" #include "translate.h"
#include "wave.h" #include "wave.h"


const char *version_string = "1.30 31.Dec.07";
const char *version_string = "1.30.01 02.Jan.08";
const int version_phdata = 0x013000; const int version_phdata = 0x013000;


int option_device_number = -1; int option_device_number = -1;

+ 2
- 2
src/translate.cpp View File



charix[N_TR_SOURCE] = count_characters; charix[N_TR_SOURCE] = count_characters;


clause_pause = (terminator & 0xff) * 10; // mS
tone = (terminator & 0xf00) >> 8;
clause_pause = (terminator & 0xfff) * 10; // mS
tone = (terminator >> 12) & 0xf;


for(p=source; *p != 0; p++) for(p=source; *p != 0; p++)
{ {

+ 18
- 18
src/translate.h View File





// Punctuation types returned by ReadClause() // Punctuation types returned by ReadClause()
// bits 0-7 pause x 10mS, bits 8-10 intonation type,
// bit 15=sentence, bit 14=clause, bits 13=voice change
// bit 12 used to distinguish otherwise identical types
#define CLAUSE_BIT_SENTENCE 0x8000
#define CLAUSE_BIT_VOICE 0x2000
#define CLAUSE_NONE 0 + 0x0400
#define CLAUSE_PARAGRAPH 70 + 0x8000
#define CLAUSE_EOF 35 + 0x9000
#define CLAUSE_VOICE 0 + 0x2400
#define CLAUSE_PERIOD 35 + 0x8000
#define CLAUSE_COMMA 20 + 0x4100
#define CLAUSE_SHORTCOMMA 15 + 0x4100
#define CLAUSE_QUESTION 35 + 0x8200
#define CLAUSE_EXCLAMATION 40 + 0x8300
#define CLAUSE_COLON 30 + 0x4000
// bits 0-7 pause x 10mS, bits 12-14 intonation type,
// bit 19=sentence, bit 18=clause, bits 17=voice change
// bit 16 used to distinguish otherwise identical types
#define CLAUSE_BIT_SENTENCE 0x80000
#define CLAUSE_BIT_VOICE 0x20000
#define CLAUSE_NONE 0 + 0x04000
#define CLAUSE_PARAGRAPH 70 + 0x80000
#define CLAUSE_EOF 35 + 0x90000
#define CLAUSE_VOICE 0 + 0x24000
#define CLAUSE_PERIOD 35 + 0x80000
#define CLAUSE_COMMA 20 + 0x41000
#define CLAUSE_SHORTCOMMA 15 + 0x41000
#define CLAUSE_QUESTION 35 + 0x82000
#define CLAUSE_EXCLAMATION 40 + 0x83000
#define CLAUSE_COLON 30 + 0x40000
#ifdef PLATFORM_RISCOS #ifdef PLATFORM_RISCOS
#define CLAUSE_SEMICOLON 30 + 0x4000
#define CLAUSE_SEMICOLON 30 + 0x40000
#else #else
#define CLAUSE_SEMICOLON 30 + 0x4100
#define CLAUSE_SEMICOLON 30 + 0x41000
#endif #endif


#define SAYAS_CHARS 0x12 #define SAYAS_CHARS 0x12

+ 3
- 1
src/voices.cpp View File

break; break;


case V_INTONATION: // intonation case V_INTONATION: // intonation
sscanf(p,"%d %d",&langopts->intonation_group,&option_tone2);
sscanf(p,"%d %d",&option_tone_flags,&option_tone2);
if((option_tone_flags & 0xff) != 0)
translator->langopts.intonation_group = option_tone_flags & 0xff;
break; break;


case V_DICTRULES: // conditional dictionary rules and list entries case V_DICTRULES: // conditional dictionary rules and list entries

Loading…
Cancel
Save