| 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}, |