int GetFileLength(const char *filename) | int GetFileLength(const char *filename) | ||||
{//==================================== | |||||
{ | |||||
struct stat statbuf; | struct stat statbuf; | ||||
if(stat(filename,&statbuf) != 0) | if(stat(filename,&statbuf) != 0) | ||||
return(-2); // a directory | return(-2); // a directory | ||||
return(statbuf.st_size); | return(statbuf.st_size); | ||||
} // end of GetFileLength | |||||
} | |||||
void strncpy0(char *dest, const char *source, int size) | void strncpy0(char *dest, const char *source, int size) | ||||
{//==================================================== | |||||
{ | |||||
if(source!=NULL) | if(source!=NULL) | ||||
{ | { | ||||
strncpy(dest,source,size); | strncpy(dest,source,size); | ||||
} | } | ||||
int utf8_in(int *c, const char *buf) | int utf8_in(int *c, const char *buf) | ||||
{//================================= | |||||
{ | |||||
// Read a unicode characater from a UTF8 string | // Read a unicode characater from a UTF8 string | ||||
// Returns the number of UTF8 bytes used. | // Returns the number of UTF8 bytes used. | ||||
// backwards: set if we are moving backwards through the UTF8 string | // backwards: set if we are moving backwards through the UTF8 string | ||||
void DisplayVoices(FILE *f_out, char *language) | void DisplayVoices(FILE *f_out, char *language) | ||||
{//============================================ | |||||
{ | |||||
int ix; | int ix; | ||||
const char *p; | const char *p; | ||||
int len; | int len; | ||||
} | } | ||||
fputc('\n',f_out); | fputc('\n',f_out); | ||||
} | } | ||||
} // end of DisplayVoices | |||||
} | |||||
static void Write4Bytes(FILE *f, int value) | static void Write4Bytes(FILE *f, int value) | ||||
{//================================= | |||||
{ | |||||
// Write 4 bytes to a file, least significant first | // Write 4 bytes to a file, least significant first | ||||
int ix; | int ix; | ||||
int OpenWavFile(char *path, int rate) | int OpenWavFile(char *path, int rate) | ||||
//=================================== | |||||
{ | { | ||||
static unsigned char wave_hdr[44] = { | static unsigned char wave_hdr[44] = { | ||||
'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ', | 'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ', | ||||
Write4Bytes(f_wavfile,rate * 2); | Write4Bytes(f_wavfile,rate * 2); | ||||
fwrite(&wave_hdr[32],1,12,f_wavfile); | fwrite(&wave_hdr[32],1,12,f_wavfile); | ||||
return(0); | return(0); | ||||
} // end of OpenWavFile | |||||
} | |||||
static void CloseWavFile() | static void CloseWavFile() | ||||
//======================== | |||||
{ | { | ||||
unsigned int pos; | unsigned int pos; | ||||
fclose(f_wavfile); | fclose(f_wavfile); | ||||
f_wavfile = NULL; | f_wavfile = NULL; | ||||
} // end of CloseWavFile | |||||
} | |||||
static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) | static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) | ||||
{//======================================================================== | |||||
{ | |||||
char fname[210]; | char fname[210]; | ||||
if(quiet) return(0); // -q quiet mode | if(quiet) return(0); // -q quiet mode | ||||
static void PrintVersion() | static void PrintVersion() | ||||
{//======================= | |||||
{ | |||||
const char *version; | const char *version; | ||||
const char *path_data; | const char *path_data; | ||||
espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, NULL, espeakINITIALIZE_DONT_EXIT); | espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, NULL, espeakINITIALIZE_DONT_EXIT); | ||||
#endif | #endif | ||||
int main (int argc, char **argv) | int main (int argc, char **argv) | ||||
//============================== | |||||
{ | { | ||||
static struct option long_options[] = | static struct option long_options[] = | ||||
{ | { | ||||
/* These options set a flag. */ | |||||
// {"verbose", no_argument, &verbose_flag, 1}, | |||||
// {"brief", no_argument, &verbose_flag, 0}, | |||||
/* These options don't set a flag. | |||||
We distinguish them by their indices. */ | |||||
{"help", no_argument, 0, 'h'}, | {"help", no_argument, 0, 'h'}, | ||||
{"stdin", no_argument, 0, 0x100}, | {"stdin", no_argument, 0, 0x100}, | ||||
{"compile-debug", optional_argument, 0, 0x101}, | {"compile-debug", optional_argument, 0, 0x101}, |
} | } | ||||
static const char *KeyToMnem(keywtab_t *ktab, int type, int value) | static const char *KeyToMnem(keywtab_t *ktab, int type, int value) | ||||
{//=============================================================== | |||||
{ | |||||
while(ktab->mnem != NULL) | while(ktab->mnem != NULL) | ||||
{ | { | ||||
if(ktab->data == value) | if(ktab->data == value) | ||||
} | } | ||||
static void DecompilePhoneme(FILE *f_out, PHONEME_TAB *ph, int compile_phoneme) | static void DecompilePhoneme(FILE *f_out, PHONEME_TAB *ph, int compile_phoneme) | ||||
{//============================================================================ | |||||
{ | |||||
USHORT *pc; | USHORT *pc; | ||||
int instn; | int instn; | ||||
int instn_category; | int instn_category; | ||||
static int ref_sorter(char **a, char **b) | static int ref_sorter(char **a, char **b) | ||||
{//====================================== | |||||
{ | |||||
int ix; | int ix; | ||||
REF_HASH_TAB *p1 = (REF_HASH_TAB *)(*a); | REF_HASH_TAB *p1 = (REF_HASH_TAB *)(*a); | ||||
return ix; | return ix; | ||||
return(p1->ph_mnemonic - p2->ph_mnemonic); | return(p1->ph_mnemonic - p2->ph_mnemonic); | ||||
} /* end of ref_sorter */ | |||||
} | |||||
static void CompileReport(void) | static void CompileReport(void) | ||||
{//============================ | |||||
{ | |||||
int ix; | int ix; | ||||
int hash; | int hash; | ||||
int n; | int n; | ||||
free(list); | free(list); | ||||
list = NULL; | list = NULL; | ||||
fclose(f_report); | fclose(f_report); | ||||
} // end of CompileReport | |||||
} | |||||
#ifdef PLATFORM_WINDOWS | #ifdef PLATFORM_WINDOWS | ||||
static int ph_sorter(char **a, char **b) | static int ph_sorter(char **a, char **b) | ||||
{//====================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int t1, t2; | int t1, t2; | ||||
char mnem1[6]; | char mnem1[6]; | ||||
strcpy(mnem1,WordToString(p1->mnemonic)); | strcpy(mnem1,WordToString(p1->mnemonic)); | ||||
return(strcasecmp(mnem1,WordToString(p2->mnemonic))); | return(strcasecmp(mnem1,WordToString(p2->mnemonic))); | ||||
} /* end of ph_sorter */ | |||||
} | |||||
static void PrintPhonemesUsed(FILE *f, const char *dsource, const char *dictname) | static void PrintPhonemesUsed(FILE *f, const char *dsource, const char *dictname) | ||||
{//============================================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
PHONEME_TAB *ph; | PHONEME_TAB *ph; | ||||
PHONEME_TAB *ph_tab[N_PHONEME_TAB]; | PHONEME_TAB *ph_tab[N_PHONEME_TAB]; | ||||
} | } | ||||
} | } | ||||
fputc('\n',f); | fputc('\n',f); | ||||
} // end of PrintPhonemesUsed | |||||
} | |||||
static void error(const char *format, const char *string) | static void error(const char *format, const char *string) | ||||
{//====================================================== | |||||
{ | |||||
if(string==NULL) | if(string==NULL) | ||||
string = ""; | string = ""; | ||||
fprintf(f_errors,"%4d: ",linenum-1); | fprintf(f_errors,"%4d: ",linenum-1); | ||||
} | } | ||||
static void Error(const char *string) | static void Error(const char *string) | ||||
{//================================== | |||||
{ | |||||
error("%s",string); | error("%s",string); | ||||
} | } | ||||
static FILE *fopen_log(FILE *f_log, const char *fname,const char *access) | static FILE *fopen_log(FILE *f_log, const char *fname,const char *access) | ||||
{//===================================================================== | |||||
{ | |||||
// performs fopen, but produces error message to f_log if it fails | // performs fopen, but produces error message to f_log if it fails | ||||
FILE *f; | FILE *f; | ||||
static unsigned int StringToWord(const char *string) | static unsigned int StringToWord(const char *string) | ||||
{//================================================= | |||||
{ | |||||
// Pack 4 characters into a word | // Pack 4 characters into a word | ||||
int ix; | int ix; | ||||
unsigned char c; | unsigned char c; | ||||
static void ReservePhCodes() | static void ReservePhCodes() | ||||
{//========================= | |||||
{ | |||||
// Reserve phoneme codes which have fixed numbers so that they can be | // Reserve phoneme codes which have fixed numbers so that they can be | ||||
// referred to from the program code. | // referred to from the program code. | ||||
unsigned int word; | unsigned int word; | ||||
n_phcodes = p->value+1; | n_phcodes = p->value+1; | ||||
p++; | p++; | ||||
} | } | ||||
} // end of ReservePhCodes | |||||
} | |||||
static int LookupPhoneme(const char *string, int control) | static int LookupPhoneme(const char *string, int control) | ||||
{//====================================================== | |||||
{ | |||||
// control = 0 explicit declaration | // control = 0 explicit declaration | ||||
// control = 1 declare phoneme if not found | // control = 1 declare phoneme if not found | ||||
// control = 2 start looking after control & stress phonemes | // control = 2 start looking after control & stress phonemes | ||||
phoneme_tab2[use].type = phINVALID; | phoneme_tab2[use].type = phINVALID; | ||||
phoneme_tab2[use].program = linenum; // for error report if the phoneme remains undeclared | phoneme_tab2[use].program = linenum; // for error report if the phoneme remains undeclared | ||||
return(use); | return(use); | ||||
} // end of Compile::LookupPhoneme | |||||
} | |||||
static unsigned int get_char() | static unsigned int get_char() | ||||
{//=========================== | |||||
{ | |||||
unsigned int c; | unsigned int c; | ||||
c = fgetc(f_in); | c = fgetc(f_in); | ||||
if(c == '\n') | if(c == '\n') | ||||
} | } | ||||
static void unget_char(unsigned int c) | static void unget_char(unsigned int c) | ||||
{//=================================== | |||||
{ | |||||
ungetc(c,f_in); | ungetc(c,f_in); | ||||
if(c == '\n') | if(c == '\n') | ||||
linenum--; | linenum--; | ||||
int CheckNextChar() | int CheckNextChar() | ||||
{//================ | |||||
{ | |||||
int c; | int c; | ||||
while(((c = get_char()) == ' ') || (c == '\t')); | while(((c = get_char()) == ' ') || (c == '\t')); | ||||
unget_char(c); | unget_char(c); | ||||
return(c); | return(c); | ||||
} // end of CheckNextChar | |||||
} | |||||
static int NextItem(int type) | static int NextItem(int type) | ||||
{//========================== | |||||
{ | |||||
int acc; | int acc; | ||||
unsigned char c=0; | unsigned char c=0; | ||||
unsigned char c2; | unsigned char c2; | ||||
return(LookupPhoneme(item_string,2)); | return(LookupPhoneme(item_string,2)); | ||||
} | } | ||||
return(-1); | return(-1); | ||||
} // end of NextItem | |||||
} | |||||
static int NextItemMax(int max) | static int NextItemMax(int max) | ||||
{//============================== | |||||
{ | |||||
// Get a number, but restrict value to max | // Get a number, but restrict value to max | ||||
int value; | int value; | ||||
char msg[80]; | char msg[80]; | ||||
static int NextItemBrackets(int type, int control) | static int NextItemBrackets(int type, int control) | ||||
{//=============================================== | |||||
{ | |||||
// Expect a parameter inside parantheses | // Expect a parameter inside parantheses | ||||
// control: bit 0 0= need ( | // control: bit 0 0= need ( | ||||
// bit 1 1= allow comma | // bit 1 1= allow comma | ||||
static void UngetItem() | static void UngetItem() | ||||
{//==================== | |||||
{ | |||||
fseek(f_in,f_in_displ,SEEK_SET); | fseek(f_in,f_in_displ,SEEK_SET); | ||||
linenum = f_in_linenum; | linenum = f_in_linenum; | ||||
} // end of UngetItem | |||||
} | |||||
static int Range(int value, int divide, int min, int max) | static int Range(int value, int divide, int min, int max) | ||||
{//====================================================== | |||||
{ | |||||
if(value < 0) | if(value < 0) | ||||
value -= divide/2; | value -= divide/2; | ||||
else | else | ||||
int CompileVowelTransition(int which) | int CompileVowelTransition(int which) | ||||
{//================================== | |||||
{ | |||||
// Compile a vowel transition | // Compile a vowel transition | ||||
int key; | int key; | ||||
int len=0; | int len=0; | ||||
prog_out += 4; | prog_out += 4; | ||||
return(0); | return(0); | ||||
} // end of VowelTransition | |||||
} | |||||
int LoadSpect(const char *path, int control) | int LoadSpect(const char *path, int control) | ||||
{//========================================= | |||||
{ | |||||
SpectSeq *spectseq; | SpectSeq *spectseq; | ||||
int peak; | int peak; | ||||
int displ; | int displ; | ||||
SpectSeqDestroy(spectseq); | SpectSeqDestroy(spectseq); | ||||
return(displ); | return(displ); | ||||
} // end of LoadSpect | |||||
} | |||||
static int LoadWavefile(FILE *f, const char *fname) | static int LoadWavefile(FILE *f, const char *fname) | ||||
{//================================================ | |||||
{ | |||||
int displ; | int displ; | ||||
unsigned char c1; | unsigned char c1; | ||||
unsigned char c3; | unsigned char c3; | ||||
remove(fname_temp); | remove(fname_temp); | ||||
} | } | ||||
return(displ | 0x800000); // set bit 23 to indicate a wave file rather than a spectrum | return(displ | 0x800000); // set bit 23 to indicate a wave file rather than a spectrum | ||||
} // end of LoadWavefile | |||||
} | |||||
static int LoadEnvelope(FILE *f, const char *fname) | static int LoadEnvelope(FILE *f, const char *fname) | ||||
{//================================================ | |||||
{ | |||||
int displ; | int displ; | ||||
char buf[128]; | char buf[128]; | ||||
} | } | ||||
return(displ); | return(displ); | ||||
} // end of LoadEnvelope | |||||
} | |||||
static int Hash8(const char *string) | |||||
//================================== | |||||
/* Generate a hash code from the specified string */ | /* Generate a hash code from the specified string */ | ||||
static int Hash8(const char *string) | |||||
{ | { | ||||
int c; | int c; | ||||
int chars=0; | int chars=0; | ||||
} | } | ||||
return((hash+chars) & 0xff); | return((hash+chars) & 0xff); | ||||
} // end of Hash8 | |||||
} | |||||
static int LoadEnvelope2(FILE *f, const char *fname) | static int LoadEnvelope2(FILE *f, const char *fname) | ||||
{//=================================================== | |||||
{ | |||||
int ix, ix2; | int ix, ix2; | ||||
int n; | int n; | ||||
int x, y; | int x, y; | ||||
} | } | ||||
static int LoadDataFile(const char *path, int control) | static int LoadDataFile(const char *path, int control) | ||||
{//=================================================== | |||||
{ | |||||
// load spectrum sequence or sample data from a file. | // load spectrum sequence or sample data from a file. | ||||
// return index into spect or sample data area. bit 23=1 if a sample | // return index into spect or sample data area. bit 23=1 if a sample | ||||
} | } | ||||
return(addr); | return(addr); | ||||
} // end of LoadDataFile | |||||
} | |||||
static int CompileToneSpec(void) | static int CompileToneSpec(void) | ||||
{//============================= | |||||
{ | |||||
int pitch1=0; | int pitch1=0; | ||||
int pitch2=0; | int pitch2=0; | ||||
int pitch_env = 0; | int pitch_env = 0; | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of CompileToneSpec | |||||
} | |||||
int CompileSound(int keyword, int isvowel) | int CompileSound(int keyword, int isvowel) | ||||
{//======================================= | |||||
{ | |||||
int addr; | int addr; | ||||
int value = 0; | int value = 0; | ||||
char path[N_ITEM_STRING]; | char path[N_ITEM_STRING]; | ||||
*prog_out++ = sound_instns[keyword-kFMT] + ((value & 0xff) << 4) + ((addr >> 16) & 0xf); | *prog_out++ = sound_instns[keyword-kFMT] + ((value & 0xff) << 4) + ((addr >> 16) & 0xf); | ||||
*prog_out++ = addr & 0xffff; | *prog_out++ = addr & 0xffff; | ||||
return(0); | return(0); | ||||
} // end of CompileSound | |||||
} | |||||
*/ | */ | ||||
int CompileIf(int elif) | int CompileIf(int elif) | ||||
{//==================== | |||||
{ | |||||
int key; | int key; | ||||
int finish = 0; | int finish = 0; | ||||
int word = 0; | int word = 0; | ||||
*prog_out++ = i_JUMP_FALSE; | *prog_out++ = i_JUMP_FALSE; | ||||
return(0); | return(0); | ||||
} // end of CompileIf | |||||
} | |||||
void FillThen(int add) | void FillThen(int add) | ||||
{//=================== | |||||
{ | |||||
USHORT *p; | USHORT *p; | ||||
int offset; | int offset; | ||||
} | } | ||||
then_count = 0; | then_count = 0; | ||||
} // end of FillThen | |||||
} | |||||
int CompileElse(void) | int CompileElse(void) | ||||
{//================== | |||||
{ | |||||
USHORT *ref; | USHORT *ref; | ||||
USHORT *p; | USHORT *p; | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of CompileElse | |||||
} | |||||
int CompileElif(void) | int CompileElif(void) | ||||
{//=================== | |||||
{ | |||||
if(if_level < 1) | if(if_level < 1) | ||||
{ | { | ||||
error("ELIF not expected",NULL); | error("ELIF not expected",NULL); | ||||
int CompileEndif(void) | int CompileEndif(void) | ||||
{//=================== | |||||
{ | |||||
USHORT *p; | USHORT *p; | ||||
int chain; | int chain; | ||||
int offset; | int offset; | ||||
if_level--; | if_level--; | ||||
return(0); | return(0); | ||||
} // end of CompileEndif | |||||
} | |||||
static int CompileSwitch(int type) | static int CompileSwitch(int type) | ||||
{//=============================== | |||||
{ | |||||
// Type 0: EndSwitch | // Type 0: EndSwitch | ||||
// 1: SwitchPrevVowelType | // 1: SwitchPrevVowelType | ||||
// 2: SwitchNextVowelType | // 2: SwitchNextVowelType | ||||
if(type == 2) | if(type == 2) | ||||
*prog_out++ = i_SWITCH_NEXTVOWEL+6; | *prog_out++ = i_SWITCH_NEXTVOWEL+6; | ||||
return(0); | return(0); | ||||
} // end of CompileSwitch | |||||
} | |||||
static PHONEME_TAB_LIST *FindPhonemeTable(const char *string) | static PHONEME_TAB_LIST *FindPhonemeTable(const char *string) | ||||
{//========================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
for(ix=0; ix<n_phoneme_tabs; ix++) | for(ix=0; ix<n_phoneme_tabs; ix++) | ||||
} | } | ||||
error("Unknown phoneme table: '%s'",string); | error("Unknown phoneme table: '%s'",string); | ||||
return(NULL); | return(NULL); | ||||
} // end of FindPhonemeTable | |||||
} | |||||
static PHONEME_TAB *FindPhoneme(const char *string) | static PHONEME_TAB *FindPhoneme(const char *string) | ||||
{//================================================ | |||||
{ | |||||
PHONEME_TAB_LIST *phtab = NULL; | PHONEME_TAB_LIST *phtab = NULL; | ||||
int ix; | int ix; | ||||
unsigned int mnem; | unsigned int mnem; | ||||
static void ImportPhoneme(void) | static void ImportPhoneme(void) | ||||
{//============================ | |||||
{ | |||||
unsigned int ph_mnem; | unsigned int ph_mnem; | ||||
unsigned int ph_code; | unsigned int ph_code; | ||||
PHONEME_TAB *ph; | PHONEME_TAB *ph; | ||||
phoneme_out->end_type = 0; // voicingswitch, this must be set later to refer to a local phoneme | phoneme_out->end_type = 0; // voicingswitch, this must be set later to refer to a local phoneme | ||||
} | } | ||||
} // end of ImportPhoneme | |||||
} | |||||
static void CallPhoneme(void) | static void CallPhoneme(void) | ||||
{//========================== | |||||
{ | |||||
PHONEME_TAB *ph; | PHONEME_TAB *ph; | ||||
int ix; | int ix; | ||||
int addr = 0; | int addr = 0; | ||||
*prog_out++ = i_CALLPH + (addr >> 16); | *prog_out++ = i_CALLPH + (addr >> 16); | ||||
*prog_out++ = addr; | *prog_out++ = addr; | ||||
} // end of CallPhoneme | |||||
} | |||||
static void DecThenCount() | static void DecThenCount() | ||||
{//======================= | |||||
{ | |||||
if(then_count >0) | if(then_count >0) | ||||
then_count--; | then_count--; | ||||
} | } | ||||
static void InstnPlusPhoneme(int instn) | static void InstnPlusPhoneme(int instn) | ||||
{//==================================== | |||||
{ | |||||
int phcode; | int phcode; | ||||
phcode = NextItemBrackets(tPHONEMEMNEM,0); | phcode = NextItemBrackets(tPHONEMEMNEM,0); | ||||
int CompilePhoneme(int compile_phoneme) | int CompilePhoneme(int compile_phoneme) | ||||
{//==================================== | |||||
{ | |||||
int endphoneme = 0; | int endphoneme = 0; | ||||
int keyword; | int keyword; | ||||
int value; | int value; | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of CompilePhoneme | |||||
} | |||||
static void WritePhonemeTables() | static void WritePhonemeTables() | ||||
{//============================= | |||||
{ | |||||
int ix; | int ix; | ||||
int j; | int j; | ||||
int n; | int n; | ||||
fwrite(&p[n],sizeof(PHONEME_TAB),1,f_phtab); // include the extra list-terminator phoneme entry | fwrite(&p[n],sizeof(PHONEME_TAB),1,f_phtab); // include the extra list-terminator phoneme entry | ||||
free(p); | free(p); | ||||
} | } | ||||
} // end of WritePhonemeTables | |||||
} | |||||
static void EndPhonemeTable() | static void EndPhonemeTable() | ||||
{//========================== | |||||
{ | |||||
int ix; | int ix; | ||||
int *pw; | int *pw; | ||||
int length; | int length; | ||||
static void StartPhonemeTable(const char *name) | static void StartPhonemeTable(const char *name) | ||||
{//============================================ | |||||
{ | |||||
int ix; | int ix; | ||||
int j; | int j; | ||||
PHONEME_TAB *p; | PHONEME_TAB *p; | ||||
} | } | ||||
n_phoneme_tabs++; | n_phoneme_tabs++; | ||||
} // end of StartPhonemeTable | |||||
} | |||||
static void CompileEquivalents() | static void CompileEquivalents() | ||||
{//============================= | |||||
{ | |||||
// a list of phonemes in another language and the equivalent phoneme strings in this language | // a list of phonemes in another language and the equivalent phoneme strings in this language | ||||
int ix; | int ix; | ||||
n_bytes = n_bytes / 4; | n_bytes = n_bytes / 4; | ||||
p_start[2] = n_bytes >> 8; // index of next table | p_start[2] = n_bytes >> 8; // index of next table | ||||
p_start[3] = n_bytes; | p_start[3] = n_bytes; | ||||
} // end of CompileEquivalents | |||||
} | |||||
static void CompilePhonemeFiles() | static void CompilePhonemeFiles() | ||||
{//============================== | |||||
{ | |||||
int item; | int item; | ||||
FILE *f; | FILE *f; | ||||
char buf[sizeof(path_home)+120]; | char buf[sizeof(path_home)+120]; | ||||
} | } | ||||
} | } | ||||
phoneme_tab2[n_phcodes+1].mnemonic = 0; // terminator | phoneme_tab2[n_phcodes+1].mnemonic = 0; // terminator | ||||
} // end of CompilePhonemeFiles | |||||
} | |||||
static espeak_ng_STATUS CompilePhonemeData2(const char *source, FILE *log) | static espeak_ng_STATUS CompilePhonemeData2(const char *source, FILE *log) | ||||
{//================================================ | |||||
{ | |||||
char fname[sizeof(path_home)+40]; | char fname[sizeof(path_home)+40]; | ||||
sprintf(fname,"%s/../phsource",path_home); | sprintf(fname,"%s/../phsource",path_home); | ||||
ReadPhondataManifest(); | ReadPhondataManifest(); | ||||
return ENS_OK; | return ENS_OK; | ||||
} // end of CompilePhonemeData | |||||
} | |||||
static const char *preset_tune_names[] = { | static const char *preset_tune_names[] = { | ||||
{"rise-fall-rise", 18}, | {"rise-fall-rise", 18}, | ||||
{NULL, -1} }; | {NULL, -1} }; | ||||
// env_fallrise3, env_fallrise3, | |||||
// env_fallrise4, env_fallrise4, | |||||
// env_fall2, env_fall2, | |||||
// env_rise2, env_rise2, | |||||
// env_risefallrise, env_risefallrise | |||||
int LookupEnvelopeName(const char *name) | int LookupEnvelopeName(const char *name) | ||||
{//================================= | |||||
{ | |||||
return(LookupMnem(envelope_names, name)); | return(LookupMnem(envelope_names, name)); | ||||
} | } | ||||
#pragma GCC visibility push(default) | #pragma GCC visibility push(default) | ||||
espeak_ng_STATUS espeak_ng_CompileIntonation(FILE *log) | espeak_ng_STATUS espeak_ng_CompileIntonation(FILE *log) | ||||
{//===================== | |||||
{ | |||||
int ix; | int ix; | ||||
char *p; | char *p; | ||||
char c; | char c; | ||||
LoadPhData(NULL); | LoadPhData(NULL); | ||||
return error_count > 0 ? ENE_COMPILE_ERRORS : ENS_OK; | return error_count > 0 ? ENE_COMPILE_ERRORS : ENS_OK; | ||||
} // end of CompileIntonation | |||||
} | |||||
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington * | * Copyright (C) 2005 to 2014 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * | ||||
int isspace2(unsigned int c) | int isspace2(unsigned int c) | ||||
{//========================= | |||||
{ | |||||
// can't use isspace() because on Windows, isspace(0xe1) gives TRUE ! | // can't use isspace() because on Windows, isspace(0xe1) gives TRUE ! | ||||
int c2; | int c2; | ||||
static FILE *fopen_log(const char *fname,const char *access) | static FILE *fopen_log(const char *fname,const char *access) | ||||
{//================================================== | |||||
{ | |||||
// performs fopen, but produces error message to f_log if it fails | // performs fopen, but produces error message to f_log if it fails | ||||
FILE *f; | FILE *f; | ||||
} | } | ||||
const char *LookupMnemName(MNEM_TAB *table, const int value) | |||||
//========================================================== | |||||
/* Lookup a mnemonic string in a table, return its name */ | /* Lookup a mnemonic string in a table, return its name */ | ||||
const char *LookupMnemName(MNEM_TAB *table, const int value) | |||||
{ | { | ||||
while(table->mnem != NULL) | while(table->mnem != NULL) | ||||
{ | { | ||||
table++; | table++; | ||||
} | } | ||||
return(""); /* not found */ | return(""); /* not found */ | ||||
} /* end of LookupMnemValue */ | |||||
} | |||||
void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len) | void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len) | ||||
{//======================================================================== | |||||
{ | |||||
int stress; | int stress; | ||||
int ix; | int ix; | ||||
const char *name; | const char *name; | ||||
char *DecodeRule(const char *group_chars, int group_length, char *rule, int control) | 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; | ||||
output[ix++]=' '; | output[ix++]=' '; | ||||
output[ix]=0; | output[ix]=0; | ||||
return(output); | return(output); | ||||
} /* end of DecodeRule */ | |||||
} | |||||
static int compile_line(char *linebuf, char *dict_line, int *hash) | static int compile_line(char *linebuf, char *dict_line, int *hash) | ||||
{//=============================================================== | |||||
{ | |||||
// Compile a line in the language_list file | // Compile a line in the language_list file | ||||
unsigned char c; | unsigned char c; | ||||
char *p; | char *p; | ||||
return(length); | return(length); | ||||
} /* end of compile_line */ | |||||
} | |||||
static void compile_dictlist_start(void) | static void compile_dictlist_start(void) | ||||
{//===================================== | |||||
{ | |||||
// initialise dictionary list | // initialise dictionary list | ||||
int ix; | int ix; | ||||
char *p; | char *p; | ||||
static void compile_dictlist_end(FILE *f_out) | static void compile_dictlist_end(FILE *f_out) | ||||
{//========================================== | |||||
{ | |||||
// Write out the compiled dictionary list | // Write out the compiled dictionary list | ||||
int hash; | int hash; | ||||
int length; | int length; | ||||
static int compile_dictlist_file(const char *path, const char* filename) | static int compile_dictlist_file(const char *path, const char* filename) | ||||
{//===================================================================== | |||||
{ | |||||
int length; | int length; | ||||
int hash; | int hash; | ||||
char *p; | char *p; | ||||
fprintf(f_log,"\t%d entries\n",count); | fprintf(f_log,"\t%d entries\n",count); | ||||
fclose(f_in); | fclose(f_in); | ||||
return(0); | return(0); | ||||
} /* end of compile_dictlist_file */ | |||||
} | |||||
static void copy_rule_string(char *string, int *state_out) | static void copy_rule_string(char *string, int *state_out) | ||||
{//======================================================= | |||||
{ | |||||
// state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes | // state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes | ||||
static char *outbuf[5] = {rule_cond, rule_pre, rule_match, rule_post, rule_phonemes}; | static char *outbuf[5] = {rule_cond, rule_pre, rule_match, rule_post, rule_phonemes}; | ||||
static int next_state[5] = {2,2,4,4,4}; | static int next_state[5] = {2,2,4,4,4}; | ||||
} | } | ||||
*state_out = next_state[state]; | *state_out = next_state[state]; | ||||
} // end of copy_rule_string | |||||
} | |||||
static char *compile_rule(char *input) | static char *compile_rule(char *input) | ||||
{//=================================== | |||||
{ | |||||
int ix; | int ix; | ||||
unsigned char c; | unsigned char c; | ||||
int wc; | int wc; | ||||
prule = (char *)malloc(len); | prule = (char *)malloc(len); | ||||
memcpy(prule,output,len); | memcpy(prule,output,len); | ||||
return(prule); | return(prule); | ||||
} // end of compile_rule | |||||
} | |||||
int __cdecl string_sorter(char **a, char **b) | int __cdecl string_sorter(char **a, char **b) | ||||
{//=========================================== | |||||
{ | |||||
char *pa, *pb; | char *pa, *pb; | ||||
int ix; | int ix; | ||||
pa += (strlen(pa)+1); | pa += (strlen(pa)+1); | ||||
pb += (strlen(pb)+1); | pb += (strlen(pb)+1); | ||||
return(strcmp(pa,pb)); | return(strcmp(pa,pb)); | ||||
} /* end of string_sorter */ | |||||
} | |||||
static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b) | static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b) | ||||
{//=================================================== | |||||
{ | |||||
// Sort long names before short names | // Sort long names before short names | ||||
int ix; | int ix; | ||||
ix = strlen(b->name) - strlen(a->name); | ix = strlen(b->name) - strlen(a->name); | ||||
#ifdef OUTPUT_FORMAT | #ifdef OUTPUT_FORMAT | ||||
static void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name) | static void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name) | ||||
{//============================================================================= | |||||
{ | |||||
int rule; | int rule; | ||||
int ix; | int ix; | ||||
unsigned char c; | unsigned char c; | ||||
#endif | #endif | ||||
//#define LIST_GROUP_INFO | |||||
static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name) | static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name) | ||||
{//============================================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int len1; | int len1; | ||||
int len2; | int len2; | ||||
printf("Group %s %c %d\n",name,ix,nextchar_count[ix]); | printf("Group %s %c %d\n",name,ix,nextchar_count[ix]); | ||||
} | } | ||||
#endif | #endif | ||||
} // end of output_rule_group | |||||
} | |||||
static int compile_lettergroup(char *input, FILE *f_out) | static int compile_lettergroup(char *input, FILE *f_out) | ||||
{//===================================================== | |||||
{ | |||||
char *p; | char *p; | ||||
char *p_start; | char *p_start; | ||||
int group; | int group; | ||||
static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) | ||||
{//==================================================================== | |||||
{ | |||||
char *prule; | char *prule; | ||||
unsigned char *p; | unsigned char *p; | ||||
int ix; | int ix; | ||||
fprintf(f_log,"\t%d rules, %d groups (%d)\n\n",count,n_rgroups,n_groups3); | fprintf(f_log,"\t%d rules, %d groups (%d)\n\n",count,n_rgroups,n_groups3); | ||||
return(0); | return(0); | ||||
} // end of compile_dictrules | |||||
} | |||||
int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err, int flags) | int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err, int flags) | ||||
{//===================================================================================================== | |||||
{ | |||||
// fname: space to write the filename in case of error | // fname: space to write the filename in case of error | ||||
// flags: bit 0: include source line number information, for debug purposes. | // flags: bit 0: include source line number information, for debug purposes. | ||||
LoadDictionary(translator, dict_name, 0); | LoadDictionary(translator, dict_name, 0); | ||||
return(error_count); | return(error_count); | ||||
} // end of compile_dictionary | |||||
} |
void strncpy0(char *to,const char *from, int size) | void strncpy0(char *to,const char *from, int size) | ||||
{//=================================================== | |||||
{ | |||||
// strcpy with limit, ensures a zero terminator | // strcpy with limit, ensures a zero terminator | ||||
strncpy(to,from,size); | strncpy(to,from,size); | ||||
to[size-1] = 0; | to[size-1] = 0; | ||||
int Reverse4Bytes(int word) | int Reverse4Bytes(int word) | ||||
{//========================== | |||||
{ | |||||
// reverse the order of bytes from little-endian to big-endian | // reverse the order of bytes from little-endian to big-endian | ||||
#ifdef ARCH_BIG | #ifdef ARCH_BIG | ||||
int ix; | int ix; | ||||
int LookupMnem(MNEM_TAB *table, const char *string) | int LookupMnem(MNEM_TAB *table, const char *string) | ||||
{//================================================== | |||||
{ | |||||
while(table->mnem != NULL) | while(table->mnem != NULL) | ||||
{ | { | ||||
if(strcmp(string,table->mnem)==0) | if(strcmp(string,table->mnem)==0) | ||||
} | } | ||||
//============================================================================================= | |||||
// Read pronunciation rules and pronunciation lookup dictionary | |||||
// | |||||
//============================================================================================= | |||||
static void InitGroups(Translator *tr) | static void InitGroups(Translator *tr) | ||||
{//=================================== | |||||
{ | |||||
// Called after dictionary 1 is loaded, to set up table of entry points for translation rule chains | // Called after dictionary 1 is loaded, to set up table of entry points for translation rule chains | ||||
// for single-letters and two-letter combinations | // for single-letters and two-letter combinations | ||||
p++; | p++; | ||||
} | } | ||||
} // end of InitGroups | |||||
} | |||||
int LoadDictionary(Translator *tr, const char *name, int no_error) | int LoadDictionary(Translator *tr, const char *name, int no_error) | ||||
{//=============================================================== | |||||
{ | |||||
int hash; | int hash; | ||||
char *p; | char *p; | ||||
int *pw; | int *pw; | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of LoadDictionary | |||||
} | |||||
int HashDictionary(const char *string) | |||||
//==================================== | |||||
/* Generate a hash code from the specified string | /* Generate a hash code from the specified string | ||||
This is used to access the dictionary_2 word-lookup dictionary | This is used to access the dictionary_2 word-lookup dictionary | ||||
*/ | */ | ||||
int HashDictionary(const char *string) | |||||
{ | { | ||||
int c; | int c; | ||||
int chars=0; | int chars=0; | ||||
} | } | ||||
return((hash+chars) & 0x3ff); // a 10 bit hash code | return((hash+chars) & 0x3ff); // a 10 bit hash code | ||||
} // end of HashDictionary | |||||
//============================================================================================= | |||||
// Translate between internal representation of phonemes and a mnemonic form for display | |||||
// | |||||
//============================================================================================= | |||||
} | |||||
const char *EncodePhonemes(const char *p, char *outptr, int *bad_phoneme) | |||||
/******************************************************************/ | |||||
/* Translate a phoneme string from ascii mnemonics to internal phoneme numbers, | /* Translate a phoneme string from ascii mnemonics to internal phoneme numbers, | ||||
from 'p' up to next blank . | from 'p' up to next blank . | ||||
Returns advanced 'p' | Returns advanced 'p' | ||||
outptr contains encoded phonemes, unrecognized phoneme stops the encoding | outptr contains encoded phonemes, unrecognized phoneme stops the encoding | ||||
bad_phoneme must point to char array of length 2 of more | bad_phoneme must point to char array of length 2 of more | ||||
*/ | */ | ||||
const char *EncodePhonemes(const char *p, char *outptr, int *bad_phoneme) | |||||
{ | { | ||||
int ix; | int ix; | ||||
unsigned char c; | unsigned char c; | ||||
/* terminate the encoded string */ | /* terminate the encoded string */ | ||||
*outptr = 0; | *outptr = 0; | ||||
return(p); | return(p); | ||||
} // end of EncodePhonemes | |||||
} | |||||
void DecodePhonemes(const char *inptr, char *outptr) | void DecodePhonemes(const char *inptr, char *outptr) | ||||
{//================================================== | |||||
{ | |||||
// Translate from internal phoneme codes into phoneme mnemonics | // Translate from internal phoneme codes into phoneme mnemonics | ||||
unsigned char phcode; | unsigned char phcode; | ||||
unsigned char c; | unsigned char c; | ||||
} | } | ||||
} | } | ||||
*outptr = 0; /* string terminator */ | *outptr = 0; /* string terminator */ | ||||
} // end of DecodePhonemes | |||||
} | |||||
// using Kirschenbaum to IPA translation, ascii 0x20 to 0x7f | // using Kirschenbaum to IPA translation, ascii 0x20 to 0x7f | ||||
char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags) | char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags) | ||||
{//=================================================================================================== | |||||
{ | |||||
int c; | int c; | ||||
int mnem; | int mnem; | ||||
int len; | int len; | ||||
phon_out = &phon_out[ix]; | phon_out = &phon_out[ix]; | ||||
*phon_out = 0; | *phon_out = 0; | ||||
return(phon_out); | return(phon_out); | ||||
} // end of WritePhMnemonic | |||||
} | |||||
const char *GetTranslatedPhonemeString(int phoneme_mode) | const char *GetTranslatedPhonemeString(int phoneme_mode) | ||||
{//======================================================= | |||||
{ | |||||
/* Called after a clause has been translated into phonemes, in order | /* Called after a clause has been translated into phonemes, in order | ||||
to display the clause in phoneme mnemonic form. | to display the clause in phoneme mnemonic form. | ||||
phon_out_buf[phon_out_ix] = 0; | phon_out_buf[phon_out_ix] = 0; | ||||
return(phon_out_buf); | return(phon_out_buf); | ||||
} // end of GetTranslatedPhonemeString | |||||
//============================================================================================= | |||||
// Is a word Unpronouncable - and so should be spoken as individual letters | |||||
// | |||||
//============================================================================================= | |||||
} | |||||
static int IsLetterGroup(Translator *tr, char *word, int group, int pre) | static int IsLetterGroup(Translator *tr, char *word, int group, int pre) | ||||
{//===================================================================== | |||||
{ | |||||
// match the word against a list of utf-8 strings | // match the word against a list of utf-8 strings | ||||
char *p; | char *p; | ||||
char *w; | char *w; | ||||
static int IsLetter(Translator *tr, int letter, int group) | static int IsLetter(Translator *tr, int letter, int group) | ||||
{//======================================================= | |||||
{ | |||||
int letter2; | int letter2; | ||||
if(tr->letter_groups[group] != NULL) | if(tr->letter_groups[group] != NULL) | ||||
int IsVowel(Translator *tr, int letter) | int IsVowel(Translator *tr, int letter) | ||||
{//==================================== | |||||
{ | |||||
return(IsLetter(tr, letter, LETTERGP_VOWEL2)); | return(IsLetter(tr, letter, LETTERGP_VOWEL2)); | ||||
} | } | ||||
static int Unpronouncable2(Translator *tr, char *word) | static int Unpronouncable2(Translator *tr, char *word) | ||||
{//=================================================== | |||||
{ | |||||
int c; | int c; | ||||
int end_flags; | int end_flags; | ||||
char ph_buf[N_WORD_PHONEMES]; | char ph_buf[N_WORD_PHONEMES]; | ||||
int Unpronouncable(Translator *tr, char *word, int posn) | int Unpronouncable(Translator *tr, char *word, int posn) | ||||
{//===================================================== | |||||
{ | |||||
/* Determines whether a word in 'unpronouncable', i.e. whether it should | /* Determines whether a word in 'unpronouncable', i.e. whether it should | ||||
be spoken as individual letters. | be spoken as individual letters. | ||||
return(0); | return(0); | ||||
} /* end of Unpronounceable */ | |||||
//============================================================================================= | |||||
// Determine the stress pattern of a word | |||||
// | |||||
//============================================================================================= | |||||
} | |||||
static int GetVowelStress(Translator *tr, unsigned char *phonemes, signed char *vowel_stress, int *vowel_count, int *stressed_syllable, int control) | static int GetVowelStress(Translator *tr, unsigned char *phonemes, signed char *vowel_stress, int *vowel_count, int *stressed_syllable, int control) | ||||
{//================================================================================================================================================= | |||||
{ | |||||
// control = 1, set stress to 1 for forced unstressed vowels | // control = 1, set stress to 1 for forced unstressed vowels | ||||
unsigned char phcode; | unsigned char phcode; | ||||
PHONEME_TAB *ph; | PHONEME_TAB *ph; | ||||
*stressed_syllable = primary_posn; | *stressed_syllable = primary_posn; | ||||
*vowel_count = count; | *vowel_count = count; | ||||
return(max_stress); | return(max_stress); | ||||
} // end of GetVowelStress | |||||
} | |||||
void ChangeWordStress(Translator *tr, char *word, int new_stress) | void ChangeWordStress(Translator *tr, char *word, int new_stress) | ||||
{//============================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
unsigned char *p; | unsigned char *p; | ||||
int max_stress; | int max_stress; | ||||
*word++ = *p++; | *word++ = *p++; | ||||
} | } | ||||
*word = 0; | *word = 0; | ||||
} // end of ChangeWordStress | |||||
} | |||||
void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int control) | void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int control) | ||||
{//===================================================================================================== | |||||
{ | |||||
/* Guess stress pattern of word. This is language specific | /* Guess stress pattern of word. This is language specific | ||||
'output' is used for input and output | 'output' is used for input and output | ||||
*output++ = 0; | *output++ = 0; | ||||
return; | return; | ||||
} /* end of SetWordStress */ | |||||
//============================================================================================= | |||||
// Look up a word in the pronunciation rules | |||||
// | |||||
//============================================================================================= | |||||
} | |||||
void AppendPhonemes(Translator *tr, char *string, int size, const char *ph) | void AppendPhonemes(Translator *tr, char *string, int size, const char *ph) | ||||
{//======================================================================== | |||||
{ | |||||
/* Add new phoneme string "ph" to "string" | /* Add new phoneme string "ph" to "string" | ||||
Keeps count of the number of vowel phonemes in the word, and whether these | Keeps count of the number of vowel phonemes in the word, and whether these | ||||
can be stressed syllables. These values can be used in translation rules | can be stressed syllables. These values can be used in translation rules | ||||
if(string != NULL) | if(string != NULL) | ||||
strcat(string,ph); | strcat(string,ph); | ||||
} /* end of AppendPhonemes */ | |||||
} | |||||
static void MatchRule(Translator *tr, char *word[], char *word_start, int group_length, char *rule, MatchRecord *match_out, int word_flags, int dict_flags) | static void MatchRule(Translator *tr, char *word[], char *word_start, int group_length, char *rule, MatchRecord *match_out, int word_flags, int dict_flags) | ||||
{//======================================================================================================================================================== | |||||
{ | |||||
/* Checks a specified word against dictionary rules. | /* Checks a specified word against dictionary rules. | ||||
Returns with phoneme code string, or NULL if no match found. | Returns with phoneme code string, or NULL if no match found. | ||||
if(best.points == 0) | if(best.points == 0) | ||||
best.phonemes = ""; | best.phonemes = ""; | ||||
memcpy(match_out,&best,sizeof(MatchRecord)); | memcpy(match_out,&best,sizeof(MatchRecord)); | ||||
} /* end of MatchRule */ | |||||
} | |||||
int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, char *end_phonemes, int word_flags, unsigned int *dict_flags) | int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, char *end_phonemes, int word_flags, unsigned int *dict_flags) | ||||
{//===================================================================================================================================== | |||||
{ | |||||
/* Translate a word bounded by space characters | /* Translate a word bounded by space characters | ||||
Append the result to 'phonemes' and any standard prefix/suffix in 'end_phonemes' */ | Append the result to 'phonemes' and any standard prefix/suffix in 'end_phonemes' */ | ||||
memcpy(p_start,word_copy,strlen(word_copy)); | memcpy(p_start,word_copy,strlen(word_copy)); | ||||
return(0); | return(0); | ||||
} /* end of TranslateRules */ | |||||
} | |||||
void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags) | void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags) | ||||
{//======================================================================== | |||||
{ | |||||
// apply after the translation is complete | // apply after the translation is complete | ||||
int ix; | int ix; | ||||
int len; | int len; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} // end of ApplySpecialAttribute2 | |||||
} | |||||
//============================================================================================= | |||||
// Look up a word in the pronunciation dictionary list | |||||
// - exceptions which override the usual pronunciation rules, or which give a word | |||||
// special properties, such as pronounce as unstressed | |||||
//============================================================================================= | |||||
int TransposeAlphabet(Translator *tr, char *text) | int TransposeAlphabet(Translator *tr, char *text) | ||||
{//============================================== | |||||
{ | |||||
// transpose cyrillic alphabet (for example) into ascii (single byte) character codes | // transpose cyrillic alphabet (for example) into ascii (single byte) character codes | ||||
// return: number of bytes, bit 6: 1=used compression | // return: number of bytes, bit 6: 1=used compression | ||||
int c; | int c; | ||||
{ | { | ||||
return(strlen(text)); | return(strlen(text)); | ||||
} | } | ||||
} // end of TransposeAlphabet | |||||
} | |||||
static const char *LookupDict2(Translator *tr, const char *word, const char *word2, | |||||
char *phonetic, unsigned int *flags, int end_flags, WORD_TAB *wtab) | |||||
//===================================================================================== | |||||
/* Find an entry in the word_dict file for a specified word. | /* Find an entry in the word_dict file for a specified word. | ||||
Returns NULL if no match, else returns 'word_end' | Returns NULL if no match, else returns 'word_end' | ||||
end_flags: indicates whether this is a retranslation after removing a suffix | end_flags: indicates whether this is a retranslation after removing a suffix | ||||
*/ | */ | ||||
static const char *LookupDict2(Translator *tr, const char *word, const char *word2, | |||||
char *phonetic, unsigned int *flags, int end_flags, WORD_TAB *wtab) | |||||
{ | { | ||||
char *p; | char *p; | ||||
char *next; | char *next; | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of LookupDict2 | |||||
} | |||||
int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab) | |||||
//================================================================================================================== | |||||
/* Lookup a specified word in the word dictionary. | /* Lookup a specified word in the word dictionary. | ||||
Returns phonetic data in 'phonetic' and bits in 'flags' | Returns phonetic data in 'phonetic' and bits in 'flags' | ||||
end_flags: indicates if a suffix has been removed | end_flags: indicates if a suffix has been removed | ||||
*/ | */ | ||||
int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab) | |||||
{ | { | ||||
int length; | int length; | ||||
const char *found; | const char *found; | ||||
ph_out[0] = 0; | ph_out[0] = 0; | ||||
return(0); | return(0); | ||||
} // end of LookupDictList | |||||
} | |||||
extern char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes | extern char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes | ||||
int Lookup(Translator *tr, const char *word, char *ph_out) | int Lookup(Translator *tr, const char *word, char *ph_out) | ||||
{//========================================================= | |||||
{ | |||||
// Look up in *_list, returns dictionary flags[0] and phonemes | // Look up in *_list, returns dictionary flags[0] and phonemes | ||||
int flags0; | int flags0; | ||||
int LookupFlags(Translator *tr, const char *word, unsigned int **flags_out) | int LookupFlags(Translator *tr, const char *word, unsigned int **flags_out) | ||||
{//=========================================================================== | |||||
{ | |||||
char buf[100]; | char buf[100]; | ||||
static unsigned int flags[2]; | static unsigned int flags[2]; | ||||
char *word1 = (char *)word; | char *word1 = (char *)word; | ||||
int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy) | int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy) | ||||
{//======================================================================== | |||||
{ | |||||
/* Removes a standard suffix from a word, once it has been indicated by the dictionary rules. | /* Removes a standard suffix from a word, once it has been indicated by the dictionary rules. | ||||
end_type: bits 0-6 number of letters | end_type: bits 0-6 number of letters | ||||
bits 8-14 suffix flags | bits 8-14 suffix flags | ||||
end_flags &= ~FLAG_SUFX; // don't consider 's as an added suffix | end_flags &= ~FLAG_SUFX; // don't consider 's as an added suffix | ||||
return(end_flags); | return(end_flags); | ||||
} /* end of RemoveEnding */ | |||||
} |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2007, Gilles Casse <[email protected]> * | * Copyright (C) 2007, Gilles Casse <[email protected]> * | ||||
* Copyright (C) 2013 Reece H. Dunn * | |||||
* Copyright (C) 2013-2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * | ||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||||
***************************************************************************/ | ***************************************************************************/ | ||||
// This source file is only used for asynchronious modes | |||||
#include "speech.h" | #include "speech.h" | ||||
#include "espeak_command.h" | #include "espeak_command.h" | ||||
#include <stdlib.h> | #include <stdlib.h> |
static void count_pitch_vowels(int start, int end, int clause_end) | static void count_pitch_vowels(int start, int end, int clause_end) | ||||
/****************************************************************/ | |||||
{ | { | ||||
int ix; | int ix; | ||||
int stress; | int stress; | ||||
// no primary stress. Use the highest stress | // no primary stress. Use the highest stress | ||||
syllable_tab[tone_posn].stress = PRIMARY_LAST; | syllable_tab[tone_posn].stress = PRIMARY_LAST; | ||||
} | } | ||||
} /* end of count_pitch_vowels */ | |||||
} | |||||
static int count_increments(int ix, int end_ix, int min_stress) | |||||
/*************************************************************/ | |||||
/* Count number of primary stresses up to tonic syllable or body_reset */ | /* Count number of primary stresses up to tonic syllable or body_reset */ | ||||
static int count_increments(int ix, int end_ix, int min_stress) | |||||
{ | { | ||||
int count = 0; | int count = 0; | ||||
int stress; | int stress; | ||||
count++; | count++; | ||||
} | } | ||||
return(count); | return(count); | ||||
} /* end of count_increments */ | |||||
} | |||||
static void set_pitch(SYLLABLE *syl, int base, int drop) | |||||
/******************************************************/ | |||||
// Set the pitch of a vowel in syllable_tab | // Set the pitch of a vowel in syllable_tab | ||||
static void set_pitch(SYLLABLE *syl, int base, int drop) | |||||
{ | { | ||||
int pitch1, pitch2; | int pitch1, pitch2; | ||||
int flags = 0; | int flags = 0; | ||||
syl->pitch1 = pitch1; | syl->pitch1 = pitch1; | ||||
syl->pitch2 = pitch2; | syl->pitch2 = pitch2; | ||||
syl->flags |= flags; | syl->flags |= flags; | ||||
} /* end of set_pitch */ | |||||
} | |||||
static int CountUnstressed(int start, int end, int limit) | static int CountUnstressed(int start, int end, int limit) | ||||
{//====================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
for(ix=start; ix <= end; ix++) | for(ix=start; ix <= end; ix++) | ||||
} | } | ||||
static int SetHeadIntonation(TUNE *tune, int syl_ix, int end_ix, int control) | static int SetHeadIntonation(TUNE *tune, int syl_ix, int end_ix, int control) | ||||
{//========================================================================== | |||||
{ | |||||
int stress; | int stress; | ||||
SYLLABLE *syl; | SYLLABLE *syl; | ||||
int ix; | int ix; | ||||
} | } | ||||
return(syl_ix); | return(syl_ix); | ||||
} // end of SetBodyIntonation | |||||
} | |||||
static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *tn, int min_stress, int continuing) | |||||
/**********************************************************************************************/ | |||||
/* Calculate pitches until next RESET or tonic syllable, or end. | /* Calculate pitches until next RESET or tonic syllable, or end. | ||||
Increment pitch if stress is >= min_stress. | Increment pitch if stress is >= min_stress. | ||||
Used for tonic segment */ | Used for tonic segment */ | ||||
static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *tn, int min_stress, int continuing) | |||||
{ | { | ||||
int stress; | int stress; | ||||
int pitch=0; | int pitch=0; | ||||
ix++; | ix++; | ||||
} | } | ||||
return(ix); | return(ix); | ||||
} /* end of calc_pitch_segment */ | |||||
} | |||||
static void SetPitchGradient(int start_ix, int end_ix, int start_pitch, int end_pitch) | static void SetPitchGradient(int start_ix, int end_ix, int start_pitch, int end_pitch) | ||||
{//==================================================================================== | |||||
{ | |||||
// Set a linear pitch change over a number of syllables. | // Set a linear pitch change over a number of syllables. | ||||
// Used for pre-head, unstressed syllables in the body, and the tail | // Used for pre-head, unstressed syllables in the body, and the tail | ||||
set_pitch(syl, (pitch >> 8), drop); | set_pitch(syl, (pitch >> 8), drop); | ||||
} | } | ||||
} | } | ||||
} // end of SetPitchGradient | |||||
} | |||||
static int calc_pitches2(int start, int end, int tune_number) | |||||
//============================================================ | |||||
// Calculate pitch values for the vowels in this tone group | // Calculate pitch values for the vowels in this tone group | ||||
static int calc_pitches2(int start, int end, int tune_number) | |||||
{ | { | ||||
int ix; | int ix; | ||||
TUNE *tune; | TUNE *tune; | ||||
SetPitchGradient(ix, end, tune->tail_start, tune->tail_end); | SetPitchGradient(ix, end, tune->tail_start, tune->tail_end); | ||||
return(tone_pitch_env); | return(tone_pitch_env); | ||||
} /* end of calc_pitches2 */ | |||||
} | |||||
static int calc_pitches(int control, int start, int end, int tune_number) | |||||
//======================================================================== | |||||
// Calculate pitch values for the vowels in this tone group | // Calculate pitch values for the vowels in this tone group | ||||
static int calc_pitches(int control, int start, int end, int tune_number) | |||||
{ | { | ||||
int ix; | int ix; | ||||
TONE_HEAD *th; | TONE_HEAD *th; | ||||
SetPitchGradient(ix, end, tn->tail_start, tn->tail_end); | SetPitchGradient(ix, end, tn->tail_start, tn->tail_end); | ||||
return(tone_pitch_env); | return(tone_pitch_env); | ||||
} /* end of calc_pitches */ | |||||
} | |||||
static void CalcPitches_Tone(Translator *tr, int clause_tone) | static void CalcPitches_Tone(Translator *tr, int clause_tone) | ||||
{//========================================================== | |||||
{ | |||||
// clause_tone: 0=. 1=, 2=?, 3=! 4=none | // clause_tone: 0=. 1=, 2=?, 3=! 4=none | ||||
PHONEME_LIST *p; | PHONEME_LIST *p; | ||||
int ix; | int ix; | ||||
} | } | ||||
} // end of Translator::CalcPitches_Tone | |||||
} | |||||
void CalcPitches(Translator *tr, int clause_type) | void CalcPitches(Translator *tr, int clause_type) | ||||
{//============================================== | |||||
{ | |||||
// clause_type: 0=. 1=, 2=?, 3=! 4=none | // clause_type: 0=. 1=, 2=?, 3=! 4=none | ||||
PHONEME_LIST *p; | PHONEME_LIST *p; | ||||
SYLLABLE *syl; | SYLLABLE *syl; | ||||
} | } | ||||
} | } | ||||
} // end of CalcPitches | |||||
} |
} | } | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of parwave | |||||
} | |||||
int Wavegen_Klatt(int resume) | int Wavegen_Klatt(int resume) | ||||
{//========================== | |||||
{ | |||||
int pk; | int pk; | ||||
int x; | int x; | ||||
int ix; | int ix; | ||||
void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v, int control) | void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v, int control) | ||||
{//=========================================================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
DOUBLEX next; | DOUBLEX next; | ||||
int qix; | int qix; | ||||
peaks[ix].ap_inc = ((next - peaks[ix].ap1) * STEPSIZE) / length; | peaks[ix].ap_inc = ((next - peaks[ix].ap1) * STEPSIZE) / length; | ||||
} | } | ||||
} | } | ||||
} // end of SetSynth_Klatt | |||||
} | |||||
int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2) | int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2) | ||||
{//=================================================================================== | |||||
{ | |||||
if(resume==0) | if(resume==0) | ||||
SetSynth_Klatt(length, modulation, fr1, fr2, wvoice, 1); | SetSynth_Klatt(length, modulation, fr1, fr2, wvoice, 1); | ||||
kt_frame.AB = 0; | kt_frame.AB = 0; | ||||
kt_frame.AVpdb = 0; | kt_frame.AVpdb = 0; | ||||
kt_frame.Gain0 = 62; // 60 | kt_frame.Gain0 = 62; // 60 | ||||
} // end of KlattInit | |||||
} |
}; | }; | ||||
static int LookupLetter2(Translator *tr, unsigned int letter, char *ph_buf) | static int LookupLetter2(Translator *tr, unsigned int letter, char *ph_buf) | ||||
{ //======================================================================== | |||||
{ | |||||
int len; | int len; | ||||
char single_letter[10]; | char single_letter[10]; | ||||
void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf) | void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf) | ||||
{//========================================================================= | |||||
{ | |||||
// lookup the character in the accents table | // lookup the character in the accents table | ||||
int accent_data = 0; | int accent_data = 0; | ||||
int accent1 = 0; | int accent1 = 0; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} // end of LookupAccentedLetter | |||||
} | |||||
void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1, int control) | void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1, int control) | ||||
{//============================================================================================== | |||||
{ | |||||
// control, bit 0: not the first letter of a word | // control, bit 0: not the first letter of a word | ||||
int len; | int len; | ||||
dict_flags[1] = 0; | dict_flags[1] = 0; | ||||
SetWordStress(tr, ph_buf1, dict_flags, -1, control & 1); | SetWordStress(tr, ph_buf1, dict_flags, -1, control & 1); | ||||
} // end of LookupLetter | |||||
} | |||||
// unicode ranges for non-ascii digits 0-9 | // unicode ranges for non-ascii digits 0-9 | ||||
int NonAsciiNumber(int letter) | int NonAsciiNumber(int letter) | ||||
{//============================ | |||||
{ | |||||
// Change non-ascii digit into ascii digit '0' to '9', (or -1 if not) | // Change non-ascii digit into ascii digit '0' to '9', (or -1 if not) | ||||
const int *p; | const int *p; | ||||
int base; | int base; | ||||
int IsSuperscript(int letter) | int IsSuperscript(int letter) | ||||
{//=========================== | |||||
{ | |||||
// is this a subscript or superscript letter ? | // is this a subscript or superscript letter ? | ||||
int ix; | int ix; | ||||
int c; | int c; | ||||
int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) | ||||
{//========================================================================= | |||||
{ | |||||
// get pronunciation for an isolated letter | // get pronunciation for an isolated letter | ||||
// return number of bytes used by the letter | // return number of bytes used by the letter | ||||
// control bit 0: a non-initial letter in a word | // control bit 0: a non-initial letter in a word | ||||
strcpy(&phonemes[len],ph_buf2); | strcpy(&phonemes[len],ph_buf2); | ||||
} | } | ||||
return(n_bytes); | return(n_bytes); | ||||
} // end of TranslateLetter | |||||
} | |||||
void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) | void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) | ||||
{//============================================================================= | |||||
{ | |||||
// Individual letter names, reduce the stress of some. | // Individual letter names, reduce the stress of some. | ||||
int ix; | int ix; | ||||
unsigned int c; | unsigned int c; | ||||
if(control >= 2) | if(control >= 2) | ||||
*phonemes++ = phonPAUSE_NOLINK; | *phonemes++ = phonPAUSE_NOLINK; | ||||
*phonemes = 0; | *phonemes = 0; | ||||
} // end of SetSpellingStress | |||||
} | |||||
static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB *wtab, int roman) | static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB *wtab, int roman) | ||||
{//============================================================================================== | |||||
{ | |||||
int ordinal = 0; | int ordinal = 0; | ||||
int c2; | int c2; | ||||
} | } | ||||
} | } | ||||
return(ordinal); | return(ordinal); | ||||
} // end of CheckDotOrdinal | |||||
} | |||||
static int hu_number_e(const char *word, int thousandplex, int value) | static int hu_number_e(const char *word, int thousandplex, int value) | ||||
{//================================================================== | |||||
{ | |||||
// lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett | // lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett | ||||
if((word[0] == 'a') || (word[0] == 'e')) | if((word[0] == 'a') || (word[0] == 'e')) | ||||
return(1); | return(1); | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of hu_numnber_e | |||||
} | |||||
int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) | int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) | ||||
{//========================================================================= | |||||
{ | |||||
int c; | int c; | ||||
char *p; | char *p; | ||||
const char *p2; | const char *p2; | ||||
strcat(ph_out,ph_roman); | strcat(ph_out,ph_roman); | ||||
return(1); | return(1); | ||||
} // end of TranslateRoman | |||||
} | |||||
static const char *M_Variant(int value) | static const char *M_Variant(int value) | ||||
{//==================================== | |||||
{ | |||||
// returns M, or perhaps MA or MB for some cases | // returns M, or perhaps MA or MB for some cases | ||||
int teens = 0; | int teens = 0; | ||||
static int LookupThousands(Translator *tr, int value, int thousandplex, int thousands_exact, char *ph_out) | static int LookupThousands(Translator *tr, int value, int thousandplex, int thousands_exact, char *ph_out) | ||||
{//======================================================================================================= | |||||
{ | |||||
// thousands_exact: bit 0 no hundreds,tens,or units, bit 1 ordinal numberr | // thousands_exact: bit 0 no hundreds,tens,or units, bit 1 ordinal numberr | ||||
int found; | int found; | ||||
int found_value=0; | int found_value=0; | ||||
return(1); | return(1); | ||||
return(found_value); | return(found_value); | ||||
} // end f LookupThousands | |||||
} | |||||
static int LookupNum2(Translator *tr, int value, int thousandplex, const int control, char *ph_out) | static int LookupNum2(Translator *tr, int value, int thousandplex, const int control, char *ph_out) | ||||
{//============================================================================= | |||||
{ | |||||
// Lookup a 2 digit number | // Lookup a 2 digit number | ||||
// control bit 0: ordinal number | // control bit 0: ordinal number | ||||
// control bit 1: final tens and units (not number of thousands) (use special form of '1', LANG=de "eins") | // control bit 1: final tens and units (not number of thousands) (use special form of '1', LANG=de "eins") | ||||
} | } | ||||
} | } | ||||
return(used_and); | return(used_and); | ||||
} // end of LookupNum2 | |||||
} | |||||
static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int control) | static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int control) | ||||
{//============================================================================================================= | |||||
{ | |||||
// Translate a 3 digit number | // Translate a 3 digit number | ||||
// control bit 0, previous thousands | // control bit 0, previous thousands | ||||
// bit 1, ordinal number | // bit 1, ordinal number | ||||
sprintf(ph_out,"%s%s%c%s",buf1,ph_hundred_and,phonEND_WORD,buf2); | sprintf(ph_out,"%s%s%c%s",buf1,ph_hundred_and,phonEND_WORD,buf2); | ||||
return(0); | return(0); | ||||
} // end of LookupNum3 | |||||
} | |||||
bool CheckThousandsGroup(char *word, int group_len) | bool CheckThousandsGroup(char *word, int group_len) | ||||
{//================================================ | |||||
{ | |||||
// Is this a group of 3 digits which looks like a thousands group? | // Is this a group of 3 digits which looks like a thousands group? | ||||
int ix; | int ix; | ||||
static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | ||||
{//===================================================================================================================== | |||||
{ | |||||
// Number translation with various options | // Number translation with various options | ||||
// the "word" may be up to 4 digits | // the "word" may be up to 4 digits | ||||
// "words" of 3 digits may be preceded by another number "word" for thousands or millions | // "words" of 3 digits may be preceded by another number "word" for thousands or millions | ||||
while(IsDigit09(word[n_digits+decimal_count])) | while(IsDigit09(word[n_digits+decimal_count])) | ||||
decimal_count++; | decimal_count++; | ||||
// if(decimal_count > 1) | |||||
{ | |||||
max_decimal_count = 2; | max_decimal_count = 2; | ||||
switch(decimal_mode = (tr->langopts.numbers & 0xe000)) | switch(decimal_mode = (tr->langopts.numbers & 0xe000)) | ||||
{ | { | ||||
strcat(ph_out, buf1); | strcat(ph_out, buf1); | ||||
} | } | ||||
} | } | ||||
} | |||||
while(IsDigit09(c = word[n_digits]) && (strlen(ph_out) < (N_WORD_PHONEMES - 10))) | while(IsDigit09(c = word[n_digits]) && (strlen(ph_out) < (N_WORD_PHONEMES - 10))) | ||||
{ | { | ||||
if(skipwords) | if(skipwords) | ||||
dictionary_skipwords = skipwords; | dictionary_skipwords = skipwords; | ||||
return(1); | return(1); | ||||
} // end of TranslateNumber_1 | |||||
} | |||||
int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) | ||||
{//============================================================================================================= | |||||
{ | |||||
if((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS)) | if((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS)) | ||||
return(0); // speak digits individually | return(0); // speak digits individually | ||||
return(TranslateNumber_1(tr, word1, ph_out, flags, wtab, control)); | return(TranslateNumber_1(tr, word1, ph_out, flags, wtab, control)); | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of TranslateNumber | |||||
} |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2010 by Jonathan Duddington * | * Copyright (C) 2005 to 2010 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * |
static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) | static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) | ||||
{//=================================================================== | |||||
{ | |||||
// Copy the phonemes list and perform any substitutions that are required for the | // Copy the phonemes list and perform any substitutions that are required for the | ||||
// current voice | // current voice | ||||
int ix; | int ix; | ||||
n_plist_out++; | n_plist_out++; | ||||
} | } | ||||
return(n_plist_out); | return(n_plist_out); | ||||
} // end of SubstitutePhonemes | |||||
} | |||||
void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | ||||
{//===================================================================== | |||||
{ | |||||
int ix=0; | int ix=0; | ||||
int j; | int j; | ||||
phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT]; | phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT]; | ||||
n_phoneme_list = ix; | n_phoneme_list = ix; | ||||
} // end of MakePhonemeList | |||||
} |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2015 by Jonathan Duddington * | * Copyright (C) 2005 to 2015 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * | ||||
} | } | ||||
static int IsRomanU(unsigned int c) | static int IsRomanU(unsigned int c) | ||||
{//================================ | |||||
{ | |||||
if((c=='I') || (c=='V') || (c=='X') || (c=='L')) | if((c=='I') || (c=='V') || (c=='X') || (c=='L')) | ||||
return(1); | return(1); | ||||
return(0); | return(0); | ||||
static void GetC_unget(int c) | static void GetC_unget(int c) | ||||
{//========================== | |||||
{ | |||||
// This is only called with UTF8 input, not wchar input | // This is only called with UTF8 input, not wchar input | ||||
if(f_input != NULL) | if(f_input != NULL) | ||||
ungetc(c,f_input); | ungetc(c,f_input); | ||||
} | } | ||||
int Eof(void) | int Eof(void) | ||||
{//========== | |||||
{ | |||||
if(ungot_char != 0) | if(ungot_char != 0) | ||||
return(0); | return(0); | ||||
static int GetC_get(void) | static int GetC_get(void) | ||||
{//====================== | |||||
{ | |||||
unsigned int c; | unsigned int c; | ||||
unsigned int c2; | unsigned int c2; | ||||
static int GetC(void) | static int GetC(void) | ||||
{//================== | |||||
{ | |||||
// Returns a unicode wide character | // Returns a unicode wide character | ||||
// Performs UTF8 checking and conversion | // Performs UTF8 checking and conversion | ||||
if(c1 >= 0xa0) | if(c1 >= 0xa0) | ||||
return(translator->charset_a0[c1-0xa0]); | return(translator->charset_a0[c1-0xa0]); | ||||
return(c1); | return(c1); | ||||
} // end of GetC | |||||
} | |||||
static void UngetC(int c) | static void UngetC(int c) | ||||
{//====================== | |||||
{ | |||||
ungot_char = c; | ungot_char = c; | ||||
} | } | ||||
const char *WordToString2(unsigned int word) | const char *WordToString2(unsigned int word) | ||||
{//============================================ | |||||
{ | |||||
// Convert a language mnemonic word into a string | // Convert a language mnemonic word into a string | ||||
int ix; | int ix; | ||||
static char buf[5]; | static char buf[5]; | ||||
static const char *LookupSpecial(Translator *tr, const char *string, char* text_out) | static const char *LookupSpecial(Translator *tr, const char *string, char* text_out) | ||||
{//================================================================================= | |||||
{ | |||||
unsigned int flags[2]; | unsigned int flags[2]; | ||||
char phonemes[55]; | char phonemes[55]; | ||||
char phonemes2[55]; | char phonemes2[55]; | ||||
static const char *LookupCharName(Translator *tr, int c, int only) | static const char *LookupCharName(Translator *tr, int c, int only) | ||||
{//=============================================================== | |||||
{ | |||||
// Find the phoneme string (in ascii) to speak the name of character c | // Find the phoneme string (in ascii) to speak the name of character c | ||||
// Used for punctuation characters and symbols | // Used for punctuation characters and symbols | ||||
} | } | ||||
int Read4Bytes(FILE *f) | int Read4Bytes(FILE *f) | ||||
{//==================== | |||||
{ | |||||
// Read 4 bytes (least significant first) into a word | // Read 4 bytes (least significant first) into a word | ||||
int ix; | int ix; | ||||
unsigned char c; | unsigned char c; | ||||
static int LoadSoundFile(const char *fname, int index) | static int LoadSoundFile(const char *fname, int index) | ||||
{//=================================================== | |||||
{ | |||||
FILE *f; | FILE *f; | ||||
char *p; | char *p; | ||||
int *ip; | int *ip; | ||||
soundicon_tab[index].length = (*ip) / 2; // length in samples | soundicon_tab[index].length = (*ip) / 2; // length in samples | ||||
soundicon_tab[index].data = p; | soundicon_tab[index].data = p; | ||||
return(0); | return(0); | ||||
} // 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 ix; | int ix; | ||||
static int LoadSoundFile2(const char *fname) | static int LoadSoundFile2(const char *fname) | ||||
{//========================================= | |||||
{ | |||||
// Load a sound file into one of the reserved slots in the sound icon table | // Load a sound file into one of the reserved slots in the sound icon table | ||||
// (if it'snot already loaded) | // (if it'snot already loaded) | ||||
static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output, int *bufix, int end_clause) | static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output, int *bufix, int end_clause) | ||||
{//============================================================================================================= | |||||
{ | |||||
// announce punctuation names | // announce punctuation names | ||||
// c1: the punctuation character | // c1: the punctuation character | ||||
// c2: the following character | // c2: the following character | ||||
return(attributes); | return(attributes); | ||||
return(short_pause); | return(short_pause); | ||||
} // end of AnnouncePunctuation | |||||
} | |||||
#define SSML_SPEAK 1 | #define SSML_SPEAK 1 | ||||
#define SSML_VOICE 2 | #define SSML_VOICE 2 | ||||
static const char *VoiceFromStack() | static const char *VoiceFromStack() | ||||
{//================================ | |||||
{ | |||||
// Use the voice properties from the SSML stack to choose a voice, and switch | // Use the voice properties from the SSML stack to choose a voice, and switch | ||||
// to that voice if it's not the current voice | // to that voice if it's not the current voice | ||||
int ix; | int ix; | ||||
return(voice_name); | return(voice_name); | ||||
} | } | ||||
return(v_id); | return(v_id); | ||||
} // end of VoiceFromStack | |||||
} | |||||
static void ProcessParamStack(char *outbuf, int *outix) | static void ProcessParamStack(char *outbuf, int *outix) | ||||
{//==================================================== | |||||
{ | |||||
// Set the speech parameters from the parameter stack | // Set the speech parameters from the parameter stack | ||||
int param; | int param; | ||||
int ix; | int ix; | ||||
*outix += strlen(buf); | *outix += strlen(buf); | ||||
} | } | ||||
} | } | ||||
} // end of ProcessParamStack | |||||
} | |||||
static PARAM_STACK *PushParamStack(int tag_type) | static PARAM_STACK *PushParamStack(int tag_type) | ||||
{//============================================= | |||||
{ | |||||
int ix; | int ix; | ||||
PARAM_STACK *sp; | PARAM_STACK *sp; | ||||
sp->parameter[ix] = -1; | sp->parameter[ix] = -1; | ||||
} | } | ||||
return(sp); | return(sp); | ||||
} // end of PushParamStack | |||||
} | |||||
static void PopParamStack(int tag_type, char *outbuf, int *outix) | static void PopParamStack(int tag_type, char *outbuf, int *outix) | ||||
{//============================================================== | |||||
{ | |||||
// unwind the stack up to and including the previous tag of this type | // unwind the stack up to and including the previous tag of this type | ||||
int ix; | int ix; | ||||
int top = 0; | int top = 0; | ||||
n_param_stack = top; | n_param_stack = top; | ||||
} | } | ||||
ProcessParamStack(outbuf, outix); | ProcessParamStack(outbuf, outix); | ||||
} // end of PopParamStack | |||||
} | |||||
static wchar_t *GetSsmlAttribute(wchar_t *pw, const char *name) | static wchar_t *GetSsmlAttribute(wchar_t *pw, const char *name) | ||||
{//============================================================ | |||||
{ | |||||
// Gets the value string for an attribute. | // Gets the value string for an attribute. | ||||
// Returns NULL if the attribute is not present | // Returns NULL if the attribute is not present | ||||
int ix; | int ix; | ||||
pw++; | pw++; | ||||
} | } | ||||
return(NULL); | return(NULL); | ||||
} // end of GetSsmlAttribute | |||||
} | |||||
static int attrcmp(const wchar_t *string1, const char *string2) | static int attrcmp(const wchar_t *string1, const char *string2) | ||||
{//============================================================ | |||||
{ | |||||
int ix; | int ix; | ||||
if(string1 == NULL) | if(string1 == NULL) | ||||
static int attrlookup(const wchar_t *string1, const MNEM_TAB *mtab) | static int attrlookup(const wchar_t *string1, const MNEM_TAB *mtab) | ||||
{//================================================================ | |||||
{ | |||||
int ix; | int ix; | ||||
for(ix=0; mtab[ix].mnem != NULL; ix++) | for(ix=0; mtab[ix].mnem != NULL; ix++) | ||||
static int attrnumber(const wchar_t *pw, int default_value, int type) | static int attrnumber(const wchar_t *pw, int default_value, int type) | ||||
{//================================================================== | |||||
{ | |||||
int value = 0; | int value = 0; | ||||
if((pw == NULL) || !IsDigit09(*pw)) | if((pw == NULL) || !IsDigit09(*pw)) | ||||
value *= 1000; | value *= 1000; | ||||
} | } | ||||
return(value); | return(value); | ||||
} // end of attrnumber | |||||
} | |||||
static int attrcopy_utf8(char *buf, const wchar_t *pw, int len) | static int attrcopy_utf8(char *buf, const wchar_t *pw, int len) | ||||
{//============================================================ | |||||
{ | |||||
// Convert attribute string into utf8, write to buf, and return its utf8 length | // Convert attribute string into utf8, write to buf, and return its utf8 length | ||||
unsigned int c; | unsigned int c; | ||||
int ix = 0; | int ix = 0; | ||||
} | } | ||||
buf[ix] = 0; | buf[ix] = 0; | ||||
return(ix); | return(ix); | ||||
} // end of attrcopy_utf8 | |||||
} | |||||
static int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out) | static int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out) | ||||
{//============================================================================= | |||||
{ | |||||
int sign = 0; | int sign = 0; | ||||
wchar_t *tail; | wchar_t *tail; | ||||
double value; | double value; | ||||
*value_out = (int)value; | *value_out = (int)value; | ||||
return(sign); // -1, 0, or 1 | return(sign); // -1, 0, or 1 | ||||
} // end of attr_prosody_value | |||||
} | |||||
int AddNameData(const char *name, int wide) | int AddNameData(const char *name, int wide) | ||||
{//======================================== | |||||
{ | |||||
// Add the name to the namedata and return its position | // Add the name to the namedata and return its position | ||||
// (Used by the Windows SAPI wrapper) | // (Used by the Windows SAPI wrapper) | ||||
int ix; | int ix; | ||||
memcpy(&namedata[ix = namedata_ix],name,len); | memcpy(&namedata[ix = namedata_ix],name,len); | ||||
namedata_ix += len; | namedata_ix += len; | ||||
return(ix); | return(ix); | ||||
} // end of AddNameData | |||||
} | |||||
void SetVoiceStack(espeak_VOICE *v, const char *variant_name) | void SetVoiceStack(espeak_VOICE *v, const char *variant_name) | ||||
{//========================================================== | |||||
{ | |||||
SSML_STACK *sp; | SSML_STACK *sp; | ||||
sp = &ssml_stack[0]; | sp = &ssml_stack[0]; | ||||
static int GetVoiceAttributes(wchar_t *pw, int tag_type) | static int GetVoiceAttributes(wchar_t *pw, int tag_type) | ||||
{//===================================================== | |||||
{ | |||||
// Determines whether voice attribute are specified in this tag, and if so, whether this means | // Determines whether voice attribute are specified in this tag, and if so, whether this means | ||||
// a voice change. | // a voice change. | ||||
// If it's a closing tag, delete the top frame of the stack and determine whether this implies | // If it's a closing tag, delete the top frame of the stack and determine whether this implies | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of GetVoiceAttributes | |||||
} | |||||
static void SetProsodyParameter(int param_type, wchar_t *attr1, PARAM_STACK *sp) | static void SetProsodyParameter(int param_type, wchar_t *attr1, PARAM_STACK *sp) | ||||
{//============================================================================= | |||||
{ | |||||
int value; | int value; | ||||
int sign; | int sign; | ||||
sp->parameter[param_type] = speech_parameters[param_type] + (value*sign); | sp->parameter[param_type] = speech_parameters[param_type] + (value*sign); | ||||
} | } | ||||
} | } | ||||
} // end of SetProsodyParemeter | |||||
} | |||||
static int ReplaceKeyName(char *outbuf, int index, int *outix) | static int ReplaceKeyName(char *outbuf, int index, int *outix) | ||||
{//=========================================================== | |||||
{ | |||||
// Replace some key-names by single characters, so they can be pronounced in different languages | // Replace some key-names by single characters, so they can be pronounced in different languages | ||||
static MNEM_TAB keynames[] = { | static MNEM_TAB keynames[] = { | ||||
{"space ",0xe020}, | {"space ",0xe020}, | ||||
static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, int self_closing) | static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, int self_closing) | ||||
{//================================================================================================== | |||||
{ | |||||
// xml_buf is the tag and attributes with a zero terminator in place of the original '>' | // xml_buf is the tag and attributes with a zero terminator in place of the original '>' | ||||
// returns a clause terminator value. | // returns a clause terminator value. | ||||
return(CLAUSE_PARAGRAPH); | return(CLAUSE_PARAGRAPH); | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of ProcessSsmlTag | |||||
} | |||||
static void RemoveChar(char *p) | static void RemoveChar(char *p) | ||||
{//======================= | |||||
{ | |||||
// Replace a UTF-8 character by spaces | // Replace a UTF-8 character by spaces | ||||
int c; | int c; | ||||
memset(p, ' ', utf8_in(&c, p)); | memset(p, ' ', utf8_in(&c, p)); | ||||
} // end of RemoveChar | |||||
} | |||||
static MNEM_TAB xml_char_mnemonics[] = { | static MNEM_TAB xml_char_mnemonics[] = { | ||||
int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix_top, int n_buf, int *tone_type, char *voice_change) | int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix_top, int n_buf, int *tone_type, char *voice_change) | ||||
{//================================================================================================================================= | |||||
{ | |||||
/* Find the end of the current clause. | /* Find the end of the current clause. | ||||
Write the clause into buf | Write the clause into buf | ||||
buf[ix] = ' '; | buf[ix] = ' '; | ||||
buf[ix+1] = 0; | buf[ix+1] = 0; | ||||
return(CLAUSE_EOF); // end of file | return(CLAUSE_EOF); // end of file | ||||
} // end of ReadClause | |||||
} | |||||
void InitNamedata(void) | void InitNamedata(void) | ||||
{//==================== | |||||
{ | |||||
namedata_ix = 0; | namedata_ix = 0; | ||||
if(namedata != NULL) | if(namedata != NULL) | ||||
{ | { | ||||
void InitText2(void) | void InitText2(void) | ||||
{//================= | |||||
{ | |||||
int param; | int param; | ||||
ungot_char = 0; | ungot_char = 0; | ||||
xmlbase = NULL; | xmlbase = NULL; | ||||
} | } | ||||
//#define TEST_SPEED | |||||
#ifdef INCLUDE_SONIC | #ifdef INCLUDE_SONIC | ||||
void SetSpeed(int control) | void SetSpeed(int control) | ||||
{//======================= | |||||
{ | |||||
int x; | int x; | ||||
int s1; | int s1; | ||||
int wpm; | int wpm; | ||||
speed.clause_pause_factor = 16; | speed.clause_pause_factor = 16; | ||||
} | } | ||||
} | } | ||||
} // end of SetSpeed | |||||
} | |||||
#else // not using sonic speed-up | #else // not using sonic speed-up | ||||
void SetSpeed(int control) | void SetSpeed(int control) | ||||
{//======================= | |||||
{ | |||||
// This is the earlier version of SetSpeed() before sonic speed-up was added | // This is the earlier version of SetSpeed() before sonic speed-up was added | ||||
int x; | int x; | ||||
int s1; | int s1; | ||||
speed.clause_pause_factor = 16; | speed.clause_pause_factor = 16; | ||||
} | } | ||||
} | } | ||||
} // end of SetSpeed | |||||
} | |||||
#endif // of INCLUDE_SONIC | #endif // of INCLUDE_SONIC | ||||
void SetParameter(int parameter, int value, int relative) | void SetParameter(int parameter, int value, int relative) | ||||
{//====================================================== | |||||
{ | |||||
// parameter: reset-all, amp, pitch, speed, linelength, expression, capitals, number grouping | // parameter: reset-all, amp, pitch, speed, linelength, expression, capitals, number grouping | ||||
// relative 0=absolute 1=relative | // relative 0=absolute 1=relative | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} // end of SetParameter | |||||
} | |||||
static void DoEmbedded2(int *embix) | static void DoEmbedded2(int *embix) | ||||
{//================================ | |||||
{ | |||||
// There were embedded commands in the text at this point | // There were embedded commands in the text at this point | ||||
unsigned int word; | unsigned int word; | ||||
void CalcLengths(Translator *tr) | void CalcLengths(Translator *tr) | ||||
{//============================== | |||||
{ | |||||
int ix; | int ix; | ||||
int ix2; | int ix2; | ||||
PHONEME_LIST *prev; | PHONEME_LIST *prev; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} // end of CalcLengths | |||||
} |
void WVoiceChanged(voice_t *wvoice) | void WVoiceChanged(voice_t *wvoice) | ||||
{//================================= | |||||
{ | |||||
// Voice change in wavegen | // Voice change in wavegen | ||||
voice_samplerate = wvoice->samplerate; | voice_samplerate = wvoice->samplerate; | ||||
} | } | ||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
static int dispatch_audio(short* outbuf, int length, espeak_EVENT* event) | static int dispatch_audio(short* outbuf, int length, espeak_EVENT* event) | ||||
{//====================================================================== | |||||
{ | |||||
ENTER("dispatch_audio"); | ENTER("dispatch_audio"); | ||||
int a_wave_can_be_played = fifo_is_command_enabled(); | int a_wave_can_be_played = fifo_is_command_enabled(); | ||||
static int create_events(short* outbuf, int length, espeak_EVENT* event, uint32_t the_write_pos) | static int create_events(short* outbuf, int length, espeak_EVENT* event, uint32_t the_write_pos) | ||||
{//===================================================================== | |||||
{ | |||||
int finished; | int finished; | ||||
int i=0; | int i=0; | ||||
int sync_espeak_terminated_msg( uint32_t unique_identifier, void* user_data) | int sync_espeak_terminated_msg( uint32_t unique_identifier, void* user_data) | ||||
{//===================================================================== | |||||
{ | |||||
ENTER("sync_espeak_terminated_msg"); | ENTER("sync_espeak_terminated_msg"); | ||||
int finished=0; | int finished=0; | ||||
static void select_output(espeak_AUDIO_OUTPUT output_type) | static void select_output(espeak_AUDIO_OUTPUT output_type) | ||||
{//======================================================= | |||||
{ | |||||
my_mode = output_type; | my_mode = output_type; | ||||
my_audio = NULL; | my_audio = NULL; | ||||
synchronous_mode = 1; | synchronous_mode = 1; | ||||
WavegenInitSound(); | WavegenInitSound(); | ||||
break; | break; | ||||
} | } | ||||
} // end of select_output | |||||
} | |||||
int GetFileLength(const char *filename) | int GetFileLength(const char *filename) | ||||
{//==================================== | |||||
{ | |||||
struct stat statbuf; | struct stat statbuf; | ||||
if(stat(filename,&statbuf) != 0) | if(stat(filename,&statbuf) != 0) | ||||
return(-2); // a directory | return(-2); // a directory | ||||
return(statbuf.st_size); | return(statbuf.st_size); | ||||
} // end of GetFileLength | |||||
} | |||||
char *Alloc(int size) | char *Alloc(int size) | ||||
{//================== | |||||
{ | |||||
char *p; | char *p; | ||||
if((p = (char *)malloc(size)) == NULL) | if((p = (char *)malloc(size)) == NULL) | ||||
fprintf(stderr,"Can't allocate memory\n"); // I was told that size+1 fixes a crash on 64-bit systems | fprintf(stderr,"Can't allocate memory\n"); // I was told that size+1 fixes a crash on 64-bit systems | ||||
} | } | ||||
void Free(void *ptr) | void Free(void *ptr) | ||||
{//================= | |||||
{ | |||||
if(ptr != NULL) | if(ptr != NULL) | ||||
free(ptr); | free(ptr); | ||||
} | } | ||||
static void init_path(const char *path) | static void init_path(const char *path) | ||||
{//==================================== | |||||
{ | |||||
#ifdef PLATFORM_WINDOWS | #ifdef PLATFORM_WINDOWS | ||||
HKEY RegKey; | HKEY RegKey; | ||||
unsigned long size; | unsigned long size; | ||||
} | } | ||||
static int initialise(int control) | static int initialise(int control) | ||||
{//=============================== | |||||
{ | |||||
int param; | int param; | ||||
int result; | int result; | ||||
int srate = 22050; // default sample rate 22050 Hz | int srate = 22050; // default sample rate 22050 Hz | ||||
static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, int flags) | static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, int flags) | ||||
{//======================================================================================== | |||||
{ | |||||
// Fill the buffer with output sound | // Fill the buffer with output sound | ||||
int length; | int length; | ||||
int finished = 0; | int finished = 0; | ||||
} | } | ||||
} | } | ||||
return(EE_OK); | return(EE_OK); | ||||
} // end of Synthesize | |||||
} | |||||
#ifdef DEBUG_ENABLED | #ifdef DEBUG_ENABLED | ||||
static const char* label[] = { | static const char* label[] = { | ||||
void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr) | void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr) | ||||
{//================================================================================================== | |||||
{ | |||||
// type: 1=word, 2=sentence, 3=named mark, 4=play audio, 5=end, 7=phoneme | // type: 1=word, 2=sentence, 3=named mark, 4=play audio, 5=end, 7=phoneme | ||||
ENTER("MarkerEvent"); | ENTER("MarkerEvent"); | ||||
espeak_EVENT *ep; | espeak_EVENT *ep; | ||||
{ | { | ||||
ep->id.number = value; | ep->id.number = value; | ||||
} | } | ||||
} // end of MarkerEvent | |||||
} | |||||
espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size, | 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 position, espeak_POSITION_TYPE position_type, | ||||
unsigned int end_position, unsigned int flags, void* user_data) | unsigned int end_position, unsigned int flags, void* user_data) | ||||
{//=========================================================================== | |||||
{ | |||||
#ifdef DEBUG_ENABLED | #ifdef DEBUG_ENABLED | ||||
ENTER("sync_espeak_Synth"); | ENTER("sync_espeak_Synth"); | ||||
SHOW_TIME("LEAVE sync_espeak_Synth"); | SHOW_TIME("LEAVE sync_espeak_Synth"); | ||||
return aStatus; | return aStatus; | ||||
} // end of sync_espeak_Synth | |||||
} | |||||
espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size, | espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size, | ||||
const char *index_mark, unsigned int end_position, | const char *index_mark, unsigned int end_position, | ||||
unsigned int flags, void* user_data) | unsigned int flags, void* user_data) | ||||
{//========================================================================= | |||||
{ | |||||
espeak_ERROR aStatus; | espeak_ERROR aStatus; | ||||
InitText(flags); | InitText(flags); | ||||
SHOW_TIME("LEAVE sync_espeak_Synth_Mark"); | SHOW_TIME("LEAVE sync_espeak_Synth_Mark"); | ||||
return (aStatus); | return (aStatus); | ||||
} // end of sync_espeak_Synth_Mark | |||||
} | |||||
void sync_espeak_Key(const char *key) | void sync_espeak_Key(const char *key) | ||||
{//================================== | |||||
{ | |||||
// symbolic name, symbolicname_character - is there a system resource of symbolic names per language? | // symbolic name, symbolicname_character - is there a system resource of symbolic names per language? | ||||
int letter; | int letter; | ||||
int ix; | int ix; | ||||
void sync_espeak_Char(wchar_t character) | void sync_espeak_Char(wchar_t character) | ||||
{//===================================== | |||||
{ | |||||
// is there a system resource of character names per language? | // is there a system resource of character names per language? | ||||
char buf[80]; | char buf[80]; | ||||
my_unique_identifier = 0; | my_unique_identifier = 0; | ||||
void sync_espeak_SetPunctuationList(const wchar_t *punctlist) | void sync_espeak_SetPunctuationList(const wchar_t *punctlist) | ||||
{//========================================================== | |||||
{ | |||||
// Set the list of punctuation which are spoken for "some". | // Set the list of punctuation which are spoken for "some". | ||||
my_unique_identifier = 0; | my_unique_identifier = 0; | ||||
my_user_data = NULL; | my_user_data = NULL; | ||||
wcsncpy(option_punctlist, punctlist, N_PUNCTLIST); | wcsncpy(option_punctlist, punctlist, N_PUNCTLIST); | ||||
option_punctlist[N_PUNCTLIST-1] = 0; | option_punctlist[N_PUNCTLIST-1] = 0; | ||||
} | } | ||||
} // end of sync_espeak_SetPunctuationList | |||||
} | |||||
ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback* SynthCallback) | ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback* SynthCallback) | ||||
{//====================================================================== | |||||
{ | |||||
ENTER("espeak_SetSynthCallback"); | ENTER("espeak_SetSynthCallback"); | ||||
synth_callback = SynthCallback; | synth_callback = SynthCallback; | ||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
} | } | ||||
ESPEAK_API void espeak_SetUriCallback(int (* UriCallback)(int, const char*, const char *)) | ESPEAK_API void espeak_SetUriCallback(int (* UriCallback)(int, const char*, const char *)) | ||||
{//======================================================================================= | |||||
{ | |||||
ENTER("espeak_SetUriCallback"); | ENTER("espeak_SetUriCallback"); | ||||
uri_callback = UriCallback; | uri_callback = UriCallback; | ||||
} | } | ||||
ESPEAK_API void espeak_SetPhonemeCallback(int (* PhonemeCallback)(const char*)) | ESPEAK_API void espeak_SetPhonemeCallback(int (* PhonemeCallback)(const char*)) | ||||
{//=========================================================================== | |||||
{ | |||||
phoneme_callback = PhonemeCallback; | phoneme_callback = PhonemeCallback; | ||||
} | } | ||||
ESPEAK_API int espeak_Initialize(espeak_AUDIO_OUTPUT output_type, int buf_length, const char *path, int options) | ESPEAK_API int espeak_Initialize(espeak_AUDIO_OUTPUT output_type, int buf_length, const char *path, int options) | ||||
{//============================================================================================================= | |||||
{ | |||||
ENTER("espeak_Initialize"); | ENTER("espeak_Initialize"); | ||||
int param; | int param; | ||||
espeak_POSITION_TYPE position_type, | 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) | unsigned int* unique_identifier, void* user_data) | ||||
{//===================================================================================== | |||||
{ | |||||
#ifdef DEBUG_ENABLED | #ifdef DEBUG_ENABLED | ||||
ENTER("espeak_Synth"); | ENTER("espeak_Synth"); | ||||
SHOW("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); | SHOW("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 | #endif | ||||
return a_error; | return a_error; | ||||
} // end of espeak_Synth | |||||
} | |||||
unsigned int flags, | unsigned int flags, | ||||
unsigned int* unique_identifier, | unsigned int* unique_identifier, | ||||
void* user_data) | void* user_data) | ||||
{//========================================================================= | |||||
{ | |||||
#ifdef DEBUG_ENABLED | #ifdef DEBUG_ENABLED | ||||
ENTER("espeak_Synth_Mark"); | ENTER("espeak_Synth_Mark"); | ||||
SHOW("espeak_Synth_Mark > index_mark=%s, end_position=%d, flags=%d, text=%s\n", index_mark, end_position, flags, text); | SHOW("espeak_Synth_Mark > index_mark=%s, end_position=%d, flags=%d, text=%s\n", index_mark, end_position, flags, text); | ||||
#endif | #endif | ||||
return a_error; | return a_error; | ||||
} // end of espeak_Synth_Mark | |||||
} | |||||
ESPEAK_API espeak_ERROR espeak_Key(const char *key) | ESPEAK_API espeak_ERROR espeak_Key(const char *key) | ||||
{//================================================ | |||||
{ | |||||
ENTER("espeak_Key"); | ENTER("espeak_Key"); | ||||
// symbolic name, symbolicname_character - is there a system resource of symbolicnames per language | // symbolic name, symbolicname_character - is there a system resource of symbolicnames per language | ||||
ESPEAK_API espeak_ERROR espeak_Char(wchar_t character) | ESPEAK_API espeak_ERROR espeak_Char(wchar_t character) | ||||
{//=========================================== | |||||
{ | |||||
ENTER("espeak_Char"); | ENTER("espeak_Char"); | ||||
// is there a system resource of character names per language? | // is there a system resource of character names per language? | ||||
ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name) | ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name) | ||||
{//============================================================ | |||||
{ | |||||
ENTER("espeak_SetVoiceByName"); | ENTER("espeak_SetVoiceByName"); | ||||
return(SetVoiceByName(name)); | return(SetVoiceByName(name)); | ||||
} // end of espeak_SetVoiceByName | |||||
} | |||||
ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_selector) | ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_selector) | ||||
{//============================================================================== | |||||
{ | |||||
ENTER("espeak_SetVoiceByProperties"); | ENTER("espeak_SetVoiceByProperties"); | ||||
return(SetVoiceByProperties(voice_selector)); | return(SetVoiceByProperties(voice_selector)); | ||||
} // end of espeak_SetVoiceByProperties | |||||
} | |||||
ESPEAK_API int espeak_GetParameter(espeak_PARAMETER parameter, int current) | ESPEAK_API int espeak_GetParameter(espeak_PARAMETER parameter, int current) | ||||
{//======================================================================== | |||||
{ | |||||
ENTER("espeak_GetParameter"); | ENTER("espeak_GetParameter"); | ||||
// current: 0=default value, 1=current value | // current: 0=default value, 1=current value | ||||
if(current) | if(current) | ||||
{ | { | ||||
return(param_defaults[parameter]); | return(param_defaults[parameter]); | ||||
} | } | ||||
} // end of espeak_GetParameter | |||||
} | |||||
ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative) | ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative) | ||||
{//============================================================================================= | |||||
{ | |||||
ENTER("espeak_SetParameter"); | ENTER("espeak_SetParameter"); | ||||
if(f_logespeak) | if(f_logespeak) | ||||
ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist) | ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist) | ||||
{//================================================================ | |||||
{ | |||||
ENTER("espeak_SetPunctuationList"); | ENTER("espeak_SetPunctuationList"); | ||||
// Set the list of punctuation which are spoken for "some". | // Set the list of punctuation which are spoken for "some". | ||||
sync_espeak_SetPunctuationList(punctlist); | sync_espeak_SetPunctuationList(punctlist); | ||||
return(EE_OK); | return(EE_OK); | ||||
#endif | #endif | ||||
} // end of espeak_SetPunctuationList | |||||
} | |||||
ESPEAK_API void espeak_SetPhonemeTrace(int phonememode, FILE *stream) | ESPEAK_API void espeak_SetPhonemeTrace(int phonememode, FILE *stream) | ||||
{//=================================================================== | |||||
{ | |||||
ENTER("espeak_SetPhonemes"); | ENTER("espeak_SetPhonemes"); | ||||
/* phonememode: Controls the output of phoneme symbols for the text | /* phonememode: Controls the output of phoneme symbols for the text | ||||
bits 0-2: | bits 0-2: | ||||
if(stream == NULL) | if(stream == NULL) | ||||
f_trans = stderr; | f_trans = stderr; | ||||
} // end of espeak_SetPhonemes | |||||
} | |||||
ESPEAK_API const char *espeak_TextToPhonemes(const void **textptr, int textmode, int phonememode) | ESPEAK_API const char *espeak_TextToPhonemes(const void **textptr, int textmode, int phonememode) | ||||
{//================================================================================================= | |||||
{ | |||||
/* phoneme_mode | /* phoneme_mode | ||||
bit 1: 0=eSpeak's ascii phoneme names, 1= International Phonetic Alphabet (as UTF-8 characters). | bit 1: 0=eSpeak's ascii phoneme names, 1= International Phonetic Alphabet (as UTF-8 characters). | ||||
bit 7: use (bits 8-23) as a tie within multi-letter phonemes names | bit 7: use (bits 8-23) as a tie within multi-letter phonemes names | ||||
ESPEAK_API void espeak_CompileDictionary(const char *path, FILE *log, int flags) | ESPEAK_API void espeak_CompileDictionary(const char *path, FILE *log, int flags) | ||||
{//============================================================================= | |||||
{ | |||||
ENTER("espeak_CompileDictionary"); | ENTER("espeak_CompileDictionary"); | ||||
CompileDictionary(path, dictionary_name, log, NULL, flags); | CompileDictionary(path, dictionary_name, log, NULL, flags); | ||||
} // end of espeak_CompileDirectory | |||||
} | |||||
ESPEAK_API espeak_ERROR espeak_Cancel(void) | ESPEAK_API espeak_ERROR espeak_Cancel(void) | ||||
{//=============================== | |||||
{ | |||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
ENTER("espeak_Cancel"); | ENTER("espeak_Cancel"); | ||||
fifo_stop(); | fifo_stop(); | ||||
SetParameter(i, saved_parameters[i], 0); | SetParameter(i, saved_parameters[i], 0); | ||||
return EE_OK; | return EE_OK; | ||||
} // end of espeak_Cancel | |||||
} | |||||
ESPEAK_API int espeak_IsPlaying(void) | ESPEAK_API int espeak_IsPlaying(void) | ||||
{//================================== | |||||
{ | |||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
if((my_mode == AUDIO_OUTPUT_PLAYBACK) && wave_is_busy(my_audio)) | if((my_mode == AUDIO_OUTPUT_PLAYBACK) && wave_is_busy(my_audio)) | ||||
return(1); | return(1); | ||||
#else | #else | ||||
return(0); | return(0); | ||||
#endif | #endif | ||||
} // end of espeak_IsPlaying | |||||
} | |||||
ESPEAK_API espeak_ERROR espeak_Synchronize(void) | ESPEAK_API espeak_ERROR espeak_Synchronize(void) | ||||
{//============================================= | |||||
{ | |||||
espeak_ERROR berr = err; | espeak_ERROR berr = err; | ||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
SHOW_TIME("espeak_Synchronize > ENTER"); | SHOW_TIME("espeak_Synchronize > ENTER"); | ||||
err = EE_OK; | err = EE_OK; | ||||
SHOW_TIME("espeak_Synchronize > LEAVE"); | SHOW_TIME("espeak_Synchronize > LEAVE"); | ||||
return berr; | return berr; | ||||
} // end of espeak_Synchronize | |||||
} | |||||
extern void FreePhData(void); | extern void FreePhData(void); | ||||
extern void FreeVoiceList(void); | extern void FreeVoiceList(void); | ||||
ESPEAK_API espeak_ERROR espeak_Terminate(void) | ESPEAK_API espeak_ERROR espeak_Terminate(void) | ||||
{//=========================================== | |||||
{ | |||||
ENTER("espeak_Terminate"); | ENTER("espeak_Terminate"); | ||||
#ifdef USE_ASYNC | #ifdef USE_ASYNC | ||||
fifo_stop(); | fifo_stop(); | ||||
} | } | ||||
return EE_OK; | return EE_OK; | ||||
} // end of espeak_Terminate | |||||
} | |||||
ESPEAK_API const char *espeak_Info(const char **ptr) | ESPEAK_API const char *espeak_Info(const char **ptr) | ||||
{//================================================= | |||||
{ | |||||
if(ptr != NULL) | if(ptr != NULL) | ||||
{ | { | ||||
*ptr = path_home; | *ptr = path_home; | ||||
} | } | ||||
#pragma GCC visibility pop | #pragma GCC visibility pop | ||||
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2007 by Jonathan Duddington * | * Copyright (C) 2005 to 2007 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2013-2015 by Reece H. Dunn * | |||||
* Copyright (C) 2013-2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * | ||||
} | } | ||||
float polint(float xa[],float ya[],int n,float x) | float polint(float xa[],float ya[],int n,float x) | ||||
{//============================================== | |||||
{ | |||||
// General polinomial interpolation routine, xa[1...n] ya[1...n] | // General polinomial interpolation routine, xa[1...n] ya[1...n] | ||||
int i,m,ns=1; | int i,m,ns=1; | ||||
float den,dif,dift,ho,hp,w; | float den,dif,dift,ho,hp,w; | ||||
y += ((2*ns < (n-m) ? c[ns+1] : d[ns--])); | y += ((2*ns < (n-m) ? c[ns+1] : d[ns--])); | ||||
} | } | ||||
return(y); | return(y); | ||||
} // end of polint | |||||
} | |||||
static void PeaksZero(peak_t *sp, peak_t *zero) | static void PeaksZero(peak_t *sp, peak_t *zero) | ||||
{//===================================== | |||||
{ | |||||
int pk; | int pk; | ||||
memcpy(zero,sp,sizeof(peak_t)*N_PEAKS); | memcpy(zero,sp,sizeof(peak_t)*N_PEAKS); | ||||
for(pk=0; pk<N_PEAKS; pk++) | for(pk=0; pk<N_PEAKS; pk++) | ||||
zero[pk].pkheight = 0; | zero[pk].pkheight = 0; | ||||
} // end of PeaksZero | |||||
} | |||||
static SpectFrame *SpectFrameCreate() | static SpectFrame *SpectFrameCreate() | ||||
{ | { | ||||
int LoadFrame(SpectFrame *frame, FILE *stream, int file_format_type) | int LoadFrame(SpectFrame *frame, FILE *stream, int file_format_type) | ||||
{//============================================================== | |||||
{ | |||||
short ix; | short ix; | ||||
short x; | short x; | ||||
unsigned short *spect_data; | unsigned short *spect_data; | ||||
frame->spect = spect_data; | frame->spect = spect_data; | ||||
return(0); | return(0); | ||||
} // End of SpectFrame::Load | |||||
} | |||||
double GetFrameRms(SpectFrame *frame, int seq_amplitude) | double GetFrameRms(SpectFrame *frame, int seq_amplitude) | ||||
{//========================================= | |||||
{ | |||||
int h; | int h; | ||||
float total=0; | float total=0; | ||||
int maxh; | int maxh; | ||||
} | } | ||||
void SpectSeqDestroy(SpectSeq *spect) | void SpectSeqDestroy(SpectSeq *spect) | ||||
{//================== | |||||
{ | |||||
int ix; | int ix; | ||||
if(spect->frames != NULL) | if(spect->frames != NULL) | ||||
{ | { | ||||
static float GetFrameLength(SpectSeq *spect, int frame) | static float GetFrameLength(SpectSeq *spect, int frame) | ||||
{//=============================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
float adjust=0; | float adjust=0; | ||||
int LoadSpectSeq(SpectSeq *spect, const char *filename) | int LoadSpectSeq(SpectSeq *spect, const char *filename) | ||||
{//======================================= | |||||
{ | |||||
short n, temp; | short n, temp; | ||||
int ix; | int ix; | ||||
uint32_t id1, id2, name_len; | uint32_t id1, id2, name_len; | ||||
spect->frames[ix]->length_adjust = spect->frames[ix]->length - GetFrameLength(spect,ix); | spect->frames[ix]->length_adjust = spect->frames[ix]->length - GetFrameLength(spect,ix); | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of SpectSeq::Load | |||||
} |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2007 by Jonathan Duddington * | * Copyright (C) 2005 to 2007 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2013-2015 by Reece H. Dunn * | |||||
* Copyright (C) 2013-2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * |
static int mbr_name_prefix = 0; | static int mbr_name_prefix = 0; | ||||
espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate) | espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate) | ||||
{//=================================================================================== | |||||
{ | |||||
// Load a phoneme name translation table from espeak-data/mbrola | // Load a phoneme name translation table from espeak-data/mbrola | ||||
int size; | int size; | ||||
strcpy(mbrola_name,mbrola_voice); | strcpy(mbrola_name,mbrola_voice); | ||||
mbrola_delay = 1000; // improve synchronization of events | mbrola_delay = 1000; // improve synchronization of events | ||||
return(EE_OK); | return(EE_OK); | ||||
} // end of LoadMbrolaTable | |||||
} | |||||
static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev, PHONEME_TAB *ph_next, int *name2, int *split, int *control) | static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev, PHONEME_TAB *ph_next, int *name2, int *split, int *control) | ||||
{//========================================================================================================================================== | |||||
{ | |||||
// Look up a phoneme in the mbrola phoneme name translation table | // Look up a phoneme in the mbrola phoneme name translation table | ||||
// It may give none, 1, or 2 mbrola phonemes | // It may give none, 1, or 2 mbrola phonemes | ||||
MBROLA_TAB *pr; | MBROLA_TAB *pr; | ||||
static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | ||||
{//=========================================================================== | |||||
{ | |||||
// final=1: only give the final pitch value. | // final=1: only give the final pitch value. | ||||
int x; | int x; | ||||
int ix; | int ix; | ||||
if(final) | if(final) | ||||
sprintf(output,"\t100 %d\n",p_end); | sprintf(output,"\t100 %d\n",p_end); | ||||
return(output); | return(output); | ||||
} // end of WritePitch | |||||
} | |||||
int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbrola) | int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbrola) | ||||
{//================================================================================= | |||||
{ | |||||
// Generate a mbrola pho file | // Generate a mbrola pho file | ||||
unsigned int name; | unsigned int name; | ||||
int len; | int len; | ||||
} | } | ||||
return 0; | return 0; | ||||
} // end of MbrolaTranslate | |||||
} | |||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | ||||
{//================================================================== | |||||
{ | |||||
FILE *f_mbrola = NULL; | FILE *f_mbrola = NULL; | ||||
if(*n_ph == 0) | if(*n_ph == 0) | ||||
int MbrolaFill(int length, int resume, int amplitude) | int MbrolaFill(int length, int resume, int amplitude) | ||||
{//================================================== | |||||
{ | |||||
// Read audio data from Mbrola (length is in millisecs) | // Read audio data from Mbrola (length is in millisecs) | ||||
static int n_samples; | static int n_samples; | ||||
void MbrolaReset(void) | void MbrolaReset(void) | ||||
{//=================== | |||||
{ | |||||
// Reset the Mbrola engine and flush the pending audio | // Reset the Mbrola engine and flush the pending audio | ||||
reset_MBR(); | reset_MBR(); |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington * | * Copyright (C) 2005 to 2014 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * | ||||
static char *ReadPhFile(void *ptr, const char *fname, int *size) | static char *ReadPhFile(void *ptr, const char *fname, int *size) | ||||
{//============================================================= | |||||
{ | |||||
FILE *f_in; | FILE *f_in; | ||||
char *p; | char *p; | ||||
unsigned int length; | unsigned int length; | ||||
if(size != NULL) | if(size != NULL) | ||||
*size = length; | *size = length; | ||||
return(p); | return(p); | ||||
} // end of ReadPhFile | |||||
} | |||||
int LoadPhData(int *srate) | int LoadPhData(int *srate) | ||||
{//======================== | |||||
{ | |||||
int ix; | int ix; | ||||
int n_phonemes; | int n_phonemes; | ||||
int version; | int version; | ||||
if(srate != NULL) | if(srate != NULL) | ||||
*srate = rate; | *srate = rate; | ||||
return(result); | return(result); | ||||
} // end of LoadPhData | |||||
} | |||||
void FreePhData(void) | void FreePhData(void) | ||||
{//================== | |||||
{ | |||||
Free(phoneme_tab_data); | Free(phoneme_tab_data); | ||||
Free(phoneme_index); | Free(phoneme_index); | ||||
Free(phondata_ptr); | Free(phondata_ptr); | ||||
int PhonemeCode(unsigned int mnem) | int PhonemeCode(unsigned int mnem) | ||||
{//=============================== | |||||
{ | |||||
int ix; | int ix; | ||||
for(ix=0; ix<n_phoneme_tab; ix++) | for(ix=0; ix<n_phoneme_tab; ix++) | ||||
int LookupPhonemeString(const char *string) | int LookupPhonemeString(const char *string) | ||||
{//======================================== | |||||
{ | |||||
int ix; | int ix; | ||||
unsigned char c; | unsigned char c; | ||||
unsigned int mnem; | unsigned int mnem; | ||||
frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, int *n_frames, PHONEME_LIST *plist) | frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, int *n_frames, PHONEME_LIST *plist) | ||||
{//=================================================================================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int nf; | int nf; | ||||
int nf1; | int nf1; | ||||
*n_frames = nf; | *n_frames = nf; | ||||
return(frames); | return(frames); | ||||
} // end of LookupSpect | |||||
} | |||||
unsigned char *GetEnvelope(int index) | unsigned char *GetEnvelope(int index) | ||||
{//================================== | |||||
{ | |||||
if(index==0) | if(index==0) | ||||
{ | { | ||||
fprintf(stderr,"espeak: No envelope\n"); | fprintf(stderr,"espeak: No envelope\n"); | ||||
static void SetUpPhonemeTable(int number, int recursing) | static void SetUpPhonemeTable(int number, int recursing) | ||||
{//===================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int includes; | int includes; | ||||
int ph_code; | int ph_code; | ||||
if(recursing == 0) | if(recursing == 0) | ||||
phoneme_tab_flags[ph_code] |= 1; // not inherited | phoneme_tab_flags[ph_code] |= 1; // not inherited | ||||
} | } | ||||
} // end of SetUpPhonemeTable | |||||
} | |||||
void SelectPhonemeTable(int number) | void SelectPhonemeTable(int number) | ||||
{//================================ | |||||
{ | |||||
n_phoneme_tab = 0; | n_phoneme_tab = 0; | ||||
SetUpPhonemeTable(number,0); // recursively for included phoneme tables | SetUpPhonemeTable(number,0); // recursively for included phoneme tables | ||||
n_phoneme_tab++; | n_phoneme_tab++; | ||||
current_phoneme_table = number; | current_phoneme_table = number; | ||||
} // end of SelectPhonemeTable | |||||
} | |||||
int LookupPhonemeTable(const char *name) | int LookupPhonemeTable(const char *name) | ||||
{//===================================== | |||||
{ | |||||
int ix; | int ix; | ||||
for(ix=0; ix<n_phoneme_tables; ix++) | for(ix=0; ix<n_phoneme_tables; ix++) | ||||
int SelectPhonemeTableName(const char *name) | int SelectPhonemeTableName(const char *name) | ||||
{//========================================= | |||||
{ | |||||
// Look up a phoneme set by name, and select it if it exists | // Look up a phoneme set by name, and select it if it exists | ||||
// Returns the phoneme table number | // Returns the phoneme table number | ||||
int ix; | int ix; | ||||
SelectPhonemeTable(ix); | SelectPhonemeTable(ix); | ||||
return(ix); | return(ix); | ||||
} // end of DelectPhonemeTableName | |||||
} | |||||
void LoadConfig(void) | void LoadConfig(void) | ||||
{//================== | |||||
{ | |||||
// Load configuration file, if one exists | // Load configuration file, if one exists | ||||
char buf[sizeof(path_home)+10]; | char buf[sizeof(path_home)+10]; | ||||
FILE *f; | FILE *f; | ||||
} | } | ||||
} | } | ||||
fclose(f); | fclose(f); | ||||
} // end of LoadConfig | |||||
} | |||||
static void InvalidInstn(PHONEME_TAB *ph, int instn) | static void InvalidInstn(PHONEME_TAB *ph, int instn) | ||||
{//==================================================== | |||||
{ | |||||
fprintf(stderr,"Invalid instruction %.4x for phoneme '%s'\n", instn, WordToString(ph->mnemonic)); | fprintf(stderr,"Invalid instruction %.4x for phoneme '%s'\n", instn, WordToString(ph->mnemonic)); | ||||
} | } | ||||
static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, int control) | static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, int control) | ||||
{//======================================================================================== | |||||
{ | |||||
// condition: | // condition: | ||||
// 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress | // 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress | ||||
} | } | ||||
return(false); | return(false); | ||||
} // end of StressCondition | |||||
} | |||||
static int CountVowelPosition(PHONEME_LIST *plist) | static int CountVowelPosition(PHONEME_LIST *plist) | ||||
{//=============================================== | |||||
{ | |||||
int count = 0; | int count = 0; | ||||
for(;;) | for(;;) | ||||
plist--; | plist--; | ||||
} | } | ||||
return(count); | return(count); | ||||
} // end of CoundVowelPosition | |||||
} | |||||
static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, USHORT *p_prog, WORD_PH_DATA *worddata) | static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, USHORT *p_prog, WORD_PH_DATA *worddata) | ||||
{//======================================================================================================================== | |||||
{ | |||||
int which; | int which; | ||||
int ix; | int ix; | ||||
unsigned int data; | unsigned int data; | ||||
} | } | ||||
} | } | ||||
return(false); | return(false); | ||||
} // end of InterpretCondition | |||||
} | |||||
static void SwitchOnVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT **p_prog, int instn_type) | static void SwitchOnVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT **p_prog, int instn_type) | ||||
{//======================================================================================================== | |||||
{ | |||||
USHORT *prog; | USHORT *prog; | ||||
int voweltype; | int voweltype; | ||||
signed char x; | signed char x; | ||||
} | } | ||||
*p_prog += 12; | *p_prog += 12; | ||||
} // end of SwitchVowelType | |||||
} | |||||
int NumInstnWords(USHORT *prog) | int NumInstnWords(USHORT *prog) | ||||
{//============================ | |||||
{ | |||||
int instn; | int instn; | ||||
int instn2; | int instn2; | ||||
int instn_type; | int instn_type; | ||||
} | } | ||||
return(2); | return(2); | ||||
} | } | ||||
} // end of NumInstnWords | |||||
} | |||||
void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata) | void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata) | ||||
{//=================================================================================================================== | |||||
{ | |||||
// control: | // control: | ||||
//bit 0: PreVoicing | //bit 0: PreVoicing | ||||
//bit 8: change phonemes | //bit 8: change phonemes | ||||
plist->phontab_addr = phdata->sound_addr[1]; // WAV address | plist->phontab_addr = phdata->sound_addr[1]; // WAV address | ||||
plist->sound_param = phdata->sound_param[1]; | plist->sound_param = phdata->sound_param[1]; | ||||
} | } | ||||
} // end of InterpretPhoneme | |||||
} | |||||
void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata) | void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata) | ||||
{//===================================================== | |||||
{ | |||||
// Examine the program of a single isolated phoneme | // Examine the program of a single isolated phoneme | ||||
int ix; | int ix; | ||||
PHONEME_LIST plist[4]; | PHONEME_LIST plist[4]; | ||||
plist[2].sourceix = 1; | plist[2].sourceix = 1; | ||||
InterpretPhoneme(NULL, 0, &plist[1], phdata, NULL); | InterpretPhoneme(NULL, 0, &plist[1], phdata, NULL); | ||||
} // end of InterpretPhoneme2 | |||||
} |
const char *WordToString(unsigned int word) | const char *WordToString(unsigned int word) | ||||
{//======================================== | |||||
{ | |||||
// Convert a phoneme mnemonic word into a string | // Convert a phoneme mnemonic word into a string | ||||
int ix; | int ix; | ||||
static char buf[5]; | static char buf[5]; | ||||
void SynthesizeInit() | void SynthesizeInit() | ||||
{//================== | |||||
{ | |||||
last_pitch_cmd = 0; | last_pitch_cmd = 0; | ||||
last_amp_cmd = 0; | last_amp_cmd = 0; | ||||
last_frame = NULL; | last_frame = NULL; | ||||
static void EndAmplitude(void) | static void EndAmplitude(void) | ||||
{//=========================== | |||||
{ | |||||
if(amp_length > 0) | if(amp_length > 0) | ||||
{ | { | ||||
if(wcmdq[last_amp_cmd][1] == 0) | if(wcmdq[last_amp_cmd][1] == 0) | ||||
static void EndPitch(int voice_break) | static void EndPitch(int voice_break) | ||||
{//================================== | |||||
{ | |||||
// posssible end of pitch envelope, fill in the length | // posssible end of pitch envelope, fill in the length | ||||
if((pitch_length > 0) && (last_pitch_cmd >= 0)) | if((pitch_length > 0) && (last_pitch_cmd >= 0)) | ||||
{ | { | ||||
syllable_centre = -1; | syllable_centre = -1; | ||||
memset(vowel_transition,0,sizeof(vowel_transition)); | memset(vowel_transition,0,sizeof(vowel_transition)); | ||||
} | } | ||||
} // end of EndPitch | |||||
} | |||||
static void DoAmplitude(int amp, unsigned char *amp_env) | static void DoAmplitude(int amp, unsigned char *amp_env) | ||||
{//===================================================== | |||||
{ | |||||
long64 *q; | long64 *q; | ||||
last_amp_cmd = wcmdq_tail; | last_amp_cmd = wcmdq_tail; | ||||
q[2] = (long64)amp_env; | q[2] = (long64)amp_env; | ||||
q[3] = amp; | q[3] = amp; | ||||
WcmdqInc(); | WcmdqInc(); | ||||
} // end of DoAmplitude | |||||
} | |||||
static void DoPitch(unsigned char *env, int pitch1, int pitch2) | static void DoPitch(unsigned char *env, int pitch1, int pitch2) | ||||
{//============================================================ | |||||
{ | |||||
long64 *q; | long64 *q; | ||||
EndPitch(0); | EndPitch(0); | ||||
q[2] = (long64)env; | q[2] = (long64)env; | ||||
q[3] = (pitch1 << 16) + pitch2; | q[3] = (pitch1 << 16) + pitch2; | ||||
WcmdqInc(); | WcmdqInc(); | ||||
} // end of DoPitch | |||||
} | |||||
int PauseLength(int pause, int control) | int PauseLength(int pause, int control) | ||||
{//==================================== | |||||
{ | |||||
unsigned int len; | unsigned int len; | ||||
if(control == 0) | if(control == 0) | ||||
static void DoPause(int length, int control) | static void DoPause(int length, int control) | ||||
{//========================================= | |||||
{ | |||||
// length in nominal mS | // length in nominal mS | ||||
// control = 1, less shortening at fast speeds | // control = 1, less shortening at fast speeds | ||||
unsigned int len; | unsigned int len; | ||||
wcmdq[wcmdq_tail][1] = fmt_amplitude = 0; | wcmdq[wcmdq_tail][1] = fmt_amplitude = 0; | ||||
WcmdqInc(); | WcmdqInc(); | ||||
} | } | ||||
} // end of DoPause | |||||
} | |||||
extern int seq_len_adjust; // temporary fix to advance the start point for playing the wav sample | extern int seq_len_adjust; // temporary fix to advance the start point for playing the wav sample | ||||
static int DoSample2(int index, int which, int std_length, int control, int length_mod, int amp) | static int DoSample2(int index, int which, int std_length, int control, int length_mod, int amp) | ||||
{//============================================================================================= | |||||
{ | |||||
int length; | int length; | ||||
int wav_length; | int wav_length; | ||||
int wav_scale; | int wav_scale; | ||||
} | } | ||||
return(length); | return(length); | ||||
} // end of DoSample2 | |||||
} | |||||
int DoSample3(PHONEME_DATA *phdata, int length_mod, int amp) | int DoSample3(PHONEME_DATA *phdata, int length_mod, int amp) | ||||
{//========================================================= | |||||
{ | |||||
int amp2; | int amp2; | ||||
int len; | int len; | ||||
EndPitch(1); | EndPitch(1); | ||||
} | } | ||||
last_frame = NULL; | last_frame = NULL; | ||||
return(len); | return(len); | ||||
} // end of DoSample3 | |||||
} | |||||
static frame_t *AllocFrame() | static frame_t *AllocFrame() | ||||
{//========================= | |||||
{ | |||||
// Allocate a temporary spectrum frame for the wavegen queue. Use a pool which is big | // Allocate a temporary spectrum frame for the wavegen queue. Use a pool which is big | ||||
// enough to use a round-robin without checks. | // enough to use a round-robin without checks. | ||||
// Only needed for modifying spectra for blending to consonants | // Only needed for modifying spectra for blending to consonants | ||||
static void set_frame_rms(frame_t *fr, int new_rms) | static void set_frame_rms(frame_t *fr, int new_rms) | ||||
{//================================================= | |||||
{ | |||||
// Each frame includes its RMS amplitude value, so to set a new | // Each frame includes its RMS amplitude value, so to set a new | ||||
// RMS just adjust the formant amplitudes by the appropriate ratio | // RMS just adjust the formant amplitudes by the appropriate ratio | ||||
h = fr->fheight[ix] * x; | h = fr->fheight[ix] * x; | ||||
fr->fheight[ix] = h/0x200; | fr->fheight[ix] = h/0x200; | ||||
} | } | ||||
} /* end of set_frame_rms */ | |||||
} | |||||
static void formants_reduce_hf(frame_t *fr, int level) | static void formants_reduce_hf(frame_t *fr, int level) | ||||
{//==================================================== | |||||
{ | |||||
// change height of peaks 2 to 8, percentage | // change height of peaks 2 to 8, percentage | ||||
int ix; | int ix; | ||||
int x; | int x; | ||||
static frame_t *CopyFrame(frame_t *frame1, int copy) | static frame_t *CopyFrame(frame_t *frame1, int copy) | ||||
{//================================================= | |||||
{ | |||||
// create a copy of the specified frame in temporary buffer | // create a copy of the specified frame in temporary buffer | ||||
frame_t *frame2; | frame_t *frame2; | ||||
static frame_t *DuplicateLastFrame(frameref_t *seq, int n_frames, int length) | static frame_t *DuplicateLastFrame(frameref_t *seq, int n_frames, int length) | ||||
{//========================================================================== | |||||
{ | |||||
frame_t *fr; | frame_t *fr; | ||||
seq[n_frames-1].length = length; | seq[n_frames-1].length = length; | ||||
static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj, int f3_adj, int hf_reduce, int flags) | static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj, int f3_adj, int hf_reduce, int flags) | ||||
{//==================================================================================================================== | |||||
{ | |||||
int x; | int x; | ||||
target = (target * voice->formant_factor)/256; | target = (target * voice->formant_factor)/256; | ||||
static int VowelCloseness(frame_t *fr) | static int VowelCloseness(frame_t *fr) | ||||
{//=================================== | |||||
{ | |||||
// return a value 0-3 depending on the vowel's f1 | // return a value 0-3 depending on the vowel's f1 | ||||
int f1; | int f1; | ||||
int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which) | int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which) | ||||
{//============================================================================================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int formant; | int formant; | ||||
int next_rms; | int next_rms; | ||||
if(flags & 16) | if(flags & 16) | ||||
return(len); | return(len); | ||||
return(0); | return(0); | ||||
} // end of FormantTransition2 | |||||
} | |||||
static void SmoothSpect(void) | static void SmoothSpect(void) | ||||
{//========================== | |||||
{ | |||||
// Limit the rate of frequence change of formants, to reduce chirping | // Limit the rate of frequence change of formants, to reduce chirping | ||||
long64 *q; | long64 *q; | ||||
} | } | ||||
syllable_start = syllable_end; | syllable_start = syllable_end; | ||||
} // end of SmoothSpect | |||||
} | |||||
static void StartSyllable(void) | static void StartSyllable(void) | ||||
{//============================ | |||||
{ | |||||
// start of syllable, if not already started | // start of syllable, if not already started | ||||
if(syllable_end == syllable_start) | if(syllable_end == syllable_start) | ||||
syllable_end = wcmdq_tail; | syllable_end = wcmdq_tail; | ||||
int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_LIST *plist, int modulation) | int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_LIST *plist, int modulation) | ||||
{//======================================================================================================== | |||||
{ | |||||
// which: 0 not a vowel, 1 start of vowel, 2 body and end of vowel | // which: 0 not a vowel, 1 start of vowel, 2 body and end of vowel | ||||
// length_mod: 256 = 100% | // length_mod: 256 = 100% | ||||
// modulation: -1 = don't write to wcmdq | // modulation: -1 = don't write to wcmdq | ||||
return(total_len); | return(total_len); | ||||
} // end of DoSpect | |||||
} | |||||
void DoMarker(int type, int char_posn, int length, int value) | void DoMarker(int type, int char_posn, int length, int value) | ||||
{//========================================================== | |||||
{ | |||||
// This could be used to return an index to the word currently being spoken | // This could be used to return an index to the word currently being spoken | ||||
// Type 1=word, 2=sentence, 3=named marker, 4=play audio, 5=end | // Type 1=word, 2=sentence, 3=named marker, 4=play audio, 5=end | ||||
if(WcmdqFree() > 5) | if(WcmdqFree() > 5) | ||||
wcmdq[wcmdq_tail][2] = value; | wcmdq[wcmdq_tail][2] = value; | ||||
WcmdqInc(); | WcmdqInc(); | ||||
} | } | ||||
} // end of DoMarker | |||||
} | |||||
void DoPhonemeMarker(int type, int char_posn, int length, char *name) | void DoPhonemeMarker(int type, int char_posn, int length, char *name) | ||||
{//================================================================== | |||||
{ | |||||
// This could be used to return an index to the word currently being spoken | // This could be used to return an index to the word currently being spoken | ||||
// Type 7=phoneme | // Type 7=phoneme | ||||
int *p; | int *p; | ||||
wcmdq[wcmdq_tail][3] = p[1]; | wcmdq[wcmdq_tail][3] = p[1]; | ||||
WcmdqInc(); | WcmdqInc(); | ||||
} | } | ||||
} // end of DoMarker | |||||
} | |||||
#ifdef INCLUDE_SONIC | #ifdef INCLUDE_SONIC | ||||
void DoSonicSpeed(int value) | void DoSonicSpeed(int value) | ||||
{//========================= | |||||
{ | |||||
// value, multiplier * 1024 | // value, multiplier * 1024 | ||||
wcmdq[wcmdq_tail][0] = WCMD_SONIC_SPEED; | wcmdq[wcmdq_tail][0] = WCMD_SONIC_SPEED; | ||||
wcmdq[wcmdq_tail][1] = value; | wcmdq[wcmdq_tail][1] = value; | ||||
WcmdqInc(); | WcmdqInc(); | ||||
} // end of DoSonicSpeed | |||||
} | |||||
#endif | #endif | ||||
void DoVoiceChange(voice_t *v) | void DoVoiceChange(voice_t *v) | ||||
{//=========================== | |||||
{ | |||||
// allocate memory for a copy of the voice data, and free it in wavegenfill() | // allocate memory for a copy of the voice data, and free it in wavegenfill() | ||||
voice_t *v2; | voice_t *v2; | ||||
void DoEmbedded(int *embix, int sourceix) | void DoEmbedded(int *embix, int sourceix) | ||||
{//====================================== | |||||
{ | |||||
// There were embedded commands in the text at this point | // There were embedded commands in the text at this point | ||||
unsigned int word; // bit 7=last command for this word, bits 5,6 sign, bits 0-4 command | unsigned int word; // bit 7=last command for this word, bits 5,6 sign, bits 0-4 command | ||||
unsigned int value; | unsigned int value; | ||||
int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | ||||
{//============================================================ | |||||
{ | |||||
static int ix; | static int ix; | ||||
static int embedded_ix; | static int embedded_ix; | ||||
static int word_count; | static int word_count; | ||||
} | } | ||||
return(0); // finished the phoneme list | return(0); // finished the phoneme list | ||||
} // end of Generate | |||||
} | |||||
static int paused = 0; | static int paused = 0; | ||||
int SynthOnTimer() | int SynthOnTimer() | ||||
{//=============== | |||||
{ | |||||
if(!timer_on) | if(!timer_on) | ||||
{ | { | ||||
return(WavegenCloseSound()); | return(WavegenCloseSound()); | ||||
int SynthStatus() | int SynthStatus() | ||||
{//============== | |||||
{ | |||||
return(timer_on | paused); | return(timer_on | paused); | ||||
} | } | ||||
int SpeakNextClause(FILE *f_in, const void *text_in, int control) | int SpeakNextClause(FILE *f_in, const void *text_in, int control) | ||||
{//============================================================== | |||||
{ | |||||
// Speak text from file (f_in) or memory (text_in) | // Speak text from file (f_in) or memory (text_in) | ||||
// control 0: start | // control 0: start | ||||
// either f_in or text_in is set, the other must be NULL | // either f_in or text_in is set, the other must be NULL | ||||
} | } | ||||
return(1); | return(1); | ||||
} // end of SpeakNextClause | |||||
} |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington * | * Copyright (C) 2005 to 2014 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * |
ALPHABET *AlphabetFromName(const char *name) | ALPHABET *AlphabetFromName(const char *name) | ||||
{//========================================== | |||||
{ | |||||
ALPHABET *alphabet; | ALPHABET *alphabet; | ||||
for(alphabet=alphabets; alphabet->name != NULL; alphabet++) | for(alphabet=alphabets; alphabet->name != NULL; alphabet++) | ||||
ALPHABET *AlphabetFromChar(int c) | ALPHABET *AlphabetFromChar(int c) | ||||
{//=============================== | |||||
{ | |||||
// Find the alphabet from a character. | // Find the alphabet from a character. | ||||
ALPHABET *alphabet = alphabets; | ALPHABET *alphabet = alphabets; | ||||
static void SetLetterVowel(Translator *tr, int c) | static void SetLetterVowel(Translator *tr, int c) | ||||
{//============================================== | |||||
{ | |||||
tr->letter_bits[c] = (tr->letter_bits[c] & 0x40) | 0x81; // keep value for group 6 (front vowels e,i,y) | tr->letter_bits[c] = (tr->letter_bits[c] & 0x40) | 0x81; // keep value for group 6 (front vowels e,i,y) | ||||
} | } | ||||
static void ResetLetterBits(Translator *tr, int groups) | static void ResetLetterBits(Translator *tr, int groups) | ||||
{//==================================================== | |||||
{ | |||||
// Clear all the specified groups | // Clear all the specified groups | ||||
unsigned int ix; | unsigned int ix; | ||||
unsigned int mask; | unsigned int mask; | ||||
} | } | ||||
static void SetLetterBits(Translator *tr, int group, const char *string) | static void SetLetterBits(Translator *tr, int group, const char *string) | ||||
{//===================================================================== | |||||
{ | |||||
int bits; | int bits; | ||||
unsigned char c; | unsigned char c; | ||||
} | } | ||||
static void SetLetterBitsRange(Translator *tr, int group, int first, int last) | static void SetLetterBitsRange(Translator *tr, int group, int first, int last) | ||||
{//=========================================================================== | |||||
{ | |||||
int bits; | int bits; | ||||
int ix; | int ix; | ||||
static Translator* NewTranslator(void) | static Translator* NewTranslator(void) | ||||
{//=================================== | |||||
{ | |||||
Translator *tr; | Translator *tr; | ||||
int ix; | int ix; | ||||
static const unsigned char stress_amps2[] = {18,18, 20,20, 20,22, 22,20 }; | static const unsigned char stress_amps2[] = {18,18, 20,20, 20,22, 22,20 }; | ||||
static const unsigned char ru_consonants[] = {0x11,0x12,0x13,0x14,0x16,0x17,0x19,0x1a,0x1b,0x1c,0x1d,0x1f,0x20,0x21,0x22,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2c, 0x73,0x7b,0x83,0x9b,0}; | static const unsigned char ru_consonants[] = {0x11,0x12,0x13,0x14,0x16,0x17,0x19,0x1a,0x1b,0x1c,0x1d,0x1f,0x20,0x21,0x22,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2c, 0x73,0x7b,0x83,0x9b,0}; | ||||
static void SetCyrillicLetters(Translator *tr) | static void SetCyrillicLetters(Translator *tr) | ||||
{//=========================================== | |||||
{ | |||||
// character codes offset by 0x420 | // character codes offset by 0x420 | ||||
static const char ru_soft[] = {0x2c,0x19,0x27,0x29,0}; // letter group B [k ts; s;] | static const char ru_soft[] = {0x2c,0x19,0x27,0x29,0}; // letter group B [k ts; s;] | ||||
static const char ru_hard[] = {0x2a,0x16,0x26,0x28,0}; // letter group H [S Z ts] | static const char ru_hard[] = {0x2a,0x16,0x26,0x28,0}; // letter group H [S Z ts] | ||||
SetLetterBits(tr,LETTERGP_G,ru_voiced); | SetLetterBits(tr,LETTERGP_G,ru_voiced); | ||||
SetLetterBits(tr,LETTERGP_Y,ru_ivowels); | SetLetterBits(tr,LETTERGP_Y,ru_ivowels); | ||||
SetLetterBits(tr,LETTERGP_VOWEL2,(char *)ru_vowels); | SetLetterBits(tr,LETTERGP_VOWEL2,(char *)ru_vowels); | ||||
} // end of SetCyrillicLetters | |||||
} | |||||
void SetIndicLetters(Translator *tr) | void SetIndicLetters(Translator *tr) | ||||
{//================================= | |||||
{ | |||||
// Set letter types for Indic scripts, Devanagari, Tamill, etc | // Set letter types for Indic scripts, Devanagari, Tamill, etc | ||||
static const char dev_consonants2[] = {0x02,0x03,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x7b,0x7c,0x7e,0x7f,0}; | static const char dev_consonants2[] = {0x02,0x03,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x7b,0x7c,0x7e,0x7f,0}; | ||||
static const char dev_vowels2[] = {0x60,0x61, 0x55,0x56,0x57,0x62,0x63,0}; // non-consecutive vowels and vowel-signs | static const char dev_vowels2[] = {0x60,0x61, 0x55,0x56,0x57,0x62,0x63,0}; // non-consecutive vowels and vowel-signs | ||||
void SetupTranslator(Translator *tr, const short *lengths, const unsigned char *amps) | void SetupTranslator(Translator *tr, const short *lengths, const unsigned char *amps) | ||||
{//================================================================================== | |||||
{ | |||||
if(lengths != NULL) | if(lengths != NULL) | ||||
memcpy(tr->stress_lengths,lengths,sizeof(tr->stress_lengths)); | memcpy(tr->stress_lengths,lengths,sizeof(tr->stress_lengths)); | ||||
if(amps != NULL) | if(amps != NULL) | ||||
Translator *SelectTranslator(const char *name) | Translator *SelectTranslator(const char *name) | ||||
{//=========================================== | |||||
{ | |||||
int name2 = 0; | int name2 = 0; | ||||
Translator *tr; | Translator *tr; | ||||
ProcessLanguageOptions(&tr->langopts); | ProcessLanguageOptions(&tr->langopts); | ||||
return(tr); | return(tr); | ||||
} // end of SelectTranslator | |||||
} | |||||
void ProcessLanguageOptions(LANGUAGE_OPTIONS *langopts) | void ProcessLanguageOptions(LANGUAGE_OPTIONS *langopts) | ||||
{//===================================================== | |||||
{ | |||||
if(langopts->numbers & NUM_DECIMAL_COMMA) | if(langopts->numbers & NUM_DECIMAL_COMMA) | ||||
{ | { | ||||
// use . and ; for thousands and decimal separators | // use . and ; for thousands and decimal separators | ||||
} | } | ||||
} | } | ||||
//********************************************************************************************************** | |||||
static void Translator_Russian(Translator *tr) | static void Translator_Russian(Translator *tr) | ||||
{//=========================================== | |||||
{ | |||||
static const unsigned char stress_amps_ru[] = {16,16, 18,18, 20,24, 24,22 }; | static const unsigned char stress_amps_ru[] = {16,16, 18,18, 20,24, 24,22 }; | ||||
static const short stress_lengths_ru[8] = {150,140, 220,220, 0,0, 260,280}; | static const short stress_lengths_ru[8] = {150,140, 220,220, 0,0, 260,280}; | ||||
static const char ru_ivowels2[] = {0x2c,0x15,0x18,0x2e,0x2f,0}; // add more vowels to letter group Y (iotated vowels & soft-sign) | static const char ru_ivowels2[] = {0x2c,0x15,0x18,0x2e,0x2f,0}; // add more vowels to letter group Y (iotated vowels & soft-sign) | ||||
tr->langopts.phoneme_change = 1; | tr->langopts.phoneme_change = 1; | ||||
tr->langopts.testing = 2; | tr->langopts.testing = 2; | ||||
} // end of Translator_Russian | |||||
} |
105,120,100,105,105,122,125,110,105, 100, /* r */ | 105,120,100,105,105,122,125,110,105, 100, /* r */ | ||||
105,120, 95,105,100,115,120,110,100, 100, /* N */ | 105,120, 95,105,100,115,120,110,100, 100, /* N */ | ||||
100,120,100,100,100,100,100,100,100, 100 | 100,120,100,100,100,100,100,100,100, 100 | ||||
}; // SPARE | |||||
}; | |||||
// as above, but for the last syllable in a word | // as above, but for the last syllable in a word | ||||
static unsigned char length_mods_en0[100] = { | static unsigned char length_mods_en0[100] = { | ||||
105,150,100,105,105,122,135,120,105, 100, /* r */ | 105,150,100,105,105,122,135,120,105, 100, /* r */ | ||||
105,150,100,105,105,115,135,110,105, 100, /* N */ | 105,150,100,105,105,115,135,110,105, 100, /* N */ | ||||
100,100,100,100,100,100,100,100,100, 100 | 100,100,100,100,100,100,100,100,100, 100 | ||||
}; // SPARE | |||||
}; | |||||
static unsigned char length_mods_equal[100] = { | static unsigned char length_mods_equal[100] = { | ||||
110,120,100,110,110,110,110,110,110, 110, /* r */ | 110,120,100,110,110,110,110,110,110, 110, /* r */ | ||||
110,120,100,110,110,110,110,110,110, 110, /* N */ | 110,120,100,110,110,110,110,110,110, 110, /* N */ | ||||
110,120,100,110,110,110,110,110,110, 110 | 110,120,100,110,110,110,110,110,110, 110 | ||||
}; // SPARE | |||||
}; | |||||
static unsigned char *length_mod_tabs[6] = { | static unsigned char *length_mod_tabs[6] = { | ||||
void SetLengthMods(Translator *tr, int value) | void SetLengthMods(Translator *tr, int value) | ||||
{//========================================== | |||||
{ | |||||
int value2; | int value2; | ||||
tr->langopts.length_mods0 = tr->langopts.length_mods = length_mod_tabs[value % 100]; | tr->langopts.length_mods0 = tr->langopts.length_mods = length_mod_tabs[value % 100]; | ||||
int IsAlpha(unsigned int c) | int IsAlpha(unsigned int c) | ||||
{//======================== | |||||
{ | |||||
// Replacement for iswalph() which also checks for some in-word symbols | // Replacement for iswalph() which also checks for some in-word symbols | ||||
static const unsigned short extra_indic_alphas[] = { | static const unsigned short extra_indic_alphas[] = { | ||||
} | } | ||||
int IsDigit09(unsigned int c) | int IsDigit09(unsigned int c) | ||||
{//============================ | |||||
{ | |||||
if((c >= '0') && (c <= '9')) | if((c >= '0') && (c <= '9')) | ||||
return(1); | return(1); | ||||
return(0); | return(0); | ||||
} | } | ||||
int IsDigit(unsigned int c) | int IsDigit(unsigned int c) | ||||
{//======================== | |||||
{ | |||||
if(iswdigit(c)) | if(iswdigit(c)) | ||||
return(1); | return(1); | ||||
} | } | ||||
int IsSpace(unsigned int c) | int IsSpace(unsigned int c) | ||||
{//======================== | |||||
{ | |||||
if(c == 0) | if(c == 0) | ||||
return(0); | return(0); | ||||
if((c >= 0x2500) && (c < 0x25a0)) | if((c >= 0x2500) && (c < 0x25a0)) | ||||
return(1); // box drawing characters | return(1); // box drawing characters | ||||
if((c >= 0xfff9) && (c <= 0xffff)) | if((c >= 0xfff9) && (c <= 0xffff)) | ||||
return(1); // unicode specials | return(1); // unicode specials | ||||
// if(wcschr(chars_space,c)) | |||||
// return(1); | |||||
return(iswspace(c)); | return(iswspace(c)); | ||||
} | } | ||||
void DeleteTranslator(Translator *tr) | void DeleteTranslator(Translator *tr) | ||||
{//================================== | |||||
{ | |||||
if(tr->data_dictlist != NULL) | if(tr->data_dictlist != NULL) | ||||
Free(tr->data_dictlist); | Free(tr->data_dictlist); | ||||
Free(tr); | Free(tr); | ||||
int lookupwchar(const unsigned short *list,int c) | int lookupwchar(const unsigned short *list,int c) | ||||
{//============================================== | |||||
{ | |||||
// Is the character c in the list ? | // Is the character c in the list ? | ||||
int ix; | int ix; | ||||
int lookupwchar2(const unsigned short *list,int c) | int lookupwchar2(const unsigned short *list,int c) | ||||
{//============================================== | |||||
{ | |||||
// Replace character c by another character. | // Replace character c by another character. | ||||
// Returns 0 = not found, 1 = delete character | // Returns 0 = not found, 1 = delete character | ||||
int ix; | int ix; | ||||
int IsBracket(int c) | int IsBracket(int c) | ||||
{//================= | |||||
{ | |||||
if((c >= 0x2014) && (c <= 0x201f)) | if((c >= 0x2014) && (c <= 0x201f)) | ||||
return(1); | return(1); | ||||
return(lookupwchar(brackets,c)); | return(lookupwchar(brackets,c)); | ||||
int utf8_out(unsigned int c, char *buf) | int utf8_out(unsigned int c, char *buf) | ||||
{//==================================== | |||||
{ | |||||
// write a unicode character into a buffer as utf8 | // write a unicode character into a buffer as utf8 | ||||
// returns the number of bytes written | // returns the number of bytes written | ||||
int n_bytes; | int n_bytes; | ||||
buf[j+1] = 0x80 + ((c >> shift) & 0x3f); | buf[j+1] = 0x80 + ((c >> shift) & 0x3f); | ||||
} | } | ||||
return(n_bytes+1); | return(n_bytes+1); | ||||
} // end of utf8_out | |||||
} | |||||
int utf8_nbytes(const char *buf) | int utf8_nbytes(const char *buf) | ||||
{//============================= | |||||
{ | |||||
// Returns the number of bytes for the first UTF-8 character in buf | // Returns the number of bytes for the first UTF-8 character in buf | ||||
unsigned char c = (unsigned char)buf[0]; | unsigned char c = (unsigned char)buf[0]; | ||||
if(c < 0x80) | if(c < 0x80) | ||||
int utf8_in2(int *c, const char *buf, int backwards) | int utf8_in2(int *c, const char *buf, int backwards) | ||||
{//================================================= | |||||
{ | |||||
// Read a unicode characater from a UTF8 string | // Read a unicode characater from a UTF8 string | ||||
// Returns the number of UTF8 bytes used. | // Returns the number of UTF8 bytes used. | ||||
// backwards: set if we are moving backwards through the UTF8 string | // backwards: set if we are moving backwards through the UTF8 string | ||||
int utf8_in(int *c, const char *buf) | int utf8_in(int *c, const char *buf) | ||||
{//================================= | |||||
{ | |||||
// Read a unicode characater from a UTF8 string | // Read a unicode characater from a UTF8 string | ||||
// Returns the number of UTF8 bytes used. | // Returns the number of UTF8 bytes used. | ||||
return(utf8_in2(c,buf,0)); | return(utf8_in2(c,buf,0)); | ||||
char *strchr_w(const char *s, int c) | char *strchr_w(const char *s, int c) | ||||
{//================================= | |||||
{ | |||||
// return NULL for any non-ascii character | // return NULL for any non-ascii character | ||||
if(c >= 0x80) | if(c >= 0x80) | ||||
return(NULL); | return(NULL); | ||||
int IsAllUpper(const char *word) | int IsAllUpper(const char *word) | ||||
{//============================= | |||||
{ | |||||
int c; | int c; | ||||
while((*word != 0) && !isspace2(*word)) | while((*word != 0) && !isspace2(*word)) | ||||
{ | { | ||||
static char *SpeakIndividualLetters(Translator *tr, char *word, char *phonemes, int spell_word) | static char *SpeakIndividualLetters(Translator *tr, char *word, char *phonemes, int spell_word) | ||||
{//============================================================================================ | |||||
{ | |||||
int posn = 0; | int posn = 0; | ||||
int capitals = 0; | int capitals = 0; | ||||
int non_initial = 0; | int non_initial = 0; | ||||
} | } | ||||
SetSpellingStress(tr,phonemes,spell_word,posn); | SetSpellingStress(tr,phonemes,spell_word,posn); | ||||
return(word); | return(word); | ||||
} // end of SpeakIndividualLetters | |||||
} | |||||
static int CheckDottedAbbrev(char *word1, WORD_TAB *wtab) | static int CheckDottedAbbrev(char *word1, WORD_TAB *wtab) | ||||
{//===================================================== | |||||
{ | |||||
int wc; | int wc; | ||||
int count = 0; | int count = 0; | ||||
int nbytes; | int nbytes; | ||||
dictionary_skipwords = (count - 1)*2; | dictionary_skipwords = (count - 1)*2; | ||||
} | } | ||||
return(count); | return(count); | ||||
} // end of CheckDottedAbbrev | |||||
} | |||||
extern char *phondata_ptr; | extern char *phondata_ptr; | ||||
int ChangeEquivalentPhonemes(Translator *tr, int lang2, char *phonemes) | int ChangeEquivalentPhonemes(Translator *tr, int lang2, char *phonemes) | ||||
{//==================================================================== | |||||
{ | |||||
// tr: the original language | // tr: the original language | ||||
// lang2: phoneme table number for the temporary language | // lang2: phoneme table number for the temporary language | ||||
// phonemes: the phonemes to be replaced | // phonemes: the phonemes to be replaced | ||||
fprintf(f_trans,"%s\n\n", phonbuf); | fprintf(f_trans,"%s\n\n", phonbuf); | ||||
} | } | ||||
return(1); | return(1); | ||||
} // end of ChangeEquivalentPhonemes | |||||
} | |||||
int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wtab, char *word_out) | int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wtab, char *word_out) | ||||
{//================================================================================================== | |||||
{ | |||||
// word1 is terminated by space (0x20) character | // word1 is terminated by space (0x20) character | ||||
char *word1; | char *word1; | ||||
dictionary_flags[0] |= was_unpronouncable; | dictionary_flags[0] |= was_unpronouncable; | ||||
memcpy(word_start, word_copy2, word_copy_length); | memcpy(word_start, word_copy2, word_copy_length); | ||||
return(dictionary_flags[0]); | return(dictionary_flags[0]); | ||||
} // end of TranslateWord | |||||
} | |||||
static void SetPlist2(PHONEME_LIST2 *p, unsigned char phcode) | static void SetPlist2(PHONEME_LIST2 *p, unsigned char phcode) | ||||
{//========================================================== | |||||
{ | |||||
p->phcode = phcode; | p->phcode = phcode; | ||||
p->stresslevel = 0; | p->stresslevel = 0; | ||||
p->tone_ph = 0; | p->tone_ph = 0; | ||||
} | } | ||||
static int CountSyllables(unsigned char *phonemes) | static int CountSyllables(unsigned char *phonemes) | ||||
{//=============================================== | |||||
{ | |||||
int count = 0; | int count = 0; | ||||
int phon; | int phon; | ||||
while((phon = *phonemes++) != 0) | while((phon = *phonemes++) != 0) | ||||
void Word_EmbeddedCmd() | void Word_EmbeddedCmd() | ||||
{//==================== | |||||
{ | |||||
// Process embedded commands for emphasis, sayas, and break | // Process embedded commands for emphasis, sayas, and break | ||||
int embedded_cmd; | int embedded_cmd; | ||||
int value; | int value; | ||||
break; | break; | ||||
} | } | ||||
} while(((embedded_cmd & 0x80) == 0) && (embedded_read < embedded_ix)); | } while(((embedded_cmd & 0x80) == 0) && (embedded_read < embedded_ix)); | ||||
} // end of Word_EmbeddedCmd | |||||
} | |||||
int SetTranslator2(const char *new_language) | int SetTranslator2(const char *new_language) | ||||
{//========================================= | |||||
{ | |||||
// Set translator2 to a second language | // Set translator2 to a second language | ||||
int new_phoneme_tab; | int new_phoneme_tab; | ||||
const char *new_phtab_name; | const char *new_phtab_name; | ||||
if(translator2 != NULL) | if(translator2 != NULL) | ||||
translator2->phonemes_repeat[0] = 0; | translator2->phonemes_repeat[0] = 0; | ||||
return(new_phoneme_tab); | return(new_phoneme_tab); | ||||
} // end of SetTranslator2 | |||||
} | |||||
static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pause, int next_pause) | static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pause, int next_pause) | ||||
{//================================================================================================= | |||||
{ | |||||
int flags=0; | int flags=0; | ||||
int stress; | int stress; | ||||
int next_stress; | int next_stress; | ||||
tr->prev_dict_flags[0] = flags; | tr->prev_dict_flags[0] = flags; | ||||
return(flags); | return(flags); | ||||
} // end of TranslateWord2 | |||||
} | |||||
static int EmbeddedCommand(unsigned int *source_index_out) | static int EmbeddedCommand(unsigned int *source_index_out) | ||||
{//======================================================= | |||||
{ | |||||
// An embedded command to change the pitch, volume, etc. | // An embedded command to change the pitch, volume, etc. | ||||
// returns number of commands added to embedded_list | // returns number of commands added to embedded_list | ||||
embedded_list[embedded_ix++] = cmd + sign + (value << 8); | embedded_list[embedded_ix++] = cmd + sign + (value << 8); | ||||
*source_index_out = source_index; | *source_index_out = source_index; | ||||
return(1); | return(1); | ||||
} // end of EmbeddedCommand | |||||
} | |||||
static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *insert, int *wordflags) | static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *insert, int *wordflags) | ||||
{//========================================================================================= | |||||
{ | |||||
int ix; | int ix; | ||||
unsigned int word; | unsigned int word; | ||||
unsigned int new_c, c2, c_lower; | unsigned int new_c, c2, c_lower; | ||||
static int TranslateChar(Translator *tr, char *ptr, int prev_in, unsigned int c, unsigned int next_in, int *insert, int *wordflags) | static int TranslateChar(Translator *tr, char *ptr, int prev_in, unsigned int c, unsigned int next_in, int *insert, int *wordflags) | ||||
{//================================================================================================================ | |||||
{ | |||||
// To allow language specific examination and replacement of characters | // To allow language specific examination and replacement of characters | ||||
int code; | int code; | ||||
static const char *UCase_ga[] = {"bp","bhf","dt","gc","hA","mb","nd","ng","ts","tA","nA",NULL}; | static const char *UCase_ga[] = {"bp","bhf","dt","gc","hA","mb","nd","ng","ts","tA","nA",NULL}; | ||||
int UpperCaseInWord(Translator *tr, char *word, int c) | int UpperCaseInWord(Translator *tr, char *word, int c) | ||||
{//===================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int len; | int len; | ||||
const char *p; | const char *p; | ||||
void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone_out, char **voice_change) | void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone_out, char **voice_change) | ||||
{//========================================================================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int c; | int c; | ||||
int cc; | int cc; | ||||
return((void *)p_wchar_input); | return((void *)p_wchar_input); | ||||
else | else | ||||
return((void *)p_textinput); | return((void *)p_textinput); | ||||
} // end of TranslateClause | |||||
} | |||||
void InitText(int control) | void InitText(int control) | ||||
{//======================= | |||||
{ | |||||
count_sentences = 0; | count_sentences = 0; | ||||
count_words = 0; | count_words = 0; | ||||
end_character_position = 0; | end_character_position = 0; | ||||
InitNamedata(); | InitNamedata(); | ||||
} | } | ||||
} | } | ||||
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2014 by Jonathan Duddington * | * Copyright (C) 2005 to 2014 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * | ||||
typedef struct | typedef struct | ||||
{//=========== | |||||
{ | |||||
LANGUAGE_OPTIONS langopts; | LANGUAGE_OPTIONS langopts; | ||||
int translator_name; | int translator_name; |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2007 by Jonathan Duddington * | * Copyright (C) 2005 to 2007 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2005 to 2015 by Jonathan Duddington * | * Copyright (C) 2005 to 2015 by Jonathan Duddington * | ||||
* email: [email protected] * | * email: [email protected] * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
* it under the terms of the GNU General Public License as published by * | * it under the terms of the GNU General Public License as published by * | ||||
static char *fgets_strip(char *buf, int size, FILE *f_in) | static char *fgets_strip(char *buf, int size, FILE *f_in) | ||||
{//====================================================== | |||||
{ | |||||
// strip trailing spaces, and truncate lines at // comment | // strip trailing spaces, and truncate lines at // comment | ||||
int len; | int len; | ||||
char *p; | char *p; | ||||
static int LookupTune(const char *name) | static int LookupTune(const char *name) | ||||
{//==================================== | |||||
{ | |||||
int ix; | int ix; | ||||
for(ix=0; ix<n_tunes; ix++) | for(ix=0; ix<n_tunes; ix++) | ||||
return(ix); | return(ix); | ||||
} | } | ||||
return(-1); | return(-1); | ||||
} // end of LookupTune | |||||
} | |||||
static void SetToneAdjust(voice_t *voice, int *tone_pts) | static void SetToneAdjust(voice_t *voice, int *tone_pts) | ||||
{//===================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int pt; | int pt; | ||||
int y; | int y; | ||||
void ReadTonePoints(char *string, int *tone_pts) | void ReadTonePoints(char *string, int *tone_pts) | ||||
{//============================================= | |||||
{ | |||||
// tone_pts[] is int[12] | // tone_pts[] is int[12] | ||||
int ix; | int ix; | ||||
static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*leafname) | static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*leafname) | ||||
{//=================================================================================== | |||||
{ | |||||
// Read a Voice file, allocate a VOICE_DATA and set data from the | // Read a Voice file, allocate a VOICE_DATA and set data from the | ||||
// file's language, gender, name lines | // file's language, gender, name lines | ||||
voice_data->variant = 0; | voice_data->variant = 0; | ||||
voice_data->xx1 = n_variants; | voice_data->xx1 = n_variants; | ||||
return(voice_data); | return(voice_data); | ||||
} // end of ReadVoiceFile | |||||
} | |||||
void VoiceReset(int tone_only) | void VoiceReset(int tone_only) | ||||
{//=========================== | |||||
{ | |||||
// Set voice to the default values | // Set voice to the default values | ||||
int pk; | int pk; | ||||
option_quiet = 0; | option_quiet = 0; | ||||
LoadMbrolaTable(NULL,NULL,0); | LoadMbrolaTable(NULL,NULL,0); | ||||
} | } | ||||
} // end of VoiceReset | |||||
} | |||||
static void VoiceFormant(char *p) | static void VoiceFormant(char *p) | ||||
{//============================== | |||||
{ | |||||
// Set parameters for a formant | // Set parameters for a formant | ||||
int ix; | int ix; | ||||
int formant; | int formant; | ||||
static void PhonemeReplacement(int type, char *p) | static void PhonemeReplacement(int type, char *p) | ||||
{//============================================== | |||||
{ | |||||
int n; | int n; | ||||
int phon; | int phon; | ||||
int flags = 0; | int flags = 0; | ||||
replace_phonemes[n_replace_phonemes].old_ph = phon; | replace_phonemes[n_replace_phonemes].old_ph = phon; | ||||
replace_phonemes[n_replace_phonemes].new_ph = LookupPhonemeString(phon_string2); | replace_phonemes[n_replace_phonemes].new_ph = LookupPhonemeString(phon_string2); | ||||
replace_phonemes[n_replace_phonemes++].type = flags; | replace_phonemes[n_replace_phonemes++].type = flags; | ||||
} // end of PhonemeReplacement | |||||
} | |||||
static int Read8Numbers(char *data_in,int *data) | static int Read8Numbers(char *data_in,int *data) | ||||
{//============================================= | |||||
{ | |||||
// Read 8 integer numbers | // Read 8 integer numbers | ||||
memset(data, 0, 8+sizeof(int)); | memset(data, 0, 8+sizeof(int)); | ||||
return(sscanf(data_in,"%d %d %d %d %d %d %d %d", | return(sscanf(data_in,"%d %d %d %d %d %d %d %d", | ||||
static unsigned int StringToWord2(const char *string) | static unsigned int StringToWord2(const char *string) | ||||
{//====================================================== | |||||
{ | |||||
// Convert a language name string to a word such as L('e','n') | // Convert a language name string to a word such as L('e','n') | ||||
int ix; | int ix; | ||||
int c; | int c; | ||||
voice_t *LoadVoice(const char *vname, int control) | voice_t *LoadVoice(const char *vname, int control) | ||||
{//=============================================== | |||||
{ | |||||
// control, bit 0 1= no_default | // control, bit 0 1= no_default | ||||
// bit 1 1 = change tone only, not language | // bit 1 1 = change tone only, not language | ||||
// bit 2 1 = don't report error on LoadDictionary | // bit 2 1 = don't report error on LoadDictionary | ||||
} | } | ||||
return(voice); | return(voice); | ||||
} // end of LoadVoice | |||||
} | |||||
static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) | ||||
{//=========================================================================== | |||||
{ | |||||
// Remove any voice variant suffix (name or number) from a voice name | // Remove any voice variant suffix (name or number) from a voice name | ||||
// Returns the voice variant name | // Returns the voice variant name | ||||
} | } | ||||
return(variant_name); | return(variant_name); | ||||
} // end of ExtractVoiceVariantName | |||||
} | |||||
voice_t *LoadVoiceVariant(const char *vname, int variant_num) | voice_t *LoadVoiceVariant(const char *vname, int variant_num) | ||||
{//========================================================== | |||||
{ | |||||
// Load a voice file. | // Load a voice file. | ||||
// Also apply a voice variant if specified by "variant", or by "+number" or "+name" in the "vname" | // Also apply a voice variant if specified by "variant", or by "+number" or "+name" in the "vname" | ||||
static int __cdecl VoiceNameSorter(const void *p1, const void *p2) | static int __cdecl VoiceNameSorter(const void *p1, const void *p2) | ||||
{//======================================================= | |||||
{ | |||||
int ix; | int ix; | ||||
espeak_VOICE *v1 = *(espeak_VOICE **)p1; | espeak_VOICE *v1 = *(espeak_VOICE **)p1; | ||||
espeak_VOICE *v2 = *(espeak_VOICE **)p2; | espeak_VOICE *v2 = *(espeak_VOICE **)p2; | ||||
static int __cdecl VoiceScoreSorter(const void *p1, const void *p2) | static int __cdecl VoiceScoreSorter(const void *p1, const void *p2) | ||||
{//======================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
espeak_VOICE *v1 = *(espeak_VOICE **)p1; | espeak_VOICE *v1 = *(espeak_VOICE **)p1; | ||||
espeak_VOICE *v2 = *(espeak_VOICE **)p2; | espeak_VOICE *v2 = *(espeak_VOICE **)p2; | ||||
static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int spec_n_parts, int spec_lang_len, espeak_VOICE *voice) | static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int spec_n_parts, int spec_lang_len, espeak_VOICE *voice) | ||||
{//========================================================================================================================= | |||||
{ | |||||
int ix; | int ix; | ||||
const char *p; | const char *p; | ||||
int c1, c2; | int c1, c2; | ||||
if(score < 1) | if(score < 1) | ||||
score = 1; | score = 1; | ||||
return(score); | return(score); | ||||
} // end of ScoreVoice | |||||
} | |||||
static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int control) | static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int control) | ||||
{//====================================================================================== | |||||
{ | |||||
// control: bit0=1 include mbrola voices | // control: bit0=1 include mbrola voices | ||||
int ix; | int ix; | ||||
int score; | int score; | ||||
qsort(voices,nv,sizeof(espeak_VOICE *),(int (__cdecl *)(const void *,const void *))VoiceScoreSorter); | qsort(voices,nv,sizeof(espeak_VOICE *),(int (__cdecl *)(const void *,const void *))VoiceScoreSorter); | ||||
return(nv); | return(nv); | ||||
} // end of SetVoiceScores | |||||
} | |||||
espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) | ||||
{//====================================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
int match_fname = -1; | int match_fname = -1; | ||||
int match_fname2 = -1; | int match_fname2 = -1; | ||||
return(NULL); | return(NULL); | ||||
return(voices[match_name]); | return(voices[match_name]); | ||||
} // end of SelectVoiceByName | |||||
} | |||||
char const *SelectVoice(espeak_VOICE *voice_select, int *found) | char const *SelectVoice(espeak_VOICE *voice_select, int *found) | ||||
{//============================================================ | |||||
{ | |||||
// Returns a path within espeak-voices, with a possible +variant suffix | // Returns a path within espeak-voices, with a possible +variant suffix | ||||
// variant is an output-only parameter | // variant is an output-only parameter | ||||
int nv; // number of candidates | int nv; // number of candidates | ||||
} | } | ||||
return(vp->identifier); | return(vp->identifier); | ||||
} // end of SelectVoice | |||||
} | |||||
static void GetVoices(const char *path) | static void GetVoices(const char *path) | ||||
{//==================================== | |||||
{ | |||||
FILE *f_voice; | FILE *f_voice; | ||||
espeak_VOICE *voice_data; | espeak_VOICE *voice_data; | ||||
int ftype; | int ftype; | ||||
closedir(dir); | closedir(dir); | ||||
#endif | #endif | ||||
#endif | #endif | ||||
} // end of GetVoices | |||||
} | |||||
espeak_ERROR SetVoiceByName(const char *name) | espeak_ERROR SetVoiceByName(const char *name) | ||||
{//========================================= | |||||
{ | |||||
espeak_VOICE *v; | espeak_VOICE *v; | ||||
int ix; | int ix; | ||||
espeak_VOICE voice_selector; | espeak_VOICE voice_selector; | ||||
} | } | ||||
} | } | ||||
return(EE_INTERNAL_ERROR); // voice name not found | return(EE_INTERNAL_ERROR); // voice name not found | ||||
} // end of SetVoiceByName | |||||
} | |||||
espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector) | espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector) | ||||
{//============================================================ | |||||
{ | |||||
const char *voice_id; | const char *voice_id; | ||||
int voice_found; | int voice_found; | ||||
SetVoiceStack(voice_selector, ""); | SetVoiceStack(voice_selector, ""); | ||||
return(EE_OK); | return(EE_OK); | ||||
} // end of SetVoiceByProperties | |||||
} | |||||
void FreeVoiceList() | void FreeVoiceList() | ||||
{//================= | |||||
{ | |||||
int ix; | int ix; | ||||
for(ix=0; ix<n_voices_list; ix++) | for(ix=0; ix<n_voices_list; ix++) | ||||
{ | { | ||||
} | } | ||||
//======================================================================= | |||||
// Library Interface Functions | |||||
//======================================================================= | |||||
#pragma GCC visibility push(default) | #pragma GCC visibility push(default) | ||||
ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) | ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) | ||||
{//======================================================================== | |||||
{ | |||||
char path_voices[sizeof(path_home)+12]; | char path_voices[sizeof(path_home)+12]; | ||||
} | } | ||||
return((const espeak_VOICE **)voices); | return((const espeak_VOICE **)voices); | ||||
#endif | #endif | ||||
} // end of espeak_ListVoices | |||||
} | |||||
ESPEAK_API espeak_VOICE *espeak_GetCurrentVoice(void) | ESPEAK_API espeak_VOICE *espeak_GetCurrentVoice(void) | ||||
{//================================================== | |||||
{ | |||||
return(¤t_voice_selected); | return(¤t_voice_selected); | ||||
} | } | ||||
#pragma GCC visibility pop | #pragma GCC visibility pop | ||||
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2007, Gilles Casse <[email protected]> * | * Copyright (C) 2007, Gilles Casse <[email protected]> * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* based on AudioIO.cc (Audacity-1.2.4b) and wavegen.cpp * | * based on AudioIO.cc (Audacity-1.2.4b) and wavegen.cpp * | ||||
* * | * * | ||||
* This program is free software; you can redistribute it and/or modify * | * This program is free software; you can redistribute it and/or modify * | ||||
#endif | #endif | ||||
return(aResult); | return(aResult); | ||||
} // end of WaveCallBack | |||||
} | |||||
void wave_flush(void* theHandler) | void wave_flush(void* theHandler) |
/*************************************************************************** | /*************************************************************************** | ||||
* Copyright (C) 2007, Gilles Casse <[email protected]> * | * Copyright (C) 2007, Gilles Casse <[email protected]> * | ||||
* Copyright (C) 2015 by Reece H. Dunn * | |||||
* Copyright (C) 2015 Reece H. Dunn * | |||||
* eSpeak driver for PulseAudio * | * eSpeak driver for PulseAudio * | ||||
* based on the XMMS PulseAudio Plugin * | * based on the XMMS PulseAudio Plugin * | ||||
* * | * * |
#ifdef LOG_FRAMES | #ifdef LOG_FRAMES | ||||
static void LogMarker(int type, int value, int value2) | static void LogMarker(int type, int value, int value2) | ||||
{//=================================================== | |||||
{ | |||||
char buf[20]; | char buf[20]; | ||||
int *p; | int *p; | ||||
#endif | #endif | ||||
void WcmdqStop() | void WcmdqStop() | ||||
{//============= | |||||
{ | |||||
wcmdq_head = 0; | wcmdq_head = 0; | ||||
wcmdq_tail = 0; | wcmdq_tail = 0; | ||||
int WcmdqFree() | int WcmdqFree() | ||||
{//============ | |||||
{ | |||||
int i; | int i; | ||||
i = wcmdq_head - wcmdq_tail; | i = wcmdq_head - wcmdq_tail; | ||||
if(i <= 0) i += N_WCMDQ; | if(i <= 0) i += N_WCMDQ; | ||||
} | } | ||||
int WcmdqUsed() | int WcmdqUsed() | ||||
{//============ | |||||
{ | |||||
return(N_WCMDQ - WcmdqFree()); | return(N_WCMDQ - WcmdqFree()); | ||||
} | } | ||||
void WcmdqInc() | void WcmdqInc() | ||||
{//============ | |||||
{ | |||||
wcmdq_tail++; | wcmdq_tail++; | ||||
if(wcmdq_tail >= N_WCMDQ) wcmdq_tail=0; | if(wcmdq_tail >= N_WCMDQ) wcmdq_tail=0; | ||||
} | } | ||||
static void WcmdqIncHead() | static void WcmdqIncHead() | ||||
{//======================= | |||||
{ | |||||
wcmdq_head++; | wcmdq_head++; | ||||
if(wcmdq_head >= N_WCMDQ) wcmdq_head=0; | if(wcmdq_head >= N_WCMDQ) wcmdq_head=0; | ||||
} | } | ||||
return(result); | return(result); | ||||
#endif | #endif | ||||
} // end of WaveCallBack | |||||
} | |||||
#if USE_PORTAUDIO == 19 | #if USE_PORTAUDIO == 19 | ||||
int WavegenOpenSound() | int WavegenOpenSound() | ||||
{//=================== | |||||
{ | |||||
PaError err, err2; | PaError err, err2; | ||||
PaError active; | PaError active; | ||||
int WavegenCloseSound() | int WavegenCloseSound() | ||||
{//==================== | |||||
{ | |||||
PaError active; | PaError active; | ||||
// check whether speaking has finished, and close the stream | // check whether speaking has finished, and close the stream | ||||
int WavegenInitSound() | int WavegenInitSound() | ||||
{//=================== | |||||
{ | |||||
PaError err; | PaError err; | ||||
if(option_quiet) | if(option_quiet) | ||||
} | } | ||||
#else | #else | ||||
int WavegenOpenSound() | int WavegenOpenSound() | ||||
{//=================== | |||||
{ | |||||
return(0); | return(0); | ||||
} | } | ||||
int WavegenCloseSound() | int WavegenCloseSound() | ||||
{//==================== | |||||
{ | |||||
return(0); | return(0); | ||||
} | } | ||||
int WavegenInitSound() | int WavegenInitSound() | ||||
{//=================== | |||||
{ | |||||
return(0); | return(0); | ||||
} | } | ||||
#endif | #endif | ||||
void WavegenInit(int rate, int wavemult_fact) | void WavegenInit(int rate, int wavemult_fact) | ||||
{//========================================== | |||||
{ | |||||
int ix; | int ix; | ||||
double x; | double x; | ||||
remove("log-espeakedit"); | remove("log-espeakedit"); | ||||
remove("log-klatt"); | remove("log-klatt"); | ||||
#endif | #endif | ||||
} // end of WavegenInit | |||||
} | |||||
int GetAmplitude(void) | int GetAmplitude(void) | ||||
{//=================== | |||||
{ | |||||
int amp; | int amp; | ||||
// normal, none, reduced, moderate, strong | // normal, none, reduced, moderate, strong | ||||
static void WavegenSetEcho(void) | static void WavegenSetEcho(void) | ||||
{//============================= | |||||
{ | |||||
int delay; | int delay; | ||||
int amp; | int amp; | ||||
// compensate (partially) for increase in amplitude due to echo | // compensate (partially) for increase in amplitude due to echo | ||||
general_amplitude = GetAmplitude(); | general_amplitude = GetAmplitude(); | ||||
general_amplitude = ((general_amplitude * (500-amp))/500); | general_amplitude = ((general_amplitude * (500-amp))/500); | ||||
} // end of WavegenSetEcho | |||||
} | |||||
int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) | ||||
{//============================================================================ | |||||
{ | |||||
// Calculate the amplitude of each harmonics from the formants | // Calculate the amplitude of each harmonics from the formants | ||||
// Only for formants 0 to 5 | // Only for formants 0 to 5 | ||||
} | } | ||||
return(hmax); // highest harmonic number | return(hmax); // highest harmonic number | ||||
} // end of PeaksToHarmspect | |||||
} | |||||
static void AdvanceParameters() | static void AdvanceParameters() | ||||
{//============================ | |||||
{ | |||||
// Called every 64 samples to increment the formant freq, height, and widths | // Called every 64 samples to increment the formant freq, height, and widths | ||||
int x; | int x; | ||||
harm_sqrt[ix] += harm_sqrt_inc[ix]; | harm_sqrt[ix] += harm_sqrt_inc[ix]; | ||||
} | } | ||||
#endif | #endif | ||||
} // end of AdvanceParameters | |||||
} | |||||
#ifndef PLATFORM_RISCOS | #ifndef PLATFORM_RISCOS | ||||
static double resonator(RESONATOR *r, double input) | static double resonator(RESONATOR *r, double input) | ||||
{//================================================ | |||||
{ | |||||
double x; | double x; | ||||
x = r->a * input + r->b * r->x1 + r->c * r->x2; | x = r->a * input + r->b * r->x1 + r->c * r->x2; | ||||
static void setresonator(RESONATOR *rp, int freq, int bwidth, int init) | static void setresonator(RESONATOR *rp, int freq, int bwidth, int init) | ||||
{//==================================================================== | |||||
{ | |||||
// freq Frequency of resonator in Hz | // freq Frequency of resonator in Hz | ||||
// bwidth Bandwidth of resonator in Hz | // bwidth Bandwidth of resonator in Hz | ||||
// init Initialize internal data | // init Initialize internal data | ||||
rp->b = x * cos(arg) * 2.0; | rp->b = x * cos(arg) * 2.0; | ||||
rp->a = 1.0 - rp->b - rp->c; | rp->a = 1.0 - rp->b - rp->c; | ||||
} // end if setresonator | |||||
} | |||||
#endif | #endif | ||||
void InitBreath(void) | void InitBreath(void) | ||||
{//================== | |||||
{ | |||||
#ifndef PLATFORM_RISCOS | #ifndef PLATFORM_RISCOS | ||||
int ix; | int ix; | ||||
setresonator(&rbreath[ix],2000,200,1); | setresonator(&rbreath[ix],2000,200,1); | ||||
} | } | ||||
#endif | #endif | ||||
} // end of InitBreath | |||||
} | |||||
static void SetBreath() | static void SetBreath() | ||||
{//==================== | |||||
{ | |||||
#ifndef PLATFORM_RISCOS | #ifndef PLATFORM_RISCOS | ||||
int pk; | int pk; | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
} // end of SetBreath | |||||
} | |||||
static int ApplyBreath(void) | static int ApplyBreath(void) | ||||
{//========================= | |||||
{ | |||||
int value = 0; | int value = 0; | ||||
#ifndef PLATFORM_RISCOS | #ifndef PLATFORM_RISCOS | ||||
int noise; | int noise; | ||||
int Wavegen() | int Wavegen() | ||||
{//========== | |||||
{ | |||||
unsigned short waveph; | unsigned short waveph; | ||||
unsigned short theta; | unsigned short theta; | ||||
int total; | int total; | ||||
return(1); | return(1); | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of Wavegen | |||||
} | |||||
static int PlaySilence(int length, int resume) | static int PlaySilence(int length, int resume) | ||||
{//=========================================== | |||||
{ | |||||
static int n_samples; | static int n_samples; | ||||
int value=0; | int value=0; | ||||
return(1); | return(1); | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of PlaySilence | |||||
} | |||||
static int PlayWave(int length, int resume, unsigned char *data, int scale, int amp) | static int PlayWave(int length, int resume, unsigned char *data, int scale, int amp) | ||||
{//================================================================================= | |||||
{ | |||||
static int n_samples; | static int n_samples; | ||||
static int ix=0; | static int ix=0; | ||||
int value; | int value; | ||||
static int SetWithRange0(int value, int max) | static int SetWithRange0(int value, int max) | ||||
{//========================================= | |||||
{ | |||||
if(value < 0) | if(value < 0) | ||||
return(0); | return(0); | ||||
if(value > max) | if(value > max) | ||||
static void SetPitchFormants() | static void SetPitchFormants() | ||||
{//=========================== | |||||
{ | |||||
int ix; | int ix; | ||||
int factor = 256; | int factor = 256; | ||||
int pitch_value; | int pitch_value; | ||||
void SetEmbedded(int control, int value) | void SetEmbedded(int control, int value) | ||||
{//===================================== | |||||
{ | |||||
// there was an embedded command in the text at this point | // there was an embedded command in the text at this point | ||||
int sign=0; | int sign=0; | ||||
int command; | int command; | ||||
void WavegenSetVoice(voice_t *v) | void WavegenSetVoice(voice_t *v) | ||||
{//============================= | |||||
{ | |||||
static voice_t v2; | static voice_t v2; | ||||
memcpy(&v2,v,sizeof(v2)); | memcpy(&v2,v,sizeof(v2)); | ||||
static void SetAmplitude(int length, unsigned char *amp_env, int value) | static void SetAmplitude(int length, unsigned char *amp_env, int value) | ||||
{//==================================================================== | |||||
{ | |||||
amp_ix = 0; | amp_ix = 0; | ||||
if(length==0) | if(length==0) | ||||
amp_inc = 0; | amp_inc = 0; | ||||
void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pitch_range) | void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pitch_range) | ||||
{//====================================================================================== | |||||
{ | |||||
int x; | int x; | ||||
int base; | int base; | ||||
int range; | int range; | ||||
void SetPitch(int length, unsigned char *env, int pitch1, int pitch2) | void SetPitch(int length, unsigned char *env, int pitch1, int pitch2) | ||||
{//================================================================== | |||||
{ | |||||
// length in samples | // length in samples | ||||
#ifdef LOG_FRAMES | #ifdef LOG_FRAMES | ||||
flutter_amp = wvoice->flutter; | flutter_amp = wvoice->flutter; | ||||
} // end of SetPitch | |||||
} | |||||
void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) | ||||
{//======================================================================== | |||||
{ | |||||
int ix; | int ix; | ||||
DOUBLEX next; | DOUBLEX next; | ||||
int length2; | int length2; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} // end of SetSynth | |||||
} | |||||
static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2) | static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2) | ||||
{//==================================================================================== | |||||
{ | |||||
if(resume==0) | if(resume==0) | ||||
SetSynth(length, modulation, fr1, fr2, wvoice); | SetSynth(length, modulation, fr1, fr2, wvoice); | ||||
} | } | ||||
void Write4Bytes(FILE *f, int value) | void Write4Bytes(FILE *f, int value) | ||||
{//================================= | |||||
{ | |||||
// Write 4 bytes to a file, least significant first | // Write 4 bytes to a file, least significant first | ||||
int ix; | int ix; | ||||
int WavegenFill2(int fill_zeros) | int WavegenFill2(int fill_zeros) | ||||
{//============================ | |||||
{ | |||||
// Pick up next wavegen commands from the queue | // Pick up next wavegen commands from the queue | ||||
// return: 0 output buffer has been filled | // return: 0 output buffer has been filled | ||||
// return: 1 input command queue is now empty | // return: 1 input command queue is now empty | ||||
} | } | ||||
return(0); | return(0); | ||||
} // end of WavegenFill2 | |||||
} | |||||
#ifdef INCLUDE_SONIC | #ifdef INCLUDE_SONIC | ||||
/* Speed up the audio samples with libsonic. */ | /* Speed up the audio samples with libsonic. */ | ||||
static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text) | static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text) | ||||
{//============================================================================== | |||||
{ | |||||
if(length_in >0) | if(length_in >0) | ||||
{ | { | ||||
if(sonicSpeedupStream == NULL) | if(sonicSpeedupStream == NULL) | ||||
sonicFlushStream(sonicSpeedupStream); | sonicFlushStream(sonicSpeedupStream); | ||||
} | } | ||||
return sonicReadShortFromStream(sonicSpeedupStream, outbuf, length_out); | return sonicReadShortFromStream(sonicSpeedupStream, outbuf, length_out); | ||||
} // end of SpeedUp | |||||
} | |||||
#endif | #endif | ||||
/* Call WavegenFill2, and then speed up the output samples. */ | /* Call WavegenFill2, and then speed up the output samples. */ | ||||
int WavegenFill(int fill_zeros) | int WavegenFill(int fill_zeros) | ||||
{//============================ | |||||
{ | |||||
int finished; | int finished; | ||||
unsigned char *p_start; | unsigned char *p_start; | ||||
} | } | ||||
#endif | #endif | ||||
return finished; | return finished; | ||||
} // end of WavegenFill | |||||
} | |||||
void DisplayVoices(FILE *f_out, char *language) | void DisplayVoices(FILE *f_out, char *language) | ||||
{//============================================ | |||||
{ | |||||
int ix; | int ix; | ||||
const char *p; | const char *p; | ||||
int len; | int len; | ||||
} | } | ||||
fputc('\n',f_out); | fputc('\n',f_out); | ||||
} | } | ||||
} // end of DisplayVoices | |||||
} | |||||
static int OpenWaveFile(const char *path, int rate) | static int OpenWaveFile(const char *path, int rate) | ||||
//================================================= | |||||
{ | { | ||||
// Set the length of 0x7ffff000 for --stdout | // Set the length of 0x7ffff000 for --stdout | ||||
// This will be changed to the correct length for -w (write to file) | // This will be changed to the correct length for -w (write to file) | ||||
return(0); | return(0); | ||||
} | } | ||||
return(1); | return(1); | ||||
} // end of OpenWaveFile | |||||
} | |||||
static void CloseWaveFile() | static void CloseWaveFile() | ||||
//========================= | |||||
{ | { | ||||
unsigned int pos; | unsigned int pos; | ||||
fclose(f_wave); | fclose(f_wave); | ||||
f_wave = NULL; | f_wave = NULL; | ||||
} // end of CloseWaveFile | |||||
} | |||||
static int WavegenFile(void) | static int WavegenFile(void) | ||||
{//========================= | |||||
{ | |||||
int finished; | int finished; | ||||
unsigned char wav_outbuf[1024]; | unsigned char wav_outbuf[1024]; | ||||
char fname[210]; | char fname[210]; | ||||
fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave); | fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave); | ||||
} | } | ||||
return(finished); | return(finished); | ||||
} // end of WavegenFile | |||||
} | |||||
static void init_path(char *argv0, char *path_specified) | static void init_path(char *argv0, char *path_specified) | ||||
{//===================================================== | |||||
{ | |||||
if(path_specified) | if(path_specified) | ||||
{ | { | ||||
static int initialise(void) | static int initialise(void) | ||||
{//======================== | |||||
{ | |||||
int param; | int param; | ||||
int result; | int result; | ||||
int srate = 22050; // default sample rate | int srate = 22050; // default sample rate | ||||
#endif | #endif | ||||
int main (int argc, char **argv) | int main (int argc, char **argv) | ||||
//============================== | |||||
{ | { | ||||
static struct option long_options[] = | static struct option long_options[] = | ||||
{ | { | ||||
/* These options set a flag. */ | |||||
// {"verbose", no_argument, &verbose_flag, 1}, | |||||
// {"brief", no_argument, &verbose_flag, 0}, | |||||
/* These options don't set a flag. | |||||
We distinguish them by their indices. */ | |||||
{"help", no_argument, 0, 'h'}, | {"help", no_argument, 0, 'h'}, | ||||
{"stdin", no_argument, 0, 0x100}, | {"stdin", no_argument, 0, 0x100}, | ||||
{"compile-debug", optional_argument, 0, 0x101}, | {"compile-debug", optional_argument, 0, 0x101}, |