diff options
Diffstat (limited to 'navit/support/espeak')
231 files changed, 0 insertions, 37904 deletions
diff --git a/navit/support/espeak/CMakeLists.txt b/navit/support/espeak/CMakeLists.txt deleted file mode 100644 index 6a20511e7..000000000 --- a/navit/support/espeak/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ - -if(INTERNAL_ESPEAK_COMPLETE) - set(ESPEAK_LIBRARY_ADDITIONAL speak_lib.c) -endif() -supportlib_add_library(support_espeak compiledict.c dictionary.c intonation.c readclause.c setlengths.c - numbers.c synth_mbrola.c synthdata.c synthesize.c translate.c tr_languages.c voices.c wavegen.c - phonemelist.c klatt.c speak_init.c ${ESPEAK_LIBRARY_ADDITIONAL}) - -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/espeak-data DESTINATION ${SHARE_DIR} PATTERN ".svn" EXCLUDE) diff --git a/navit/support/espeak/StdAfx.h b/navit/support/espeak/StdAfx.h deleted file mode 100644 index c9a526fdf..000000000 --- a/navit/support/espeak/StdAfx.h +++ /dev/null @@ -1,3 +0,0 @@ -// This is a dummy file. -// A file of this name is needed on Windows - diff --git a/navit/support/espeak/compiledict.c b/navit/support/espeak/compiledict.c deleted file mode 100755 index a2b7865f9..000000000 --- a/navit/support/espeak/compiledict.c +++ /dev/null @@ -1,1671 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <wctype.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "translate.h" - -//#define OPT_FORMAT // format the text and write formatted copy to Log file -//#define OUTPUT_FORMAT - -extern void Write4Bytes(FILE *f, int value); -int HashDictionary(const char *string); - -static FILE *f_log = NULL; -extern char *dir_dictionary; - -static int linenum; -static int error_count; -static int transpose_offset; // transpose character range for LookupDictList() -static int transpose_min; -static int transpose_max; -static int text_mode = 0; -static int debug_flag = 0; - -static int hash_counts[N_HASH_DICT]; -static char *hash_chains[N_HASH_DICT]; -static char letterGroupsDefined[N_LETTER_GROUPS]; - -#define __cdecl - -MNEM_TAB mnem_flags[] = { - // these in the first group put a value in bits0-3 of dictionary_flags - {"$1", 0x41}, // stress on 1st syllable - {"$2", 0x42}, // stress on 2nd syllable - {"$3", 0x43}, - {"$4", 0x44}, - {"$5", 0x45}, - {"$6", 0x46}, - {"$7", 0x47}, - {"$u", 0x48}, // reduce to unstressed - {"$u1", 0x49}, - {"$u2", 0x4a}, - {"$u3", 0x4b}, - {"$u+", 0x4c}, // reduce to unstressed, but stress at end of clause - {"$u1+", 0x4d}, - {"$u2+", 0x4e}, - {"$u3+", 0x4f}, - - - // these set the corresponding numbered bit if dictionary_flags - {"$pause", 8}, /* ensure pause before this word */ - {"$only", 9}, /* only match on this word without suffix */ - {"$onlys", 10}, /* only match with none, or with 's' suffix */ - {"$strend", 11}, /* full stress if at end of clause */ - {"$strend2", 12}, /* full stress if at end of clause, or only followed by unstressed */ - {"$unstressend",13}, /* reduce stress at end of clause */ - {"$atend", 14}, /* use this pronunciation if at end of clause */ - - {"$dot", 16}, /* ignore '.' after this word (abbreviation) */ - {"$abbrev", 17}, /* use this pronuciation rather than split into letters */ - {"$stem", 18}, // must have a suffix - -// language specific - {"$double", 19}, // IT double the initial consonant of next word - {"$alt", 20}, // use alternative pronunciation - {"$alt2", 21}, - - - {"$max3", 27}, // limit to 3 repetitions - {"$brk", 28}, // a shorter $pause - {"$text", 29}, // word translates to replcement text, not phonemes - -// flags in dictionary word 2 - {"$verbf", 0x20}, /* verb follows */ - {"$verbsf", 0x21}, /* verb follows, allow -s suffix */ - {"$nounf", 0x22}, /* noun follows */ - {"$pastf", 0x23}, /* past tense follows */ - {"$verb", 0x24}, /* use this pronunciation when its a verb */ - {"$noun", 0x25}, /* use this pronunciation when its a noun */ - {"$past", 0x26}, /* use this pronunciation when its past tense */ - {"$verbextend",0x28}, /* extend influence of 'verb follows' */ - {"$capital", 0x29}, /* use this pronunciation if initial letter is upper case */ - {"$allcaps", 0x2a}, /* use this pronunciation if initial letter is upper case */ - {"$accent", 0x2b}, // character name is base-character name + accent name - - // doesn't set dictionary_flags - {"$?", 100}, // conditional rule, followed by byte giving the condition number - - {"$textmode", 200}, - {"$phonememode", 201}, - {NULL, -1} -}; - - -#define LEN_GROUP_NAME 12 - -typedef struct { - char name[LEN_GROUP_NAME+1]; - unsigned int start; - unsigned int length; -} RGROUP; - - -int isspace2(unsigned int c) -{//========================= -// can't use isspace() because on Windows, isspace(0xe1) gives TRUE ! - int c2; - - if(((c2 = (c & 0xff)) == 0) || (c > ' ')) - return(0); - return(1); -} - - -static const char *LookupMnem2(MNEM_TAB *table, int value) -{//======================================================= - while(table->mnem != NULL) - { - if(table->value == value) - return(table->mnem); - table++; - } - return(""); -} - - -char *print_dictionary_flags(unsigned int *flags) -{//============================================== - static char buf[20]; - - sprintf(buf,"%s 0x%x/%x",LookupMnem2(mnem_flags,(flags[0] & 0xf)+0x40), flags[0], flags[1]); - return(buf); -} - - - -static FILE *fopen_log(const char *fname,const char *access) -{//================================================== -// performs fopen, but produces error message to f_log if it fails - FILE *f; - - if((f = fopen(fname,access)) == NULL) - { - if(f_log != NULL) - fprintf(f_log,"Can't access (%s) file '%s'\n",access,fname); - } - return(f); -} - - -#ifdef OPT_FORMAT -static const char *lookup_mnem(MNEM_TAB *table, int value) -//======================================================== -/* Lookup a mnemonic string in a table, return its name */ -{ - while(table->mnem != NULL) - { - if(table->value==value) - return(table->mnem); - table++; - } - return("??"); /* not found */ -} /* end of mnem */ -#endif - - - - -static int compile_line(char *linebuf, char *dict_line, int *hash) -{//=============================================================== -// Compile a line in the language_list file - unsigned char c; - char *p; - char *word; - char *phonetic; - unsigned int ix; - int step; - unsigned int n_flag_codes = 0; - int flag_offset; - int length; - int multiple_words = 0; - int multiple_numeric_hyphen = 0; - char *multiple_string = NULL; - char *multiple_string_end = NULL; - - int len_word; - int len_phonetic; - int text_not_phonemes; // this word specifies replacement text, not phonemes - unsigned int wc; - int all_upper_case; - - char *mnemptr; - char *comment; - unsigned char flag_codes[100]; - char encoded_ph[200]; - unsigned char bad_phoneme[4]; -static char nullstring[] = {0}; - - comment = NULL; - text_not_phonemes = 0; - phonetic = word = nullstring; - -if(memcmp(linebuf,"_-",2)==0) -{ -step=1; // TEST -} - p = linebuf; -// while(isspace2(*p)) p++; - -#ifdef deleted - if(*p == '$') - { - if(memcmp(p,"$textmode",9) == 0) - { - text_mode = 1; - return(0); - } - if(memcmp(p,"$phonememode",12) == 0) - { - text_mode = 0; - return(0); - } - } -#endif - - step = 0; - - c = 0; - while(c != '\n') - { - c = *p; - - if((c == '?') && (step==0)) - { - // conditional rule, allow only if the numbered condition is set for the voice - flag_offset = 100; - - p++; - if(*p == '!') - { - // allow only if the numbered condition is NOT set - flag_offset = 132; - p++; - } - - ix = 0; - if(isdigit(*p)) - { - ix += (*p-'0'); - p++; - } - if(isdigit(*p)) - { - ix = ix*10 + (*p-'0'); - p++; - } - flag_codes[n_flag_codes++] = ix + flag_offset; - c = *p; - } - - if((c == '$') && isalnum(p[1])) - { - /* read keyword parameter */ - mnemptr = p; - while(!isspace2(c = *p)) p++; - *p = 0; - - ix = LookupMnem(mnem_flags,mnemptr); - if(ix > 0) - { - if(ix == 200) - { - text_mode = 1; - } - else - if(ix == 201) - { - text_mode = 0; - } - else - if(ix == BITNUM_FLAG_TEXTMODE) - { - text_not_phonemes = 1; - } - else - { - flag_codes[n_flag_codes++] = ix; - } - } - else - { - fprintf(f_log,"%5d: Unknown keyword: %s\n",linenum,mnemptr); - error_count++; - } - } - - if((c == '/') && (p[1] == '/') && (multiple_words==0)) - { - c = '\n'; /* "//" treat comment as end of line */ - comment = p; - } - - switch(step) - { - case 0: - if(c == '(') - { - multiple_words = 1; - word = p+1; - step = 1; - } - else - if(!isspace2(c)) - { - word = p; - step = 1; - } - break; - - case 1: - if((c == '-') && (word[0] != '_')) - { - if(isdigit(word[0])) - { - multiple_numeric_hyphen = 1; - } - else - { - flag_codes[n_flag_codes++] = BITNUM_FLAG_HYPHENATED; - } - c = ' '; - } - if(isspace2(c)) - { - p[0] = 0; /* terminate english word */ - - if(multiple_words) - { - multiple_string = multiple_string_end = p+1; - step = 2; - } - else - { - step = 3; - } - } - else - if((c == ')') && multiple_words) - { - p[0] = 0; - step = 3; - multiple_words = 0; - } - break; - - case 2: - if(isspace2(c)) - { - multiple_words++; - } - else - if(c == ')') - { - p[0] = ' '; // terminate extra string - multiple_string_end = p+1; - step = 3; - } - break; - - case 3: - if(!isspace2(c)) - { - phonetic = p; - step = 4; - } - break; - - case 4: - if(isspace2(c)) - { - p[0] = 0; /* terminate phonetic */ - step = 5; - } - break; - - case 5: - break; - } - p++; - } - - if(word[0] == 0) - { -#ifdef OPT_FORMAT - if(comment != NULL) - fprintf(f_log,"%s",comment); - else - fputc('\n',f_log); -#endif - return(0); /* blank line */ - } - - if(text_mode) - text_not_phonemes = 1; - - if(text_not_phonemes != translator->langopts.textmode) - { - flag_codes[n_flag_codes++] = BITNUM_FLAG_TEXTMODE; - } - - if(text_not_phonemes) - { - // this is replacement text, so don't encode as phonemes. Restrict the length of the replacement word - strncpy0(encoded_ph,phonetic,N_WORD_BYTES-4); - } - else - { - EncodePhonemes(phonetic,encoded_ph,bad_phoneme); - if(strchr(encoded_ph,phonSWITCH) != 0) - { - flag_codes[n_flag_codes++] = BITNUM_FLAG_ONLY_S; // don't match on suffixes (except 's') when switching languages - } - - // check for errors in the phonemes codes - for(ix=0; ix<sizeof(encoded_ph); ix++) - { - c = encoded_ph[ix]; - if(c == 0) break; - - if(c == 255) - { - /* unrecognised phoneme, report error */ - fprintf(f_log,"%5d: Bad phoneme [%c] (0x%x) in: %s %s\n",linenum,bad_phoneme[0],bad_phoneme[0],word,phonetic); - error_count++; - } - } - } - - if(sscanf(word,"U+%x",&wc) == 1) - { - // Character code - ix = utf8_out(wc, word); - word[ix] = 0; - } - else - if(word[0] != '_') - { - // convert to lower case, and note if the word is all-capitals - int c2; - - all_upper_case = 1; - p = word; - for(p=word;;) - { - // this assumes that the lower case char is the same length as the upper case char - // OK, except for Turkish "I", but use towlower() rather than towlower2() - ix = utf8_in(&c2,p); - if(c2 == 0) - break; - if(iswupper(c2)) - { - utf8_out(towlower(c2),p); - } - else - { - all_upper_case = 0; - } - p += ix; - } - if(all_upper_case) - { - flag_codes[n_flag_codes++] = BITNUM_FLAG_ALLCAPS; - } - } - - len_word = strlen(word); - - if(transpose_offset > 0) - { - len_word = TransposeAlphabet(word, transpose_offset, transpose_min, transpose_max); - } - - *hash = HashDictionary(word); - len_phonetic = strlen(encoded_ph); - - dict_line[1] = len_word; // bit 6 indicates whether the word has been compressed - len_word &= 0x3f; - - memcpy(&dict_line[2],word,len_word); - - if(len_phonetic == 0) - { - // no phonemes specified. set bit 7 - dict_line[1] |= 0x80; - length = len_word + 2; - } - else - { - length = len_word + len_phonetic + 3; - strcpy(&dict_line[(len_word)+2],encoded_ph); - } - - for(ix=0; ix<n_flag_codes; ix++) - { - dict_line[ix+length] = flag_codes[ix]; - } - length += n_flag_codes; - - if((multiple_string != NULL) && (multiple_words > 0)) - { - if(multiple_words > 10) - { - fprintf(f_log,"%5d: Two many parts in a multi-word entry: %d\n",linenum,multiple_words); - } - else - { - dict_line[length++] = 80 + multiple_words + multiple_numeric_hyphen; // if numeric, count a hyphen as an extra word - ix = multiple_string_end - multiple_string; - if(multiple_numeric_hyphen) - { - // the first part is numeric, so keep the hyphen to match on - dict_line[length++] = '-'; - dict_line[length++] = ' '; - } - memcpy(&dict_line[length],multiple_string,ix); - length += ix; - } - } - dict_line[0] = length; - -#ifdef OPT_FORMAT - spaces = 16; - for(ix=0; ix<n_flag_codes; ix++) - { - if(flag_codes[ix] >= 100) - { - fprintf(f_log,"?%d ",flag_codes[ix]-100); - spaces -= 3; - } - } - - fprintf(f_log,"%s",word); - spaces -= strlen(word); - DecodePhonemes(encoded_ph,decoded_ph); - while(spaces-- > 0) fputc(' ',f_log); - spaces += (14 - strlen(decoded_ph)); - - fprintf(f_log," %s",decoded_ph); - while(spaces-- > 0) fputc(' ',f_log); - for(ix=0; ix<n_flag_codes; ix++) - { - if(flag_codes[ix] < 100) - fprintf(f_log," %s",lookup_mnem(mnem_flags,flag_codes[ix])); - } - if(comment != NULL) - fprintf(f_log," %s",comment); - else - fputc('\n',f_log); -#endif - - return(length); -} /* end of compile_line */ - - - -static void compile_dictlist_start(void) -{//===================================== -// initialise dictionary list - int ix; - char *p; - char *p2; - - for(ix=0; ix<N_HASH_DICT; ix++) - { - p = hash_chains[ix]; - while(p != NULL) - { - memcpy(&p2,p,sizeof(char *)); - free(p); - p = p2; - } - hash_chains[ix] = NULL; - hash_counts[ix]=0; - } -} - - -static void compile_dictlist_end(FILE *f_out) -{//========================================== -// Write out the compiled dictionary list - int hash; - int length; - char *p; - - if(f_log != NULL) - { -#ifdef OUTPUT_FORMAT - for(hash=0; hash<N_HASH_DICT; hash++) - { - fprintf(f_log,"%8d",hash_counts[hash]); - if((hash & 7) == 7) - fputc('\n',f_log); - } - fflush(f_log); -#endif - } - - for(hash=0; hash<N_HASH_DICT; hash++) - { - p = hash_chains[hash]; - hash_counts[hash] = (int)ftell(f_out); - - while(p != NULL) - { - length = *(p+sizeof(char *)); - fwrite(p+sizeof(char *),length,1,f_out); - memcpy(&p,p,sizeof(char *)); - } - fputc(0,f_out); - } -} - - - -static int compile_dictlist_file(const char *path, const char* filename) -{//===================================================================== - int length; - int hash; - char *p; - int count=0; - FILE *f_in; - char buf[200]; - char fname[sizeof(path_home)+45]; - char dict_line[128]; - - text_mode = 0; - - sprintf(fname,"%s%s",path,filename); - if((f_in = fopen(fname,"r")) == NULL) - return(-1); - - fprintf(f_log,"Compiling: '%s'\n",fname); - - linenum=0; - - while(fgets(buf,sizeof(buf),f_in) != NULL) - { - linenum++; - - length = compile_line(buf,dict_line,&hash); - if(length == 0) continue; /* blank line */ - - hash_counts[hash]++; - - p = (char *)malloc(length+sizeof(char *)); - if(p == NULL) - { - if(f_log != NULL) - { - fprintf(f_log,"Can't allocate memory\n"); - error_count++; - } - break; - } - - memcpy(p,&hash_chains[hash],sizeof(char *)); - hash_chains[hash] = p; - memcpy(p+sizeof(char *),dict_line,length); - count++; - } - - fprintf(f_log,"\t%d entries\n",count); - fclose(f_in); - return(0); -} /* end of compile_dictlist_file */ - - - -static char rule_cond[80]; -static char rule_pre[80]; -static char rule_post[80]; -static char rule_match[80]; -static char rule_phonemes[80]; -static char group_name[LEN_GROUP_NAME+1]; - -#define N_RULES 2000 // max rules for each group - - - -static void copy_rule_string(char *string, int *state) -{//=================================================== -// 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 int next_state[5] = {2,2,4,4,4}; - char *output; - char *p; - int ix; - int len; - char c; - int sxflags; - int value; - int literal; - - if(string[0] == 0) return; - - output = outbuf[*state]; - if(*state==4) - { - // append to any previous phoneme string, i.e. allow spaces in the phoneme string - len = strlen(rule_phonemes); - if(len > 0) - rule_phonemes[len++] = ' '; - output = &rule_phonemes[len]; - } - sxflags = 0x808000; // to ensure non-zero bytes - - for(p=string,ix=0;;) - { - literal = 0; - c = *p++; - if(c == '\\') - { - c = *p++; // treat next character literally - if((c >= '0') && (c <= '3') && (p[0] >= '0') && (p[0] <= '7') && (p[1] >= '0') && (p[1] <= '7')) - { - // character code given by 3 digit octal value; - c = (c-'0')*64 + (p[0]-'0')*8 + (p[1]-'0'); - p += 2; - } - literal = 1; - } - - if(((*state)==1) || ((*state)==3)) - { - // replace special characters (note: 'E' is reserved for a replaced silent 'e') - if(literal == 0) - { - static const char lettergp_letters[9] = {LETTERGP_A,LETTERGP_B,LETTERGP_C,0,0,LETTERGP_F,LETTERGP_G,LETTERGP_H,LETTERGP_Y}; - switch(c) - { - case '_': - c = RULE_SPACE; - break; - - case 'Y': - c = 'I'; // drop through to next case - case 'A': // vowel - case 'B': - case 'C': - case 'H': - case 'F': - case 'G': - if((*state) == 1) - { - // pre-rule, put the number before the RULE_LETTERGP; - output[ix++] = lettergp_letters[c-'A'] + 'A'; - c = RULE_LETTERGP; - } - else - { - output[ix++] = RULE_LETTERGP; - c = lettergp_letters[c-'A'] + 'A'; - } - break; - case 'D': - c = RULE_DIGIT; - break; - case 'K': - c = RULE_NOTVOWEL; - break; - case 'N': - c = RULE_NO_SUFFIX; - break; - case 'V': - c = RULE_IFVERB; - break; - case 'Z': - c = RULE_NONALPHA; - break; - case '+': - c = RULE_INC_SCORE; - break; - case '@': - c = RULE_SYLLABLE; - break; - case '&': - c = RULE_STRESSED; - break; - case '%': - c = RULE_DOUBLE; - break; - case '#': - c = RULE_DEL_FWD; - break; - case '!': - c = RULE_CAPITAL; - break; - case 'T': - c = RULE_ALT1; - break; - case 'W': - c = RULE_SPELLING; - break; - case 'X': - c = RULE_NOVOWELS; - break; - case 'L': - // expect two digits - c = *p++ - '0'; - value = *p++ - '0'; - c = c * 10 + value; - if((value < 0) || (value > 9)) - { - c = 0; - fprintf(f_log,"%5d: Expected 2 digits after 'L'\n",linenum); - error_count++; - } - else - if((c <= 0) || (c >= N_LETTER_GROUPS) || (letterGroupsDefined[(int)c] == 0)) - { - fprintf(f_log,"%5d: Letter group L%.2d not defined\n",linenum,c); - error_count++; - } - c += 'A'; - if((*state) == 1) - { - // pre-rule, put the group number before the RULE_LETTERGP command - output[ix++] = c; - c = RULE_LETTERGP2; - } - else - { - output[ix++] = RULE_LETTERGP2; - } - break; - - case '$': // obsolete, replaced by S - fprintf(f_log,"%5d: $ now not allowed, use S for suffix",linenum); - error_count++; - break; - case 'P': - sxflags |= SUFX_P; // Prefix, now drop through to Suffix - case 'S': - output[ix++] = RULE_ENDING; - value = 0; - while(!isspace2(c = *p++) && (c != 0)) - { - switch(c) - { - case 'e': - sxflags |= SUFX_E; - break; - case 'i': - sxflags |= SUFX_I; - break; - case 'p': // obsolete, replaced by 'P' above - sxflags |= SUFX_P; - break; - case 'v': - sxflags |= SUFX_V; - break; - case 'd': - sxflags |= SUFX_D; - break; - case 'f': - sxflags |= SUFX_F; - break; - case 'q': - sxflags |= SUFX_Q; - break; - case 't': - sxflags |= SUFX_T; - break; - case 'b': - sxflags |= SUFX_B; - break; - default: - if(isdigit(c)) - value = (value*10) + (c - '0'); - break; - } - } - p--; - output[ix++] = sxflags >> 16; - output[ix++] = sxflags >> 8; - c = value | 0x80; - break; - } - } - } - output[ix++] = c; - if(c == 0) break; - } - - *state = next_state[*state]; -} // end of copy_rule_string - - - -static char *compile_rule(char *input) -{//=================================== - int ix; - unsigned char c; - int wc; - char *p; - char *prule; - int len; - int len_name; - int state=2; - int finish=0; - int pre_bracket=0; - char buf[80]; - char output[150]; - unsigned char bad_phoneme[4]; - - buf[0]=0; - rule_cond[0]=0; - rule_pre[0]=0; - rule_post[0]=0; - rule_match[0]=0; - rule_phonemes[0]=0; - - p = buf; - - for(ix=0; finish==0; ix++) - { - c = input[ix]; - - switch(c = input[ix]) - { - case ')': // end of prefix section - *p = 0; - state = 1; - pre_bracket = 1; - copy_rule_string(buf,&state); - p = buf; - break; - - case '(': // start of suffix section - *p = 0; - state = 2; - copy_rule_string(buf,&state); - state = 3; - p = buf; - break; - - case '\n': // end of line - case '\r': - case 0: // end of line - *p = 0; - copy_rule_string(buf,&state); - finish=1; - break; - - case '\t': // end of section section - case ' ': - *p = 0; - copy_rule_string(buf,&state); - p = buf; - break; - - case '?': - if(state==2) - state=0; - else - *p++ = c; - break; - - default: - *p++ = c; - break; - } - } - - if(strcmp(rule_match,"$group")==0) - strcpy(rule_match,group_name); - - if(rule_match[0]==0) - return(NULL); - - EncodePhonemes(rule_phonemes,buf,bad_phoneme); - for(ix=0;; ix++) - { - if((c = buf[ix])==0) break; - if(c==255) - { - fprintf(f_log,"%5d: Bad phoneme [%c] in %s",linenum,bad_phoneme[0],input); - error_count++; - break; - } - } - strcpy(output,buf); - len = strlen(buf)+1; - - len_name = strlen(group_name); - if((len_name > 0) && (memcmp(rule_match,group_name,len_name) != 0)) - { - utf8_in(&wc,rule_match); - if((group_name[0] == '9') && IsDigit(wc)) - { - // numeric group, rule_match starts with a digit, so OK - } - else - { - fprintf(f_log,"%5d: Wrong initial letters '%s' for group '%s'\n",linenum,rule_match,group_name); - error_count++; - } - } - strcpy(&output[len],rule_match); - len += strlen(rule_match); - - if(debug_flag) - { - output[len] = RULE_LINENUM; - output[len+1] = (linenum % 255) + 1; - output[len+2] = (linenum / 255) + 1; - len+=3; - } - - if(rule_cond[0] != 0) - { - ix = -1; - if(rule_cond[0] == '!') - { - // allow the rule only if the condition number is NOT set for the voice - ix = atoi(&rule_cond[1]) + 32; - } - else - { - // allow the rule only if the condition number is set for the voice - ix = atoi(rule_cond); - } - - if((ix > 0) && (ix < 255)) - { - output[len++] = RULE_CONDITION; - output[len++] = ix; - } - else - { - fprintf(f_log,"%5d: bad condition number ?%d\n",linenum,ix); - error_count++; - } - } - if(rule_pre[0] != 0) - { - output[len++] = RULE_PRE; - // output PRE string in reverse order - for(ix = strlen(rule_pre)-1; ix>=0; ix--) - output[len++] = rule_pre[ix]; - } - - if(rule_post[0] != 0) - { - sprintf(&output[len],"%c%s",RULE_POST,rule_post); - len += (strlen(rule_post)+1); - } - output[len++]=0; - prule = (char *)malloc(len); - memcpy(prule,output,len); - return(prule); -} // end of compile_rule - - -static int __cdecl string_sorter(char **a, char **b) -{//================================================= - char *pa, *pb; - int ix; - - if((ix = strcmp(pa = *a,pb = *b)) != 0) - return(ix); - pa += (strlen(pa)+1); - pb += (strlen(pb)+1); - return(strcmp(pa,pb)); -} /* end of string_sorter */ - - -static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b) -{//=================================================== - int ix; - ix = strcmp(a->name,b->name); - if(ix != 0) return(ix); - return(a->start-b->start); -} - - -#ifdef OUTPUT_FORMAT -static void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name) -{//============================================================================= - int rule; - int ix; - unsigned char c; - int len1; - int len2; - int spaces; - char *p; - char *pout; - int condition; - char buf[80]; - char suffix[12]; - - static unsigned char symbols[] = {'@','&','%','+','#','$','D','Z','A','B','C','F'}; - - fprintf(f_out,"\n$group %s\n",name); - - for(rule=0; rule<n_rules; rule++) - { - p = rules[rule]; - len1 = strlen(p) + 1; - p = &p[len1]; - len2 = strlen(p); - - rule_match[0]=0; - rule_pre[0]=0; - rule_post[0]=0; - condition = 0; - - pout = rule_match; - for(ix=0; ix<len2; ix++) - { - switch(c = p[ix]) - { - case RULE_PRE: - *pout = 0; - pout = rule_pre; - break; - case RULE_POST: - *pout = 0; - pout = rule_post; - break; - case RULE_CONDITION: - condition = p[++ix]; - break; - case RULE_ENDING: - sprintf(suffix,"$%d[%x]",(p[ix+2]),p[ix+1] & 0x7f); - ix += 2; - strcpy(pout,suffix); - pout += strlen(suffix); - break; - default: - if(c <= RULE_LETTER7) - c = symbols[c-RULE_SYLLABLE]; - if(c == ' ') - c = '_'; - *pout++ = c; - break; - } - } - *pout = 0; - - spaces = 12; - if(condition > 0) - { - sprintf(buf,"?%d ",condition); - spaces -= strlen(buf); - fprintf(f_out,"%s",buf); - } - - if(rule_pre[0] != 0) - { - p = buf; - for(ix=strlen(rule_pre)-1;ix>=0;ix--) - *p++ = rule_pre[ix]; - sprintf(p,") "); - spaces -= strlen(buf); - for(ix=0; ix<spaces; ix++) - fputc(' ',f_out); - fprintf(f_out,"%s",buf); - spaces = 0; - } - - for(ix=0; ix<spaces; ix++) - fputc(' ',f_out); - - spaces = 14; - sprintf(buf," %s ",rule_match); - if(rule_post[0] != 0) - { - p = &buf[strlen(buf)]; - sprintf(p,"(%s ",rule_post); - } - fprintf(f_out,"%s",buf); - spaces -= strlen(buf); - - for(ix=0; ix<spaces; ix++) - fputc(' ',f_out); - DecodePhonemes(rules[rule],buf); - fprintf(f_out,"%s\n",buf); // phonemes - } -} -#endif - - -//#define LIST_GROUP_INFO -static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name) -{//============================================================================== - int ix; - int len1; - int len2; - int len_name; - char *p; - char *p2, *p3; - const char *common; - - short nextchar_count[256]; - memset(nextchar_count,0,sizeof(nextchar_count)); - - len_name = strlen(name); - -#ifdef OUTPUT_FORMAT - print_rule_group(f_log,n_rules,rules,name); -#endif - - // sort the rules in this group by their phoneme string - common = ""; - qsort((void *)rules,n_rules,sizeof(char *),(int (__cdecl *)(const void *,const void *))string_sorter); - - if(strcmp(name,"9")==0) - len_name = 0; // don't remove characters from numeric match strings - - for(ix=0; ix<n_rules; ix++) - { - p = rules[ix]; - len1 = strlen(p) + 1; // phoneme string - p3 = &p[len1]; - p2 = p3 + len_name; // remove group name from start of match string - len2 = strlen(p2); - - nextchar_count[(unsigned char)(p2[0])]++; // the next byte after the group name - - if((common[0] != 0) && (strcmp(p,common)==0)) - { - fwrite(p2,len2,1,f_out); - fputc(0,f_out); // no phoneme string, it's the same as previous rule - } - else - { - if((ix < n_rules-1) && (strcmp(p,rules[ix+1])==0)) - { - common = rules[ix]; // phoneme string is same as next, set as common - fputc(RULE_PH_COMMON,f_out); - } - - fwrite(p2,len2,1,f_out); - fputc(RULE_PHONEMES,f_out); - fwrite(p,len1,1,f_out); - } - } - -#ifdef LIST_GROUP_INFO - for(ix=32; ix<256; ix++) - { - if(nextchar_count[ix] > 30) - printf("Group %s %c %d\n",name,ix,nextchar_count[ix]); - } -#endif -} // end of output_rule_group - - - -static int compile_lettergroup(char *input, FILE *f_out) -{//===================================================== - char *p; - char *p_start; - int group; - int ix; - int n_items; - int length; - int max_length = 0; - - #define N_LETTERGP_ITEMS 200 - char *items[N_LETTERGP_ITEMS]; - char item_length[N_LETTERGP_ITEMS]; - - p = input; - if(!isdigit(p[0]) || !isdigit(p[1])) - { - fprintf(f_log,"%5d: Expected 2 digits after '.L'\n",linenum); - error_count++; - return(1); - } - - group = atoi(&p[0]); - if(group >= N_LETTER_GROUPS) - { - fprintf(f_log,"%5d: lettergroup out of range (01-%.2d)\n",linenum,N_LETTER_GROUPS-1); - error_count++; - return(1); - } - - while(!isspace2(*p)) p++; - - fputc(RULE_GROUP_START,f_out); - fputc(RULE_LETTERGP2,f_out); - fputc(group + 'A', f_out); - if(letterGroupsDefined[group] != 0) - { - fprintf(f_log,"%5d: lettergroup L%.2d is already defined\n",linenum,group); - error_count++; - } - letterGroupsDefined[group] = 1; - - n_items = 0; - while(n_items < N_LETTERGP_ITEMS) - { - while(isspace2(*p)) p++; - if(*p == 0) - break; - - items[n_items] = p_start = p; - while((*p & 0xff) > ' ') - { - p++; - } - *p++ = 0; - length = p - p_start; - if(length > max_length) - max_length = length; - item_length[n_items++] = length; - } - - // write out the items, longest first - while(max_length > 1) - { - for(ix=0; ix < n_items; ix++) - { - if(item_length[ix] == max_length) - { - fwrite(items[ix],1,max_length,f_out); - } - } - max_length--; - } - - fputc(RULE_GROUP_END,f_out); - - return(0); -} - - -static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) -{//==================================================================== - char *prule; - unsigned char *p; - int ix; - int c; - int gp; - FILE *f_temp; - int n_rules=0; - int count=0; - int different; - const char *prev_rgroup_name; - unsigned int char_code; - int compile_mode=0; - char *buf; - char buf1[200]; - char *rules[N_RULES]; - - int n_rgroups = 0; - RGROUP rgroup[N_RULE_GROUP2]; - - linenum = 0; - group_name[0] = 0; - - if((f_temp = fopen_log(fname_temp,"wb")) == NULL) - return(1); - - for(;;) - { - linenum++; - buf = fgets(buf1,sizeof(buf1),f_in); - if(buf != NULL) - { - if((p = (unsigned char *)strstr(buf,"//")) != NULL) - *p = 0; - - if(buf[0] == '\r') buf++; // ignore extra \r in \r\n - } - - if((buf == NULL) || (buf[0] == '.')) - { - // next .group or end of file, write out the previous group - - if(n_rules > 0) - { - strcpy(rgroup[n_rgroups].name,group_name); - rgroup[n_rgroups].start = ftell(f_temp); - output_rule_group(f_temp,n_rules,rules,group_name); - rgroup[n_rgroups].length = ftell(f_temp) - rgroup[n_rgroups].start; - n_rgroups++; - - count += n_rules; - } - n_rules = 0; - - if(compile_mode == 2) - { - // end of the character replacements section - fwrite(&n_rules,1,4,f_out); // write a zero word to terminate the replacemenmt list - compile_mode = 0; - } - - if(buf == NULL) break; // end of file - - if(memcmp(buf,".L",2)==0) - { - compile_lettergroup(&buf[2], f_out); - continue; - } - - if(memcmp(buf,".replace",8)==0) - { - compile_mode = 2; - fputc(RULE_GROUP_START,f_out); - fputc(RULE_REPLACEMENTS,f_out); - - // advance to next word boundary - while((ftell(f_out) & 3) != 0) - fputc(0,f_out); - } - - if(memcmp(buf,".group",6)==0) - { - compile_mode = 1; - - p = (unsigned char *)&buf[6]; - while((p[0]==' ') || (p[0]=='\t')) p++; // Note: Windows isspace(0xe1) gives TRUE ! - ix = 0; - while((*p > ' ') && (ix < LEN_GROUP_NAME)) - group_name[ix++] = *p++; - group_name[ix]=0; - - if(sscanf(group_name,"0x%x",&char_code)==1) - { - // group character is given as a character code (max 16 bits) - p = (unsigned char *)group_name; - - if(char_code > 0x100) - { - *p++ = (char_code >> 8); - } - *p++ = char_code; - *p = 0; - } - - if(strlen(group_name) > 2) - { - if(utf8_in(&c,group_name) < 2) - { - fprintf(f_log,"%5d: Group name longer than 2 bytes (UTF8)",linenum); - error_count++; - } - - group_name[2] = 0; - } - } - - continue; - } - - switch(compile_mode) - { - case 1: // .group - prule = compile_rule(buf); - if((prule != NULL) && (n_rules < N_RULES)) - { - rules[n_rules++] = prule; - } - break; - - case 2: // .replace - { - int replace1; - int replace2; - char *p; - - p = buf; - replace1 = 0; - replace2 = 0; - while(isspace2(*p)) p++; - ix = 0; - while((unsigned char)(*p) > 0x20) // not space or zero-byte - { - p += utf8_in(&c,p); - replace1 += (c << ix); - ix += 16; - } - while(isspace2(*p)) p++; - ix = 0; - while((unsigned char)(*p) > 0x20) - { - p += utf8_in(&c,p); - replace2 += (c << ix); - ix += 16; - } - if(replace1 != 0) - { - Write4Bytes(f_out,replace1); // write as little-endian - Write4Bytes(f_out,replace2); // if big-endian, reverse the bytes in LoadDictionary() - } - } - break; - } - } - fclose(f_temp); - - qsort((void *)rgroup,n_rgroups,sizeof(rgroup[0]),(int (__cdecl *)(const void *,const void *))rgroup_sorter); - - if((f_temp = fopen(fname_temp,"rb"))==NULL) - return(2); - - prev_rgroup_name = "\n"; - - for(gp = 0; gp < n_rgroups; gp++) - { - fseek(f_temp,rgroup[gp].start,SEEK_SET); - - if((different = strcmp(rgroup[gp].name, prev_rgroup_name)) != 0) - { - // not the same as the previous group - if(gp > 0) - fputc(RULE_GROUP_END,f_out); - fputc(RULE_GROUP_START,f_out); - fprintf(f_out, prev_rgroup_name = rgroup[gp].name); - fputc(0,f_out); - } - - for(ix=rgroup[gp].length; ix>0; ix--) - { - c = fgetc(f_temp); - fputc(c,f_out); - } - - if(different) - { - } - } - fputc(RULE_GROUP_END,f_out); - fputc(0,f_out); - - fclose(f_temp); -#if 0 - remove(fname_temp); -#endif - - fprintf(f_log,"\t%d rules, %d groups\n\n",count,n_rgroups); - return(0); -} // end of compile_dictrules - - - -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 -// flags: bit 0: include source line number information, for debug purposes. - - FILE *f_in; - FILE *f_out; - int offset_rules=0; - int value; - char fname_in[sizeof(path_home)+45]; - char fname_out[sizeof(path_home)+15]; - char fname_temp[sizeof(path_home)+15]; - char path[sizeof(path_home)+40]; // path_dsource+20 - - error_count = 0; - memset(letterGroupsDefined,0,sizeof(letterGroupsDefined)); - - debug_flag = flags & 1; - - if(dsource == NULL) - dsource = ""; - - f_log = log; -//f_log = fopen("log2.txt","w"); - if(f_log == NULL) - f_log = stderr; - - sprintf(path,"%s%s_",dsource,dict_name); - sprintf(fname_in,"%srules",path); - f_in = fopen_log(fname_in,"r"); - if(f_in == NULL) - { - if(fname_err) - strcpy(fname_err,fname_in); - return(-1); - } - - sprintf(fname_out,"%s%c%s_dict",path_home,PATHSEP,dict_name); - if((f_out = fopen_log(fname_out,"wb+")) == NULL) - { - if(fname_err) - strcpy(fname_err,fname_in); - return(-1); - } - sprintf(fname_temp,"%s%ctemp",path_home,PATHSEP); - - transpose_offset = 0; - - if(strcmp(dict_name,"ru") == 0) - { - // transpose cyrillic alphabet from unicode to iso8859-5 -// transpose_offset = 0x430-0xd0; - transpose_offset = 0x42f; // range 0x01 to 0x22 - transpose_min = 0x430; - transpose_max = 0x451; - } - - value = N_HASH_DICT; - Write4Bytes(f_out,value); - Write4Bytes(f_out,offset_rules); - - compile_dictlist_start(); - - fprintf(f_log,"Using phonemetable: '%s'\n",phoneme_tab_list[phoneme_tab_number].name); - compile_dictlist_file(path,"roots"); - if(translator->langopts.listx) - { - compile_dictlist_file(path,"list"); - compile_dictlist_file(path,"listx"); - } - else - { - compile_dictlist_file(path,"listx"); - compile_dictlist_file(path,"list"); - } - compile_dictlist_file(path,"extra"); - - compile_dictlist_end(f_out); - offset_rules = ftell(f_out); - - fprintf(f_log,"Compiling: '%s'\n",fname_in); - - compile_dictrules(f_in,f_out,fname_temp); - fclose(f_in); - - fseek(f_out,4,SEEK_SET); - Write4Bytes(f_out,offset_rules); - fclose(f_out); - - LoadDictionary(translator, dict_name, 0); - - return(error_count); -} // end of compile_dictionary - diff --git a/navit/support/espeak/debug.c b/navit/support/espeak/debug.c deleted file mode 100644 index 38ea57c99..000000000 --- a/navit/support/espeak/debug.c +++ /dev/null @@ -1,74 +0,0 @@ -#include <stdio.h> -#include <stdarg.h> -#include "speech.h" -#include "debug.h" - -#ifdef DEBUG_ENABLED -#include <sys/time.h> -#include <unistd.h> - -static FILE* fd_log=NULL; -static const char* FILENAME="/tmp/espeak.log"; - -void debug_init() -{ - if((fd_log = fopen(FILENAME,"a")) != NULL) - setvbuf(fd_log, NULL, _IONBF, 0); -} - -void debug_enter(const char* text) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - // fd_log = fopen(FILENAME,"a"); - if (!fd_log) - { - debug_init(); - } - - if (fd_log) - { - fprintf(fd_log, "%03d.%03dms > ENTER %s\n",(int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text); - // fclose(fd_log); - } -} - - -void debug_show(const char *format, ...) -{ - va_list args; - va_start(args, format); - // fd_log = fopen(FILENAME,"a"); - if (!fd_log) - { - debug_init(); - } - if (fd_log) - { - vfprintf(fd_log, format, args); - // fclose(fd_log); - } - va_end(args); -} - -void debug_time(const char* text) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - // fd_log = fopen(FILENAME,"a"); - if (!fd_log) - { - debug_init(); - } - if (fd_log) - { - fprintf(fd_log, "%03d.%03dms > %s\n",(int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text); - // fclose(fd_log); - } -} - -#endif diff --git a/navit/support/espeak/debug.h b/navit/support/espeak/debug.h deleted file mode 100644 index c3fb9c920..000000000 --- a/navit/support/espeak/debug.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef DEBUG_H -#define DEBUG_H - -//#define DEBUG_ENABLED - -#ifdef DEBUG_ENABLED -#define ENTER(text) debug_enter(text) -#define SHOW(format,...) debug_show(format,__VA_ARGS__); -#define SHOW_TIME(text) debug_time(text); -extern void debug_enter(const char* text); -extern void debug_show(const char* format,...); -extern void debug_time(const char* text); - -#else - -#ifdef PLATFORM_WINDOWS -#define SHOW(format) // VC6 doesn't allow "..." -#else -#define SHOW(format,...) -#endif -#define SHOW_TIME(text) -#define ENTER(text) -#endif - - -#endif diff --git a/navit/support/espeak/dictionary.c b/navit/support/espeak/dictionary.c deleted file mode 100755 index d7dd3dc65..000000000 --- a/navit/support/espeak/dictionary.c +++ /dev/null @@ -1,3490 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#define LOG_TRANSLATE - -#include <stdio.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#include <wctype.h> -#include <wchar.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "translate.h" - - -int dictionary_skipwords; -char dictionary_name[40]; - -extern char *print_dictionary_flags(unsigned int *flags); - -// accented characters which indicate (in some languages) the start of a separate syllable -//static const unsigned short diereses_list[7] = {L'ä',L'ë',L'ï',L'ö',L'ü',L'ÿ',0}; -static const unsigned short diereses_list[7] = {0xe4,0xeb,0xef,0xf6,0xfc,0xff,0}; - -// convert characters to an approximate 7 bit ascii equivalent -// used for checking for vowels -static unsigned char remove_accent[] = { -'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i', // 0c0 -'d','n','o','o','o','o','o', 0, 'o','u','u','u','u','y','t','s', // 0d0 -'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i', // 0e0 -'d','n','o','o','o','o','o', 0 ,'o','u','u','u','u','y','t','y', // 0f0 - -'a','a','a','a','a','a','c','c','c','c','c','c','c','c','d','d', // 100 -'d','d','e','e','e','e','e','e','e','e','e','e','g','g','g','g', // 110 -'g','g','g','g','h','h','h','h','i','i','i','i','i','i','i','i', // 120 -'i','i','i','i','j','j','k','k','k','l','l','l','l','l','l','l', // 130 -'l','l','l','n','n','n','n','n','n','n','n','n','o','o','o','o', // 140 -'o','o','o','o','r','r','r','r','r','r','s','s','s','s','s','s', // 150 -'s','s','t','t','t','t','t','t','u','u','u','u','u','u','u','u', // 160 -'u','u','u','u','w','w','y','y','y','z','z','z','z','z','z','s', // 170 -'b','b','b','b', 0, 0, 'o','c','c','d','d','d','d','d','e','e', // 180 -'e','f','f','g','g','h','i','i','k','k','l','l','m','n','n','o', // 190 -'o','o','o','o','p','p','y', 0, 0, 's','s','t','t','t','t','u', // 1a0 -'u','u','v','y','y','z','z','z','z','z','z','z', 0, 0, 0, 'w', // 1b0 -'t','t','t','k','d','d','d','l','l','l','n','n','n','a','a','i', // 1c0 -'i','o','o','u','u','u','u','u','u','u','u','u','u','e','a','a', // 1d0 -'a','a','a','a','g','g','g','g','k','k','o','o','o','o','z','z', // 1e0 -'j','d','d','d','g','g','w','w','n','n','a','a','a','a','o','o', // 1f0 - -'a','a','a','a','e','e','e','e','i','i','i','i','o','o','o','o', // 200 -'r','r','r','r','u','u','u','u','s','s','t','t','y','y','h','h', // 210 -'n','d','o','o','z','z','a','a','e','e','o','o','o','o','o','o', // 220 -'o','o','y','y','l','n','t','j','d','q','a','c','c','l','t','s', // 230 -'z', 0 }; - - - - -void strncpy0(char *to,const char *from, int size) -{//=============================================== - // strcpy with limit, ensures a zero terminator - strncpy(to,from,size); - to[size-1] = 0; -} - - -static int reverse_word_bytes(int word) -{//============================= - // reverse the order of bytes from little-endian to big-endian -#ifdef ARCH_BIG - int ix; - int word2 = 0; - - for(ix=0; ix<=24; ix+=8) - { - word2 = word2 << 8; - word2 |= (word >> ix) & 0xff; - } - return(word2); -#else - return(word); -#endif -} - - -int LookupMnem(MNEM_TAB *table, char *string) -{//========================================== - while(table->mnem != NULL) - { - if(strcmp(string,table->mnem)==0) - return(table->value); - table++; - } - return(table->value); -} - - - -//============================================================================================= -// Read pronunciation rules and pronunciation lookup dictionary -// -//============================================================================================= - - -static void InitGroups(Translator *tr) -{//=================================== -/* Called after dictionary 1 is loaded, to set up table of entry points for translation rule chains - for single-letters and two-letter combinations -*/ - - int ix; - char *p; - char *p_name; - unsigned int *pw; - unsigned char c, c2; - int len; - - tr->n_groups2 = 0; - for(ix=0; ix<256; ix++) - { - tr->groups1[ix]=NULL; - tr->groups2_count[ix]=0; - tr->groups2_start[ix]=255; // indicates "not set" - } - memset(tr->letterGroups,0,sizeof(tr->letterGroups)); - - p = tr->data_dictrules; - while(*p != 0) - { - if(*p != RULE_GROUP_START) - { - fprintf(stderr,"Bad rules data in '%s_dict' at 0x%x\n",dictionary_name,(unsigned int)(p - tr->data_dictrules)); - break; - } - p++; - - if(p[0] == RULE_REPLACEMENTS) - { - pw = (unsigned int *)(((long)p+4) & ~3); // advance to next word boundary - tr->langopts.replace_chars = pw; - while(pw[0] != 0) - { - pw += 2; // find the end of the replacement list, each entry is 2 words. - } - p = (char *)(pw+1); - -#ifdef ARCH_BIG - pw = (unsigned int *)(tr->langopts.replace_chars); - while(*pw != 0) - { - *pw = reverse_word_bytes(*pw); - pw++; - *pw = reverse_word_bytes(*pw); - pw++; - } -#endif - continue; - } - - if(p[0] == RULE_LETTERGP2) - { - ix = p[1] - 'A'; - p += 2; - if((ix >= 0) && (ix < N_LETTER_GROUPS)) - { - tr->letterGroups[ix] = p; - } - } - else - { - len = strlen(p); - p_name = p; - c = p_name[0]; - - p += (len+1); - if(len == 1) - { - tr->groups1[c] = p; - } - else - if(len == 0) - { - tr->groups1[0] = p; - } - else - { - if(tr->groups2_start[c] == 255) - tr->groups2_start[c] = tr->n_groups2; - - tr->groups2_count[c]++; - tr->groups2[tr->n_groups2] = p; - c2 = p_name[1]; - tr->groups2_name[tr->n_groups2++] = (c + (c2 << 8)); - } - } - - // skip over all the rules in this group - while(*p != RULE_GROUP_END) - { - p += (strlen(p) + 1); - } - p++; - } - -} // end of InitGroups - - - -int LoadDictionary(Translator *tr, const char *name, int no_error) -{//=============================================================== - int hash; - char *p; - int *pw; - int length; - FILE *f; - unsigned int size; - char fname[sizeof(path_home)+20]; - - strcpy(dictionary_name,name); // currently loaded dictionary name - - if(no_error) // don't load dictionary, just set the dictionary_name - return(1); - - // Load a pronunciation data file into memory - // bytes 0-3: offset to rules data - // bytes 4-7: number of hash table entries - sprintf(fname,"%s%c%s_dict",path_home,PATHSEP,name); - size = GetFileLength(fname); - - f = fopen(fname,"rb"); - if((f == NULL) || (size <= 0)) - { - if(no_error == 0) - { - fprintf(stderr,"Can't read dictionary file: '%s'\n",fname); - } - return(1); - } - - if(tr->data_dictlist != NULL) - Free(tr->data_dictlist); - - tr->data_dictlist = Alloc(size); - fread(tr->data_dictlist,size,1,f); - fclose(f); - - - pw = (int *)(tr->data_dictlist); - length = reverse_word_bytes(pw[1]); - - if(size <= (N_HASH_DICT + sizeof(int)*2)) - { - fprintf(stderr,"Empty _dict file: '%s\n",fname); - return(2); - } - - if((reverse_word_bytes(pw[0]) != N_HASH_DICT) || - (length <= 0) || (length > 0x8000000)) - { - fprintf(stderr,"Bad data: '%s' (%x length=%x)\n",fname,reverse_word_bytes(pw[0]),length); - return(2); - } - tr->data_dictrules = &(tr->data_dictlist[length]); - - // set up indices into data_dictrules - InitGroups(tr); - if(tr->groups1[0] == NULL) - { - fprintf(stderr,"Error in %s_rules, no default rule group\n",name); - } - - // set up hash table for data_dictlist - p = &(tr->data_dictlist[8]); - - for(hash=0; hash<N_HASH_DICT; hash++) - { - tr->dict_hashtab[hash] = p; - while((length = *p) != 0) - { - p += length; - } - p++; // skip over the zero which terminates the list for this hash value - } - - return(0); -} // end of LoadDictionary - - -int HashDictionary(const char *string) -//==================================== -/* Generate a hash code from the specified string - This is used to access the dictionary_2 word-lookup dictionary -*/ -{ - int c; - int chars=0; - int hash=0; - - while((c = (*string++ & 0xff)) != 0) - { - hash = hash * 8 + c; - hash = (hash & 0x3ff) ^ (hash >> 8); /* exclusive or */ - chars++; - } - - return((hash+chars) & 0x3ff); // a 10 bit hash code -} // end of HashDictionary - - - -//============================================================================================= -// Translate between internal representation of phonemes and a mnemonic form for display -// -//============================================================================================= - - - -char *EncodePhonemes(char *p, char *outptr, unsigned char *bad_phoneme) -/*********************************************************************/ -/* Translate a phoneme string from ascii mnemonics to internal phoneme numbers, - from 'p' up to next blank . - Returns advanced 'p' - outptr contains encoded phonemes, unrecognised phonemes are encoded as 255 - bad_phoneme must point to char array of length 2 of more -*/ -{ - int ix; - unsigned char c; - int count; /* num. of matching characters */ - int max; /* highest num. of matching found so far */ - int max_ph; /* corresponding phoneme with highest matching */ - int consumed; - unsigned int mnemonic_word; - - bad_phoneme[0] = 0; - - // skip initial blanks - while(isspace(*p)) - { - p++; - } - - while(((c = *p) != 0) && !isspace(c)) - { - consumed = 0; - - switch(c) - { - case '|': - // used to separate phoneme mnemonics if needed, to prevent characters being treated - // as a multi-letter mnemonic - - if((c = p[1]) == '|') - { - // treat double || as a word-break symbol, drop through - // to the default case with c = '|' - } - else - { - p++; - break; - } - - default: - // lookup the phoneme mnemonic, find the phoneme with the highest number of - // matching characters - max= -1; - max_ph= 0; - - for(ix=1; ix<n_phoneme_tab; ix++) - { - if(phoneme_tab[ix] == NULL) - continue; - if(phoneme_tab[ix]->type == phINVALID) - continue; // this phoneme is not defined for this language - - count = 0; - mnemonic_word = phoneme_tab[ix]->mnemonic; - - while(((c = p[count]) > ' ') && (count < 4) && - (c == ((mnemonic_word >> (count*8)) & 0xff))) - count++; - - if((count > max) && - ((count == 4) || (((mnemonic_word >> (count*8)) & 0xff)==0))) - { - max = count; - max_ph = phoneme_tab[ix]->code; - } - } - - if(max_ph == 0) - { - max_ph = 255; /* not recognised */ - bad_phoneme[0] = *p; - bad_phoneme[1] = 0; - } - - if(max <= 0) - max = 1; - p += (consumed + max); - *outptr++ = (char)(max_ph); - - if(max_ph == phonSWITCH) - { - // Switch Language: this phoneme is followed by a text string - char *p_lang = outptr; - while(!isspace(c = *p) && (c != 0)) - { - p++; - *outptr++ = tolower(c); - } - *outptr = 0; - if(c == 0) - { - if(strcmp(p_lang,"en")==0) - { - *p_lang = 0; // don't need "en", it's assumed by default - return(p); - } - } - else - { - *outptr++ = '|'; // more phonemes follow, terminate language string with separator - } - } - break; - } - } - /* terminate the encoded string */ - *outptr = 0; - return(p); -} // end of EncodePhonemes - - - -void DecodePhonemes(const char *inptr, char *outptr) -//================================================== -// Translate from internal phoneme codes into phoneme mnemonics -{ - unsigned char phcode; - unsigned char c; - unsigned int mnem; - PHONEME_TAB *ph; - static const char *stress_chars = "==,,'* "; - - while((phcode = *inptr++) > 0) - { - if(phcode == 255) - continue; /* indicates unrecognised phoneme */ - if((ph = phoneme_tab[phcode]) == NULL) - continue; - - if((ph->type == phSTRESS) && (ph->std_length <= 4) && (ph->spect == 0)) - { - if(ph->std_length > 1) - *outptr++ = stress_chars[ph->std_length]; - } - else - { - mnem = ph->mnemonic; - - while((c = (mnem & 0xff)) != 0) - { - *outptr++ = c; - mnem = mnem >> 8; - } - if(phcode == phonSWITCH) - { - while(isalpha(*inptr)) - { - *outptr++ = *inptr++; - } - } - } - } - *outptr = 0; /* string terminator */ -} // end of DecodePhonemes - - - -static void WriteMnemonic(char *phon_out, int *ix, int mnem) -{//========================================================= - unsigned char c; - - while((c = mnem & 0xff) != 0) - { - if((c == '/') && (option_phoneme_variants==0)) - break; // discard phoneme variant indicator - phon_out[(*ix)++]= c; - // phon_out[phon_out_ix++]= ipa1[c]; - mnem = mnem >> 8; - } -} - - - -void GetTranslatedPhonemeString(char *phon_out, int n_phon_out) -{//============================================================ -/* Can be called after a clause has been translated into phonemes, in order - to display the clause in phoneme mnemonic form. -*/ - - int ix; - int phon_out_ix=0; - int stress; - char *p; - PHONEME_LIST *plist; - - static const char *stress_chars = "==,,''"; - - if(phon_out != NULL) - { - for(ix=1; ix<(n_phoneme_list-2) && (phon_out_ix < (n_phon_out - 6)); ix++) - { - plist = &phoneme_list[ix]; - if(plist->newword) - phon_out[phon_out_ix++] = ' '; - - if(plist->synthflags & SFLAG_SYLLABLE) - { - if((stress = plist->stresslevel) > 1) - { - if(stress > 5) stress = 5; - phon_out[phon_out_ix++] = stress_chars[stress]; - } - } - WriteMnemonic(phon_out, &phon_out_ix, plist->ph->mnemonic); - - if(plist->synthflags & SFLAG_LENGTHEN) - { - WriteMnemonic(phon_out, &phon_out_ix, phoneme_tab[phonLENGTHEN]->mnemonic); - } - if((plist->synthflags & SFLAG_SYLLABLE) && (plist->type != phVOWEL)) - { - // syllablic consonant - WriteMnemonic(phon_out, &phon_out_ix, phoneme_tab[phonSYLLABIC]->mnemonic); - } - if(plist->ph->code == phonSWITCH) - { - // the tone_ph field contains a phoneme table number - p = phoneme_tab_list[plist->tone_ph].name; - while(*p != 0) - { - phon_out[phon_out_ix++] = *p++; - } - phon_out[phon_out_ix++] = ' '; - } - else - if(plist->tone_ph > 0) - { - WriteMnemonic(phon_out, &phon_out_ix, phoneme_tab[plist->tone_ph]->mnemonic); - } - } - - if(phon_out_ix >= n_phon_out) - phon_out_ix = n_phon_out - 1; - phon_out[phon_out_ix] = 0; - } -} // 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) -{//===================================================================== - // match the word against a list of utf-8 strings - char *p; - char *w; - int len=0; - - p = tr->letterGroups[group]; - if(p == NULL) - return(0); - - while(*p != RULE_GROUP_END) - { - if(pre) - { - len = strlen(p); - w = word - len + 1; - } - else - { - w = word; - } - while(*p == *w) - { - w++; - p++; - } - if(*p == 0) - { - if(pre) - return(len); - return(w-word); // matched a complete string - } - - while(*p++ != 0); // skip to end of string - } - return(0); -} - - -static int IsLetter(Translator *tr, int letter, int group) -{//======================================================= - int letter2; - - if(tr->letter_groups[group] != NULL) - { - if(wcschr(tr->letter_groups[group],letter)) - return(1); - return(0); - } - - if(group > 7) - return(0); - - if(tr->letter_bits_offset > 0) - { - if(((letter2 = (letter - tr->letter_bits_offset)) > 0) && (letter2 < 0x80)) - letter = letter2; - else - return(0); - } - else - { - if((letter >= 0xc0) && (letter <= 0x241)) - return(tr->letter_bits[remove_accent[letter-0xc0]] & (1L << group)); - } - - if((letter >= 0) && (letter < 0x80)) - return(tr->letter_bits[letter] & (1L << group)); - - return(0); -} - - -static int IsVowel(Translator *tr, int letter) -{//=========================================== - return(IsLetter(tr, letter, 0)); -} - - - - -static int Unpronouncable_en(Translator *tr, char *word) -{//===================================================== -/* Determines whether a word in 'unpronouncable', i.e. whether it should - be spoken as individual letters. - - This function is language specific. -*/ - - int c; - int vowel_posn=9; - int index; - int count; - int ix; - int apostrophe=0; - - static unsigned char initials_bitmap[86] = { - 0x00, 0x00, 0x00, 0x00, 0x22, 0x08, 0x00, 0x88, // 0 - 0x20, 0x24, 0x20, 0x80, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x08, 0x00, 0x88, 0x22, 0x04, 0x00, // 16 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x88, 0x22, 0x04, 0x00, 0x02, 0x00, 0x04, // 32 - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x8a, 0x03, 0x00, 0x00, 0x40, 0x00, // 48 - 0x02, 0x00, 0x41, 0xca, 0xbb, 0x06, 0x20, 0x80, - 0x91, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, // 64 - 0x08, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, }; - - - // words which we pass through to the dictionary, even though they look unpronouncable - static const char *exceptions[] = { - "'s ", "st ","nd ","rd ","th ",NULL }; - - if((*word == ' ') || (*word == 0)) - return(0); - - for(ix=0; exceptions[ix] != NULL; ix++) - { - // Seemingly uncpronouncable words, but to be looked in the dictionary rules instead - if(memcmp(word,exceptions[ix],3)==0) - return(0); - } - - index=0; - count=0; - for(;;) - { - index += utf8_in(&c,&word[index]); - count++; - - if((c==0) || (c==' ')) - break; - - if(IsVowel(tr, c) || (c == 'y')) - { - vowel_posn = count; - break; - } - - if(c == '\'') - apostrophe = 1; - else - if(!IsAlpha(c)) - return(0); // letter (not vowel) outside Latin character range or apostrophe, abort test - } - if((vowel_posn > 5) || ((word[0]!='s') && (vowel_posn > 4))) - return(1); // no vowel, or no vowel in first four letters - - /* there is at least one vowel, is the initial letter combination valid ? */ - - if(vowel_posn < 3) - return(0); /* vowel in first two letters, OK */ - - if(apostrophe) - return(0); // first two letters not a-z, abort test - - index = (word[0]-'a') * 26 + (word[1]-'a'); - if(initials_bitmap[index >> 3] & (1L << (index & 7))) - return(0); - else - return(1); /****/ -} /* end of Unpronounceable */ - - - - -int Unpronouncable(Translator *tr, char *word) -{//=========================================== -/* Determines whether a word in 'unpronouncable', i.e. whether it should - be spoken as individual letters. - - This function may be language specific. This is a generic version. -*/ - - int c; - int c1=0; - int vowel_posn=9; - int index; - int count; - int apostrophe=0; - - if(tr->translator_name == L('e','n')) - { - return(Unpronouncable_en(tr,word)); - } - - utf8_in(&c,word); - if((tr->letter_bits_offset > 0) && (c < 0x241)) - { - // Latin characters for a language with a non-latin alphabet - return(0); // so we can re-translate the word as English - } - - if(tr->langopts.param[LOPT_UNPRONOUNCABLE] == 1) - return(0); - - if((*word == ' ') || (*word == 0)) - return(0); - - index = 0; - count = 0; - for(;;) - { - index += utf8_in(&c,&word[index]); - if((c==0) || (c==' ')) - break; - - if(count==0) - c1 = c; - count++; - - if(IsVowel(tr, c)) - { - vowel_posn = count; // position of the first vowel - break; - } - - if(c == '\'') - apostrophe = 1; - else - if(!iswalpha(c)) - return(0); // letter (not vowel) outside a-z range or apostrophe, abort test - } - - if((vowel_posn < 9) && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 2)) - return(0); // option means allow any word with a vowel - - if(c1 == tr->langopts.param[LOPT_UNPRONOUNCABLE]) - vowel_posn--; // disregard this as the initial letter when counting - - if(vowel_posn > (tr->langopts.max_initial_consonants+1)) - return(1); // no vowel, or no vowel in first four letters - -return(0); - -} /* end of Unpronounceable */ - - - -//============================================================================================= -// Determine the stress pattern of a word -// -//============================================================================================= - - - -static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char *vowel_stress, int *vowel_count, int *stressed_syllable, int control) -{//==================================================================================================================================================== -// control = 1, set stress to 1 for forced unstressed vowels - unsigned char phcode; - PHONEME_TAB *ph; - unsigned char *ph_out = phonemes; - int count = 1; - int max_stress = 0; - int ix; - int j; - int stress = 0; - int primary_posn = 0; - - vowel_stress[0] = 0; - while(((phcode = *phonemes++) != 0) && (count < (N_WORD_PHONEMES/2)-1)) - { - if((ph = phoneme_tab[phcode]) == NULL) - continue; - - if((ph->type == phSTRESS) && (ph->spect == 0)) - { - /* stress marker, use this for the following vowel */ - - if(phcode == phonSTRESS_PREV) - { - /* primary stress on preceeding vowel */ - j = count - 1; - while((j > 0) && (*stressed_syllable == 0) && (vowel_stress[j] < 4)) - { - if(vowel_stress[j] != 1) - { - // don't promote a phoneme which must be unstressed - vowel_stress[j] = 4; - - if(max_stress < 4) - { - max_stress = 4; - primary_posn = j; - } - - /* reduce any preceding primary stress markers */ - for(ix=1; ix<j; ix++) - { - if(vowel_stress[ix] == 4) - vowel_stress[ix] = 3; - } - break; - } - j--; - } - } - else - { - if((ph->std_length < 4) || (*stressed_syllable == 0)) - { - stress = ph->std_length; - - if(stress > max_stress) - max_stress = stress; - } - } - continue; - } - - if((ph->type == phVOWEL) && !(ph->phflags & phNONSYLLABIC)) - { - vowel_stress[count] = (char)stress; - if((stress >= 4) && (stress >= max_stress)) - { - primary_posn = count; - max_stress = stress; - } - - if((stress == 0) && (control & 1) && (ph->phflags & phUNSTRESSED)) - vowel_stress[count] = 1; /* weak vowel, must be unstressed */ - - count++; - stress = 0; - } - else - if(phcode == phonSYLLABIC) - { - // previous consonant phoneme is syllablic - vowel_stress[count] = (char)stress; - if((stress == 0) && (control & 1)) - vowel_stress[count++] = 1; // syllabic consonant, usually unstressed - } - - *ph_out++ = phcode; - } - vowel_stress[count] = 0; - *ph_out = 0; - - /* has the position of the primary stress been specified by $1, $2, etc? */ - if(*stressed_syllable > 0) - { - if(*stressed_syllable >= count) - *stressed_syllable = count-1; // the final syllable - - vowel_stress[*stressed_syllable] = 4; - max_stress = 4; - primary_posn = *stressed_syllable; - } - - if(max_stress == 5) - { - // priority stress, replaces any other primary stress marker - for(ix=1; ix<count; ix++) - { - if(vowel_stress[ix] == 4) - { - if(tr->langopts.stress_flags & 0x20000) - vowel_stress[ix] = 0; - else - vowel_stress[ix] = 3; - } - - if(vowel_stress[ix] == 5) - { - vowel_stress[ix] = 4; - primary_posn = ix; - } - } - max_stress = 4; - } - - *stressed_syllable = primary_posn; - *vowel_count = count; - return(max_stress); -} // end of GetVowelStress - - - -static char stress_phonemes[] = {phonSTRESS_U, phonSTRESS_D, phonSTRESS_2, phonSTRESS_3, - phonSTRESS_P, phonSTRESS_P2, phonSTRESS_TONIC}; - - -void ChangeWordStress(Translator *tr, char *word, int new_stress) -{//============================================================== - int ix; - unsigned char *p; - int max_stress; - int vowel_count; // num of vowels + 1 - int stressed_syllable=0; // position of stressed syllable - unsigned char phonetic[N_WORD_PHONEMES]; - unsigned char vowel_stress[N_WORD_PHONEMES/2]; - - strcpy((char *)phonetic,word); - max_stress = GetVowelStress(tr, phonetic, vowel_stress, &vowel_count, &stressed_syllable, 0); - - if(new_stress >= 4) - { - // promote to primary stress - for(ix=1; ix<vowel_count; ix++) - { - if(vowel_stress[ix] >= max_stress) - { - vowel_stress[ix] = new_stress; - break; - } - } - } - else - { - // remove primary stress - for(ix=1; ix<vowel_count; ix++) - { - if(vowel_stress[ix] > new_stress) // >= allows for diminished stress (=1) - vowel_stress[ix] = new_stress; - } - } - - // write out phonemes - ix = 1; - p = phonetic; - while(*p != 0) - { - if((phoneme_tab[*p]->type == phVOWEL) && !(phoneme_tab[*p]->phflags & phNONSYLLABIC)) - { - if(vowel_stress[ix] != 0) - *word++ = stress_phonemes[vowel_stress[ix]]; - - ix++; - } - *word++ = *p++; - } - *word = 0; -} // end of ChangeWordStress - - - -void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int prev_stress) -{//========================================================================================================= -/* Guess stress pattern of word. This is language specific - - 'dictionary_flags' has bits 0-3 position of stressed vowel (if > 0) - or unstressed (if == 7) or syllables 1 and 2 (if == 6) - bits 8... dictionary flags - - If 'tonic' is set (>= 0), replace highest stress by this value. - - Parameter used for input and output -*/ - - unsigned char phcode; - unsigned char *p; - PHONEME_TAB *ph; - int stress; - int max_stress; - int vowel_count; // num of vowels + 1 - int ix; - int v; - int v_stress; - int stressed_syllable; // position of stressed syllable - int max_stress_posn; - int unstressed_word = 0; - char *max_output; - int final_ph; - int final_ph2; - int mnem; - int mnem2; - int post_tonic; - int opt_length; - int done; - int stressflags; - - unsigned char vowel_stress[N_WORD_PHONEMES/2]; - char syllable_weight[N_WORD_PHONEMES/2]; - char vowel_length[N_WORD_PHONEMES/2]; - unsigned char phonetic[N_WORD_PHONEMES]; - - static char consonant_types[16] = {0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0}; - - - /* stress numbers STRESS_BASE + - 0 diminished, unstressed within a word - 1 unstressed, weak - 2 - 3 secondary stress - 4 main stress */ - - stressflags = tr->langopts.stress_flags; - - /* copy input string into internal buffer */ - for(ix=0; ix<N_WORD_PHONEMES; ix++) - { - phonetic[ix] = output[ix]; - // check for unknown phoneme codes - if(phonetic[ix] >= n_phoneme_tab) - phonetic[ix] = phonSCHWA; - if(phonetic[ix] == 0) - break; - } - if(ix == 0) return; - final_ph = phonetic[ix-1]; - final_ph2 = phonetic[ix-2]; - - max_output = output + (N_WORD_PHONEMES-3); /* check for overrun */ - - // any stress position marked in the xx_list dictionary ? - stressed_syllable = (*dictionary_flags) & 0x7; - if((*dictionary_flags) & 0x8) - { - // this indicates a word without a primary stress - stressed_syllable = (*dictionary_flags) & 0x3; - unstressed_word = 1; - } - - max_stress = GetVowelStress(tr, phonetic, vowel_stress, &vowel_count, &stressed_syllable, 1); - - if((max_stress == 0) && (tr->langopts.stress_flags & 1) && (vowel_count == 2)) - { - // option: don't stress monosyllables except at end-of-clause - vowel_stress[1] = 1; - (*dictionary_flags) |= FLAG_STRESS_END2; - } - - // heavy or light syllables - ix = 1; - for(p = phonetic; *p != 0; p++) - { - if((phoneme_tab[p[0]]->type == phVOWEL) && !(phoneme_tab[p[0]]->phflags & phNONSYLLABIC)) - { - int weight = 0; - int lengthened = 0; - - if(phoneme_tab[p[1]]->code == phonLENGTHEN) - lengthened = 1; - - if(lengthened || (phoneme_tab[p[0]]->phflags & phLONG)) - { - // long vowel, increase syllable weight - weight++; - } - vowel_length[ix] = weight; - - if(lengthened) p++; // advance over phonLENGTHEN - - if(consonant_types[phoneme_tab[p[1]]->type] && ((phoneme_tab[p[2]]->type != phVOWEL) || (phoneme_tab[p[1]]->phflags & phLONG))) - { - // followed by two consonants, a long consonant, or consonant and end-of-word - weight++; - } - syllable_weight[ix] = weight; - ix++; - } - } - - switch(tr->langopts.stress_rule) - { - case 8: - // stress on first syllable, unless it is a light syllable - if(syllable_weight[1] > 0) - break; - // else drop through to case 1 - case 1: - // stress on second syllable - if((stressed_syllable == 0) && (vowel_count > 2)) - { - stressed_syllable = 2; - if(max_stress == 0) - { - vowel_stress[stressed_syllable] = 4; - } - max_stress = 4; - } - break; - - case 2: - // a language with stress on penultimate vowel - - if(stressed_syllable == 0) - { - /* no explicit stress - stress the penultimate vowel */ - max_stress = 4; - - if(vowel_count > 2) - { - stressed_syllable = vowel_count - 2; - - if(stressflags & 0x300) - { - // LANG=Spanish, stress on last vowel if the word ends in a consonant other than 'n' or 's' - if(phoneme_tab[final_ph]->type != phVOWEL) - { - if(stressflags & 0x100) - { - stressed_syllable = vowel_count - 1; - } - else - { - mnem = phoneme_tab[final_ph]->mnemonic; - mnem2 = phoneme_tab[final_ph2]->mnemonic; - - if((mnem == 's') && (mnem2 == 'n')) - { - // -ns stress remains on penultimate syllable - } - else - if(((mnem != 'n') && (mnem != 's')) || (phoneme_tab[final_ph2]->type != phVOWEL)) - { - stressed_syllable = vowel_count - 1; - } - } - } - } - if(stressflags & 0x80000) - { - // stress on last syllable if it has a long vowel, but previous syllable has a short vowel - if(vowel_length[vowel_count - 1] > vowel_length[vowel_count - 2]) - { - stressed_syllable = vowel_count - 1; - } - } - - if(vowel_stress[stressed_syllable] == 1) - { - // but this vowel is explicitly marked as unstressed - if(stressed_syllable > 1) - stressed_syllable--; - else - stressed_syllable++; - } - } - else - { - stressed_syllable = 1; - } - - // only set the stress if it's not already marked explicitly - if(vowel_stress[stressed_syllable] == 0) - { - // don't stress if next and prev syllables are stressed - if((vowel_stress[stressed_syllable-1] < 4) || (vowel_stress[stressed_syllable+1] < 4)) - vowel_stress[stressed_syllable] = max_stress; - } - } - break; - - case 3: - // stress on last vowel - if(stressed_syllable == 0) - { - /* no explicit stress - stress the final vowel */ - stressed_syllable = vowel_count - 1; - if(max_stress == 0) - { - while(stressed_syllable > 0) - { - if(vowel_stress[stressed_syllable] == 0) - { - vowel_stress[stressed_syllable] = 4; - break; - } - else - stressed_syllable--; - } - } - max_stress = 4; - } - break; - - case 4: // stress on antipenultimate vowel - if(stressed_syllable == 0) - { - stressed_syllable = vowel_count - 3; - if(stressed_syllable < 1) - stressed_syllable = 1; - - if(max_stress == 0) - { - vowel_stress[stressed_syllable] = 4; - } - max_stress = 4; - } - break; - - case 5: - // LANG=Russian - if(stressed_syllable == 0) - { - /* no explicit stress - guess the stress from the number of syllables */ - static char guess_ru[16] = {0,0,1,1,2,3,3,4,5,6,7,7,8,9,10,11}; - static char guess_ru_v[16] = {0,0,1,1,2,2,3,3,4,5,6,7,7,8,9,10}; // for final phoneme is a vowel - static char guess_ru_t[16] = {0,0,1,2,3,3,3,4,5,6,7,7,7,8,9,10}; // for final phoneme is an unvoiced stop - - stressed_syllable = vowel_count - 3; - if(vowel_count < 16) - { - if(phoneme_tab[final_ph]->type == phVOWEL) - stressed_syllable = guess_ru_v[vowel_count]; - else - if(phoneme_tab[final_ph]->type == phSTOP) - stressed_syllable = guess_ru_t[vowel_count]; - else - stressed_syllable = guess_ru[vowel_count]; - } - vowel_stress[stressed_syllable] = 4; - max_stress = 4; - } - break; - - case 6: // LANG=hi stress on the last heaviest syllable - if(stressed_syllable == 0) - { - int wt; - int max_weight = -1; - int prev_stressed; - - // find the heaviest syllable, excluding the final syllable - for(ix = 1; ix < (vowel_count-1); ix++) - { - if(vowel_stress[ix] == 0) - { - if((wt = syllable_weight[ix]) >= max_weight) - { - max_weight = wt; - prev_stressed = stressed_syllable; - stressed_syllable = ix; - } - } - } - - if((syllable_weight[vowel_count-1] == 2) && (max_weight< 2)) - { - // the only double=heavy syllable is the final syllable, so stress this - stressed_syllable = vowel_count-1; - } - else - if(max_weight <= 0) - { - // all syllables, exclusing the last, are light. Stress the first syllable - stressed_syllable = 1; - } - - vowel_stress[stressed_syllable] = 4; - max_stress = 4; - } - break; - - case 7: // LANG=tr, the last syllable for any vowel markes explicitly as unstressed - if(stressed_syllable == 0) - { - stressed_syllable = vowel_count - 1; - for(ix=1; ix < vowel_count; ix++) - { - if(vowel_stress[ix] == 1) - { - stressed_syllable = ix-1; - break; - } - } - vowel_stress[stressed_syllable] = 4; - max_stress = 4; - } - break; - - case 9: // mark all as stressed - for(ix=1; ix<vowel_count; ix++) - { - if(vowel_stress[ix] == 0) - vowel_stress[ix] = 4; - } - break; - } - - /* now guess the complete stress pattern */ - if(max_stress < 4) - stress = 4; /* no primary stress marked, use for 1st syllable */ - else - stress = 3; - - - if((stressflags & 0x1000) && (vowel_count == 2)) - { - // Two syllable word, if one syllable has primary stress, then give the other secondary stress - if(vowel_stress[1] == 4) - vowel_stress[2] = 3; - if(vowel_stress[2] == 4) - vowel_stress[1] = 3; - } -#if deleted - if((stressflags & 0x2000) && (vowel_stress[1] == 0)) - { - // If there is only one syllable before the primary stress, give it a secondary stress - if((vowel_count > 2) && (vowel_stress[2] >= 4)) - { - vowel_stress[1] = 3; - } - } -#endif - - done = 0; - for(v=1; v<vowel_count; v++) - { - if(vowel_stress[v] == 0) - { - if((stressflags & 0x10) && (stress < 4) && (v == vowel_count-1)) - { - // flag: don't give secondary stress to final vowel - } - else - if((stressflags & 0x8000) && (done == 0)) - { - vowel_stress[v] = (char)stress; - done =1; - stress = 3; /* use secondary stress for remaining syllables */ - } - else - if((vowel_stress[v-1] <= 1) && ((vowel_stress[v+1] <= 1) || ((stress == 4) && (vowel_stress[v+1] <= 2)))) - { - /* trochaic: give stress to vowel surrounded by unstressed vowels */ - - if((stress == 3) && (stressflags & 0x20)) - continue; // don't use secondary stress - - if((v > 1) && (stressflags & 0x40) && (syllable_weight[v]==0) && (syllable_weight[v+1]>0)) - { - // don't put secondary stress on a light syllable which is followed by a heavy syllable - continue; - } - -// should start with secondary stress on the first syllable, or should it count back from -// the primary stress and put secondary stress on alternate syllables? - vowel_stress[v] = (char)stress; - done =1; - stress = 3; /* use secondary stress for remaining syllables */ - } - } - } - - if((unstressed_word) && (tonic < 0)) - { - if(vowel_count <= 2) - tonic = tr->langopts.unstressed_wd1; /* monosyllable - unstressed */ - else - tonic = tr->langopts.unstressed_wd2; /* more than one syllable, used secondary stress as the main stress */ - } - - max_stress = 0; - max_stress_posn = 0; - for(v=1; v<vowel_count; v++) - { - if(vowel_stress[v] >= max_stress) - { - max_stress = vowel_stress[v]; - max_stress_posn = v; - } - } - - if(tonic >= 0) - { - /* find position of highest stress, and replace it by 'tonic' */ - - /* don't disturb an explicitly set stress by 'unstress-at-end' flag */ - if((tonic > max_stress) || (max_stress <= 4)) - vowel_stress[max_stress_posn] = (char)tonic; - max_stress = tonic; - } - - - /* produce output phoneme string */ - p = phonetic; - v = 1; - - if((ph = phoneme_tab[*p]) != NULL) - { - - if(ph->type == phSTRESS) - ph = phoneme_tab[p[1]]; - -#ifdef deleted - int gap = tr->langopts.word_gap & 0x700; - if((gap) && (vowel_stress[1] >= 4) && (prev_stress >= 4)) - { - /* two primary stresses together, insert a short pause */ - *output++ = pause_phonemes[gap >> 8]; - } - else -#endif - if((tr->langopts.vowel_pause & 0x30) && (ph->type == phVOWEL)) - { - // word starts with a vowel - - if((tr->langopts.vowel_pause & 0x20) && (vowel_stress[1] >= 4)) - { - *output++ = phonPAUSE_NOLINK; // not to be replaced by link - } - else - { - *output++ = phonPAUSE_VSHORT; // break, but no pause - } - } - } - - p = phonetic; - post_tonic = 0; - while(((phcode = *p++) != 0) && (output < max_output)) - { - if((ph = phoneme_tab[phcode]) == NULL) - continue; - -// if(ph->type == phSTRESS) -// continue; - - if(ph->type == phPAUSE) - { - tr->prev_last_stress = 0; - } - else - if(((ph->type == phVOWEL) && !(ph->phflags & phNONSYLLABIC)) || (*p == phonSYLLABIC)) - { - // a vowel, or a consonant followed by a syllabic consonant marker - - v_stress = vowel_stress[v]; - tr->prev_last_stress = v_stress; - - if(vowel_stress[v-1] >= max_stress) - post_tonic = 1; - - if(v_stress <= 1) - { - if((v > 1) && (max_stress >= 4) && (stressflags & 4) && (v == (vowel_count-1))) - { - // option: mark unstressed final syllable as diminished - v_stress = 1; - } - else - if((stressflags & 2) || (v == 1) || (v == (vowel_count-1))) - { - // first or last syllable, or option 'don't set diminished stress' - v_stress = 0; - } - else - if((v == (vowel_count-2)) && (vowel_stress[vowel_count-1] <= 1)) - { - // penultimate syllable, followed by an unstressed final syllable - v_stress = 0; - } - else - { - // unstressed syllable within a word - if((vowel_stress[v-1] != 1) || ((stressflags & 0x10000) == 0)) - { - v_stress = 1; /* change from 0 (unstressed) to 1 (diminished stress) */ - vowel_stress[v] = v_stress; - } - } - } - - if(v_stress > 0) - *output++ = stress_phonemes[v_stress]; // mark stress of all vowels except 0 (unstressed) - - - if(vowel_stress[v] > max_stress) - { - max_stress = vowel_stress[v]; - } - - if((*p == phonLENGTHEN) && ((opt_length = tr->langopts.param[LOPT_IT_LENGTHEN]) & 1)) - { - // remove lengthen indicator from non-stressed syllables - int shorten=0; - - if(opt_length & 0x10) - { - // only allow lengthen indicator on the highest stress syllable in the word - if(v != max_stress_posn) - shorten = 1; - } - else - if(v_stress < 4) - { - // only allow lengthen indicator if stress >= 4. - shorten = 1; - } - - if(shorten) - p++; - } - - if((v_stress >= 4) && (tr->langopts.param[LOPT_IT_LENGTHEN] == 2)) - { - // LANG=Italian, lengthen penultimate stressed vowels, unless followed by 2 consonants - if((v == (vowel_count - 2)) && (syllable_weight[v] == 0)) - { - *output++ = phcode; - phcode = phonLENGTHEN; - } - } - - v++; - } - - if(phcode != 1) - *output++ = phcode; - } - *output++ = 0; - -} /* end of SetWordStress */ - - - - -//============================================================================================= -// Look up a word in the pronunciation rules -// -//============================================================================================= - - -#ifdef LOG_TRANSLATE -static char *DecodeRule(const char *group, char *rule) -{//================================================== -/* Convert compiled match template to ascii */ - - unsigned char rb; - unsigned char c; - char *p; - int ix; - int match_type; - int finished=0; - int value; - int linenum=0; - int flags; - int suffix_char; - int condition_num=0; - char buf[60]; - char buf_pre[60]; - char suffix[20]; - static char output[60]; - - static char symbols[] = {' ',' ',' ',' ',' ',' ',' ',' ',' ', - '@','&','%','+','#','S','D','Z','A','L',' ',' ',' ',' ',' ','N','K','V',' ','T','X','?','W'}; - - static char symbols_lg[] = {'A','B','C','H','F','G','Y'}; - - match_type = 0; - buf_pre[0] = 0; - strcpy(buf,group); - p = &buf[strlen(buf)]; - while(!finished) - { - rb = *rule++; - - if(rb <= RULE_LINENUM) - { - switch(rb) - { - case 0: - case RULE_PHONEMES: - finished=1; - break; - case RULE_PRE: - match_type = RULE_PRE; - *p = 0; - p = buf_pre; - break; - case RULE_POST: - match_type = RULE_POST; - *p = 0; - strcat(buf," ("); - p = &buf[strlen(buf)]; - break; - case RULE_PH_COMMON: - break; - case RULE_CONDITION: - /* conditional rule, next byte gives condition number */ - condition_num = *rule++; - break; - case RULE_LINENUM: - value = (rule[1] & 0xff) - 1; - linenum = (rule[0] & 0xff) - 1 + (value * 255); - rule+=2; - break; - } - continue; - } - - if(rb == RULE_ENDING) - { - static const char *flag_chars = "ei vtfq t"; - flags = ((rule[0] & 0x7f)<< 8) + (rule[1] & 0x7f); - suffix_char = 'S'; - if(flags & (SUFX_P >> 8)) - suffix_char = 'P'; - sprintf(suffix,"%c%d",suffix_char,rule[2] & 0x7f); - rule += 3; - for(ix=0;ix<9;ix++) - { - if(flags & 1) - sprintf(&suffix[strlen(suffix)],"%c",flag_chars[ix]); - flags = (flags >> 1); - } - strcpy(p,suffix); - p += strlen(suffix); - c = ' '; - } - else - if(rb == RULE_LETTERGP) - { - c = symbols_lg[*rule++ - 'A']; - } - else - if(rb == RULE_LETTERGP2) - { - value = *rule++ - 'A'; - p[0] = 'L'; - p[1] = (value / 10) + '0'; - c = (value % 10) + '0'; - - if(match_type == RULE_PRE) - { - p[0] = c; - c = 'L'; - } - p+=2; - } - else - if(rb <= RULE_LAST_RULE) - c = symbols[rb]; - else - if(rb == RULE_SPACE) - c = '_'; - else - c = rb; - *p++ = c; - } - *p = 0; - - p = output; - if(linenum > 0) - { - sprintf(p,"%5d:\t",linenum); - p += 7; - } - if(condition_num > 0) - { - sprintf(p,"?%d ",condition_num); - p = &p[strlen(p)]; - } - if((ix = strlen(buf_pre)) > 0) - { - while(--ix >= 0) - *p++ = buf_pre[ix]; - *p++ = ')'; - *p++ = ' '; - } - *p = 0; - strcat(p,buf); - ix = strlen(output); - while(ix < 8) - output[ix++]=' '; - output[ix]=0; - return(output); -} /* end of decode_match */ -#endif - - - -void AppendPhonemes(Translator *tr, char *string, int size, const char *ph) -{//======================================================================== -/* Add new phoneme string "ph" to "string" - 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 -*/ - const char *p; - unsigned char c; - int unstress_mark; - int length; - - length = strlen(ph) + strlen(string); - if(length >= size) - { - return; - } - - /* any stressable vowel ? */ - unstress_mark = 0; - p = ph; - while((c = *p++) != 0) - { - if(c >= n_phoneme_tab) continue; - - if(phoneme_tab[c]->type == phSTRESS) - { - if(phoneme_tab[c]->std_length < 4) - unstress_mark = 1; - } - else - { - if(phoneme_tab[c]->type == phVOWEL) - { - if(((phoneme_tab[c]->phflags & phUNSTRESSED) == 0) && - (unstress_mark == 0)) - { - tr->word_stressed_count++; - } - unstress_mark = 0; - tr->word_vowel_count++; - } - } - } - - if(string != NULL) - strcat(string,ph); -} /* end of AppendPhonemes */ - - - -static void MatchRule(Translator *tr, char *word[], const char *group, char *rule, MatchRecord *match_out, int word_flags, int dict_flags) -{//======================================================================================================================================= -/* Checks a specified word against dictionary rules. - Returns with phoneme code string, or NULL if no match found. - - word (indirect) points to current character group within the input word - This is advanced by this procedure as characters are consumed - - group: the initial characters used to choose the rules group - - rule: address of dictionary rule data for this character group - - match_out: returns best points score - - word_flags: indicates whether this is a retranslation after a suffix has been removed -*/ - - unsigned char rb; // current instuction from rule - unsigned char letter; // current letter from input word, single byte - int letter_w; // current letter, wide character - int letter_xbytes; // number of extra bytes of multibyte character (num bytes - 1) - unsigned char last_letter; - - char *pre_ptr; - char *post_ptr; /* pointer to first character after group */ - - char *rule_start; /* start of current match template */ - char *p; - - int match_type; /* left, right, or consume */ - int failed; - int consumed; /* number of letters consumed from input */ - int count; /* count through rules in the group */ - int syllable_count; - int vowel; - int letter_group; - int distance_right; - int distance_left; - int lg_pts; - int n_bytes; - int add_points; - - MatchRecord match; - static MatchRecord best; - - int total_consumed; /* letters consumed for best match */ - int group_length; - - unsigned char condition_num; - char *common_phonemes; /* common to a group of entries */ - - - - if(rule == NULL) - { - match_out->points = 0; - (*word)++; - return; - } - - - total_consumed = 0; - count = 0; - common_phonemes = NULL; - match_type = 0; - - best.points = 0; - best.phonemes = ""; - best.end_type = 0; - best.del_fwd = NULL; - - group_length = strlen(group); - - /* search through dictionary rules */ - while(rule[0] != RULE_GROUP_END) - { - match_type=0; - consumed = 0; - letter = 0; - distance_right= -6; /* used to reduce points for matches further away the current letter */ - distance_left= -2; - count++; - - match.points = 1; - match.end_type = 0; - match.del_fwd = NULL; - - pre_ptr = *word; - post_ptr = *word + group_length; - - /* work through next rule until end, or until no-match proved */ - rule_start = rule; - failed = 0; - while(!failed) - { - rb = *rule++; - - if(rb <= RULE_LINENUM) - { - switch(rb) - { - case 0: // no phoneme string for this rule, use previous common rule - if(common_phonemes != NULL) - { - match.phonemes = common_phonemes; - while(((rb = *match.phonemes++) != 0) && (rb != RULE_PHONEMES)) - { - if(rb == RULE_CONDITION) - match.phonemes++; // skip over condition number - } - } - else - { - match.phonemes = ""; - } - rule--; // so we are still pointing at the 0 - failed=2; // matched OK - break; - case RULE_PRE: - match_type = RULE_PRE; - break; - case RULE_POST: - match_type = RULE_POST; - break; - case RULE_PHONEMES: - match.phonemes = rule; - failed=2; // matched OK - break; - case RULE_PH_COMMON: - common_phonemes = rule; - break; - case RULE_CONDITION: - /* conditional rule, next byte gives condition number */ - condition_num = *rule++; - - if(condition_num >= 32) - { - // allow the rule only if the condition number is NOT set - if((tr->dict_condition & (1L << (condition_num-32))) != 0) - failed = 1; - } - else - { - // allow the rule only if the condition number is set - if((tr->dict_condition & (1L << condition_num)) == 0) - failed = 1; - } - - if(!failed) - match.points++; // add one point for a matched conditional rule - break; - case RULE_LINENUM: - rule+=2; - break; - } - continue; - } - - add_points = 0; - - switch(match_type) - { - case 0: - /* match and consume this letter */ - last_letter = letter; - letter = *post_ptr++; - - if((letter == rb) || ((letter==(unsigned char)REPLACED_E) && (rb=='e'))) - { - add_points = 21; - consumed++; - } - else - failed = 1; - break; - - - case RULE_POST: - /* continue moving fowards */ - distance_right += 6; - if(distance_right > 18) - distance_right = 19; - last_letter = letter; - letter_xbytes = utf8_in(&letter_w,post_ptr)-1; - letter = *post_ptr++; - - switch(rb) - { - case RULE_LETTERGP: - letter_group = *rule++ - 'A'; - if(IsLetter(tr, letter_w, letter_group)) - { - lg_pts = 20; - if(letter_group==2) - lg_pts = 19; // fewer points for C, general consonant - add_points = (lg_pts-distance_right); - post_ptr += letter_xbytes; - } - else - failed = 1; - break; - - case RULE_LETTERGP2: // match against a list of utf-8 strings - letter_group = *rule++ - 'A'; - if((n_bytes = IsLetterGroup(tr, post_ptr-1,letter_group,0)) >0) - { - add_points = (20-distance_right); - post_ptr += (n_bytes-1); - } - else - failed =1; - break; - - case RULE_NOTVOWEL: - if(!IsLetter(tr, letter_w,0)) - { - add_points = (20-distance_right); - post_ptr += letter_xbytes; - } - else - failed = 1; - break; - - case RULE_DIGIT: - if(IsDigit(letter_w)) - { - add_points = (20-distance_right); - post_ptr += letter_xbytes; - } - else - if(tr->langopts.tone_numbers) - { - // also match if there is no digit - add_points = (20-distance_right); - post_ptr--; - } - else - failed = 1; - break; - - case RULE_NONALPHA: - if(!iswalpha(letter_w)) - { - add_points = (21-distance_right); - post_ptr += letter_xbytes; - } - else - failed = 1; - break; - - case RULE_DOUBLE: - if(letter == last_letter) - add_points = (21-distance_right); - else - failed = 1; - break; - - case RULE_ALT1: - if(dict_flags & FLAG_ALT_TRANS) - add_points = 1; - else - failed = 1; - break; - - case '-': - if((letter == '-') || ((letter == ' ') && (word_flags & FLAG_HYPHEN_AFTER))) - { - add_points = (22-distance_right); // one point more than match against space - } - else - failed = 1; - break; - - case RULE_SYLLABLE: - { - /* more than specified number of vowel letters to the right */ - char *p = post_ptr + letter_xbytes; - - syllable_count = 1; - while(*rule == RULE_SYLLABLE) - { - rule++; - syllable_count+=1; /* number of syllables to match */ - } - vowel = 0; - while(letter_w != RULE_SPACE) - { - if((vowel==0) && IsLetter(tr, letter_w,LETTERGP_VOWEL2)) - { - // this is counting vowels which are separated by non-vowels - syllable_count--; - } - vowel = IsLetter(tr, letter_w,LETTERGP_VOWEL2); - p += utf8_in(&letter_w,p); - } - if(syllable_count <= 0) - add_points = (19-distance_right); - else - failed = 1; - } - break; - - case RULE_NOVOWELS: - { - char *p = post_ptr + letter_xbytes; - while(letter_w != RULE_SPACE) - { - if(IsLetter(tr, letter_w,LETTERGP_VOWEL2)) - { - failed = 1; - break; - } - p += utf8_in(&letter_w,p); - } - if(!failed) - add_points = (19-distance_right); - } - break; - - case RULE_INC_SCORE: - add_points = 20; // force an increase in points - break; - - case RULE_DEL_FWD: - // find the next 'e' in the word and replace by '' - for(p = *word + group_length; *p != ' '; p++) - { - if(*p == 'e') - { - match.del_fwd = p; - break; - } - } - break; - - case RULE_ENDING: - // next 3 bytes are a (non-zero) ending type. 2 bytes of flags + suffix length - match.end_type = (rule[0] << 16) + ((rule[1] & 0x7f) << 8) + (rule[2] & 0x7f); - rule += 3; - break; - - case RULE_NO_SUFFIX: - if(word_flags & FLAG_SUFFIX_REMOVED) - failed = 1; // a suffix has been removed - else - add_points = 1; - break; - - default: - if(letter == rb) - { - if(letter == RULE_SPACE) - add_points = (21-distance_right); - else - add_points = (21-distance_right); - } - else - failed = 1; - break; - } - break; - - - case RULE_PRE: - /* match backwards from start of current group */ - distance_left += 2; - if(distance_left > 18) - distance_left = 19; - - last_letter = *pre_ptr; - pre_ptr--; - letter_xbytes = utf8_in2(&letter_w,pre_ptr,1)-1; - letter = *pre_ptr; - - switch(rb) - { - case RULE_LETTERGP: - letter_group = *rule++ - 'A'; - if(IsLetter(tr, letter_w,letter_group)) - { - lg_pts = 20; - if(letter_group==2) - lg_pts = 19; // fewer points for C, general consonant - add_points = (lg_pts-distance_left); - pre_ptr -= letter_xbytes; - } - else - failed = 1; - break; - - case RULE_LETTERGP2: // match against a list of utf-8 strings - letter_group = *rule++ - 'A'; - if((n_bytes = IsLetterGroup(tr, pre_ptr,letter_group,1)) >0) - { - add_points = (20-distance_right); - pre_ptr -= (n_bytes-1); - } - else - failed =1; - break; - - case RULE_NOTVOWEL: - if(!IsLetter(tr, letter_w,0)) - { - add_points = (20-distance_left); - pre_ptr -= letter_xbytes; - } - else - failed = 1; - break; - - case RULE_DOUBLE: - if(letter == last_letter) - add_points = (21-distance_left); - else - failed = 1; - break; - - case RULE_DIGIT: - if(IsDigit(letter_w)) - { - add_points = (21-distance_left); - pre_ptr -= letter_xbytes; - } - else - failed = 1; - break; - - case RULE_NONALPHA: - if(!iswalpha(letter_w)) - { - add_points = (21-distance_right); - pre_ptr -= letter_xbytes; - } - else - failed = 1; - break; - - case RULE_SYLLABLE: - /* more than specified number of vowels to the left */ - syllable_count = 1; - while(*rule == RULE_SYLLABLE) - { - rule++; - syllable_count++; /* number of syllables to match */ - } - if(syllable_count <= tr->word_vowel_count) - add_points = (19-distance_left); - else - failed = 1; - break; - - case RULE_STRESSED: - if(tr->word_stressed_count > 0) - add_points = 19; - else - failed = 1; - break; - - case RULE_NOVOWELS: - { - char *p = pre_ptr - letter_xbytes - 1; - while(letter_w != RULE_SPACE) - { - if(IsLetter(tr, letter_w,LETTERGP_VOWEL2)) - { - failed = 1; - break; - } - p -= utf8_in2(&letter_w,p,1); - } - if(!failed) - add_points = 3; - } - break; - - case RULE_IFVERB: - if(tr->expect_verb) - add_points = 1; - else - failed = 1; - break; - - case RULE_CAPITAL: - if(word_flags & FLAG_FIRST_UPPER) - add_points = 1; - else - failed = 1; - break; - - case '.': - // dot in pre- section, match on any dot before this point in the word - for(p=pre_ptr; *p != ' '; p--) - { - if(*p == '.') - { - add_points = 50; - break; - } - } - if(*p == ' ') - failed = 1; - break; - - case '-': - if((letter == '-') || ((letter == ' ') && (word_flags & FLAG_HYPHEN))) - { - add_points = (22-distance_right); // one point more than match against space - } - else - failed = 1; - break; - - default: - if(letter == rb) - { - if(letter == RULE_SPACE) - add_points = 4; - else - add_points = (21-distance_left); - } - else - failed = 1; - break; - } - break; - } - - if(failed == 0) - match.points += add_points; - } - - if(failed == 2) - { - /* matched OK, is this better than the last best match ? */ - if(match.points >= best.points) - { - memcpy(&best,&match,sizeof(match)); - total_consumed = consumed; - } - -#ifdef LOG_TRANSLATE - if((option_phonemes == 2) && (match.points > 0) && ((word_flags & FLAG_NO_TRACE) == 0)) - { - // show each rule that matches, and it's points score - int pts; - char decoded_phonemes[80]; - - // note: 'count' contains the rule number, if we want to include it - pts = match.points; - if(group_length > 1) - pts += 35; // to account for an extra letter matching - DecodePhonemes(match.phonemes,decoded_phonemes); - fprintf(f_trans,"%3d\t%s [%s]\n",pts,DecodeRule(group,rule_start),decoded_phonemes); - } -#endif - - } - - /* skip phoneme string to reach start of next template */ - while(*rule++ != 0); - } - -#ifdef LOG_TRANSLATE - if((option_phonemes == 2) && ((word_flags & FLAG_NO_TRACE)==0)) - { - if(group_length <= 1) - fprintf(f_trans,"\n"); - } -#endif - - /* advance input data pointer */ - total_consumed += group_length; - if(total_consumed == 0) - total_consumed = 1; /* always advance over 1st letter */ - - *word += total_consumed; - - if(best.points == 0) - best.phonemes = ""; - 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) -{//===================================================================================================================================== -/* Translate a word bounded by space characters - Append the result to 'phonemes' and any standard prefix/suffix in 'end_phonemes' */ - - unsigned char c, c2; - unsigned int c12; - int wc=0; - int wc_prev; - int wc_bytes; - char *p2; /* copy of p for use in double letter chain match */ - int found; - int g; /* group chain number */ - int g1; /* first group for this letter */ - int n; - int letter; - int any_alpha=0; - int ix; - unsigned int digit_count=0; - char *p; - int dict_flags0=0; - MatchRecord match1; - MatchRecord match2; - char ph_buf[40]; - char word_copy[N_WORD_BYTES]; - static const char str_pause[2] = {phonPAUSE_NOLINK,0}; - - char group_name[4]; - - if(tr->data_dictrules == NULL) - return(0); - - if(dict_flags != NULL) - dict_flags0 = dict_flags[0]; - - for(ix=0; ix<(N_WORD_BYTES-1);) - { - c = p_start[ix]; - word_copy[ix++] = c; - if(c == 0) - break; - } - word_copy[ix] = 0; - - -#ifdef LOG_TRANSLATE - if((option_phonemes == 2) && ((word_flags & FLAG_NO_TRACE)==0)) - { - char wordbuf[120]; - int ix; - - for(ix=0; ((c = p_start[ix]) != ' ') && (c != 0); ix++) - { - wordbuf[ix] = c; - } - wordbuf[ix] = 0; - fprintf(f_trans,"Translate '%s'\n",wordbuf); - } -#endif - - p = p_start; - tr->word_vowel_count = 0; - tr->word_stressed_count = 0; - - if(end_phonemes != NULL) - end_phonemes[0] = 0; - - while(((c = *p) != ' ') && (c != 0)) - { - wc_prev = wc; - wc_bytes = utf8_in(&wc,p); - if(IsAlpha(wc)) - any_alpha++; - - n = tr->groups2_count[c]; - if(IsDigit(wc) && ((tr->langopts.tone_numbers == 0) || !any_alpha)) - { - // lookup the number in *_list not *_rules - char string[8]; - char buf[40]; - string[0] = '_'; - memcpy(&string[1],p,wc_bytes); - string[1+wc_bytes] = 0; - Lookup(tr, string,buf); - if(++digit_count >= 2) - { - strcat(buf,str_pause); - digit_count=0; - } - AppendPhonemes(tr,phonemes,ph_size,buf); - p += wc_bytes; - continue; - } - else - { - digit_count = 0; - found = 0; - - if(n > 0) - { - /* there are some 2 byte chains for this initial letter */ - c2 = p[1]; - c12 = c + (c2 << 8); /* 2 characters */ - - g1 = tr->groups2_start[c]; - for(g=g1; g < (g1+n); g++) - { - if(tr->groups2_name[g] == c12) - { - found = 1; - - group_name[0] = c; - group_name[1] = c2; - group_name[2] = 0; - p2 = p; - MatchRule(tr, &p2, group_name, tr->groups2[g], &match2, word_flags, dict_flags0); - if(match2.points > 0) - match2.points += 35; /* to acount for 2 letters matching */ - - /* now see whether single letter chain gives a better match ? */ - group_name[1] = 0; - MatchRule(tr, &p, group_name, tr->groups1[c], &match1, word_flags, dict_flags0); - - if(match2.points >= match1.points) - { - // use match from the 2-letter group - memcpy(&match1,&match2,sizeof(MatchRecord)); - p = p2; - } - } - } - } - - if(!found) - { - /* alphabetic, single letter chain */ - group_name[0] = c; - group_name[1] = 0; - - if(tr->groups1[c] != NULL) - MatchRule(tr, &p, group_name, tr->groups1[c], &match1, word_flags, dict_flags0); - else - { - // no group for this letter, use default group - MatchRule(tr, &p, "", tr->groups1[0], &match1, word_flags, dict_flags0); - - if((match1.points == 0) && ((option_sayas & 0x10) == 0)) - { - n = utf8_in(&letter,p-1)-1; - - if(tr->letter_bits_offset > 0) - { - // not a Latin alphabet, switch to the default Latin alphabet language - if((letter <= 0x241) && iswalpha(letter)) - { - sprintf(phonemes,"%c%s",phonSWITCH,tr->langopts.ascii_language); - return(0); - } - } -#ifdef deleted -// can't switch to a tone language, because the tone-phoneme numbers are not valid for the original language - if((letter >= 0x4e00) && (letter < 0xa000) && (tr->langopts.ideographs != 1)) - { - // Chinese ideogram - sprintf(phonemes,"%czh",phonSWITCH); - return(0); - } -#endif - - // is it a bracket ? - if(IsBracket(letter)) - { - if(pre_pause < 4) - pre_pause = 4; - } - - // no match, try removing the accent and re-translating the word - if((letter >= 0xc0) && (letter <= 0x241) && ((ix = remove_accent[letter-0xc0]) != 0)) - { - // within range of the remove_accent table - if((p[-2] != ' ') || (p[n] != ' ')) - { - // not the only letter in the word - p2 = p-1; - p[-1] = ix; - while((p[0] = p[n]) != ' ') p++; - while(n-- > 0) *p++ = ' '; // replacement character must be no longer than original - - if(tr->langopts.param[LOPT_DIERESES] && (lookupwchar(diereses_list,letter) > 0)) - { - // vowel with dieresis, replace and continue from this point - p = p2; - continue; - } - - phonemes[0] = 0; // delete any phonemes which have been produced so far - p = p_start; - tr->word_vowel_count = 0; - tr->word_stressed_count = 0; - continue; // start again at the beginning of the word - } - } - else - if((letter >= 0x3200) && (letter < 0xa700) && (end_phonemes != NULL)) - { - // ideograms - // outside the range of the accent table, speak the unknown symbol sound - Lookup(tr, "_??", ph_buf); - match1.phonemes = ph_buf; - match1.points = 1; - p += (wc_bytes-1); - } - } - } - - if(match1.points == 0) - { - if((wc >= 0x300) && (wc <= 0x36f)) - { - // combining accent inside a word, ignore - } - else - if(IsAlpha(wc)) - { - if((any_alpha > 1) || (p[wc_bytes-1] > ' ')) - { - // an unrecognised character in a word, abort and then spell the word - phonemes[0] = 0; - if(dict_flags != NULL) - dict_flags[0] |= FLAG_SPELLWORD; - break; - } - } - else - { - LookupLetter(tr, wc, -1, ph_buf); - if(ph_buf[0]) - { - match1.phonemes = ph_buf; - match1.points = 1; - } - } - p += (wc_bytes-1); - } - else - { - tr->phonemes_repeat_count = 0; - } - } - } - - if(match1.phonemes == NULL) - match1.phonemes = ""; - - if(match1.points > 0) - { - if((match1.phonemes[0] == phonSWITCH) && ((word_flags & FLAG_DONT_SWITCH_TRANSLATOR)==0)) - { - // an instruction to switch language, return immediately so we can re-translate - strcpy(phonemes,match1.phonemes); - return(0); - } - - if((match1.end_type != 0) && (end_phonemes != NULL)) - { - /* a standard ending has been found, re-translate the word without it */ - if((match1.end_type & SUFX_P) && (word_flags & FLAG_NO_PREFIX)) - { - // ignore the match on a prefix - } - else - { - if((match1.end_type & SUFX_P) && ((match1.end_type & 0x7f) == 0)) - { - // no prefix length specified - match1.end_type |= p - p_start; - } - strcpy(end_phonemes,match1.phonemes); - memcpy(p_start,word_copy,strlen(word_copy)); - return(match1.end_type); - } - } - if(match1.del_fwd != NULL) - *match1.del_fwd = REPLACED_E; - AppendPhonemes(tr,phonemes,ph_size,match1.phonemes); - } - } - - // any language specific changes ? - ApplySpecialAttribute(tr,phonemes,dict_flags0); - memcpy(p_start,word_copy,strlen(word_copy)); - - return(0); -} /* end of TranslateRules */ - - -void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags) -{//======================================================================== - // apply after the translation is complete - int ix; - int len; - char *p; - - len = strlen(phonemes); - - switch(tr->translator_name) - { - case L('i','t'): - for(ix=0; ix<(len-1); ix++) - { - if(phonemes[ix] == phonSTRESS_P) - { - p = &phonemes[ix+1]; - if((dict_flags & FLAG_ALT2_TRANS) != 0) - { - if(*p == PhonemeCode('E')) - *p = PhonemeCode('e'); - if(*p == PhonemeCode('O')) - *p = PhonemeCode('o'); - } - else - { - if(*p == PhonemeCode('e')) - *p = PhonemeCode('E'); - if(*p == PhonemeCode('o')) - *p = PhonemeCode('O'); - } - break; - } - } - break; - } -} // end of ApplySpecialAttribute2 - - -void ApplySpecialAttribute(Translator *tr, char *phonemes, int dict_flags) -{//======================================================================= -// Amend the translated phonemes according to an attribute which is specific for the language. - int len; - int ix; - char *p_end; - int phoneme_1; - - if((dict_flags & (FLAG_ALT_TRANS | FLAG_ALT2_TRANS)) == 0) - return; - - len = strlen(phonemes); - p_end = &phonemes[len-1]; - - switch(tr->translator_name) - { - case L('d','e'): - if(p_end[0] == PhonemeCode2('i',':')) - { - // words ends in ['i:], change to [=I@] - p_end[-1] = phonSTRESS_PREV; - p_end[0] = PhonemeCode('I'); - p_end[1] = phonSCHWA; - p_end[2] = 0; - } - break; - - case L('p','t'): - phoneme_1 = PhonemeCode('o'); - for(ix=0; ix<(len-1); ix++) - { - if(phonemes[ix] == phoneme_1) - { - phonemes[ix] = PhonemeCode('O'); - break; - } - } - break; - - case L('r','o'): - if(p_end[0] == PhonemeCode('j')) - { - // word end in [j], change to ['i] - p_end[0] = phonSTRESS_P; - p_end[1] = PhonemeCode('i'); - p_end[2] = 0; - } - break; - } -} // end of ApplySpecialAttribute - - - -//============================================================================================= -// 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 -//============================================================================================= - -// common letter pairs, encode these as a single byte -static const short pairs_ru[] = { -0x010c, // ла 21052 0x23 -0x010e, // на 18400 -0x0113, // та 14254 -0x0301, // ав 31083 -0x030f, // ов 13420 -0x060e, // не 21798 -0x0611, // ре 19458 -0x0903, // ви 16226 -0x0b01, // ак 14456 -0x0b0f, // ок 17836 -0x0c01, // ал 13324 -0x0c09, // ил 16877 -0x0e01, // ан 15359 -0x0e06, // ен 13543 0x30 -0x0e09, // ин 17168 -0x0e0e, // нн 15973 -0x0e0f, // он 22373 -0x0e1c, // ын 15052 -0x0f03, // во 24947 -0x0f11, // ро 13552 -0x0f12, // со 16368 -0x100f, // оп 19054 -0x1011, // рп 17067 -0x1101, // ар 23967 -0x1106, // ер 18795 -0x1109, // ир 13797 -0x110f, // ор 21737 -0x1213, // тс 25076 -0x1220, // яс 14310 -0x7fff}; -//0x040f ог 12976 -//0x1306 ет 12826 -//0x0f0d мо 12688 - - -int TransposeAlphabet(char *text, int offset, int min, int max) -{//============================================================ -// transpose cyrillic alphabet (for example) into ascii (single byte) character codes -// return: number of bytes, bit 6: 1=used compression - int c; - int c2; - int ix; - char *p = text; - char *p2 = text; - int all_alpha=1; - int bits; - int acc; - - do { - p += utf8_in(&c,p); - if((c >= min) && (c <= max)) - { - *p2++ = c - offset; - } - else - if(c != 0) - { - p2 += utf8_out(c,p2); - all_alpha=0; - } - } while (c != 0); - *p2 = 0; - - if(all_alpha) - { - // compress to 6 bits per character - acc=0; - bits=0; - - p = text; - p2 = text; - while((c = *p++) != 0) - { - c2 = c + (*p << 8); - for(ix=0; c2 >= pairs_ru[ix]; ix++) - { - if(c2 == pairs_ru[ix]) - { - // found an encoding for a 2-character pair - c = ix + 0x23; // 2-character codes start at 0x23 - p++; - break; - } - } - acc = (acc << 6) + (c & 0x3f); - bits += 6; - - if(bits >= 8) - { - bits -= 8; - *p2++ = (acc >> bits); - } - } - if(bits > 0) - { - *p2++ = (acc << (8-bits)); - } - *p2 = 0; - return((p2 - text) | 0x40); // bit 6 indicates compressed characters - } - return(p2 - 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. - Returns NULL if no match, else returns 'word_end' - - word zero terminated word to match - word2 pointer to next word(s) in the input text (terminated by space) - - flags: returns dictionary flags which are associated with a matched word - - end_flags: indicates whether this is a retranslation after removing a suffix -*/ -{ - char *p; - char *next; - int hash; - int phoneme_len; - int wlen; - unsigned char flag; - unsigned int dictionary_flags; - unsigned int dictionary_flags2; - int condition_failed=0; - int n_chars; - int no_phonemes; - int skipwords; - int ix; - const char *word_end; - const char *word1; - int wflags = 0; - char word_buf[N_WORD_BYTES]; - - if(wtab != NULL) - { - wflags = wtab->flags; - } - - word1 = word; - if(tr->transpose_offset > 0) - { - strcpy(word_buf,word); - wlen = TransposeAlphabet(word_buf, tr->transpose_offset, tr->transpose_min, tr->transpose_max); - word = word_buf; - } - else - { - wlen = strlen(word); - } - - hash = HashDictionary(word); - p = tr->dict_hashtab[hash]; - - if(p == NULL) - { - if(flags != NULL) - *flags = 0; - return(0); - } - - // Find the first entry in the list for this hash value which matches. - // This corresponds to the last matching entry in the *_list file. - - while(*p != 0) - { - next = p + p[0]; - - if(((p[1] & 0x7f) != wlen) || (memcmp(word,&p[2],wlen & 0x3f) != 0)) - { - // bit 6 of wlen indicates whether the word has been compressed; so we need to match on this also. - p = next; - continue; - } - - /* found matching entry. Decode the phonetic string */ - word_end = word2; - - dictionary_flags = 0; - dictionary_flags2 = 0; - no_phonemes = p[1] & 0x80; - - p += ((p[1] & 0x3f) + 2); - - if(no_phonemes) - { - phonetic[0] = 0; - phoneme_len = 0; - } - else - { - strcpy(phonetic,p); - phoneme_len = strlen(p); - p += (phoneme_len + 1); - } - - while(p < next) - { - // examine the flags which follow the phoneme string - - flag = *p++; - if(flag >= 100) - { - // conditional rule - if(flag >= 132) - { - // fail if this condition is set - if((tr->dict_condition & (1 << (flag-132))) != 0) - condition_failed = 1; - } - else - { - // allow only if this condition is set - if((tr->dict_condition & (1 << (flag-100))) == 0) - condition_failed = 1; - } - } - else - if(flag > 80) - { - // flags 81 to 90 match more than one word - // This comes after the other flags - n_chars = next - p; - skipwords = flag - 80; - - // don't use the contraction if any of the words are emphasized - for(ix=0; ix <= skipwords; ix++) - { - if(wflags & FLAG_EMPHASIZED2) - { - condition_failed = 1; - } - } - - if(memcmp(word2,p,n_chars) != 0) - condition_failed = 1; - - if(condition_failed) - { - p = next; - break; - } - - dictionary_flags |= FLAG_SKIPWORDS; - dictionary_skipwords = skipwords; - p = next; - word_end = word2 + n_chars; - } - else - if(flag > 64) - { - // stressed syllable information, put in bits 0-3 - dictionary_flags = (dictionary_flags & ~0xf) | (flag & 0xf); - if((flag & 0xc) == 0xc) - dictionary_flags |= FLAG_STRESS_END; - } - else - if(flag >= 32) - { - dictionary_flags2 |= (1L << (flag-32)); - } - else - { - dictionary_flags |= (1L << flag); - } - } - - if(condition_failed) - { - condition_failed=0; - continue; - } - - if((end_flags & FLAG_SUFX)==0) - { - // no suffix has been removed - if(dictionary_flags & FLAG_STEM) - continue; // this word must have a suffix - } - - if((end_flags & SUFX_P) && (dictionary_flags & (FLAG_ONLY | FLAG_ONLY_S))) - continue; // $only or $onlys, don't match if a prefix has been removed - - if(end_flags & FLAG_SUFX) - { - // a suffix was removed from the word - if(dictionary_flags & FLAG_ONLY) - continue; // no match if any suffix - - if((dictionary_flags & FLAG_ONLY_S) && ((end_flags & FLAG_SUFX_S)==0)) - { - // only a 's' suffix allowed, but the suffix wasn't 's' - continue; - } - } - - if(dictionary_flags2 & FLAG_HYPHENATED) - { - if(!(wflags & FLAG_HYPHEN_AFTER)) - { - continue; - } - } - if(dictionary_flags2 & FLAG_CAPITAL) - { - if(!(wflags & FLAG_FIRST_UPPER)) - { - continue; - } - } - if(dictionary_flags2 & FLAG_ALLCAPS) - { - if(!(wflags & FLAG_ALL_UPPER)) - { - continue; - } - } - - if((dictionary_flags & FLAG_ATEND) && (word_end < tr->clause_end)) - { - // only use this pronunciation if it's the last word of the clause - continue; - } - - if(dictionary_flags2 & FLAG_VERB) - { - // this is a verb-form pronunciation - - if(tr->expect_verb || (tr->expect_verb_s && (end_flags & FLAG_SUFX_S))) - { - // OK, we are expecting a verb - } - else - { - /* don't use the 'verb' pronunciation unless we are - expecting a verb */ - continue; - } - } - if(dictionary_flags2 & FLAG_PAST) - { - if(!tr->expect_past) - { - /* don't use the 'past' pronunciation unless we are - expecting past tense */ - continue; - } - } - if(dictionary_flags2 & FLAG_NOUN) - { - if(!tr->expect_noun) - { - /* don't use the 'noun' pronunciation unless we are - expecting a noun */ - continue; - } - } - - if(flags != NULL) - { - flags[0] = dictionary_flags | FLAG_FOUND_ATTRIBUTES; - flags[1] = dictionary_flags2; - } - - if(phoneme_len == 0) - { - if(option_phonemes == 2) - { - fprintf(f_trans,"Flags: %s %s\n",word1,print_dictionary_flags(flags)); - } - return(0); // no phoneme translation found here, only flags. So use rules - } - - if(flags != NULL) - flags[0] |= FLAG_FOUND; // this flag indicates word was found in dictionary - - if(option_phonemes == 2) - { - unsigned int flags1 = 0; - char ph_decoded[N_WORD_PHONEMES]; - int textmode; - - DecodePhonemes(phonetic,ph_decoded); - if(flags != NULL) - flags1 = flags[0]; - - if((dictionary_flags & FLAG_TEXTMODE) == 0) - textmode = 0; - else - textmode = 1; - - if(textmode == translator->langopts.textmode) - { - // only show this line if the word translates to phonemes, not replacement text - fprintf(f_trans,"Found: %s [%s] %s\n",word1,ph_decoded,print_dictionary_flags(flags)); - } - } - return(word_end); - - } - 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. - Returns phonetic data in 'phonetic' and bits in 'flags' - - end_flags: indicates if a suffix has been removed -*/ -{ - int length; - const char *found; - const char *word1; - const char *word2; - unsigned char c; - int nbytes; - int len; - char word[N_WORD_BYTES]; - static char word_replacement[N_WORD_BYTES]; - - length = 0; - word2 = word1 = *wordptr; - - while((word2[nbytes = utf8_nbytes(word2)]==' ') && (word2[nbytes+1]=='.')) - { - // look for an abbreviation of the form a.b.c - // try removing the spaces between the dots and looking for a match - memcpy(&word[length],word2,nbytes); - length += nbytes; - word[length++] = '.'; - word2 += nbytes+3; - } - if(length > 0) - { - // found an abbreviation containing dots - nbytes = 0; - while(((c = word2[nbytes]) != 0) && (c != ' ')) - { - nbytes++; - } - memcpy(&word[length],word2,nbytes); - word[length+nbytes] = 0; - found = LookupDict2(tr, word, word2, ph_out, flags, end_flags, wtab); - if(found) - { - // set the skip words flag - flags[0] |= FLAG_SKIPWORDS; - dictionary_skipwords = length; - return(1); - } - } - - for(length=0; length<N_WORD_BYTES; length++) - { - if(((c = *word1++)==0) || (c == ' ')) - break; - word[length] = c; - } - word[length] = 0; - - found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab); - - if(flags[0] & FLAG_MAX3) - { - if(strcmp(ph_out, tr->phonemes_repeat) == 0) - { - tr->phonemes_repeat_count++; - if(tr->phonemes_repeat_count > 3) - { - ph_out[0] = 0; - } - } - else - { - strncpy0(tr->phonemes_repeat, ph_out, sizeof(tr->phonemes_repeat)); - tr->phonemes_repeat_count = 1; - } - } - else - { - tr->phonemes_repeat_count = 0; - } - - - if((found == 0) && (flags[1] & FLAG_ACCENT)) - { - int letter; - word2 = word; - if(*word2 == '_') word2++; - len = utf8_in(&letter, word2); - LookupAccentedLetter(tr,letter, ph_out); - found = word2 + len; - } - - if(found == 0) - { - ph_out[0] = 0; - - // try modifications to find a recognised word - - if((end_flags & FLAG_SUFX_E_ADDED) && (word[length-1] == 'e')) - { - // try removing an 'e' which has been added by RemoveEnding - word[length-1] = 0; - found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab); - } - else - if((end_flags & SUFX_D) && (word[length-1] == word[length-2])) - { - // try removing a double letter - word[length-1] = 0; - found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab); - } - } - - if(found) - { - // if textmode is the default, then words which have phonemes are marked. - if(tr->langopts.textmode) - *flags ^= FLAG_TEXTMODE; - - if(*flags & FLAG_TEXTMODE) - { - // the word translates to replacement text, not to phonemes - - if(end_flags & FLAG_ALLOW_TEXTMODE) - { - // only use replacement text if this is the original word, not if a prefix or suffix has been removed - word_replacement[0] = 0; - word_replacement[1] = ' '; - sprintf(&word_replacement[2],"%s ",ph_out); // replacement word, preceded by zerochar and space - - word1 = *wordptr; - *wordptr = &word_replacement[2]; - - if(option_phonemes == 2) - { - len = found - word1; - memcpy(word,word1,len); // include multiple matching words - word[len] = 0; - fprintf(f_trans,"Replace: %s %s\n",word,*wordptr); - } - } - - ph_out[0] = 0; - return(0); - } - - return(1); - } - - ph_out[0] = 0; - return(0); -} // end of LookupDictList - - - -int Lookup(Translator *tr, const char *word, char *ph_out) -{//=================================================== - unsigned int flags[2]={0,0}; - char* word1 = (char *)word; - return(LookupDictList(tr, &word1, ph_out, flags, 0, NULL)); -} - - - -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. - end_type: bits 0-6 number of letters - bits 8-14 suffix flags - - word_copy: make a copy of the original word - This routine is language specific. In English it deals with reversing y->i and e-dropping - that were done when the suffix was added to the original word. -*/ - - int i; - char *word_end; - int len_ending; - int end_flags; - const char *p; - int len; - static char ending[12]; - - // these lists are language specific, but are only relevent if the 'e' suffix flag is used - static const char *add_e_exceptions[] = { - "ion", NULL }; - - static const char *add_e_additions[] = { - "c", "rs", "ir", "ur", "ath", "ns", "lu", NULL }; - - for(word_end = word; *word_end != ' '; word_end++) - { - /* replace discarded 'e's */ - if(*word_end == REPLACED_E) - *word_end = 'e'; - } - i = word_end - word; - memcpy(word_copy,word,i); - word_copy[i] = 0; - - // look for multibyte characters to increase the number of bytes to remove - for(len_ending = i = (end_type & 0x3f); i>0 ;i--) // num.of characters of the suffix - { - word_end--; - while((*word_end & 0xc0) == 0x80) - { - word_end--; // for multibyte characters - len_ending++; - } - } - - // remove bytes from the end of the word and replace them by spaces - for(i=0; i<len_ending; i++) - { - ending[i] = word_end[i]; - word_end[i] = ' '; - } - ending[i] = 0; - word_end--; /* now pointing at last character of stem */ - - end_flags = (end_type & 0xfff0) | FLAG_SUFX; - - /* add an 'e' to the stem if appropriate, - if stem ends in vowel+consonant - or stem ends in 'c' (add 'e' to soften it) */ - - if(end_type & SUFX_I) - { - if(word_end[0] == 'i') - word_end[0] = 'y'; - } - - if(end_type & SUFX_E) - { - // add 'e' to end of stem - if(IsLetter(tr, word_end[-1],LETTERGP_VOWEL2) && IsLetter(tr, word_end[0],1)) - { - // vowel(incl.'y') + hard.consonant - - for(i=0; (p = add_e_exceptions[i]) != NULL; i++) - { - len = strlen(p); - if(memcmp(p,&word_end[1-len],len)==0) - { - break; - } - } - if(p == NULL) - end_flags |= FLAG_SUFX_E_ADDED; // no exception found - } - else - { - for(i=0; (p = add_e_additions[i]) != NULL; i++) - { - len = strlen(p); - if(memcmp(p,&word_end[1-len],len)==0) - { - end_flags |= FLAG_SUFX_E_ADDED; - break; - } - } - } - - if(end_flags & FLAG_SUFX_E_ADDED) - { - word_end[1] = 'e'; -#ifdef LOG_TRANSLATE -if(option_phonemes == 2) -{ - fprintf(f_trans,"add e\n"); -} -#endif - } - } - - if((end_type & SUFX_V) && (tr->expect_verb==0)) - tr->expect_verb = 1; // this suffix indicates the verb pronunciation - - - if((strcmp(ending,"s")==0) || (strcmp(ending,"es")==0)) - end_flags |= FLAG_SUFX_S; - - if(strcmp(ending,"'s")==0) - end_flags &= ~FLAG_SUFX; // don't consider 's as an added suffix - - return(end_flags); -} /* end of RemoveEnding */ - - diff --git a/navit/support/espeak/espeak-data/af_dict b/navit/support/espeak/espeak-data/af_dict Binary files differdeleted file mode 100644 index 7819c9fe0..000000000 --- a/navit/support/espeak/espeak-data/af_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/ca_dict b/navit/support/espeak/espeak-data/ca_dict Binary files differdeleted file mode 100644 index b9a4ea43a..000000000 --- a/navit/support/espeak/espeak-data/ca_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/config b/navit/support/espeak/espeak-data/config deleted file mode 100755 index be1b6246a..000000000 --- a/navit/support/espeak/espeak-data/config +++ /dev/null @@ -1,9 +0,0 @@ -//pa_device 7 - -// play a sound for punctuation, rather than speak its name -//soundicon _( /usr/share/sounds/sound-icons/left-round-bracket -//soundicon _) /usr/share/sounds/sound-icons/right-round-bracket -//soundicon _[ /usr/share/sounds/sound-icons/left-square-bracket -//soundicon _] /usr/share/sounds/sound-icons/right-square-bracket -//soundicon _{ /usr/share/sounds/sound-icons/left-brace -//soundicon _} /usr/share/sounds/sound-icons/right-brace diff --git a/navit/support/espeak/espeak-data/cs_dict b/navit/support/espeak/espeak-data/cs_dict Binary files differdeleted file mode 100644 index 3391b98b2..000000000 --- a/navit/support/espeak/espeak-data/cs_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/cy_dict b/navit/support/espeak/espeak-data/cy_dict Binary files differdeleted file mode 100644 index 13a768030..000000000 --- a/navit/support/espeak/espeak-data/cy_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/da_dict b/navit/support/espeak/espeak-data/da_dict Binary files differdeleted file mode 100644 index 75ccbd670..000000000 --- a/navit/support/espeak/espeak-data/da_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/de_dict b/navit/support/espeak/espeak-data/de_dict Binary files differdeleted file mode 100644 index 988f4c31b..000000000 --- a/navit/support/espeak/espeak-data/de_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/el_dict b/navit/support/espeak/espeak-data/el_dict Binary files differdeleted file mode 100644 index a6ab63dee..000000000 --- a/navit/support/espeak/espeak-data/el_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/en_dict b/navit/support/espeak/espeak-data/en_dict Binary files differdeleted file mode 100644 index d15b0e9ab..000000000 --- a/navit/support/espeak/espeak-data/en_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/eo_dict b/navit/support/espeak/espeak-data/eo_dict Binary files differdeleted file mode 100644 index 155523963..000000000 --- a/navit/support/espeak/espeak-data/eo_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/es_dict b/navit/support/espeak/espeak-data/es_dict Binary files differdeleted file mode 100644 index 203da2639..000000000 --- a/navit/support/espeak/espeak-data/es_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/fi_dict b/navit/support/espeak/espeak-data/fi_dict Binary files differdeleted file mode 100644 index a08d45a6f..000000000 --- a/navit/support/espeak/espeak-data/fi_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/fr_dict b/navit/support/espeak/espeak-data/fr_dict Binary files differdeleted file mode 100644 index e66708e04..000000000 --- a/navit/support/espeak/espeak-data/fr_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/grc_dict b/navit/support/espeak/espeak-data/grc_dict Binary files differdeleted file mode 100644 index 0aeab45e0..000000000 --- a/navit/support/espeak/espeak-data/grc_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/hbs_dict b/navit/support/espeak/espeak-data/hbs_dict Binary files differdeleted file mode 100644 index 91ee7ba4b..000000000 --- a/navit/support/espeak/espeak-data/hbs_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/hi_dict b/navit/support/espeak/espeak-data/hi_dict Binary files differdeleted file mode 100644 index 388d3f246..000000000 --- a/navit/support/espeak/espeak-data/hi_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/hu_dict b/navit/support/espeak/espeak-data/hu_dict Binary files differdeleted file mode 100644 index 5a1f21165..000000000 --- a/navit/support/espeak/espeak-data/hu_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/hy_dict b/navit/support/espeak/espeak-data/hy_dict Binary files differdeleted file mode 100644 index 18c3e2027..000000000 --- a/navit/support/espeak/espeak-data/hy_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/id_dict b/navit/support/espeak/espeak-data/id_dict Binary files differdeleted file mode 100644 index 3c9967ce8..000000000 --- a/navit/support/espeak/espeak-data/id_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/is_dict b/navit/support/espeak/espeak-data/is_dict Binary files differdeleted file mode 100644 index 10cf846f8..000000000 --- a/navit/support/espeak/espeak-data/is_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/it_dict b/navit/support/espeak/espeak-data/it_dict Binary files differdeleted file mode 100644 index 40cf952a2..000000000 --- a/navit/support/espeak/espeak-data/it_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/jbo_dict b/navit/support/espeak/espeak-data/jbo_dict Binary files differdeleted file mode 100644 index f7ebcf454..000000000 --- a/navit/support/espeak/espeak-data/jbo_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/ku_dict b/navit/support/espeak/espeak-data/ku_dict Binary files differdeleted file mode 100644 index 18d285845..000000000 --- a/navit/support/espeak/espeak-data/ku_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/la_dict b/navit/support/espeak/espeak-data/la_dict Binary files differdeleted file mode 100644 index 3ef82f832..000000000 --- a/navit/support/espeak/espeak-data/la_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/lv_dict b/navit/support/espeak/espeak-data/lv_dict Binary files differdeleted file mode 100644 index 3ecb61b51..000000000 --- a/navit/support/espeak/espeak-data/lv_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/af1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/af1_phtrans Binary files differdeleted file mode 100644 index fc9ad0179..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/af1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/ca1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/ca1_phtrans Binary files differdeleted file mode 100644 index 4fe4188e5..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/ca1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/cr1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/cr1_phtrans Binary files differdeleted file mode 100644 index 15e2c4988..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/cr1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/cs_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/cs_phtrans Binary files differdeleted file mode 100644 index 85ebb03e3..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/cs_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/de2_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/de2_phtrans Binary files differdeleted file mode 100644 index c5af1a7c4..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/de2_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/de4_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/de4_phtrans Binary files differdeleted file mode 100644 index b10fc8441..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/de4_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/de6_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/de6_phtrans Binary files differdeleted file mode 100644 index 4cb62d9c2..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/de6_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/en1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/en1_phtrans Binary files differdeleted file mode 100644 index c847d1703..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/en1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/es_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/es_phtrans Binary files differdeleted file mode 100644 index b959f92c1..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/es_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/fr1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/fr1_phtrans Binary files differdeleted file mode 100644 index 1a242b36f..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/fr1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/gr2_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/gr2_phtrans Binary files differdeleted file mode 100644 index b3775abbd..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/gr2_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/grc-de6_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/grc-de6_phtrans Binary files differdeleted file mode 100644 index e41d3105c..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/grc-de6_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/hu1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/hu1_phtrans Binary files differdeleted file mode 100644 index 26dad49a0..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/hu1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/id1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/id1_phtrans Binary files differdeleted file mode 100644 index 452de8c8a..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/id1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/in1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/in1_phtrans Binary files differdeleted file mode 100644 index 7f4631899..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/in1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/it3_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/it3_phtrans Binary files differdeleted file mode 100644 index 6d826477b..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/it3_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/la1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/la1_phtrans Binary files differdeleted file mode 100644 index 1f2eb9290..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/la1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/nl_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/nl_phtrans Binary files differdeleted file mode 100644 index d982c1845..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/nl_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/pl1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/pl1_phtrans Binary files differdeleted file mode 100644 index 9d4e50fd7..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/pl1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/pt1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/pt1_phtrans Binary files differdeleted file mode 100644 index c5172f7b3..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/pt1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/pt_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/pt_phtrans Binary files differdeleted file mode 100644 index 9de1630d9..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/pt_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/ptbr4_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/ptbr4_phtrans Binary files differdeleted file mode 100644 index 0b94de719..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/ptbr4_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/ptbr_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/ptbr_phtrans Binary files differdeleted file mode 100644 index a1dbba000..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/ptbr_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/ro1_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/ro1_phtrans Binary files differdeleted file mode 100644 index 4aeaf54ec..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/ro1_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/sv2_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/sv2_phtrans Binary files differdeleted file mode 100644 index ae119d86e..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/sv2_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/sv_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/sv_phtrans Binary files differdeleted file mode 100644 index bb556eb28..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/sv_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/us3_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/us3_phtrans Binary files differdeleted file mode 100644 index 449b419ac..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/us3_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mbrola_ph/us_phtrans b/navit/support/espeak/espeak-data/mbrola_ph/us_phtrans Binary files differdeleted file mode 100644 index bdeef5d1a..000000000 --- a/navit/support/espeak/espeak-data/mbrola_ph/us_phtrans +++ /dev/null diff --git a/navit/support/espeak/espeak-data/mk_dict b/navit/support/espeak/espeak-data/mk_dict Binary files differdeleted file mode 100644 index a6cf3dc53..000000000 --- a/navit/support/espeak/espeak-data/mk_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/nl_dict b/navit/support/espeak/espeak-data/nl_dict Binary files differdeleted file mode 100644 index f286bee90..000000000 --- a/navit/support/espeak/espeak-data/nl_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/no_dict b/navit/support/espeak/espeak-data/no_dict Binary files differdeleted file mode 100644 index 4f8f84f0d..000000000 --- a/navit/support/espeak/espeak-data/no_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/pap_dict b/navit/support/espeak/espeak-data/pap_dict Binary files differdeleted file mode 100644 index 11eb4b515..000000000 --- a/navit/support/espeak/espeak-data/pap_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/phondata b/navit/support/espeak/espeak-data/phondata Binary files differdeleted file mode 100644 index d46417ed0..000000000 --- a/navit/support/espeak/espeak-data/phondata +++ /dev/null diff --git a/navit/support/espeak/espeak-data/phondata-manifest b/navit/support/espeak/espeak-data/phondata-manifest deleted file mode 100644 index 4197d142d..000000000 --- a/navit/support/espeak/espeak-data/phondata-manifest +++ /dev/null @@ -1,729 +0,0 @@ -# This file lists the type of data that has been compiled into the -# phondata file -# -# The first character of a line indicates the type of data: -# S - A SPECT_SEQ structure -# W - A wavefile segment -# E - An envelope -# -# Address is the displacement within phondata of this item -# -# Address Data file -# ------- --------- -W 0x00004 ustop/null -S 0x00154 vowel/@ -S 0x00218 vowel/@- -W 0x002dc ustop/percus10 -S 0x004e8 j/j@ -S 0x005ec j2/j2@ -S 0x006b0 w/w@ -S 0x00774 l/l@ -S 0x00838 l^/j2@ -S 0x008fc r/r@ -S 0x009c0 r2/r2@ -S 0x00a84 m/m@ -S 0x00b88 n/n@ -S 0x00c8c nn/nn@ -S 0x00d50 n^/n^@ -S 0x00ed4 l/L1_@L -S 0x00fd8 l/L2_@L -S 0x010dc l/l_@ -S 0x011a0 l/xl -S 0x01224 w/xw -S 0x012a8 j/xj -S 0x0132c r/xr -S 0x013b0 r3/r_@ -S 0x01474 j/ja -S 0x01578 j2/j2a -S 0x0163c w/wa -S 0x01700 l/la -S 0x01784 l^/j2a -S 0x01848 r/ra -S 0x0190c r2/r2a -S 0x019d0 m/ma -S 0x01ad4 n/na -S 0x01bd8 nn/nna -S 0x01c9c n^/n^a -S 0x01de0 l/L1_aL -S 0x01ee4 l/L2_aL -S 0x01fe8 l/l_a -S 0x020ac r3/r_a -S 0x02170 j/je -S 0x02274 j2/j2e -S 0x02338 w/we -S 0x023fc l/le -S 0x02480 l^/j2e -S 0x02544 r/re -S 0x02608 r2/r2e -S 0x0270c m/me -S 0x02810 n/ne -S 0x02914 nn/nne -S 0x029d8 n^/n^e -S 0x02b5c l/L1_eL -S 0x02c20 l/L2_eL -S 0x02ce4 l/l_e -S 0x02d68 r3/r_e -S 0x02e2c j/ji -S 0x02ef0 j2/j2i -S 0x02fb4 w/wi -S 0x03078 l/li -S 0x0313c l^/j2i -S 0x03200 r/ri -S 0x032c4 r2/r2i -S 0x03388 m/mi -S 0x034cc n/ni -S 0x035d0 nn/nni -S 0x03694 n^/n^i -S 0x03818 l/L1_iL -S 0x0391c l/L2_iL -S 0x03a20 l/l_i -S 0x03ae4 nn/inn -S 0x03ba8 j2/xj2 -S 0x03c2c r3/r_i -S 0x03cf0 j/jo -S 0x03e34 j2/j2o -S 0x03f38 w/wo -S 0x03ffc l/lo -S 0x04100 l^/j2o -S 0x04204 r/ro -S 0x042c8 r2/r2o -S 0x0438c m/mo -S 0x04490 n/no -S 0x04594 nn/nno -S 0x04658 n^/n^o -S 0x0481c l/L1_oL -S 0x04960 l/L2_oL -S 0x04aa4 l/l_o -S 0x04ba8 r3/r_o -S 0x04c6c j/ju -S 0x04d30 j2/j2u -S 0x04df4 w/wu -S 0x04eb8 l/lu -S 0x04f7c l^/j2u -S 0x05080 r/ru -S 0x05144 r2/r2u -S 0x05208 m/mu -S 0x0530c n/nu -S 0x05410 nn/nnu -S 0x054d4 n^/n^u -S 0x05658 l/L1_uL -S 0x0575c l/L2_uL -S 0x05860 l/l_u -S 0x05924 r3/r_u -S 0x059e8 r/r -S 0x05aac r/_r -S 0x05b70 r/tr -S 0x05bf4 r/r_ -S 0x05d38 r3/r_ -W 0x05dbc r3/rx -S 0x07114 r3/r_n -S 0x07198 r/rr -S 0x0725c r/trr -S 0x07320 r2/_r2 -S 0x073e4 r3/r_trill2 -W 0x074a8 r3/r_trill2.wav -S 0x07bb4 r3/r_trill -W 0x07cb8 r3/r_trill.wav -W 0x08724 r3/r_trill3.wav -S 0x08b68 r3/r_uvl -W 0x08c6c r3/r_uvl.wav -S 0x09b74 l/l -S 0x09bf8 l/_l -S 0x09cbc l/tl -S 0x09d40 l/l_long -S 0x09dc4 l/l_ -S 0x09e48 l^/l^ -S 0x09f4c l^/_l^ -S 0x0a050 w/w -S 0x0a0d4 w/_w -S 0x0a198 w/w_ -S 0x0a25c w/iw_ -S 0x0a320 j/_j -S 0x0a3a4 j/j_ -S 0x0a468 j2/_j2 -S 0x0a4ec m/_m -S 0x0a570 m/m_ -S 0x0a634 m/mj -S 0x0a6f8 n/_n -S 0x0a77c n/n_ -S 0x0a840 n/nj -S 0x0a904 n/_nr -S 0x0a988 n/nr_ -S 0x0aa4c n^/_n^ -S 0x0aad0 n^/n^_ -S 0x0ac14 nn/_nn -S 0x0ac98 nn/nn_ -S 0x0ad5c nn/nnj -S 0x0ade0 r3/@tap -S 0x0af24 r3/@tap2 -S 0x0b068 r3/@tap_rfx -S 0x0b1ac b/b -W 0x0b2b0 x/b -S 0x0b414 b/b_ -W 0x0b4d8 x/b_ -S 0x0b8f0 b/ba -S 0x0b9f4 b/b@ -S 0x0baf8 b/be -S 0x0bbfc b/bi -S 0x0bd00 b/bo -S 0x0be04 b/bu -S 0x0bf08 b/b@2 -S 0x0c00c b/xb -S 0x0c0d0 d/d -W 0x0c194 x/d -S 0x0c3b0 d/d_ -W 0x0c474 x/d_ -S 0x0c89c d/dr -S 0x0c920 d/xd -W 0x0c9e4 x/d_dnt -S 0x0ccc8 d/tap3 -S 0x0cdcc d/tap1 -S 0x0ce90 dzh/dzh -W 0x0cf54 x/dzh -S 0x0d360 dzh/dzh_ -W 0x0d424 x/dzh_ -S 0x0de5c dzh/xdzh -W 0x0df20 x/dz_pzd -S 0x0e380 dzh/dz_pzd -S 0x0e444 dzh/dz_pzd_ -S 0x0e508 dzh/xdz_pzd -S 0x0e5cc g/g -W 0x0e690 x/g2 -S 0x0e918 g/g_ -W 0x0e9dc x/g_ -S 0x0ed9c g/xg -S 0x0ee60 g2/g -W 0x0ef24 x/g2_ -S 0x0f2e4 g2/g_ -S 0x0f3a8 g2/xg -S 0x0f46c voc/bh -W 0x0f530 vocw/v -S 0x0fe30 voc/v_ -S 0x0fef4 voc/v -S 0x0fff8 voc/vj -S 0x100fc voc/dh -W 0x101c0 vocw/dh -S 0x10ac8 voc/dh_ -S 0x10b8c voc/z -W 0x10c50 ufric/s_ -S 0x11704 voc/z_ -S 0x117c8 voc/zh -W 0x1188c vocw/zh -S 0x121f4 voc/zh_ -W 0x122b8 vocw/zh_rfx -S 0x12b48 voc/z_pzd -W 0x12c0c ufric/s_pzd -S 0x13544 voc/z_pzd_ -W 0x13608 ufric/s_pzd_ -W 0x1410c ufric/sh_pzd -W 0x14a40 ufric/sh_pzd_ -S 0x15508 voc/j -W 0x1560c ufric/ch -S 0x15d24 voc/Q -W 0x15de8 vocw/Q -S 0x165f4 voc/Q_ -W 0x166b8 vocw/Q_ -S 0x16ec4 voc/Q_ulv -W 0x16fc8 ufric/xx -W 0x17ac4 ustop/p -W 0x17e34 ustop/p_ -W 0x18644 ustop/pr -W 0x18a8c ustop/p_unasp -W 0x18db8 ustop/pl -W 0x191b0 ustop/t -W 0x195e4 ustop/t_ -W 0x19aa4 ustop/t_dnt -W 0x19eb4 ustop/tr -W 0x1a614 ustop/t_hi -W 0x1a9b0 ustop/tsh -W 0x1aff0 ustop/tsh_ -W 0x1b930 ustop/ts_pzd -W 0x1c034 ustop/c -W 0x1c2e4 ustop/t_pzd -W 0x1c730 ustop/k -W 0x1cc04 ustop/k_ -W 0x1d0c0 ustop/kr -W 0x1d700 ustop/k_unasp -W 0x1dbd4 ustop/kl -W 0x1e204 ustop/ki -W 0x1e7cc ustop/q -W 0x1e938 ustop/q_u -W 0x1ea58 ufric/f -W 0x1f248 ufric/f_ -W 0x1fd18 ufric/th -W 0x205b0 ufric/th_ -W 0x20e30 ufric/s -W 0x215d0 ufric/s! -W 0x21e80 ufric/sh -W 0x22830 ufric/sh_ -W 0x232e0 ufric/sh_rfx -W 0x23c7c ufric/ll -W 0x246c0 ufric/ch_ -W 0x24fe8 ufric/x_hr -W 0x258fc ufric/x -W 0x26260 h/h_ -W 0x2690c h/h@ -W 0x26e60 h/ha -W 0x274dc h/he -W 0x27b70 h/hi -W 0x28108 h/ho -W 0x287c4 h/hu -S 0x28ee8 vowel/a_2 -S 0x28fec vowel/a# -S 0x290f0 vowel/e -S 0x291f4 vowel/ee_1 -S 0x29338 vowel/i -S 0x2943c vowel/o -S 0x29580 vowel/oo_4 -S 0x29684 vowel/u_bck -S 0x29788 vowel/uu_2 -S 0x2988c vowel/y -S 0x299d0 vowel/y# -S 0x29ad4 vdiph/au_4 -S 0x29c58 vdiph/eu -S 0x29d9c vdiph2/iu -S 0x29f20 vdiph/ai -S 0x2a064 vdiph/ei -S 0x2a1a8 vdiph/eei -S 0x2a32c vdiph/oi -S 0x2a4f0 vdiph/ui -S 0x2a634 w/w2 -W 0x2a6f8 ustop/p_unasp_ -W 0x2a834 ustop/ts -W 0x2b290 ustop/ts_ -W 0x2bbf0 ustop/t_dnt2 -S 0x2be48 vwl_en/@L -S 0x2bf0c vowel/a -S 0x2c010 vowel/a#_3 -S 0x2c0d4 vowel/ee_2 -S 0x2c1d8 vowel/ii_4 -S 0x2c2dc vowel/ii_en -S 0x2c3a0 vowel/0 -S 0x2c4a4 vowel/V_2 -S 0x2c5a8 vowel/uu -S 0x2c6ac vowel/aa_2 -S 0x2c830 vowel/3_en -S 0x2c974 vowel/i_en -S 0x2cab8 w/wi2 -S 0x2cbbc vowel/oo_en -S 0x2cd00 vdiph2/uw_2 -S 0x2ce44 vwl_en/u_L -S 0x2cf88 vdiph/au -S 0x2d10c vdiph/@u_en -S 0x2d290 vdiph/ai_2 -S 0x2d454 vdiph/ooi -S 0x2d618 vdiph2/ii@ -S 0x2d79c vdiph2/uu@ -S 0x2d8e0 vwl_en/aI@ -S 0x2daa4 vwl_en/aU@ -S 0x2dc28 vowelr/V_r -S 0x2dd6c vowelr/V3_r -S 0x2deb0 vnasal/aa_n2 -S 0x2dff4 vnasal/ee_n -S 0x2e138 vnasal/oo_n -S 0x2e23c vowel/oe -S 0x2e300 vowel/@_fr -S 0x2e3c4 vowel/ee -S 0x2e4c8 vowel/ii -S 0x2e5cc vowel/e_3 -S 0x2e6d0 vowel/0_2 -S 0x2e7d4 vowel/o-_2 -S 0x2e8d8 vowel/aa_5 -S 0x2ea1c vwl_en_n/aa_5 -S 0x2eb60 vowel/3_2 -S 0x2eca4 vowel/oo_1 -S 0x2ede8 vwl_en_n/O@ -S 0x2eeec vdiph2/uw_4 -S 0x2f030 vdiph/eeu_3 -S 0x2f174 vdiph/ae_2 -S 0x2f2f8 vdiph2/ee@ -S 0x2f43c vdiph2/i@ -S 0x2f600 vwl_en_us/3_us -S 0x2f704 vowel/@_4 -S 0x2f7c8 vowel/@_low2 -S 0x2f88c vwl_en_us/a -S 0x2f990 vnasal/ee_n2 -S 0x2fad4 vwl_en_us/ee -S 0x2fbd8 vowel/ii#_3 -S 0x2fcdc vowel/ii_final -S 0x2fde0 vowel/aa_8 -S 0x2fee4 vwl_en_us/oor -S 0x30028 vowel/V_6 -S 0x3012c vowel/8_2 -S 0x30230 vwl_en_us/ar -S 0x30374 vwl_en_us/3_us2 -S 0x304b8 vowel/0_3 -S 0x305bc vwl_en_us/or -S 0x30700 vowel/aa# -S 0x30804 vdiph2/uw -S 0x30948 vdiph/aoo -S 0x30a8c vdiph/8u -S 0x30bd0 vdiph/aae -S 0x30d54 vdiph2/ei_4 -S 0x30e98 vdiph/ooi_4 -S 0x30fdc vwl_en_us/er -S 0x31120 vwl_en_us/ir -S 0x31264 vwl_en_us/ur -S 0x313a8 vwl_en_us/ai@ -S 0x3152c d/tap2 -S 0x315f0 d/x_tap -S 0x316b4 vowel/@_3 -S 0x31778 vowel/V -S 0x3187c vowel/a_3 -S 0x31980 vowel/e_e -S 0x31a84 vowel/e# -S 0x31b88 vowel/e_5 -S 0x31c8c vowel/oo_2 -S 0x31d90 vowel/V_4 -S 0x31e94 vowel/u#_4 -S 0x31f98 vowelr/aa_r -S 0x3215c vdiph2/e@ -S 0x322a0 vowel/i_5 -S 0x323a4 vowel/oo -S 0x324a8 vowelr/oo_r -S 0x325ac vowelr/o_r -S 0x32730 vowel/u# -S 0x32834 vdiph/au# -S 0x32978 vowel/o_3 -S 0x32a7c vdiph/ai_7 -S 0x32c00 vwl_en/aI@_2 -S 0x32d84 vwl_en/@L_2 -S 0x32e88 vowel/e_2 -S 0x32f8c vdiph/0i_2 -S 0x33110 vowelr/i_r -S 0x33254 vdiph2/u#@ -S 0x33398 vowel/@_low -S 0x3345c vowel/& -S 0x33560 vowel/e_mid -S 0x33664 vowel/V_3 -S 0x33728 vowel/o-_3 -S 0x3382c vwl_en_rp/aa -S 0x33970 vowel/3_3 -S 0x33ab4 vowel/u_fnt -S 0x33bb8 vdiph/au_3 -S 0x33d3c vdiph/@u_2 -S 0x33e80 vdiph/ai_6 -S 0x34044 vdiph2/ei_2 -S 0x34188 vdiph/ooi_3 -S 0x3430c vdiph2/ee@_2 -S 0x34450 vwl_en_rp/i@ -S 0x345d4 vowel/o_mid -S 0x346d8 vwl_en_rp/aU@ -S 0x3485c vowel/ii_6 -S 0x34920 vdiph2/ei_3 -S 0x34a64 vdiph/@u -S 0x34ba8 vdiph/Vu_2 -S 0x34d2c vdiph/@i_3 -S 0x34e70 vdiph2/i@_2 -S 0x34ff4 vwl_en/ooi@ -S 0x351b8 vowel/@_fnt -S 0x352bc vowel/uu_bck -S 0x353c0 vowel/i_fnt -S 0x354c4 vdiph2/o_oo -S 0x35608 vowel/u -S 0x3570c vdiph/aau_2 -S 0x35850 vdiph2/ie -S 0x35994 vwl_af/@ -S 0x35a58 vwl_af/r@ -S 0x35b1c vowel/e_mid2 -S 0x35c20 vwl_af/I -S 0x35ce4 vowel/oo_3 -S 0x35da8 vowel/uu_3 -S 0x35e6c vowel/ee_3 -S 0x35f30 l/L_eL_af -S 0x35ff4 vowel/aa_3 -S 0x360f8 vdiph/i@_2 -S 0x3627c vowel/i_3 -S 0x36380 vdiph2/o@ -S 0x36504 vowel/y_3 -S 0x36608 vdiph2/iu_3 -S 0x367cc vdiph/Vu -S 0x36950 vdiph/ai_4 -S 0x36ad4 vdiph/aai_2 -S 0x36c98 vdiph/@i_2 -S 0x36ddc vdiph/ooi_2 -S 0x36f60 vdiph/oi_2 -S 0x37124 vdiph/ui_2 -S 0x372a8 vdiph/y#y_2 -S 0x3742c vdiph2/y#@ -S 0x37570 vnasal/aa_n3 -S 0x376b4 vnasal/e_n -S 0x377b8 vnasal/o_n2 -W 0x378fc ufric/x2 -S 0x38254 vowel/ii_3 -S 0x38358 vowel/ii# -S 0x3845c vowel/i# -S 0x38560 vowel/o_2 -S 0x386a4 vdiph2/iu_4 -S 0x387e8 vdiph/ui_3 -S 0x3896c vowel/aa_6 -S 0x38ab0 vowel/i_2 -S 0x38bb4 vdiph/ai_5 -S 0x38cf8 vowel/yy_4 -S 0x38dfc l/l_3 -S 0x38e80 j/_j_short -S 0x38f04 vdiph/eei_2 -S 0x39048 vowelr/r-voc -S 0x3918c vwl_hi/l-voc -S 0x39290 vowel/i_4 -S 0x39394 vowel/aa_9 -S 0x39498 vowel/u_2 -S 0x3959c vowel/uu_4 -S 0x396a0 vdiph/aai_3 -S 0x39824 vdiph/&i -S 0x39968 vdiph/y#i -S 0x39aac vdiph/ui_4 -S 0x39bf0 vdiph/yi -S 0x39d34 vdiph/aau -S 0x39eb8 vdiph/ou -S 0x39ffc vdiph/eu_2 -S 0x3a140 vdiph2/iu_2 -S 0x3a2c4 vdiph/&y -S 0x3a408 vdiph/eey -S 0x3a54c vdiph/y#y -S 0x3a690 vdiph2/iy -S 0x3a7d4 vdiph2/uo -S 0x3a918 vdiph2/y-y# -S 0x3aa5c r3/r_trill_short -W 0x3ab60 ufric/s_continue -W 0x3b310 h/hu_fi -S 0x3bc00 vwl_fr/tr -S 0x3bc84 vwl_fr/@R5 -S 0x3bd48 vowel/@_hgh -S 0x3be0c vwl_fr/r_@ -S 0x3bed0 vowel/a_6 -S 0x3bfd4 vwl_fr/r_a -S 0x3c058 vowel/e_8 -S 0x3c15c vwl_fr/r_e -S 0x3c220 vwl_fr/r_i -S 0x3c2e4 vwl_fr/r_o -S 0x3c3a8 vowel/u_bck2 -S 0x3c4ac vwl_fr/r_u -S 0x3c570 vowel/y_2 -S 0x3c6b4 l/l_y -S 0x3c778 vwl_fr/r_y -S 0x3c83c vowel/@_5 -S 0x3c900 vwl_fr/r_@2 -S 0x3c984 vwl_fr/w_a -S 0x3cac8 vdiph/yi_fr -S 0x3cc4c vnasal/aa_n4 -S 0x3cd90 vwl_fr/r_a~ -S 0x3ce14 vnasal/W_n -S 0x3cf58 vowel/a_en -S 0x3d05c vwl_fr/r -S 0x3d0e0 r3/r_2 -W 0x3d164 ustop/t_short -S 0x3d3a8 vowel/yy -S 0x3d4ac vdiph/ae -S 0x3d5f0 vowel/aa -S 0x3d6f4 vwl_fr/@R2 -S 0x3d7f8 vowel/@_bck -S 0x3d8fc vowel/i_6 -S 0x3da00 vdiph/ee-e -S 0x3db44 vnasal/i_n2 -S 0x3dc48 vnasal/aa_n -S 0x3dd8c vnasal/V_n -S 0x3de90 vnasal/oo_n2 -S 0x3dfd4 vnasal/o_n -S 0x3e118 vnasal/u_n -S 0x3e21c vdiph/aau_3 -S 0x3e3a0 l^/l_rfx -S 0x3e464 voc/v# -S 0x3e568 voc/v#_ -W 0x3e62c ustop/p_asp -S 0x3eb30 d/xd3 -W 0x3ebf4 ustop/ts_pzd2 -W 0x3ef28 ustop/ts_pzd_ -W 0x3f3ec ustop/k_asp -S 0x3faf0 vowel/a_5 -S 0x3fbf4 vowel/u#_3 -S 0x3fcf8 vowel/u#_2 -S 0x3fdfc vowel/y#_2 -S 0x3ff00 vowel/8_7 -S 0x40004 vdiph/aai -S 0x40188 vdiph2/uaa -S 0x4030c vdiph2/ie_2 -W 0x40450 ustop/ts2 -S 0x40920 vowel/o_5 -S 0x40a24 vowel/o_6 -S 0x40ae8 vowel/aa_7 -S 0x40bec vdiph/y#y_3 -S 0x40cf0 vdiph/Vu_3 -S 0x40e74 vdiph2/yu -S 0x40ff8 voc/Q_less -W 0x410bc vocw/Q2 -W 0x41988 ufric/sx_sv -S 0x421d0 vowel/a#_2 -S 0x422d4 vowel/ee# -S 0x423d8 vowel/i_7 -S 0x424dc vowel/oo_5 -S 0x425e0 vowel/ii#_2 -S 0x426e4 vnasal/ee_u_n -S 0x42868 vnasal/oo_n3 -W 0x429ec x/d_pzd -S 0x42e00 d/xd_pzd -S 0x42ec4 d/xdz -S 0x42f88 vowel/ee_6 -S 0x4304c vdiph/ou_2 -S 0x43190 vdiph/eei_3 -W 0x432d4 r3/rz_cs -S 0x43d80 voc/zh_2 -S 0x43e44 vdiph/oou -W 0x43f88 ufric/sh3 -W 0x4491c ustop/tsh2 -W 0x45028 ustop/ts_pzd3 -S 0x456a8 dzh/dzh2 -W 0x4576c ustop/t_sr -S 0x45aa4 d/d_dnt -W 0x45b68 ufric/x_sr -W 0x463e8 ufric/ch_sr -W 0x46fc8 ufric/sh_pzd2 -W 0x47b18 ustop/ts_sr -W 0x482d4 ustop/tsh_sr -S 0x48bec vwl_ru/ii- -S 0x48cb0 vwl_ro/mi -S 0x48df4 vwl_ru/i -S 0x48ef8 vwl_ru/ii# -S 0x48fbc vwl_ru/i# -S 0x490c0 vwl_ru/ii -S 0x491c4 vwl_ru/e -S 0x492c8 vwl_ru/E# -S 0x493cc vwl_ru/E@ -S 0x494d0 vwl_ru/a -S 0x495d4 vwl_ru/o -S 0x496d8 vwl_ru/oo -S 0x4979c vwl_ru/u -S 0x498a0 vwl_ru/u# -S 0x499e4 vwl_ru/u#u -S 0x49b28 vwl_ru/8 -S 0x49bec vwl_ru/ee -S 0x49d30 vwl_ru/ju -S 0x49e34 vwl_ru/ja -S 0x49fb8 vwl_ru/aa -S 0x4a0bc r3/r_ru2 -W 0x4a1c0 r3/r_ru -S 0x4a4c4 vowel/ii_5 -S 0x4a5c8 vdiph/eeu_2 -S 0x4a70c d/tap4 -S 0x4a810 voc/v2 -S 0x4a8d4 vnasal/i_n -S 0x4a9d8 vnasal/a#_n -S 0x4aadc vnasal/a#u_n -S 0x4ac20 vnasal/oi_n -S 0x4ade4 vdiph/0i -S 0x4afa8 vdiph/eeu -S 0x4b0ec vowel/i#_5 -S 0x4b1f0 vowel/u_6 -S 0x4b2f4 vwl_fr/@R -S 0x4b3f8 vwl_ro/ii- -S 0x4b4bc vwl_ro/li -S 0x4b5c0 vwl_ro/ni -S 0x4b6c4 vowel/o-_4 -S 0x4b7c8 vdiph/@u_3 -S 0x4b94c vdiph/ii -S 0x4bb10 vdiph/i#i -S 0x4bc54 vdiph2/uw_3 -S 0x4bd98 vdiph2/ea -S 0x4bedc vdiph2/eo -S 0x4c060 vdiph2/e[u -S 0x4c1a4 vdiph2/oa -S 0x4c2e8 d/tap -S 0x4c3ac d/tap_i -S 0x4c470 vowel/a_4 -S 0x4c574 vowel/ee#_2 -S 0x4c678 vowel/y_5 -S 0x4c7bc vowel/yy_3 -S 0x4c8c0 vowel/oe_4 -S 0x4c984 vowel/aa_4 -S 0x4ca88 vwl_sv/r_sv3 -S 0x4cc8c vowel/y_4 -S 0x4cd90 vowel/oe_2 -S 0x4ce94 vwl_no/y# -S 0x4cf98 vwl_no/& -S 0x4d09c vwl_no/u# -S 0x4d1a0 vwl_no/u#2 -S 0x4d2e4 vdiph/ai_3 -S 0x4d428 vwl_no/y#y -S 0x4d56c vwl_no/au- -S 0x4d730 vowel/y## -S 0x4d834 vowel/y#_3 -S 0x4d938 vdiph/ou_3 -S 0x4da3c vdiph/y#i_2 -S 0x4db80 m/m#_ -S 0x4dc84 n/n#_ -S 0x4dd88 n^/n^#_ -S 0x4de8c nn/nn#_ -W 0x4df90 ufric/tl# -S 0x4e8f8 r3/r#_ -E 0x4e97c envelope/p_level -E 0x4e9fc envelope/p_fall -E 0x4ea7c envelope/p_rise -E 0x4eafc envelope/p_fallrise -E 0x4eb7c envelope/p_214 -E 0x4ebfc envelope/vi_5amp -E 0x4ec7c envelope/p_512 -E 0x4ecfc envelope/vi_6amp -S 0x4ed7c vowel/u_7 -S 0x4ee80 vowel/u#_5 -S 0x4ef84 vowel/@_2 -S 0x4f088 vdiph/&i_3 -S 0x4f20c vdiph/@i -S 0x4f350 vdiph/u-i -S 0x4f494 vdiph/aau_4 -S 0x4f618 vdiph2/ii@_3 -S 0x4f79c l/l_vi -S 0x4f8a0 vwl_zh/ang -S 0x4faa4 vwl_zh/aang -S 0x4fce8 vdiph/au_2 -S 0x4fe6c vwl_zh/eng -S 0x50070 vwl_zh/ing -S 0x502b4 vwl_zh/ng -S 0x503f8 vwl_zh/oeng -S 0x505bc vwl_zh/ong -S 0x50740 vwl_zh/ung -S 0x508c4 vowel/8_3 -E 0x509c8 envelope/i_risefall -W 0x50a48 ustop/t_unasp2 -S 0x50b54 n/n_long_ -W 0x50c18 ustop/k_unasp_ -W 0x50ed4 ustop/tsh_pzd_unasp -W 0x51724 ustop/tsh_pzd -W 0x52264 ustop/ts_unasp -W 0x52adc ustop/ts_rfx_unasp -W 0x536c8 ustop/ts_rfx -S 0x543a8 nn/nn2_ -S 0x5446c vwl_zh/a_n -S 0x54570 vwl_zh/aau -S 0x546b4 vowel/ii_2 -S 0x54778 vowel/i#_7 -S 0x5487c vowel/i#_6 -S 0x54980 vwl_zh/iaa -S 0x54ac4 vwl_zh/iaau -S 0x54c48 vwl_zh/ie -S 0x54d8c vdiph2/iioo -S 0x54ed0 vwl_zh/iou -S 0x55054 vowel/8 -S 0x55158 vwl_zh/uaa -S 0x5529c vwl_zh/uai -S 0x55420 vwl_zh/uei -S 0x555a4 vwl_zh/uo -S 0x55728 vwl_zh/y& -S 0x5586c vwl_zh/yee -S 0x559b0 vdiph2/y@ -S 0x55af4 vowel/u_5 -S 0x55bf8 vnasal/m- -S 0x55cfc vnasal/n- -S 0x55e00 vnasal/nn- -S 0x55f04 vowel/u#_7 -S 0x56008 vowel/8_5 -S 0x5610c vowel/o_7 -S 0x56210 vowel/uu# -S 0x56314 vowel/8_6 -S 0x56418 vowel/ee_4 -S 0x5651c vdiph2/ye -S 0x56660 l/l_front_ -S 0x567a4 l/l_front -S 0x568a8 l/l_4 -S 0x5696c vwl_fr/@R3 -S 0x56a30 vwl_fr/@R4 -S 0x56af4 r/a_ diff --git a/navit/support/espeak/espeak-data/phonindex b/navit/support/espeak/espeak-data/phonindex Binary files differdeleted file mode 100644 index 8bed38930..000000000 --- a/navit/support/espeak/espeak-data/phonindex +++ /dev/null diff --git a/navit/support/espeak/espeak-data/phontab b/navit/support/espeak/espeak-data/phontab Binary files differdeleted file mode 100644 index c0d3a751d..000000000 --- a/navit/support/espeak/espeak-data/phontab +++ /dev/null diff --git a/navit/support/espeak/espeak-data/pl_dict b/navit/support/espeak/espeak-data/pl_dict Binary files differdeleted file mode 100644 index e46b00b04..000000000 --- a/navit/support/espeak/espeak-data/pl_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/pt_dict b/navit/support/espeak/espeak-data/pt_dict Binary files differdeleted file mode 100644 index 9ba2a7a78..000000000 --- a/navit/support/espeak/espeak-data/pt_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/ro_dict b/navit/support/espeak/espeak-data/ro_dict Binary files differdeleted file mode 100644 index b0a72f406..000000000 --- a/navit/support/espeak/espeak-data/ro_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/ru_dict b/navit/support/espeak/espeak-data/ru_dict Binary files differdeleted file mode 100644 index 52d652ccd..000000000 --- a/navit/support/espeak/espeak-data/ru_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/sk_dict b/navit/support/espeak/espeak-data/sk_dict Binary files differdeleted file mode 100644 index a5d7e7c75..000000000 --- a/navit/support/espeak/espeak-data/sk_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/sq_dict b/navit/support/espeak/espeak-data/sq_dict Binary files differdeleted file mode 100644 index aea3d0625..000000000 --- a/navit/support/espeak/espeak-data/sq_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/sv_dict b/navit/support/espeak/espeak-data/sv_dict Binary files differdeleted file mode 100644 index 1327d8d0c..000000000 --- a/navit/support/espeak/espeak-data/sv_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/sw_dict b/navit/support/espeak/espeak-data/sw_dict Binary files differdeleted file mode 100644 index 77e2fd233..000000000 --- a/navit/support/espeak/espeak-data/sw_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/ta_dict b/navit/support/espeak/espeak-data/ta_dict Binary files differdeleted file mode 100644 index 214e2f4da..000000000 --- a/navit/support/espeak/espeak-data/ta_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/tr_dict b/navit/support/espeak/espeak-data/tr_dict Binary files differdeleted file mode 100644 index a3f685047..000000000 --- a/navit/support/espeak/espeak-data/tr_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/vi_dict b/navit/support/espeak/espeak-data/vi_dict Binary files differdeleted file mode 100644 index 24a645a03..000000000 --- a/navit/support/espeak/espeak-data/vi_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/voices/!v/croak b/navit/support/espeak/espeak-data/voices/!v/croak deleted file mode 100755 index ae76a4c4d..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/croak +++ /dev/null @@ -1,11 +0,0 @@ -language variant -name croak -gender male 70 - -pitch 85 117 -flutter 20 - -formant 0 100 80 110 - - - diff --git a/navit/support/espeak/espeak-data/voices/!v/f1 b/navit/support/espeak/espeak-data/voices/!v/f1 deleted file mode 100755 index 13664a34f..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/f1 +++ /dev/null @@ -1,18 +0,0 @@ -language variant -name female1 -gender female - -pitch 145 200 -flutter 7 -roughness 4 -formant 0 115 80 150 -formant 1 120 80 180 -formant 2 100 70 150 150 -formant 3 115 70 150 -formant 4 110 80 150 -formant 5 110 90 150 -formant 6 105 80 150 -formant 7 110 70 150 -formant 8 110 70 150 - -stressAdd -10 -10 -20 -20 0 0 40 70 diff --git a/navit/support/espeak/espeak-data/voices/!v/f2 b/navit/support/espeak/espeak-data/voices/!v/f2 deleted file mode 100755 index e92946707..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/f2 +++ /dev/null @@ -1,20 +0,0 @@ -language variant -name female2 -gender female - -pitch 142 220 -roughness 3 - -formant 0 105 80 150 -formant 1 110 80 160 -formant 2 110 70 150 -formant 3 110 70 150 -formant 4 115 80 150 -formant 5 115 80 150 -formant 6 110 70 150 -formant 7 110 70 150 -formant 8 110 70 150 - -stressAdd 0 0 -10 -10 0 0 10 40 -breath 0 2 3 3 3 3 3 2 -echo 140 10 diff --git a/navit/support/espeak/espeak-data/voices/!v/f3 b/navit/support/espeak/espeak-data/voices/!v/f3 deleted file mode 100644 index 92a158281..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/f3 +++ /dev/null @@ -1,22 +0,0 @@ -language variant -name female3 -gender female - -pitch 140 240 -formant 0 105 80 150 -formant 1 120 75 150 -50 -formant 2 135 70 150 -250 -formant 3 125 80 150 -formant 4 125 80 150 -formant 5 125 80 150 -formant 6 120 70 150 -formant 7 110 70 150 -formant 8 110 70 150 - -stressAmp 18 18 20 20 20 20 20 20 -//breath 0 2 4 4 4 4 4 4 -breath 0 2 3 3 3 3 3 2 -echo 120 10 -roughness 4 - - diff --git a/navit/support/espeak/espeak-data/voices/!v/f4 b/navit/support/espeak/espeak-data/voices/!v/f4 deleted file mode 100644 index 52c5ac935..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/f4 +++ /dev/null @@ -1,18 +0,0 @@ -language variant -name female4 -gender female - -echo 130 15 -pitch 142 200 -formant 0 120 80 150 -formant 1 115 80 160 -20 -formant 2 130 75 150 -200 -formant 3 123 75 150 -formant 4 125 80 150 -formant 5 125 80 150 -formant 6 110 80 150 -formant 7 110 75 150 -formant 8 110 75 150 - -stressAdd -20 -20 -20 -20 0 0 20 120 -stressAmp 18 16 20 20 20 20 20 20 diff --git a/navit/support/espeak/espeak-data/voices/!v/fast b/navit/support/espeak/espeak-data/voices/!v/fast deleted file mode 100755 index 30441d7e2..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/fast +++ /dev/null @@ -1,11 +0,0 @@ -language variant -name fast_test - -// Try decreasing these values to make eSpeak's fastest speed faster. -// The 3 parameters affect: -// pauses, -// unvoiced consonants, -// vowels and voiced consonants -// The default values are: fast 15 72 110 - -fast_test 15 72 110 diff --git a/navit/support/espeak/espeak-data/voices/!v/m1 b/navit/support/espeak/espeak-data/voices/!v/m1 deleted file mode 100755 index 57603a885..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/m1 +++ /dev/null @@ -1,19 +0,0 @@ -language variant -name male1 -gender male 70 - -pitch 74 109 -flutter 4 -roughness 4 - -formant 0 98 95 100 -formant 1 97 95 100 -formant 2 97 95 100 -formant 3 97 100 100 -formant 4 97 100 100 -formant 5 105 100 100 -formant 6 95 100 100 -formant 7 100 100 100 -formant 8 100 100 100 - -stressAdd -10 -10 -20 -20 0 0 40 70 diff --git a/navit/support/espeak/espeak-data/voices/!v/m2 b/navit/support/espeak/espeak-data/voices/!v/m2 deleted file mode 100644 index c234f4687..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/m2 +++ /dev/null @@ -1,15 +0,0 @@ -language variant -name male2 -gender male - -pitch 88 115 -echo 130 15 -formant 0 100 80 120 -formant 1 90 85 120 -formant 2 110 85 120 -formant 3 105 90 120 -formant 4 100 90 120 -formant 5 100 90 120 -formant 6 100 90 120 -formant 7 100 90 120 -formant 8 100 90 120 diff --git a/navit/support/espeak/espeak-data/voices/!v/m3 b/navit/support/espeak/espeak-data/voices/!v/m3 deleted file mode 100644 index 581cd883f..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/m3 +++ /dev/null @@ -1,16 +0,0 @@ -language variant -name male3 -gender male - -pitch 80 122 -formant 0 100 100 100 -formant 1 96 97 100 -formant 2 96 97 100 -formant 3 96 103 100 -formant 4 95 103 100 -formant 5 95 103 100 -formant 6 100 100 100 -formant 7 100 100 100 -formant 8 100 100 100 - -stressAdd 10 10 0 0 0 0 -30 -30 diff --git a/navit/support/espeak/espeak-data/voices/!v/m4 b/navit/support/espeak/espeak-data/voices/!v/m4 deleted file mode 100644 index 7199341c3..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/m4 +++ /dev/null @@ -1,17 +0,0 @@ -language variant -name male4 -gender male - -pitch 70 110 - -formant 0 103 100 100 -formant 1 103 100 100 -formant 2 103 100 100 -formant 3 103 100 100 -formant 4 106 100 100 -formant 5 106 100 100 -formant 6 106 100 100 -formant 7 103 100 100 -formant 8 103 100 100 - -stressAdd -10 -10 -30 -30 0 0 60 90 diff --git a/navit/support/espeak/espeak-data/voices/!v/m5 b/navit/support/espeak/espeak-data/voices/!v/m5 deleted file mode 100755 index d25865608..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/m5 +++ /dev/null @@ -1,15 +0,0 @@ -language variant -name male5 -gender male - -formant 0 100 85 130 -formant 1 90 85 130 40 -formant 2 80 85 130 310 -formant 3 105 85 130 -formant 4 105 85 130 -formant 5 105 85 130 -formant 6 105 85 150 -formant 7 105 85 150 -formant 8 105 85 150 - -intonation 2 diff --git a/navit/support/espeak/espeak-data/voices/!v/m6 b/navit/support/espeak/espeak-data/voices/!v/m6 deleted file mode 100755 index bd336a988..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/m6 +++ /dev/null @@ -1,13 +0,0 @@ -language variant -name male6 -gender male - -pitch 82 117 - -formant 0 100 90 120 -formant 1 100 90 140 -formant 2 100 70 140 -formant 3 100 75 140 -formant 4 100 80 140 -formant 5 100 80 140 - diff --git a/navit/support/espeak/espeak-data/voices/!v/m7 b/navit/support/espeak/espeak-data/voices/!v/m7 deleted file mode 100755 index 9a8370622..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/m7 +++ /dev/null @@ -1,18 +0,0 @@ -language variant
-gender male 35
-name male5
-
-formant 0 120 150 220
-
-formant 1 100 100 100
-formant 2 100 100 100
-formant 3 100 100 100
-
-formant 4 100 80 100
-formant 5 100 100 100
-
-formant 6 80 200 80
-formant 7 80 200 100
-
-pitch 80 118
-tone 600 150 255 50 100 100
diff --git a/navit/support/espeak/espeak-data/voices/!v/whisper b/navit/support/espeak/espeak-data/voices/!v/whisper deleted file mode 100755 index 4f8f5e88f..000000000 --- a/navit/support/espeak/espeak-data/voices/!v/whisper +++ /dev/null @@ -1,13 +0,0 @@ -language variant -name whisper -gender male - -pitch 82 117 -flutter 20 - -formant 0 100 0 100 -formant 1 100 80 100 - -voicing 17 -breath 75 75 50 40 15 10 -breathw 150 150 200 200 400 400 diff --git a/navit/support/espeak/espeak-data/voices/af b/navit/support/espeak/espeak-data/voices/af deleted file mode 100755 index bcbb2a005..000000000 --- a/navit/support/espeak/espeak-data/voices/af +++ /dev/null @@ -1,8 +0,0 @@ -name afrikaans -language af -gender male -roughness 0 -pitch 63 120 - - - diff --git a/navit/support/espeak/espeak-data/voices/bs b/navit/support/espeak/espeak-data/voices/bs deleted file mode 100755 index eadd70732..000000000 --- a/navit/support/espeak/espeak-data/voices/bs +++ /dev/null @@ -1,16 +0,0 @@ -name bosnian -language bs -phonemes hr -dictionary hbs -gender male - -pitch 81 120 -formant 0 100 100 100 -formant 1 97 97 100 -formant 2 97 97 100 -formant 3 97 102 100 -formant 4 97 102 100 -formant 5 97 102 100 - -stressAdd 10 10 0 0 0 0 -30 -30 -dictrules 3 4 diff --git a/navit/support/espeak/espeak-data/voices/ca b/navit/support/espeak/espeak-data/voices/ca deleted file mode 100644 index dc51396ce..000000000 --- a/navit/support/espeak/espeak-data/voices/ca +++ /dev/null @@ -1,4 +0,0 @@ -name catalan -language ca -gender male - diff --git a/navit/support/espeak/espeak-data/voices/cs b/navit/support/espeak/espeak-data/voices/cs deleted file mode 100755 index 1c2992dd5..000000000 --- a/navit/support/espeak/espeak-data/voices/cs +++ /dev/null @@ -1,4 +0,0 @@ -name czech -language cs -gender male - diff --git a/navit/support/espeak/espeak-data/voices/cy b/navit/support/espeak/espeak-data/voices/cy deleted file mode 100755 index 2991e99d1..000000000 --- a/navit/support/espeak/espeak-data/voices/cy +++ /dev/null @@ -1,5 +0,0 @@ -language cy -name welsh-test -gender male - -intonation 4 diff --git a/navit/support/espeak/espeak-data/voices/da b/navit/support/espeak/espeak-data/voices/da deleted file mode 100755 index ec9936cc2..000000000 --- a/navit/support/espeak/espeak-data/voices/da +++ /dev/null @@ -1,3 +0,0 @@ -name danish-test -language da -gender male diff --git a/navit/support/espeak/espeak-data/voices/de b/navit/support/espeak/espeak-data/voices/de deleted file mode 100755 index 653c3f5c4..000000000 --- a/navit/support/espeak/espeak-data/voices/de +++ /dev/null @@ -1,5 +0,0 @@ -name german -language de -gender male - - diff --git a/navit/support/espeak/espeak-data/voices/default b/navit/support/espeak/espeak-data/voices/default deleted file mode 100755 index b2fd9d084..000000000 --- a/navit/support/espeak/espeak-data/voices/default +++ /dev/null @@ -1,4 +0,0 @@ -name default -language en -gender male - diff --git a/navit/support/espeak/espeak-data/voices/el b/navit/support/espeak/espeak-data/voices/el deleted file mode 100755 index 1e9a757f8..000000000 --- a/navit/support/espeak/espeak-data/voices/el +++ /dev/null @@ -1,5 +0,0 @@ -name greek -language el -gender male - - diff --git a/navit/support/espeak/espeak-data/voices/en/en b/navit/support/espeak/espeak-data/voices/en/en deleted file mode 100755 index 43e2ca1fc..000000000 --- a/navit/support/espeak/espeak-data/voices/en/en +++ /dev/null @@ -1,9 +0,0 @@ -name english -language en-uk 2 -language en 2 -gender male - -//pitch 80 117 - -replace 03 I i -replace 03 I2 i diff --git a/navit/support/espeak/espeak-data/voices/en/en-n b/navit/support/espeak/espeak-data/voices/en/en-n deleted file mode 100755 index 933311dad..000000000 --- a/navit/support/espeak/espeak-data/voices/en/en-n +++ /dev/null @@ -1,14 +0,0 @@ -name lancashire -language en-uk-north -language en-uk 3 -gender male - -phonemes en_n - -stressLength 160 150 180 180 220 220 290 290 - -replace 00 i@3 i@ -replace 03 N n -//replace 03 I i -//replace 03 I2 i - diff --git a/navit/support/espeak/espeak-data/voices/en/en-rp b/navit/support/espeak/espeak-data/voices/en/en-rp deleted file mode 100755 index 3489f28ad..000000000 --- a/navit/support/espeak/espeak-data/voices/en/en-rp +++ /dev/null @@ -1,12 +0,0 @@ -name english_rp -language en-uk-rp -language en-uk 4 -gender male - -phonemes en_rp -replace 00 o@ O@ -replace 00 i@3 i@ -replace 03 I i -replace 03 I2 i -replace 03 @ a2 -replace 03 3 a2 diff --git a/navit/support/espeak/espeak-data/voices/en/en-sc b/navit/support/espeak/espeak-data/voices/en/en-sc deleted file mode 100755 index e16ae25a8..000000000 --- a/navit/support/espeak/espeak-data/voices/en/en-sc +++ /dev/null @@ -1,16 +0,0 @@ -name en-scottish -language en-sc -language en 4 -gender male - -phonemes en_sc -dictrules 5 6 7 -stressLength 180 130 200 200 0 0 250 270 - -replace 03 @ V -replace 03 I i -replace 03 I2 i -replace 01 aI aI2 -replace 02 a a/ -replace 02 u: U -replace 02 3: VR diff --git a/navit/support/espeak/espeak-data/voices/en/en-us b/navit/support/espeak/espeak-data/voices/en/en-us deleted file mode 100755 index c2656b28c..000000000 --- a/navit/support/espeak/espeak-data/voices/en/en-us +++ /dev/null @@ -1,17 +0,0 @@ -// moving towards US English -name english-us -language en-us 2 -language en-r -language en 3 -gender male - -phonemes en_us -dictrules 3 6 -option 12 1 // reduce [t] - -stressLength 145 125 170 170 0 0 265 290 -stressAmp 17 16 20 20 20 22 22 20 - -replace 03 I i -replace 03 I2 i -replace 03 @ @/ diff --git a/navit/support/espeak/espeak-data/voices/en/en-wi b/navit/support/espeak/espeak-data/voices/en/en-wi deleted file mode 100755 index 28a42a563..000000000 --- a/navit/support/espeak/espeak-data/voices/en/en-wi +++ /dev/null @@ -1,19 +0,0 @@ -name en-westindies -language en-wi -language en-uk 4 -gender male - -phonemes en_wi -dictrules 8 -stressLength 175 175 175 175 220 220 250 290 - -replace 00 D d -replace 00 T t[ -replace 00 U@ o@ -replace 00 i@3 i@ -replace 03 @ a2 -replace 03 3 a2 -replace 03 N n - -formant 1 98 100 100 -formant 2 98 100 100 diff --git a/navit/support/espeak/espeak-data/voices/en/en-wm b/navit/support/espeak/espeak-data/voices/en/en-wm deleted file mode 100755 index aa82f88fb..000000000 --- a/navit/support/espeak/espeak-data/voices/en/en-wm +++ /dev/null @@ -1,12 +0,0 @@ -name english_wmids -language en-uk-wmids -gender male - -phonemes en_wm - -replace 00 h NULL -replace 00 o@ O@ -replace 00 i@3 i@ -dictrules 6 -intonation 4 -stressAdd 0 0 0 0 0 0 0 20 diff --git a/navit/support/espeak/espeak-data/voices/eo b/navit/support/espeak/espeak-data/voices/eo deleted file mode 100755 index 36a4bff65..000000000 --- a/navit/support/espeak/espeak-data/voices/eo +++ /dev/null @@ -1,3 +0,0 @@ -name esperanto -language eo -gender male diff --git a/navit/support/espeak/espeak-data/voices/es b/navit/support/espeak/espeak-data/voices/es deleted file mode 100755 index 1a9e53b6e..000000000 --- a/navit/support/espeak/espeak-data/voices/es +++ /dev/null @@ -1,7 +0,0 @@ -name spanish -language es -gender male - -dictrules 1 -intonation 3 - diff --git a/navit/support/espeak/espeak-data/voices/es-la b/navit/support/espeak/espeak-data/voices/es-la deleted file mode 100755 index c326c46f5..000000000 --- a/navit/support/espeak/espeak-data/voices/es-la +++ /dev/null @@ -1,11 +0,0 @@ -name spanish-latin-american -language es-la -language es-mx 6 -gender male - -phonemes es_la -dictrules 2 -intonation 2 -stressLength 170 200 180 180 0 0 250 280 - -replace 00 T s diff --git a/navit/support/espeak/espeak-data/voices/fi b/navit/support/espeak/espeak-data/voices/fi deleted file mode 100755 index 6e11c9312..000000000 --- a/navit/support/espeak/espeak-data/voices/fi +++ /dev/null @@ -1,4 +0,0 @@ -name finnish -language fi -gender male - diff --git a/navit/support/espeak/espeak-data/voices/fr b/navit/support/espeak/espeak-data/voices/fr deleted file mode 100755 index 973073161..000000000 --- a/navit/support/espeak/espeak-data/voices/fr +++ /dev/null @@ -1,7 +0,0 @@ -language fr -name french -gender male - -dictrules 1 -intonation 3 - diff --git a/navit/support/espeak/espeak-data/voices/fr-be b/navit/support/espeak/espeak-data/voices/fr-be deleted file mode 100755 index cba9b2757..000000000 --- a/navit/support/espeak/espeak-data/voices/fr-be +++ /dev/null @@ -1,7 +0,0 @@ -language fr-be -name french (Belgium) -gender male - -dictrules 2 -intonation 3 - diff --git a/navit/support/espeak/espeak-data/voices/hi b/navit/support/espeak/espeak-data/voices/hi deleted file mode 100755 index de4786c94..000000000 --- a/navit/support/espeak/espeak-data/voices/hi +++ /dev/null @@ -1,9 +0,0 @@ -name hindi-test -language hi -gender male - -translator hi -phonemes hi -dictionary hi - -dictrules 1 diff --git a/navit/support/espeak/espeak-data/voices/hr b/navit/support/espeak/espeak-data/voices/hr deleted file mode 100755 index d6811d3ae..000000000 --- a/navit/support/espeak/espeak-data/voices/hr +++ /dev/null @@ -1,18 +0,0 @@ -name croatian -language hr -language hbs -gender male - -dictionary hbs - -// attributes towards !variant3 -pitch 81 120 -formant 0 100 100 100 -formant 1 97 97 100 -formant 2 97 97 100 -formant 3 97 102 100 -formant 4 97 102 100 -formant 5 97 102 100 - -stressAdd 10 10 0 0 0 0 -30 -30 -dictrules 1 diff --git a/navit/support/espeak/espeak-data/voices/hu b/navit/support/espeak/espeak-data/voices/hu deleted file mode 100755 index ba2bdde41..000000000 --- a/navit/support/espeak/espeak-data/voices/hu +++ /dev/null @@ -1,3 +0,0 @@ -name hungarian -language hu -gender male diff --git a/navit/support/espeak/espeak-data/voices/hy b/navit/support/espeak/espeak-data/voices/hy deleted file mode 100644 index 6c65e3c68..000000000 --- a/navit/support/espeak/espeak-data/voices/hy +++ /dev/null @@ -1,3 +0,0 @@ -name armenian -language hy -gender male diff --git a/navit/support/espeak/espeak-data/voices/hy-west b/navit/support/espeak/espeak-data/voices/hy-west deleted file mode 100644 index 46317618d..000000000 --- a/navit/support/espeak/espeak-data/voices/hy-west +++ /dev/null @@ -1,19 +0,0 @@ -name armenian-west -language hy -gender male - -// change consonants for West Armenian pronunciation -replace 00 b p# -replace 00 d t# -replace 00 dz ts# -replace 00 dZ tS -replace 00 g k# - -replace 00 p b -replace 00 t d -replace 00 ts dz -replace 00 c dZ -replace 00 k g - -replace 00 ** R // ?? -replace 00 r R diff --git a/navit/support/espeak/espeak-data/voices/id b/navit/support/espeak/espeak-data/voices/id deleted file mode 100755 index ce800f70b..000000000 --- a/navit/support/espeak/espeak-data/voices/id +++ /dev/null @@ -1,8 +0,0 @@ -name indonesian-test -language id -gender male - -stressLength 160 200 180 180 0 0 220 240 -stressAmp 16 18 18 18 0 0 22 21 - -consonants 80 80 diff --git a/navit/support/espeak/espeak-data/voices/is b/navit/support/espeak/espeak-data/voices/is deleted file mode 100755 index 9e9c4e747..000000000 --- a/navit/support/espeak/espeak-data/voices/is +++ /dev/null @@ -1,4 +0,0 @@ -name icelandic-test -language is -gender male - diff --git a/navit/support/espeak/espeak-data/voices/it b/navit/support/espeak/espeak-data/voices/it deleted file mode 100755 index 53c2a7048..000000000 --- a/navit/support/espeak/espeak-data/voices/it +++ /dev/null @@ -1,6 +0,0 @@ -name italian -language it -gender male - -replace 03 i I - diff --git a/navit/support/espeak/espeak-data/voices/ku b/navit/support/espeak/espeak-data/voices/ku deleted file mode 100755 index 536957cb8..000000000 --- a/navit/support/espeak/espeak-data/voices/ku +++ /dev/null @@ -1,6 +0,0 @@ -name kurdish -language ku -gender male - -//words 1 48 - diff --git a/navit/support/espeak/espeak-data/voices/la b/navit/support/espeak/espeak-data/voices/la deleted file mode 100644 index f3e97b523..000000000 --- a/navit/support/espeak/espeak-data/voices/la +++ /dev/null @@ -1,13 +0,0 @@ -name latin -language la -gender male -stressrule 2 33 0 2 -// rule=penultimate -// flags=0100001 (no automatic secondary stress + don't stres monosyllables) -// unstressed_wd1=0 -// unstressed_wd2=2 - -// short gap between words -words 2 - -// Note: The Latin voice needs long vowels to be marked with macrons diff --git a/navit/support/espeak/espeak-data/voices/lv b/navit/support/espeak/espeak-data/voices/lv deleted file mode 100755 index 0278ea213..000000000 --- a/navit/support/espeak/espeak-data/voices/lv +++ /dev/null @@ -1,6 +0,0 @@ -name latvian -language lv -gender male - -replace 03 o o: - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-af1 b/navit/support/espeak/espeak-data/voices/mb/mb-af1 deleted file mode 100755 index 03dac4f6b..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-af1 +++ /dev/null @@ -1,7 +0,0 @@ -name afrikaans-mbrola-1 -language af 7 -gender male - -pitch 82 117 -mbrola af1 af1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-af1-en b/navit/support/espeak/espeak-data/voices/mb/mb-af1-en deleted file mode 100755 index 71ecab719..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-af1-en +++ /dev/null @@ -1,7 +0,0 @@ -name en-afrikaans -language en 11 -gender male - -pitch 82 117 -mbrola af1 af1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-br1 b/navit/support/espeak/espeak-data/voices/mb/mb-br1 deleted file mode 100755 index ba7c42cc4..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-br1 +++ /dev/null @@ -1,9 +0,0 @@ -language pt 7 -name brazil-mbrola-1 -gender male -pitch 82 117 - -dictrules 2 3 4 - -mbrola br1 ptbr_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-br3 b/navit/support/espeak/espeak-data/voices/mb/mb-br3 deleted file mode 100644 index 8479e658e..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-br3 +++ /dev/null @@ -1,9 +0,0 @@ -language pt 7 -name brazil-mbrola-3 -gender male -pitch 82 117 - -dictrules 2 3 4 - -mbrola br3 ptbr_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-br4 b/navit/support/espeak/espeak-data/voices/mb/mb-br4 deleted file mode 100644 index d3d772007..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-br4 +++ /dev/null @@ -1,9 +0,0 @@ -language pt 7 -name brazil-mbrola-4 -gender female -pitch 140 220 - -dictrules 2 3 4 - -mbrola br4 ptbr4_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-cr1 b/navit/support/espeak/espeak-data/voices/mb/mb-cr1 deleted file mode 100755 index 9b280bf8b..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-cr1 +++ /dev/null @@ -1,9 +0,0 @@ -name croatian-mbrola-1 -language hr 7 -gender male - -dictionary hbs -dictrules 1 - -pitch 82 117 -mbrola cr1 cr1_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-cz2 b/navit/support/espeak/espeak-data/voices/mb/mb-cz2 deleted file mode 100755 index dbde21234..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-cz2 +++ /dev/null @@ -1,6 +0,0 @@ -name czech-mbrola-2 -language cs 7 -gender male - -pitch 82 117 -mbrola cz2 cs_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-de2 b/navit/support/espeak/espeak-data/voices/mb/mb-de2 deleted file mode 100755 index c0a5475ec..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-de2 +++ /dev/null @@ -1,6 +0,0 @@ -name german-mbrola-2 -language de 6 -gender male - -mbrola de2 de2_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-de4 b/navit/support/espeak/espeak-data/voices/mb/mb-de4 deleted file mode 100755 index 31bd479a3..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-de4 +++ /dev/null @@ -1,6 +0,0 @@ -name german-mbrola-4 -language de 6 -gender male - -mbrola de4 de4_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-de4-en b/navit/support/espeak/espeak-data/voices/mb/mb-de4-en deleted file mode 100755 index 8fd4a63a1..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-de4-en +++ /dev/null @@ -1,6 +0,0 @@ -name en-german -language en 9 -gender male - -mbrola de4 de4_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-de5 b/navit/support/espeak/espeak-data/voices/mb/mb-de5 deleted file mode 100755 index 569f9d054..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-de5 +++ /dev/null @@ -1,10 +0,0 @@ -name german-mbrola-5 -language de 7 -gender female - -pitch 140 220 -mbrola de5 de6_phtrans 22050 - -// avoid glottal stops. de5 assumes [?] between pause and vowel -replace 00 _! _ -replace 00 _| _ diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-de5-en b/navit/support/espeak/espeak-data/voices/mb/mb-de5-en deleted file mode 100755 index e416c6dc5..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-de5-en +++ /dev/null @@ -1,7 +0,0 @@ -name en-german-5 -language en -gender female - -pitch 140 220 -mbrola de5 de6_phtrans 22050 - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-de6 b/navit/support/espeak/espeak-data/voices/mb/mb-de6 deleted file mode 100644 index 35a4a3fc5..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-de6 +++ /dev/null @@ -1,6 +0,0 @@ -name german-mbrola-6 -language de 6 -gender male - -mbrola de6 de6_phtrans 22050 - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-de6-grc b/navit/support/espeak/espeak-data/voices/mb/mb-de6-grc deleted file mode 100644 index a6e0f46bb..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-de6-grc +++ /dev/null @@ -1,6 +0,0 @@ -name german-mbrola-6 -language grc 6 -gender male - -mbrola de6 grc-de6_phtrans 22050 - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-de7 b/navit/support/espeak/espeak-data/voices/mb/mb-de7 deleted file mode 100755 index aa80edaad..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-de7 +++ /dev/null @@ -1,7 +0,0 @@ -name german-mbrola-7 -language de 7 -gender female - -pitch 140 220 -mbrola de7 de6_phtrans 22050 - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-en1 b/navit/support/espeak/espeak-data/voices/mb/mb-en1 deleted file mode 100755 index fc60f4167..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-en1 +++ /dev/null @@ -1,7 +0,0 @@ -name english-mb-en1 -language en-uk 3 -language en 2 -gender male - -pitch 82 117 -mbrola en1 en1_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-es1 b/navit/support/espeak/espeak-data/voices/mb/mb-es1 deleted file mode 100755 index d59fe7952..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-es1 +++ /dev/null @@ -1,7 +0,0 @@ -language es 7 -name spanish-mbrola-1 -gender male -pitch 82 117 - -mbrola es1 es_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-es2 b/navit/support/espeak/espeak-data/voices/mb/mb-es2 deleted file mode 100644 index 42de58882..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-es2 +++ /dev/null @@ -1,7 +0,0 @@ -language es 7 -name spanish-mbrola-2 -gender male -pitch 82 117 - -mbrola es2 es_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-fr1 b/navit/support/espeak/espeak-data/voices/mb/mb-fr1 deleted file mode 100755 index 7cbdab338..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-fr1 +++ /dev/null @@ -1,9 +0,0 @@ -language fr 7 -name french-mbrola-1 -gender male - -dictrules 1 -stressLength 180 180 180 180 0 0 220 220 -pitch 82 117 -mbrola fr1 fr1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-fr1-en b/navit/support/espeak/espeak-data/voices/mb/mb-fr1-en deleted file mode 100755 index 366653147..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-fr1-en +++ /dev/null @@ -1,8 +0,0 @@ -name en-french -language en 10 -gender male - -dictrules 1 -pitch 82 117 -mbrola fr1 fr1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-fr4 b/navit/support/espeak/espeak-data/voices/mb/mb-fr4 deleted file mode 100755 index c276bec0d..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-fr4 +++ /dev/null @@ -1,8 +0,0 @@ -language fr 7 -name french-mbrola-4 -gender female - -dictrules 1 -pitch 140 220 -mbrola fr1 fr1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-fr4-en b/navit/support/espeak/espeak-data/voices/mb/mb-fr4-en deleted file mode 100755 index b8f782946..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-fr4-en +++ /dev/null @@ -1,8 +0,0 @@ -language en 10 -name en-french -gender female - -dictrules 1 -pitch 140 220 -mbrola fr1 fr1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-gr2 b/navit/support/espeak/espeak-data/voices/mb/mb-gr2 deleted file mode 100755 index 30dea8920..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-gr2 +++ /dev/null @@ -1,6 +0,0 @@ -name greek-mbrola-1 -language el 7 -gender male - -pitch 82 117 -mbrola gr2 gr2_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-gr2-en b/navit/support/espeak/espeak-data/voices/mb/mb-gr2-en deleted file mode 100755 index b48b1788b..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-gr2-en +++ /dev/null @@ -1,6 +0,0 @@ -name en-greek -language en 7 -gender male - -pitch 82 117 -mbrola gr2 gr2_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-hu1 b/navit/support/espeak/espeak-data/voices/mb/mb-hu1 deleted file mode 100755 index b8519559d..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-hu1 +++ /dev/null @@ -1,6 +0,0 @@ -name hungarian-mbrola-1 -language hu 7 -gender female - -pitch 140 220 -mbrola hu1 hu1_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-hu1-en b/navit/support/espeak/espeak-data/voices/mb/mb-hu1-en deleted file mode 100755 index 73ac62a4a..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-hu1-en +++ /dev/null @@ -1,6 +0,0 @@ -name en-hungarian -language en 10 -gender female - -pitch 140 220 -mbrola hu1 hu1_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-id1 b/navit/support/espeak/espeak-data/voices/mb/mb-id1 deleted file mode 100755 index b86f59306..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-id1 +++ /dev/null @@ -1,7 +0,0 @@ -name indonesian-mbrola-1 -language id 7 -gender male - -pitch 82 117 -mbrola id1 id1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-it3 b/navit/support/espeak/espeak-data/voices/mb/mb-it3 deleted file mode 100755 index 00e88867c..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-it3 +++ /dev/null @@ -1,8 +0,0 @@ -name italian-mbrola-3 -language it 7 -gender male - -pitch 82 117 -mbrola it3 it3_phtrans - -replace 03 i I // final unstressed "i" diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-it4 b/navit/support/espeak/espeak-data/voices/mb/mb-it4 deleted file mode 100755 index f2130ba4f..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-it4 +++ /dev/null @@ -1,8 +0,0 @@ -name italian-mbrola-4 -language it 7 -gender female - -pitch 140 220 -mbrola it4 it3_phtrans - -replace 03 i I // final unstressed "i" diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-la1 b/navit/support/espeak/espeak-data/voices/mb/mb-la1 deleted file mode 100755 index 7ef93a5ed..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-la1 +++ /dev/null @@ -1,6 +0,0 @@ -name latin-mbrola-1 -language la 7 -gender male - -pitch 82 117 -mbrola la1 la1_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-nl2 b/navit/support/espeak/espeak-data/voices/mb/mb-nl2 deleted file mode 100755 index fc377156b..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-nl2 +++ /dev/null @@ -1,7 +0,0 @@ -language nl 7 -name dutch-mbrola-2 -gender male - -pitch 82 117 -mbrola nl2 nl_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-nl2-en b/navit/support/espeak/espeak-data/voices/mb/mb-nl2-en deleted file mode 100755 index 0c2d13a65..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-nl2-en +++ /dev/null @@ -1,7 +0,0 @@ -language en 10 -name en-dutch -gender male - -pitch 82 117 -mbrola nl2 nl_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-pl1 b/navit/support/espeak/espeak-data/voices/mb/mb-pl1 deleted file mode 100755 index 4e2b9d23e..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-pl1 +++ /dev/null @@ -1,6 +0,0 @@ -name polish-mbrola-1 -language pl 7 -gender female - -pitch 140 220 -mbrola pl1 pl1_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-pl1-en b/navit/support/espeak/espeak-data/voices/mb/mb-pl1-en deleted file mode 100755 index 9ba872a49..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-pl1-en +++ /dev/null @@ -1,6 +0,0 @@ -name en-polish -language en 11 -gender female - -pitch 140 220 -mbrola pl1 pl1_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-pt1 b/navit/support/espeak/espeak-data/voices/mb/mb-pt1 deleted file mode 100644 index ebd92ffb3..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-pt1 +++ /dev/null @@ -1,9 +0,0 @@ -language pt 7 -name portugal-mbrola-1 -gender female -pitch 140 220 - -dictrules 1 - -mbrola pt1 pt1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-ro1 b/navit/support/espeak/espeak-data/voices/mb/mb-ro1 deleted file mode 100755 index 14417c1fd..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-ro1 +++ /dev/null @@ -1,7 +0,0 @@ -name romanian-mbrola-1 -language ro 7 -gender male - -pitch 82 117 -mbrola ro1 ro1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-ro1-en b/navit/support/espeak/espeak-data/voices/mb/mb-ro1-en deleted file mode 100755 index f310f868e..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-ro1-en +++ /dev/null @@ -1,7 +0,0 @@ -name en-romanian -language en 9 -gender male - -pitch 82 117 -mbrola ro1 ro1_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-sw1 b/navit/support/espeak/espeak-data/voices/mb/mb-sw1 deleted file mode 100755 index 4c6239268..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-sw1 +++ /dev/null @@ -1,7 +0,0 @@ -name swedish-mbrola-1 -language sv 7 -gender male - -pitch 82 117 -mbrola sw1 sv_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-sw1-en b/navit/support/espeak/espeak-data/voices/mb/mb-sw1-en deleted file mode 100755 index 52692c385..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-sw1-en +++ /dev/null @@ -1,7 +0,0 @@ -name en-swedish -language en 11 -gender male - -pitch 82 117 -mbrola sw1 sv_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-sw2 b/navit/support/espeak/espeak-data/voices/mb/mb-sw2 deleted file mode 100755 index c632e263c..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-sw2 +++ /dev/null @@ -1,7 +0,0 @@ -name swedish-mbrola-2 -language sv 8 -gender female - -pitch 140 220 -mbrola sw2 sv2_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-sw2-en b/navit/support/espeak/espeak-data/voices/mb/mb-sw2-en deleted file mode 100755 index f2033dc11..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-sw2-en +++ /dev/null @@ -1,7 +0,0 @@ -name en-swedish-f -language en -gender female - -pitch 140 220 -mbrola sw2 sv2_phtrans - diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-us1 b/navit/support/espeak/espeak-data/voices/mb/mb-us1 deleted file mode 100755 index c62589be7..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-us1 +++ /dev/null @@ -1,12 +0,0 @@ -name us-mbrola-1 -language en-us -language en 8 -gender female - -phonemes en_us -dictrules 3 6 - -stressLength 170 135 205 205 0 0 245 275 - -pitch 140 220 -mbrola us1 us_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-us2 b/navit/support/espeak/espeak-data/voices/mb/mb-us2 deleted file mode 100755 index d94fce5a4..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-us2 +++ /dev/null @@ -1,12 +0,0 @@ -name us-mbrola-2 -language en-us -language en 7 -gender male - -phonemes en_us -dictrules 3 6 - -stressLength 170 135 205 205 0 0 245 275 - -pitch 82 117 -mbrola us2 us_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mb/mb-us3 b/navit/support/espeak/espeak-data/voices/mb/mb-us3 deleted file mode 100755 index 645e1b7d0..000000000 --- a/navit/support/espeak/espeak-data/voices/mb/mb-us3 +++ /dev/null @@ -1,12 +0,0 @@ -name us-mbrola-3 -language en-us -language en 8 -gender male - -phonemes en_us -dictrules 3 6 - -stressLength 170 135 205 205 0 0 245 275 - -pitch 82 117 -mbrola us3 us3_phtrans diff --git a/navit/support/espeak/espeak-data/voices/mk b/navit/support/espeak/espeak-data/voices/mk deleted file mode 100755 index 4607dd079..000000000 --- a/navit/support/espeak/espeak-data/voices/mk +++ /dev/null @@ -1,4 +0,0 @@ -name macedonian-test -language mk -gender male - diff --git a/navit/support/espeak/espeak-data/voices/nl b/navit/support/espeak/espeak-data/voices/nl deleted file mode 100755 index 6a8d5efd8..000000000 --- a/navit/support/espeak/espeak-data/voices/nl +++ /dev/null @@ -1,3 +0,0 @@ -language nl -name dutch-test -gender male diff --git a/navit/support/espeak/espeak-data/voices/no b/navit/support/espeak/espeak-data/voices/no deleted file mode 100755 index 77b60b963..000000000 --- a/navit/support/espeak/espeak-data/voices/no +++ /dev/null @@ -1,6 +0,0 @@ -name norwegian-test -language no -language nb -gender male - -intonation 4 diff --git a/navit/support/espeak/espeak-data/voices/pl b/navit/support/espeak/espeak-data/voices/pl deleted file mode 100755 index 8fc65d4ba..000000000 --- a/navit/support/espeak/espeak-data/voices/pl +++ /dev/null @@ -1,5 +0,0 @@ -name polish -language pl -gender male - -intonation 2 diff --git a/navit/support/espeak/espeak-data/voices/pt b/navit/support/espeak/espeak-data/voices/pt deleted file mode 100755 index 53cb31446..000000000 --- a/navit/support/espeak/espeak-data/voices/pt +++ /dev/null @@ -1,7 +0,0 @@ -name brazil -language pt -language pt-br -gender male - -dictrules 2 - diff --git a/navit/support/espeak/espeak-data/voices/pt-pt b/navit/support/espeak/espeak-data/voices/pt-pt deleted file mode 100755 index e23915f39..000000000 --- a/navit/support/espeak/espeak-data/voices/pt-pt +++ /dev/null @@ -1,7 +0,0 @@ -name portugal -language pt-pt -gender male -phonemes pt_pt - -dictrules 1 -intonation 2 diff --git a/navit/support/espeak/espeak-data/voices/ro b/navit/support/espeak/espeak-data/voices/ro deleted file mode 100755 index d8ecd252c..000000000 --- a/navit/support/espeak/espeak-data/voices/ro +++ /dev/null @@ -1,5 +0,0 @@ -name romanian -language ro -gender male - - diff --git a/navit/support/espeak/espeak-data/voices/ru b/navit/support/espeak/espeak-data/voices/ru deleted file mode 100755 index 238c69126..000000000 --- a/navit/support/espeak/espeak-data/voices/ru +++ /dev/null @@ -1,6 +0,0 @@ -name russian_test -language ru -gender male - -replace 03 a a# - diff --git a/navit/support/espeak/espeak-data/voices/sk b/navit/support/espeak/espeak-data/voices/sk deleted file mode 100755 index 026363f6a..000000000 --- a/navit/support/espeak/espeak-data/voices/sk +++ /dev/null @@ -1,4 +0,0 @@ -name slovak -language sk -gender male - diff --git a/navit/support/espeak/espeak-data/voices/sq b/navit/support/espeak/espeak-data/voices/sq deleted file mode 100644 index d0b729579..000000000 --- a/navit/support/espeak/espeak-data/voices/sq +++ /dev/null @@ -1,6 +0,0 @@ -name albanian -language sq -gender male - -// add this line to remove 'ë' at the end of words -// replace 00 @/ NULL diff --git a/navit/support/espeak/espeak-data/voices/sr b/navit/support/espeak/espeak-data/voices/sr deleted file mode 100644 index a7a8223db..000000000 --- a/navit/support/espeak/espeak-data/voices/sr +++ /dev/null @@ -1,15 +0,0 @@ -name serbian -language sr -gender male -dictionary hbs - -// attributes towards !variant3 pitch 80 120 -formant 0 100 100 100 -formant 1 97 97 100 -formant 2 97 97 100 -formant 3 97 102 100 -formant 4 97 102 100 -formant 5 97 102 100 - -stressAdd 10 10 0 0 0 0 -30 -30 -dictrules 2 4 diff --git a/navit/support/espeak/espeak-data/voices/sv b/navit/support/espeak/espeak-data/voices/sv deleted file mode 100755 index df70f4387..000000000 --- a/navit/support/espeak/espeak-data/voices/sv +++ /dev/null @@ -1,4 +0,0 @@ -name swedish -language sv -gender male - diff --git a/navit/support/espeak/espeak-data/voices/sw b/navit/support/espeak/espeak-data/voices/sw deleted file mode 100755 index cf584b7dd..000000000 --- a/navit/support/espeak/espeak-data/voices/sw +++ /dev/null @@ -1,4 +0,0 @@ -name swahihi-test -language sw -gender male - diff --git a/navit/support/espeak/espeak-data/voices/ta b/navit/support/espeak/espeak-data/voices/ta deleted file mode 100755 index 8848d6820..000000000 --- a/navit/support/espeak/espeak-data/voices/ta +++ /dev/null @@ -1,6 +0,0 @@ -name tamil -language ta -gender male - -intonation 2 -consonants 80 diff --git a/navit/support/espeak/espeak-data/voices/test/grc b/navit/support/espeak/espeak-data/voices/test/grc deleted file mode 100755 index ffa942063..000000000 --- a/navit/support/espeak/espeak-data/voices/test/grc +++ /dev/null @@ -1,8 +0,0 @@ -name greek-ancient -language grc -gender male - -stressLength 170 170 190 190 0 0 230 240 -dictrules 1 -words 3 - diff --git a/navit/support/espeak/espeak-data/voices/test/jbo b/navit/support/espeak/espeak-data/voices/test/jbo deleted file mode 100644 index ebab1a875..000000000 --- a/navit/support/espeak/espeak-data/voices/test/jbo +++ /dev/null @@ -1,3 +0,0 @@ -name lojban -language jbo - diff --git a/navit/support/espeak/espeak-data/voices/test/pap b/navit/support/espeak/espeak-data/voices/test/pap deleted file mode 100644 index 3b105a7fb..000000000 --- a/navit/support/espeak/espeak-data/voices/test/pap +++ /dev/null @@ -1,5 +0,0 @@ -name papiamento-test -language pap - -phonemes base2 - diff --git a/navit/support/espeak/espeak-data/voices/tr b/navit/support/espeak/espeak-data/voices/tr deleted file mode 100755 index 4f1904e51..000000000 --- a/navit/support/espeak/espeak-data/voices/tr +++ /dev/null @@ -1,4 +0,0 @@ -name turkish -language tr -gender male - diff --git a/navit/support/espeak/espeak-data/voices/vi b/navit/support/espeak/espeak-data/voices/vi deleted file mode 100755 index 1596e3c77..000000000 --- a/navit/support/espeak/espeak-data/voices/vi +++ /dev/null @@ -1,6 +0,0 @@ -name vietnam-test -language vi -gender male - -words 1 -pitch 80 118 diff --git a/navit/support/espeak/espeak-data/voices/zh b/navit/support/espeak/espeak-data/voices/zh deleted file mode 100644 index 03edde41d..000000000 --- a/navit/support/espeak/espeak-data/voices/zh +++ /dev/null @@ -1,30 +0,0 @@ -name Mandarin -language zh -gender male -words 1 -pitch 80 118 - -//for some dialects - -//[en]: replace ng with n -//[zh]: ��������ng���n -//replace 0 N n - -//[en]: replace rfx consonants -//[zh]: ��������r���l��z��er���e -//replace 0 ts.h tsh -//replace 0 ts. ts -//replace 0 s. s -//replace 0 i. i[ -//replace 0 z. l -//replace 0 z. z -//replace 0 @r @ - -//[en]: replace beginning n or l -//[zh]: ����nl��n���l��l���n -//replace 2 n l -//replace 2 l n - -//[en]: replace beginning w with v -//[zh]: w���v -//replace 0 w v
\ No newline at end of file diff --git a/navit/support/espeak/espeak-data/voices/zh-yue b/navit/support/espeak/espeak-data/voices/zh-yue deleted file mode 100755 index ba8723264..000000000 --- a/navit/support/espeak/espeak-data/voices/zh-yue +++ /dev/null @@ -1,14 +0,0 @@ -name cantonese-test -language zh-yue -language yue -language zhy - -translator zhy -phonemes zhy -dictionary zhy -gender male - -// interpret English letters as 1=English words, 2=jyutping -dictrules 1 - -words 1 diff --git a/navit/support/espeak/espeak-data/zh_dict b/navit/support/espeak/espeak-data/zh_dict Binary files differdeleted file mode 100644 index 0b611f845..000000000 --- a/navit/support/espeak/espeak-data/zh_dict +++ /dev/null diff --git a/navit/support/espeak/espeak-data/zhy_dict b/navit/support/espeak/espeak-data/zhy_dict Binary files differdeleted file mode 100644 index 4ad9e7c21..000000000 --- a/navit/support/espeak/espeak-data/zhy_dict +++ /dev/null diff --git a/navit/support/espeak/espeak.c b/navit/support/espeak/espeak.c deleted file mode 100644 index 7997d0673..000000000 --- a/navit/support/espeak/espeak.c +++ /dev/null @@ -1,665 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <time.h> -#include <sys/stat.h> - -#include "speak_lib.h" - -// This version of the command-line speak program uses the -// libespeak.so.1 library - - - -static const char *help_text = -"\nspeak [options] [\"<words>\"]\n\n" -"-f <text file> Text file to speak\n" -"--stdin Read text input from stdin instead of a file\n\n" -"If neither -f nor --stdin, <words> are spoken, or if none then text is\n" -"spoken from stdin, each line separately.\n\n" -"-a <integer>\n" -"\t Amplitude, 0 to 200, default is 100\n" -"-g <integer>\n" -"\t Word gap. Pause between words, units of 10mS at the default speed\n" -"-l <integer>\n" -"\t Line length. If not zero (which is the default), consider\n" -"\t lines less than this length as end-of-clause\n" -"-p <integer>\n" -"\t Pitch adjustment, 0 to 99, default is 50\n" -"-s <integer>\n" -"\t Speed in words per minute, 80 to 390, default is 170\n" -"-v <voice name>\n" -"\t Use voice file of this name from espeak-data/voices\n" -"-w <wave file name>\n" -"\t Write output to this WAV file, rather than speaking it directly\n" -"-b\t Input text encoding, 1=UTF8, 2=8 bit, 4=16 bit \n" -"-m\t Interpret SSML markup, and ignore other < > tags\n" -"-q\t Quiet, don't produce any speech (may be useful with -x)\n" -"-x\t Write phoneme mnemonics to stdout\n" -"-X\t Write phonemes mnemonics and translation trace to stdout\n" -"-z\t No final sentence pause at the end of the text\n" -"--stdout Write speech output to stdout\n" -"--compile=<voice name>\n" -"\t Compile the pronunciation rules and dictionary in the current\n" -"\t directory. =<voice name> is optional and specifies which language\n" -"--path=\"<path>\"\n" -"\t Specifies the directory containing the espeak-data directory\n" -"--phonout=\"<filename>\"\n" -"\t Write output from -x -X commands and mbrola phoneme data to this file\n" -"--punct=\"<characters>\"\n" -"\t Speak the names of punctuation characters during speaking. If\n" -"\t =<characters> is omitted, all punctuation is spoken.\n" -"--split=\"<minutes>\"\n" -"\t Starts a new WAV file every <minutes>. Used with -w\n" -"--voices=<language>\n" -"\t List the available voices for the specified language.\n" -"\t If <language> is omitted, then list all voices.\n" -"-k <integer>\n" -"\t Indicate capital letters with: 1=sound, 2=the word \"capitals\",\n" -"\t higher values = a pitch increase (try -k20).\n"; - - - - -int samplerate; -int quiet = 0; -unsigned int samples_total = 0; -unsigned int samples_split = 0; -unsigned int wavefile_count = 0; - -FILE *f_wavfile = NULL; -char filetype[5]; -char wavefile[200]; - - -int GetFileLength(const char *filename) -{//==================================== - struct stat statbuf; - - if(stat(filename,&statbuf) != 0) - return(0); - - if((statbuf.st_mode & S_IFMT) == S_IFDIR) - return(-2); // a directory - - return(statbuf.st_size); -} // end of GetFileLength - - -void strncpy0(char *dest, const char *source, int size) -{//==================================================== - if(source!=NULL) - { - strncpy(dest,source,size); - dest[size-1] = 0; - } -} - - -void DisplayVoices(FILE *f_out, char *language) -{//============================================ - int ix; - const char *p; - int len; - int count; - int scores = 0; - const espeak_VOICE *v; - const char *lang_name; - char age_buf[12]; - const espeak_VOICE **voices; - espeak_VOICE voice_select; - - static char genders[4] = {' ','M','F',' '}; - - if((language != NULL) && (language[0] != 0)) - { - // display only voices for the specified language, in order of priority - voice_select.languages = language; - voice_select.age = 0; - voice_select.gender = 0; - voice_select.name = NULL; - voices = espeak_ListVoices(&voice_select); - scores = 1; - } - else - { - voices = espeak_ListVoices(NULL); - } - - fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Langs\n"); - - for(ix=0; (v = voices[ix]) != NULL; ix++) - { - count = 0; - p = v->languages; - while(*p != 0) - { - len = strlen(p+1); - lang_name = p+1; - - if(v->age == 0) - strcpy(age_buf," "); - else - sprintf(age_buf,"%3d",v->age); - - if(count==0) - { - fprintf(f_out,"%2d %-12s%s%c %-17s %-11s ", - p[0],lang_name,age_buf,genders[v->gender],v->name,v->identifier); - } - else - { - fprintf(f_out,"(%s %d)",lang_name,p[0]); - } - count++; - p += len+2; - } -// if(scores) -// fprintf(f_out,"%3d ",v->score); - fputc('\n',f_out); - } -} // end of DisplayVoices - - - - -static void Write4Bytes(FILE *f, int value) -{//================================= -// Write 4 bytes to a file, least significant first - int ix; - - for(ix=0; ix<4; ix++) - { - fputc(value & 0xff,f); - value = value >> 8; - } -} - - - -int OpenWavFile(char *path, int rate) -//=================================== -{ - static unsigned char wave_hdr[44] = { - 'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ', - 0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0, - 2,0,0x10,0,'d','a','t','a', 0x00,0xf0,0xff,0x7f}; - - if(path == NULL) - return(2); - - if(path[0] == 0) - return(0); - - if(strcmp(path,"stdout")==0) - f_wavfile = stdout; - else - f_wavfile = fopen(path,"wb"); - - if(f_wavfile != NULL) - { - fwrite(wave_hdr,1,24,f_wavfile); - Write4Bytes(f_wavfile,rate); - Write4Bytes(f_wavfile,rate * 2); - fwrite(&wave_hdr[32],1,12,f_wavfile); - return(0); - } - return(1); -} // end of OpenWavFile - - - -static void CloseWavFile() -//======================== -{ - unsigned int pos; - - if((f_wavfile==NULL) || (f_wavfile == stdout)) - return; - - fflush(f_wavfile); - pos = ftell(f_wavfile); - - fseek(f_wavfile,4,SEEK_SET); - Write4Bytes(f_wavfile,pos - 8); - - fseek(f_wavfile,40,SEEK_SET); - Write4Bytes(f_wavfile,pos - 44); - - fclose(f_wavfile); - f_wavfile = NULL; - -} // end of CloseWavFile - - -static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) -{//======================================================================== - char fname[210]; - - if(quiet) return(0); // -q quiet mode - - if(wav == NULL) - { - CloseWavFile(); - return(0); - } - - if(samples_split > 0) - { - // start a new WAV file when this limit is reached, at the next sentence boundary - while(events->type != 0) - { - if((events->type == espeakEVENT_SENTENCE) && (samples_total > samples_split)) - { - CloseWavFile(); - samples_total = 0; - } - events++; - } - } - - if(f_wavfile == NULL) - { - sprintf(fname,"%s_%.2d%s",wavefile,++wavefile_count,filetype); - if(OpenWavFile(fname, samplerate) != 0) - return(1); - } - - if(numsamples > 0) - { - samples_total += numsamples; - fwrite(wav,numsamples*2,1,f_wavfile); - } - return(0); -} - - - -int main (int argc, char **argv) -//============================== -{ - 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'}, - {"stdin", no_argument, 0, 0x100}, - {"compile-debug", optional_argument, 0, 0x101}, - {"compile", optional_argument, 0, 0x102}, - {"punct", optional_argument, 0, 0x103}, - {"voices", optional_argument, 0, 0x104}, - {"stdout", no_argument, 0, 0x105}, - {"split", optional_argument, 0, 0x106}, - {"path", required_argument, 0, 0x107}, - {"phonout", required_argument, 0, 0x108}, - {0, 0, 0, 0} - }; - - static const char* err_load = "Failed to read "; - - - FILE *f_text=NULL; - char *p_text=NULL; - FILE *f_phonemes_out = stdout; - char *data_path = NULL; // use default path for espeak-data - - int option_index = 0; - int c; - int ix; - int value; - int flag_stdin = 0; - int flag_compile = 0; - int filesize = 0; - int synth_flags = espeakCHARS_AUTO | espeakPHONEMES | espeakENDPAUSE; - - int volume = -1; - int speed = -1; - int pitch = -1; - int wordgap = -1; - int option_capitals = -1; - int option_punctuation = -1; - int option_phonemes = -1; - int option_linelength = 0; - int option_waveout = 0; - - espeak_VOICE voice_select; - char filename[200]; - char voicename[40]; - char voice_mbrola[20]; - char dictname[40]; -#define N_PUNCTLIST 100 - wchar_t option_punctlist[N_PUNCTLIST]; - - voicename[0] = 0; - voice_mbrola[0] = 0; - dictname[0] = 0; - wavefile[0] = 0; - filename[0] = 0; - option_punctlist[0] = 0; - - while(true) - { - c = getopt_long (argc, argv, "a:b:f:g:hk:l:mp:qs:v:w:xXz", - long_options, &option_index); - - /* Detect the end of the options. */ - if (c == -1) - break; - - switch (c) - { - case 'b': - // input character encoding, 8bit, 16bit, UTF8 - if((sscanf(optarg,"%d",&value) == 1) && (value <= 4)) - synth_flags |= value; - else - synth_flags |= espeakCHARS_8BIT; - break; - - case 'h': - printf("\n"); - printf("eSpeak text-to-speech: %s\n%s",espeak_Info(),help_text); - exit(0); - break; - - case 'k': - option_capitals = atoi(optarg); - break; - - case 'x': - option_phonemes = 1; - break; - - case 'X': - option_phonemes = 2; - break; - - case 'm': - synth_flags |= espeakSSML; - break; - - case 'p': - pitch = atoi(optarg); - break; - - case 'q': - quiet = 1; - break; - - case 'f': - strncpy0(filename,optarg,sizeof(filename)); - break; - - case 'l': - option_linelength = atoi(optarg); - break; - - case 'a': - volume = atoi(optarg); - break; - - case 's': - speed = atoi(optarg); - break; - - case 'g': - wordgap = atoi(optarg); - break; - - case 'v': - strncpy0(voicename,optarg,sizeof(voicename)); - break; - - case 'w': - option_waveout = 1; - strncpy0(wavefile,optarg,sizeof(filename)); - break; - - case 'z': // remove pause from the end of a sentence - synth_flags &= ~espeakENDPAUSE; - break; - - case 0x100: // --stdin - flag_stdin = 1; - break; - - case 0x105: // --stdout - option_waveout = 1; - strcpy(wavefile,"stdout"); - break; - - case 0x101: // --compile-debug - case 0x102: // --compile - strncpy0(voicename,optarg,sizeof(voicename)); - flag_compile = c; - quiet = 1; - break; - - case 0x103: // --punct - option_punctuation = 1; - if(optarg != NULL) - { - ix = 0; - while((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg[ix]) != 0)) ix++; - option_punctlist[N_PUNCTLIST-1] = 0; - option_punctuation = 2; - } - break; - - case 0x104: // --voices - espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,0,data_path,0); - DisplayVoices(stdout,optarg); - exit(0); - - case 0x106: // -- split - if(optarg == NULL) - samples_split = 30; // default 30 minutes - else - samples_split = atoi(optarg); - break; - - case 0x107: // --path - data_path = optarg; - break; - - case 0x108: // --phonout - if((f_phonemes_out = fopen(optarg,"w")) == NULL) - { - fprintf(stderr,"Can't write to: %s\n",optarg); - } - break; - - default: - exit(0); - } - } - - - if(option_waveout || quiet) - { - // writing to a file (or no output), we can use synchronous mode - samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,0,data_path,0); - samples_split = (samplerate * samples_split) * 60; - - espeak_SetSynthCallback(SynthCallback); - if(samples_split) - { - char *extn; - extn = strrchr(wavefile,'.'); - if((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) - { - strcpy(filetype,extn); - *extn = 0; - } - } - else - if(option_waveout) - { - if(OpenWavFile(wavefile,samplerate) != 0) - exit(4); - } - } - else - { - // play the sound output - samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0); - } - - - if(voicename[0] == 0) - strcpy(voicename,"default"); - - if(espeak_SetVoiceByName(voicename) != EE_OK) - { - memset(&voice_select,0,sizeof(voice_select)); - voice_select.languages = voicename; - if(espeak_SetVoiceByProperties(&voice_select) != EE_OK) - { - fprintf(stderr,"%svoice '%s'\n",err_load,voicename); - exit(2); - } - } - - if(flag_compile) - { - // This must be done after the voice is set - espeak_CompileDictionary("", stderr, flag_compile & 0x1); - exit(0); - } - - // set any non-default values of parameters. This must be done after espeak_Initialize() - if(speed > 0) - espeak_SetParameter(espeakRATE,speed,0); - if(volume >= 0) - espeak_SetParameter(espeakVOLUME,volume,0); - if(pitch >= 0) - espeak_SetParameter(espeakPITCH,pitch,0); - if(option_capitals >= 0) - espeak_SetParameter(espeakCAPITALS,option_capitals,0); - if(option_punctuation >= 0) - espeak_SetParameter(espeakPUNCTUATION,option_punctuation,0); - if(wordgap >= 0) - espeak_SetParameter(espeakWORDGAP,wordgap,0); - if(option_linelength > 0) - espeak_SetParameter(espeakLINELENGTH,option_linelength,0); - if(option_punctuation == 2) - espeak_SetPunctuationList(option_punctlist); - espeak_SetPhonemeTrace(option_phonemes,f_phonemes_out); - - if(filename[0]==0) - { - if((optind < argc) && (flag_stdin == 0)) - { - // there's a non-option parameter, and no -f or --stdin - // use it as text - p_text = argv[optind]; - } - else - { - f_text = stdin; - if(flag_stdin == 0) - { - flag_stdin = 2; - } - } - } - else - { - filesize = GetFileLength(filename); - f_text = fopen(filename,"r"); - } - - if((f_text == NULL) && (p_text == NULL)) - { - fprintf(stderr,"%sfile '%s'\n",err_load,filename); - exit(1); - } - - - if(p_text != NULL) - { - int size; - size = strlen(p_text); - espeak_Synth(p_text,size+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); - } - else - if(flag_stdin) - { - int max = 1000; - p_text = (char *)malloc(max); - - if(flag_stdin == 2) - { - // line by line input on stdin - while(fgets(p_text,max,stdin) != NULL) - { - p_text[max-1] = 0; - espeak_Synth(p_text,max,0,POS_CHARACTER,0,synth_flags,NULL,NULL); - - } - } - else - { - // bulk input on stdin - ix = 0; - while(!feof(stdin)) - { - p_text[ix++] = fgetc(stdin); - if(ix >= (max-1)) - { - max += 1000; - p_text = (char *)realloc(p_text,max); - } - } - if(ix > 0) - { - p_text[ix-1] = 0; - espeak_Synth(p_text,ix+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); - } - } - } - else - if(f_text != NULL) - { - if((p_text = (char *)malloc(filesize+1)) == NULL) - { - fprintf(stderr,"Failed to allocate memory %d bytes",filesize); - exit(3); - } - - fread(p_text,1,filesize,f_text); - p_text[filesize]=0; - espeak_Synth(p_text,filesize+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); - fclose(f_text); - } - - espeak_Synchronize(); - - if(f_phonemes_out != stdout) - fclose(f_phonemes_out); // needed for WinCE - return(0); -} diff --git a/navit/support/espeak/espeak_command.c b/navit/support/espeak/espeak_command.c deleted file mode 100644 index 1b59333c1..000000000 --- a/navit/support/espeak/espeak_command.c +++ /dev/null @@ -1,707 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007, Gilles Casse <gcasse@oralux.org> * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "speech.h" - -#ifdef USE_ASYNC -// This source file is only used for asynchronious modes - -#include "espeak_command.h" -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <wchar.h> - -#include "debug.h" - - -static unsigned int my_current_text_id=0; - - -//<create_espeak_text -t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void* user_data) -{ - ENTER("create_espeak_text"); - int a_error=1; - void* a_text = NULL; - t_espeak_text* data = NULL; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - - if (!text || !size || !a_command) - { - goto text_error; - } - - a_text = malloc( size ); - if (!a_text) - { - goto text_error; - } - memcpy(a_text, text, size); - - a_command->type = ET_TEXT; - a_command->state = CS_UNDEFINED; - data = &(a_command->u.my_text); - data->unique_identifier = ++my_current_text_id; - data->text = a_text; - data->size = size; - data->position = position; - data->position_type = position_type; - data->end_position = end_position; - data->flags = flags; - data->user_data = user_data; - a_error=0; - - SHOW("ET_TEXT malloc text=%x, command=%x (uid=%d)\n", a_text, a_command, data->unique_identifier); - - text_error: - if (a_error) - { - if (a_text) - { - free (a_text); - } - if (a_command) - { - free (a_command); - } - a_command = NULL; - } - - SHOW("command=0x%x\n", a_command); - - return a_command; -} - -//> - - -t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, void* user_data) -{ - ENTER("create_espeak_terminated_msg"); - int a_error=1; - t_espeak_terminated_msg* data = NULL; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - - if (!a_command) - { - goto msg_error; - } - - a_command->type = ET_TERMINATED_MSG; - a_command->state = CS_UNDEFINED; - data = &(a_command->u.my_terminated_msg); - data->unique_identifier = unique_identifier; - data->user_data = user_data; - a_error=0; - - SHOW("ET_TERMINATED_MSG command=%x (uid=%d, user_data=0x%x)\n", a_command, unique_identifier, (int)user_data); - - msg_error: - if (a_error) - { - if (a_command) - { - free (a_command); - } - a_command = NULL; - } - - SHOW("command=0x%x\n", a_command); - - return a_command; - -} - - - - -//<create_espeak_mark -t_espeak_command* create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void* user_data) -{ - ENTER("create_espeak_mark"); - int a_error=1; - void* a_text = NULL; - char *a_index_mark = NULL; - t_espeak_mark* data = NULL; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - - if (!text || !size || !index_mark || !a_command) - { - goto mark_error; - } - - a_text = malloc( size ); - if (!a_text) - { - goto mark_error; - } - memcpy(a_text, text, size); - - a_index_mark = strdup( index_mark); - - a_command->type = ET_MARK; - a_command->state = CS_UNDEFINED; - data = &(a_command->u.my_mark); - data->unique_identifier = ++my_current_text_id; - data->text = a_text; - data->size = size; - data->index_mark = a_index_mark; - data->end_position = end_position; - data->flags = flags; - data->user_data = user_data; - a_error=0; - - mark_error: - if (a_error) - { - if (a_text) - { - free (a_text); - } - if (a_command) - { - free (a_command); - } - a_command = NULL; - if (a_index_mark) - { - free (a_index_mark); - } - } - - SHOW("ET_MARK malloc text=%x, command=%x (uid=%d)\n", a_text, a_command, data->unique_identifier); - - return a_command; -} -//> -//< create_espeak_key, create_espeak_char - -t_espeak_command* create_espeak_key(const char *key_name, void *user_data) -{ - ENTER("create_espeak_key"); - int a_error=1; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - - if (!key_name || !a_command) - { - goto key_error; - } - - a_command->type = ET_KEY; - a_command->state = CS_UNDEFINED; - a_command->u.my_key.user_data = user_data; - a_command->u.my_key.unique_identifier = ++my_current_text_id; - a_command->u.my_key.key_name = strdup( key_name); - a_error=0; - - key_error: - if (a_error) - { - if (a_command) - { - free (a_command); - } - a_command = NULL; - } - - SHOW("command=0x%x\n", a_command); - - return a_command; -} - -t_espeak_command* create_espeak_char(wchar_t character, void* user_data) -{ - ENTER("create_espeak_char"); - int a_error=1; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - if (!a_command) - { - goto char_error; - } - - a_command->type = ET_CHAR; - a_command->state = CS_UNDEFINED; - a_command->u.my_char.user_data = user_data; - a_command->u.my_char.unique_identifier = ++my_current_text_id; - a_command->u.my_char.character = character; - a_error=0; - - char_error: - if (a_error) - { - if (a_command) - { - free (a_command); - } - a_command = NULL; - } - - SHOW("command=0x%x\n", a_command); - - return a_command; -} - -//> -//< create_espeak_parameter - -t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative) -{ - ENTER("create_espeak_parameter"); - int a_error=1; - t_espeak_parameter* data = NULL; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - if (!a_command) - { - goto param_error; - } - - a_command->type = ET_PARAMETER; - a_command->state = CS_UNDEFINED; - data = &(a_command->u.my_param); - data->parameter = parameter; - data->value = value; - data->relative = relative; - a_error=0; - - param_error: - if (a_error) - { - if (a_command) - { - free (a_command); - } - a_command = NULL; - } - - SHOW("command=0x%x\n", a_command); - - return a_command; -} - -//> -//< create_espeak_punctuation_list - -t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist) -{ - ENTER("create_espeak_punctuation_list"); - int a_error=1; - // wchar_t *a_list = NULL; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - - if (!punctlist || !a_command) - { - goto list_error; - } - - a_command->type = ET_PUNCTUATION_LIST; - a_command->state = CS_UNDEFINED; - - { - size_t len = (wcslen(punctlist) + 1)*sizeof(wchar_t); - wchar_t* a_list = (wchar_t*)malloc(len); - memcpy(a_list, punctlist, len); - a_command->u.my_punctuation_list = a_list; - } - - a_error=0; - - list_error: - if (a_error) - { - if (a_command) - { - free (a_command); - } - a_command = NULL; - } - - SHOW("command=0x%x\n", a_command); - - return a_command; -} - -//> -//< create_espeak_voice_name, create_espeak_voice_spec - -t_espeak_command* create_espeak_voice_name(const char *name) -{ - ENTER("create_espeak_voice_name"); - - int a_error=1; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - - if (!name || !a_command) - { - goto name_error; - } - - a_command->type = ET_VOICE_NAME; - a_command->state = CS_UNDEFINED; - a_command->u.my_voice_name = strdup( name); - a_error=0; - - name_error: - if (a_error) - { - if (a_command) - { - free (a_command); - } - a_command = NULL; - } - - SHOW("command=0x%x\n", a_command); - - return a_command; -} - -t_espeak_command* create_espeak_voice_spec(espeak_VOICE *voice) -{ - ENTER("create_espeak_voice_spec"); - int a_error=1; - t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); - - if (!voice || !a_command) - { - goto spec_error; - } - - a_command->type = ET_VOICE_SPEC; - a_command->state = CS_UNDEFINED; - { - espeak_VOICE* data = &(a_command->u.my_voice_spec); - memcpy(data, voice, sizeof(espeak_VOICE)); - - if (voice->name) - { - data->name = strdup(voice->name); - } - - if (voice->languages) - { - data->languages = strdup(voice->languages); - } - - if (voice->identifier) - { - data->identifier = strdup(voice->identifier); - } - - a_error=0; - } - - spec_error: - if (a_error) - { - if (a_command) - { - free (a_command); - } - a_command = NULL; - } - - SHOW("command=0x%x\n", a_command); - - return a_command; -} - -//> -//< delete_espeak_command -int delete_espeak_command( t_espeak_command* the_command) -{ - ENTER("delete_espeak_command"); - int a_status = 0; - if (the_command) - { - switch(the_command->type) - { - case ET_TEXT: - if (the_command->u.my_text.text) - { - SHOW("delete_espeak_command > ET_TEXT free text=%x, command=%x, uid=%d\n", the_command->u.my_text.text, the_command, the_command->u.my_text.unique_identifier); - free(the_command->u.my_text.text); - } - break; - - case ET_MARK: - if (the_command->u.my_mark.text) - { - free(the_command->u.my_mark.text); - } - if (the_command->u.my_mark.index_mark) - { - free((void*)(the_command->u.my_mark.index_mark)); - } - break; - - case ET_TERMINATED_MSG: - { - // if the terminated msg is pending, - // it must be processed here for informing the calling program - // that its message is finished. - // This can be important for cleaning the related user data. - t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg); - if (the_command->state == CS_PENDING) - { - the_command->state = CS_PROCESSED; - SHOW("delete_espeak_command > ET_TERMINATED_MSG callback (command=0x%x, uid=%d) \n", the_command, data->unique_identifier); - sync_espeak_terminated_msg( data->unique_identifier, data->user_data); - } - } - break; - - case ET_KEY: - if (the_command->u.my_key.key_name) - { - free((void*)(the_command->u.my_key.key_name)); - } - break; - - case ET_CHAR: - case ET_PARAMETER: - // No allocation - break; - - case ET_PUNCTUATION_LIST: - if (the_command->u.my_punctuation_list) - { - free((void*)(the_command->u.my_punctuation_list)); - } - break; - - case ET_VOICE_NAME: - if (the_command->u.my_voice_name) - { - free((void*)(the_command->u.my_voice_name)); - } - break; - - case ET_VOICE_SPEC: - { - espeak_VOICE* data = &(the_command->u.my_voice_spec); - - if (data->name) - { - free((void *)data->name); - } - - if (data->languages) - { - free((void *)data->languages); - } - - if (data->identifier) - { - free((void *)data->identifier); - } - } - break; - - default: - assert(0); - } - SHOW("delete_espeak_command > free command=0x%x\n", the_command); - free(the_command); - a_status = 1; - } - return a_status; -} -//> -//< process_espeak_command -void process_espeak_command( t_espeak_command* the_command) -{ - ENTER("process_espeak_command"); - - SHOW("command=0x%x\n", the_command); - - if (the_command == NULL) - { - return; - } - - the_command->state = CS_PROCESSED; - - switch(the_command->type) - { - case ET_TEXT: - { - t_espeak_text* data = &(the_command->u.my_text); - sync_espeak_Synth( data->unique_identifier, data->text, data->size, - data->position, data->position_type, - data->end_position, data->flags, data->user_data); - } - break; - - case ET_MARK: - { - t_espeak_mark* data = &(the_command->u.my_mark); - sync_espeak_Synth_Mark( data->unique_identifier, data->text, data->size, - data->index_mark, data->end_position, data->flags, - data->user_data); - } - break; - - case ET_TERMINATED_MSG: - { - t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg); - sync_espeak_terminated_msg( data->unique_identifier, data->user_data); - } - break; - - case ET_KEY: - { - const char* data = the_command->u.my_key.key_name; - sync_espeak_Key(data); - } - break; - - case ET_CHAR: - { - const wchar_t data = the_command->u.my_char.character; - sync_espeak_Char( data); - } - break; - - case ET_PARAMETER: - { - t_espeak_parameter* data = &(the_command->u.my_param); - SetParameter( data->parameter, data->value, data->relative); - } - break; - - case ET_PUNCTUATION_LIST: - { - const wchar_t* data = the_command->u.my_punctuation_list; - sync_espeak_SetPunctuationList( data); - } - break; - - case ET_VOICE_NAME: - { - const char* data = the_command->u.my_voice_name; - SetVoiceByName( data); - } - break; - - case ET_VOICE_SPEC: - { - espeak_VOICE* data = &(the_command->u.my_voice_spec); - SetVoiceByProperties(data); - } - break; - - default: - assert(0); - break; - } -} - -//> - -//< process_espeak_command -void display_espeak_command( t_espeak_command* the_command) -{ - ENTER("display_espeak_command"); -#ifdef DEBUG_ENABLED - if (the_command == NULL) - { - SHOW("display_espeak_command > command=%s\n","NULL"); - return; - } - - SHOW("display_espeak_command > state=%d\n",the_command->state); - - switch(the_command->type) - { - case ET_TEXT: - { - t_espeak_text* data = &(the_command->u.my_text); - SHOW("display_espeak_command > (0x%x) uid=%d, TEXT=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char*)data->text, (int)(data->user_data)); - } - break; - - case ET_MARK: - { - t_espeak_mark* data = &(the_command->u.my_mark); - SHOW("display_espeak_command > (0x%x) uid=%d, MARK=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char*)data->text, (int)(data->user_data)); - } - break; - - case ET_KEY: - { - const char* data = the_command->u.my_key; - SHOW("display_espeak_command > (0x%x) KEY=%c\n", the_command, data); - } - break; - - case ET_TERMINATED_MSG: - { - t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg); - - SHOW("display_espeak_command > (0x%x) TERMINATED_MSG uid=%d, user_data=0x%x, state=%d\n", - the_command, data->unique_identifier, data->user_data, - the_command->state); - } - break; - - case ET_CHAR: - { - const wchar_t data = the_command->u.my_char; - SHOW("display_espeak_command > (0x%x) CHAR=%c\n", the_command, (char)data); - } - break; - - case ET_PARAMETER: - { - t_espeak_parameter* data = &(the_command->u.my_param); - SHOW("display_espeak_command > (0x%x) PARAMETER=%d, value=%d, relative=%d\n", - the_command, data->parameter, data->value, data->relative); - } - break; - - case ET_PUNCTUATION_LIST: - { - const wchar_t* data = the_command->u.my_punctuation_list; - sync_espeak_SetPunctuationList( data); - SHOW("display_espeak_command > (0x%x) PUNCTLIST=%s\n", the_command, (char*)data); - } - break; - - case ET_VOICE_NAME: - { - const char* data = the_command->u.my_voice_name; - SHOW("display_espeak_command > (0x%x) VOICE_NAME=%s\n", the_command, data); - } - break; - - case ET_VOICE_SPEC: - { - SHOW("display_espeak_command > (0x%x) VOICE_SPEC", the_command); - } - break; - - default: - assert(0); - break; - } -#endif -} - -#endif -//> diff --git a/navit/support/espeak/espeak_command.h b/navit/support/espeak/espeak_command.h deleted file mode 100644 index b2664be6a..000000000 --- a/navit/support/espeak/espeak_command.h +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef ESPEAK_COMMAND_H -#define ESPEAK_COMMAND_H - -#ifndef PLATFORM_WINDOWS -#include <unistd.h> -#endif -#include "speak_lib.h" - -enum t_espeak_type - { - ET_TEXT, - ET_MARK, - ET_KEY, - ET_CHAR, - ET_PARAMETER, - ET_PUNCTUATION_LIST, - ET_VOICE_NAME, - ET_VOICE_SPEC, - ET_TERMINATED_MSG - }; - -typedef struct -{ - unsigned int unique_identifier; - void* text; - size_t size; - unsigned int position; - espeak_POSITION_TYPE position_type; - unsigned int end_position; - unsigned int flags; - void* user_data; -} t_espeak_text; - -typedef struct -{ - unsigned int unique_identifier; - void* text; - size_t size; - const char* index_mark; - unsigned int end_position; - unsigned int flags; - void* user_data; -} t_espeak_mark; - -typedef struct -{ - unsigned int unique_identifier; - void* user_data; - wchar_t character; -} t_espeak_character; - -typedef struct -{ - unsigned int unique_identifier; - void* user_data; - const char* key_name; -} t_espeak_key; - - -typedef struct -{ - unsigned int unique_identifier; - void* user_data; -} t_espeak_terminated_msg; - - -typedef struct -{ - espeak_PARAMETER parameter; - int value; - int relative; -} t_espeak_parameter; - -enum t_command_state -{ - CS_UNDEFINED, // The command has just been created - CS_PENDING, // stored in the fifo - CS_PROCESSED // processed -}; - -typedef struct -{ - enum t_espeak_type type; - enum t_command_state state; - - union command - { - t_espeak_text my_text; - t_espeak_mark my_mark; - t_espeak_key my_key; - t_espeak_character my_char; - t_espeak_parameter my_param; - const wchar_t* my_punctuation_list; - const char *my_voice_name; - espeak_VOICE my_voice_spec; - t_espeak_terminated_msg my_terminated_msg; - } u; -} t_espeak_command; - - -t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void* user_data); - -t_espeak_command* create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void* user_data); - -t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, void* user_data); - -t_espeak_command* create_espeak_key(const char *key_name, void *user_data); - -t_espeak_command* create_espeak_char(wchar_t character, void *user_data); - -t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative); - -t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist); - -t_espeak_command* create_espeak_voice_name(const char *name); - -t_espeak_command* create_espeak_voice_spec(espeak_VOICE *voice_spec); - -void process_espeak_command( t_espeak_command* the_command); - -int delete_espeak_command( t_espeak_command* the_command); - -void display_espeak_command(t_espeak_command* the_command); - - -espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size, - unsigned int position, espeak_POSITION_TYPE position_type, - unsigned int end_position, unsigned int flags, void* user_data); -espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size, - const char *index_mark, unsigned int end_position, - unsigned int flags, void* user_data); -void sync_espeak_Key(const char *key); -void sync_espeak_Char(wchar_t character); -void sync_espeak_SetPunctuationList(const wchar_t *punctlist); -void sync_espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative); -int sync_espeak_SetVoiceByName(const char *name); -int sync_espeak_SetVoiceByProperties(espeak_VOICE *voice_selector); -espeak_ERROR SetVoiceByName(const char *name); -espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector); -void SetParameter(int parameter, int value, int relative); - -int sync_espeak_terminated_msg(unsigned int unique_identifier, void* user_data); - -//> -#endif diff --git a/navit/support/espeak/event.c b/navit/support/espeak/event.c deleted file mode 100644 index cc696272d..000000000 --- a/navit/support/espeak/event.c +++ /dev/null @@ -1,725 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007, Gilles Casse <gcasse@oralux.org> * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "speech.h" - -#ifdef USE_ASYNC -// This source file is only used for asynchronious modes - - -//<includes -#include <unistd.h> -#include <assert.h> -#include <string.h> -#include <stdlib.h> -#include <pthread.h> -#include <semaphore.h> -#include <sys/time.h> -#include <errno.h> - -#include "speak_lib.h" -#include "event.h" -#include "wave.h" -#include "debug.h" -//> -//<decls and function prototypes - - -// my_mutex: protects my_thread_is_talking, -static pthread_mutex_t my_mutex; -static sem_t my_sem_start_is_required; -static sem_t my_sem_stop_is_required; -static sem_t my_sem_stop_is_acknowledged; -// my_thread: polls the audio duration and compares it to the duration of the first event. -static pthread_t my_thread; - -static t_espeak_callback* my_callback = NULL; -static int my_event_is_running=0; - -enum {MIN_TIMEOUT_IN_MS=10, - ACTIVITY_TIMEOUT=50, // in ms, check that the stream is active - MAX_ACTIVITY_CHECK=6 -}; - - -typedef struct t_node -{ - void* data; - t_node *next; -} node; - -static node* head=NULL; -static node* tail=NULL; -static int node_counter=0; -static espeak_ERROR push(void* data); -static void* pop(); -static void init(); -static void* polling_thread(void*); - -//> -//<event_init - -void event_set_callback(t_espeak_callback* SynthCallback) -{ - my_callback = SynthCallback; -} - -void event_init(void) -{ - ENTER("event_init"); - - my_event_is_running=0; - - // security - pthread_mutex_init( &my_mutex, (const pthread_mutexattr_t *)NULL); - init(); - - assert(-1 != sem_init(&my_sem_start_is_required, 0, 0)); - assert(-1 != sem_init(&my_sem_stop_is_required, 0, 0)); - assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0)); - - pthread_attr_t a_attrib; - if (pthread_attr_init (& a_attrib) - || pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) - || pthread_create( &my_thread, - & a_attrib, - polling_thread, - (void*)NULL)) - { - assert(0); - } - - pthread_attr_destroy(&a_attrib); -} -//> -//<event_display -static void event_display(espeak_EVENT* event) -{ -ENTER("event_display"); - -#ifdef DEBUG_ENABLED - if (event==NULL) - { - SHOW("event_display > event=%s\n","NULL"); - } - else - { - static const char* label[] = { - "LIST_TERMINATED", - "WORD", - "SENTENCE", - "MARK", - "PLAY", - "END", - "MSG_TERMINATED" - }; - - SHOW("event_display > event=0x%x\n",event); - SHOW("event_display > type=%s\n",label[event->type]); - SHOW("event_display > uid=%d\n",event->unique_identifier); - SHOW("event_display > text_position=%d\n",event->text_position); - SHOW("event_display > length=%d\n",event->length); - SHOW("event_display > audio_position=%d\n",event->audio_position); - SHOW("event_display > sample=%d\n",event->sample); - SHOW("event_display > user_data=0x%x\n",event->user_data); - } -#endif -} -//> -//<event_copy - -static espeak_EVENT* event_copy (espeak_EVENT* event) -{ - ENTER("event_copy"); - - if (event==NULL) - { - return NULL; - } - - espeak_EVENT* a_event=(espeak_EVENT*)malloc(sizeof(espeak_EVENT)); - if (a_event) - { - memcpy(a_event, event, sizeof(espeak_EVENT)); - - switch(event->type) - { - case espeakEVENT_MARK: - case espeakEVENT_PLAY: - if (event->id.name) - { - a_event->id.name = strdup(event->id.name); - } - break; - - default: - break; - } - } - - event_display(a_event); - - return a_event; -} - -//> -//<event_notify - -// Call the user supplied callback -// -// Note: the current sequence is: -// -// * First call with: event->type = espeakEVENT_SENTENCE -// * 0, 1 or several calls: event->type = espeakEVENT_WORD -// * Last call: event->type = espeakEVENT_MSG_TERMINATED -// - -static void event_notify(espeak_EVENT* event) -{ -ENTER("event_notify"); - static unsigned int a_old_uid = 0; - - espeak_EVENT events[2]; - memcpy(&events[0],event,sizeof(espeak_EVENT)); // the event parameter in the callback function should be an array of eventd - memcpy(&events[1],event,sizeof(espeak_EVENT)); - events[1].type = espeakEVENT_LIST_TERMINATED; // ... terminated by an event type=0 - - if (event && my_callback) - { - event_display(event); - - switch(event->type) - { - case espeakEVENT_SENTENCE: - my_callback(NULL, 0, events); - a_old_uid = event->unique_identifier; - break; - - case espeakEVENT_MSG_TERMINATED: - case espeakEVENT_MARK: - case espeakEVENT_WORD: - case espeakEVENT_END: - case espeakEVENT_PHONEME: - { -// jonsd - I'm not sure what this is for. gilles says it's for when Gnome Speech reads a file of blank lines - if (a_old_uid != event->unique_identifier) - { - espeak_EVENT_TYPE a_new_type = events[0].type; - events[0].type = espeakEVENT_SENTENCE; - my_callback(NULL, 0, events); - events[0].type = a_new_type; - usleep(50000); - } - my_callback(NULL, 0, events); - a_old_uid = event->unique_identifier; - } - break; - - default: - case espeakEVENT_LIST_TERMINATED: - case espeakEVENT_PLAY: - break; - } - } -} -//> -//<event_delete - -static int event_delete(espeak_EVENT* event) -{ -ENTER("event_delete"); - - event_display(event); - - if(event==NULL) - { - return 0; - } - - switch(event->type) - { - case espeakEVENT_MSG_TERMINATED: - event_notify(event); - break; - - case espeakEVENT_MARK: - case espeakEVENT_PLAY: - if(event->id.name) - { - free((void*)(event->id.name)); - } - break; - - default: - break; - } - - free(event); - return 1; -} - -//> -//<event_declare - -espeak_ERROR event_declare (espeak_EVENT* event) -{ -ENTER("event_declare"); - - event_display(event); - - if (!event) - { - return EE_INTERNAL_ERROR; - } - - int a_status = pthread_mutex_lock(&my_mutex); - espeak_ERROR a_error = EE_OK; - - if (!a_status) - { - SHOW_TIME("event_declare > locked\n"); - espeak_EVENT* a_event = event_copy(event); - a_error = push(a_event); - if (a_error != EE_OK) - { - event_delete(a_event); - } - SHOW_TIME("event_declare > unlocking\n"); - a_status = pthread_mutex_unlock(&my_mutex); - } - - // TBD: remove the comment - // reminder: code in comment. - // This wait can lead to an underrun - // -// if (!a_status && !my_event_is_running && (a_error == EE_OK)) -// { -// // quit when command is actually started -// // (for possible forthcoming 'end of command' checks) - SHOW_TIME("event_declare > post my_sem_start_is_required\n"); - sem_post(&my_sem_start_is_required); -// int val=1; -// while (val) -// { -// usleep(50000); // TBD: event? -// sem_getvalue(&my_sem_start_is_required, &val); -// } -// } - - if (a_status != 0) - { - a_error = EE_INTERNAL_ERROR; - } - - return a_error; -} - -//> -//<event_clear_all - -espeak_ERROR event_clear_all () -{ - ENTER("event_clear_all"); - - int a_status = pthread_mutex_lock(&my_mutex); - int a_event_is_running = 0; - - SHOW_TIME("event_stop > locked\n"); - if (a_status != 0) - { - return EE_INTERNAL_ERROR; - } - - if (my_event_is_running) - { - SHOW_TIME("event_stop > post my_sem_stop_is_required\n"); - sem_post(&my_sem_stop_is_required); - a_event_is_running = 1; - } - else - { - init(); // clear pending events - } - SHOW_TIME("event_stop > unlocking\n"); - a_status = pthread_mutex_unlock(&my_mutex); - if (a_status != 0) - { - return EE_INTERNAL_ERROR; - } - - if (a_event_is_running) - { - SHOW_TIME("event_stop > wait for my_sem_stop_is_acknowledged\n"); - while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) - { - continue; // Restart when interrupted by handler - } - SHOW_TIME("event_stop > get my_sem_stop_is_acknowledged\n"); - } - - SHOW_TIME("LEAVE event_stop\n"); - - return EE_OK; -} - -//> -//<sleep_until_timeout_or_stop_request - -static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms) -{ -ENTER("sleep_until_timeout_or_stop_request"); - - int a_stop_is_required=0; - struct timespec ts, to; - struct timeval tv; - int err=0; - - clock_gettime2( &ts); - to.tv_sec = ts.tv_sec; - to.tv_nsec = ts.tv_nsec; - - add_time_in_ms( &ts, time_in_ms); - - SHOW("polling_thread > sleep_until_timeout_or_stop_request > start sem_timedwait from %d.%09lu to %d.%09lu \n", - to.tv_sec, to.tv_nsec, - ts.tv_sec, ts.tv_nsec); - - while ((err = sem_timedwait(&my_sem_stop_is_required, &ts)) == -1 - && errno == EINTR) - { - continue; // Restart when interrupted by handler - } - - assert (gettimeofday(&tv, NULL) != -1); - SHOW("polling_thread > sleep_until_timeout_or_stop_request > stop sem_timedwait %d.%09lu \n", - tv.tv_sec, tv.tv_usec*1000); - - if (err == 0) - { - SHOW("polling_thread > sleep_until_timeout_or_stop_request > %s\n","stop required!"); - a_stop_is_required=1; // stop required - } - return a_stop_is_required; -} - -//> -//<get_remaining_time -// Asked for the time interval required for reaching the sample. -// If the stream is opened but the audio samples are not played, -// a timeout is started. - -static int get_remaining_time(uint32_t sample, uint32_t* time_in_ms, int* stop_is_required) -{ -ENTER("get_remaining_time"); - - int err = 0; - *stop_is_required = 0; - int i=0; - - for (i=0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++) - { - err = wave_get_remaining_time( sample, time_in_ms); - - if (err || wave_is_busy(NULL) || (*time_in_ms == 0)) - { // if err, stream not available: quit - // if wave is busy, time_in_ms is known: quit - // if wave is not busy but remaining time == 0, event is reached: quit - break; - } - - // stream opened but not active - // - // Several possible states: - // * the stream is opened but not yet started: - // - // wait for the start of stream - // - // * some samples have already been played, - // ** the end of stream is reached - // ** or there is an underrun - // - // wait for the close of stream - - *stop_is_required = sleep_until_timeout_or_stop_request( ACTIVITY_TIMEOUT); - } - - return err; -} - -//> -//<polling_thread - -static void* polling_thread(void*) -{ -ENTER("polling_thread"); - - while(1) - { - int a_stop_is_required=0; - - SHOW_TIME("polling_thread > locking\n"); - int a_status = pthread_mutex_lock(&my_mutex); - SHOW_TIME("polling_thread > locked (my_event_is_running = 0)\n"); - my_event_is_running = 0; - pthread_mutex_unlock(&my_mutex); - SHOW_TIME("polling_thread > unlocked\n"); - - SHOW_TIME("polling_thread > wait for my_sem_start_is_required\n"); - - while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) - { - continue; // Restart when interrupted by handler - } - - SHOW_TIME("polling_thread > get my_sem_start_is_required\n"); - - a_status = pthread_mutex_lock(&my_mutex); - SHOW_TIME("polling_thread > locked (my_event_is_running = 1)\n"); - my_event_is_running = 1; - pthread_mutex_unlock(&my_mutex); - SHOW_TIME("polling_thread > unlocked\n"); - - a_stop_is_required=0; - a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); - if ((a_status==0) && a_stop_is_required) - { - SHOW("polling_thread > stop required (%d)\n", __LINE__); - while(0 == sem_trywait(&my_sem_stop_is_required)) - { - }; - } - else - { - a_stop_is_required=0; - } - - // In this loop, my_event_is_running = 1 - while (head && !a_stop_is_required) - { - SHOW_TIME("polling_thread > check head\n"); - while(0 == sem_trywait(&my_sem_start_is_required)) - { - }; - - espeak_EVENT* event = (espeak_EVENT*)(head->data); - assert(event); - - uint32_t time_in_ms = 0; - - int err = get_remaining_time((uint32_t)event->sample, - &time_in_ms, - &a_stop_is_required); - if (a_stop_is_required) - { - break; - } - else if (err != 0) - { - // No available time: the event is deleted. - SHOW("polling_thread > %s\n","audio device down"); - a_status = pthread_mutex_lock(&my_mutex); - SHOW_TIME("polling_thread > locked\n"); - event_delete( (espeak_EVENT*)pop()); - a_status = pthread_mutex_unlock(&my_mutex); - SHOW_TIME("polling_thread > unlocked\n"); - } - else if (time_in_ms==0) - { // the event is already reached. - if (my_callback) - { - event_notify(event); - // the user_data (and the type) are cleaned to be sure - // that MSG_TERMINATED is called twice (at delete time too). - event->type=espeakEVENT_LIST_TERMINATED; - event->user_data=NULL; - } - - a_status = pthread_mutex_lock(&my_mutex); - SHOW_TIME("polling_thread > locked\n"); - event_delete( (espeak_EVENT*)pop()); - a_status = pthread_mutex_unlock(&my_mutex); - SHOW_TIME("polling_thread > unlocked\n"); - - a_stop_is_required=0; - a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); - - if ((a_status==0) && a_stop_is_required) - { - SHOW("polling_thread > stop required (%d)\n", __LINE__); - while(0 == sem_trywait(&my_sem_stop_is_required)) - { - }; - } - else - { - a_stop_is_required=0; - } - } - else - { // The event will be notified soon: sleep until timeout or stop request - a_stop_is_required = sleep_until_timeout_or_stop_request(time_in_ms); - } - } - - a_status = pthread_mutex_lock(&my_mutex); - SHOW_TIME("polling_thread > locked\n"); - - SHOW_TIME("polling_thread > my_event_is_running = 0\n"); - my_event_is_running = 0; - - if(!a_stop_is_required) - { - a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); - if ((a_status==0) && a_stop_is_required) - { - SHOW("polling_thread > stop required (%d)\n", __LINE__); - while(0 == sem_trywait(&my_sem_stop_is_required)) - { - }; - } - else - { - a_stop_is_required=0; - } - } - - a_status = pthread_mutex_unlock(&my_mutex); - SHOW_TIME("polling_thread > unlocked\n"); - - if (a_stop_is_required) - { - SHOW("polling_thread > %s\n","stop required!"); - // no mutex required since the stop command is synchronous - // and waiting for my_sem_stop_is_acknowledged - init(); - - // acknowledge the stop request - SHOW_TIME("polling_thread > post my_sem_stop_is_acknowledged\n"); - a_status = sem_post(&my_sem_stop_is_acknowledged); - } - } - - return NULL; -} - -//> -//<push, pop, init -enum {MAX_NODE_COUNTER=1000}; -// return 1 if ok, 0 otherwise -static espeak_ERROR push(void* the_data) -{ - ENTER("event > push"); - - assert((!head && !tail) || (head && tail)); - - if (the_data == NULL) - { - SHOW("event > push > event=0x%x\n", NULL); - return EE_INTERNAL_ERROR; - } - - if (node_counter >= MAX_NODE_COUNTER) - { - SHOW("event > push > %s\n", "EE_BUFFER_FULL"); - return EE_BUFFER_FULL; - } - - node *n = (node *)malloc(sizeof(node)); - if (n == NULL) - { - return EE_INTERNAL_ERROR; - } - - if (head == NULL) - { - head = n; - tail = n; - } - else - { - tail->next = n; - tail = n; - } - - tail->next = NULL; - tail->data = the_data; - - node_counter++; - SHOW("event > push > counter=%d (uid=%d)\n",node_counter,((espeak_EVENT*)the_data)->unique_identifier); - - return EE_OK; -} - -static void* pop() -{ - ENTER("event > pop"); - void* the_data = NULL; - - assert((!head && !tail) || (head && tail)); - - if (head != NULL) - { - node* n = head; - the_data = n->data; - head = n->next; - free(n); - node_counter--; - SHOW("event > pop > event=0x%x (counter=%d, uid=%d)\n",the_data, node_counter,((espeak_EVENT*)the_data)->unique_identifier); - } - - if(head == NULL) - { - tail = NULL; - } - - return the_data; -} - - -static void init() -{ - ENTER("event > init"); - - while (event_delete( (espeak_EVENT*)pop() )) - {} - - node_counter = 0; -} - -//> -//<event_terminate -void event_terminate() -{ -ENTER("event_terminate"); - - if (my_thread) - { - pthread_cancel(my_thread); - pthread_join(my_thread,NULL); - pthread_mutex_destroy(&my_mutex); - sem_destroy(&my_sem_start_is_required); - sem_destroy(&my_sem_stop_is_required); - sem_destroy(&my_sem_stop_is_acknowledged); - init(); // purge event - } -} - -#endif -//> - diff --git a/navit/support/espeak/event.h b/navit/support/espeak/event.h deleted file mode 100644 index c9ee482b0..000000000 --- a/navit/support/espeak/event.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef EVENT_H -#define EVENT_H - -/* -Manage events (sentence, word, mark, end,...), is responsible of calling the external -callback as soon as the relevant audio sample is played. - - -The audio stream is composed of samples from synthetised messages or audio icons. -Each event is associated to a sample. - -Scenario: - -- event_declare is called for each expected event. - -- A timeout is started for the first pending event. - -- When the timeout happens, the synth_callback is called. - -Note: the timeout is checked against the real progress of the audio stream, which depends on pauses or underruns. If the real progress is lower than the expected one, a new timeout starts. - -*/ - -#include "speak_lib.h" - -// Initialize the event component. -// First function to be called. -// the callback will be called when the event actually occurs. -// The callback is detailled in speak_lib.h . -void event_init(void); -void event_set_callback(t_espeak_callback* cb); - -// Clear any pending event. -// -// Return: EE_OK: operation achieved -// EE_INTERNAL_ERROR. -espeak_ERROR event_clear_all (); - -// Declare a future event -// -// Return: EE_OK: operation achieved -// EE_BUFFER_FULL: the event can not be buffered; -// you may try after a while to call the function again. -// EE_INTERNAL_ERROR. -espeak_ERROR event_declare (espeak_EVENT* event); - -// Terminate the event component. -// Last function to be called. -void event_terminate(); - -#endif diff --git a/navit/support/espeak/fifo.c b/navit/support/espeak/fifo.c deleted file mode 100644 index 95d5ab1ed..000000000 --- a/navit/support/espeak/fifo.c +++ /dev/null @@ -1,593 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007, Gilles Casse <gcasse@oralux.org> * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "speech.h" - -#ifdef USE_ASYNC -// This source file is only used for asynchronious modes - - -//<includes - -#include <unistd.h> -#include <assert.h> -#include <string.h> -#include <stdlib.h> -#include <pthread.h> -#include <semaphore.h> -#include <wchar.h> -#include <errno.h> -#include <sys/time.h> -#include <time.h> - -#include "fifo.h" -#include "wave.h" -#include "debug.h" - - -//> -//<decls and function prototypes - -// my_mutex: protects my_thread_is_talking, -// my_stop_is_required, and the command fifo -static pthread_mutex_t my_mutex; -static int my_command_is_running = 0; -static int my_stop_is_required = 0; -// + fifo -// - -// my_thread: reads commands from the fifo, and runs them. -static pthread_t my_thread; -static sem_t my_sem_start_is_required; -static sem_t my_sem_stop_is_acknowledged; - -static void* say_thread(void*); - -static espeak_ERROR push(t_espeak_command* the_command); -static t_espeak_command* pop(); -static void init(); -static int node_counter=0; -enum {MAX_NODE_COUNTER=400, - INACTIVITY_TIMEOUT=50, // in ms, check that the stream is inactive - MAX_INACTIVITY_CHECK=2 -}; - -//> -//<fifo_init -void fifo_init() -{ - ENTER("fifo_init"); - - // security - pthread_mutex_init( &my_mutex, (const pthread_mutexattr_t *)NULL); - init(); - - assert(-1 != sem_init(&my_sem_start_is_required, 0, 0)); - assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0)); - - pthread_attr_t a_attrib; - if (pthread_attr_init (& a_attrib) - || pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) - || pthread_create( &my_thread, - & a_attrib, - say_thread, - (void*)NULL)) - { - assert(0); - } - - pthread_attr_destroy(&a_attrib); - - // leave once the thread is actually started - SHOW_TIME("fifo > wait for my_sem_stop_is_acknowledged\n"); - while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) - { - continue; // Restart when interrupted by handler - } - SHOW_TIME("fifo > get my_sem_stop_is_acknowledged\n"); -} -//> -//<fifo_add_command - -espeak_ERROR fifo_add_command (t_espeak_command* the_command) -{ - ENTER("fifo_add_command"); - - int a_status = pthread_mutex_lock(&my_mutex); - espeak_ERROR a_error = EE_OK; - - if (!a_status) - { - SHOW_TIME("fifo_add_command > locked\n"); - a_error = push(the_command); - SHOW_TIME("fifo_add_command > unlocking\n"); - a_status = pthread_mutex_unlock(&my_mutex); - } - - if (!a_status && !my_command_is_running && (a_error == EE_OK)) - { - // quit when command is actually started - // (for possible forthcoming 'end of command' checks) - SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n"); - sem_post(&my_sem_start_is_required); - int val=1; - while (val) - { - usleep(50000); // TBD: event? - sem_getvalue(&my_sem_start_is_required, &val); - } - } - - if (a_status != 0) - { - a_error = EE_INTERNAL_ERROR; - } - - SHOW_TIME("LEAVE fifo_add_command"); - return a_error; -} - -//> -//<fifo_add_commands - -espeak_ERROR fifo_add_commands (t_espeak_command* command1, t_espeak_command* command2) -{ - ENTER("fifo_add_command"); - - int a_status = pthread_mutex_lock(&my_mutex); - espeak_ERROR a_error = EE_OK; - - if (!a_status) - { - SHOW_TIME("fifo_add_commands > locked\n"); - - if (node_counter+1 >= MAX_NODE_COUNTER) - { - SHOW("push > %s\n", "EE_BUFFER_FULL"); - a_error = EE_BUFFER_FULL; - } - else - { - push(command1); - push(command2); - } - SHOW_TIME("fifo_add_command > unlocking\n"); - a_status = pthread_mutex_unlock(&my_mutex); - } - - if (!a_status && !my_command_is_running && (a_error == EE_OK)) - { - // quit when one command is actually started - // (for possible forthcoming 'end of command' checks) - SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n"); - sem_post(&my_sem_start_is_required); - int val=1; - while (val) - { - usleep(50000); // TBD: event? - sem_getvalue(&my_sem_start_is_required, &val); - } - } - - if (a_status != 0) - { - a_error = EE_INTERNAL_ERROR; - } - - SHOW_TIME("LEAVE fifo_add_commands"); - return a_error; -} - -//> -//<fifo_stop - -espeak_ERROR fifo_stop () -{ - ENTER("fifo_stop"); - - int a_command_is_running = 0; - int a_status = pthread_mutex_lock(&my_mutex); - SHOW_TIME("fifo_stop > locked\n"); - if (a_status != 0) - { - return EE_INTERNAL_ERROR; - } - - if (my_command_is_running) - { - a_command_is_running = 1; - my_stop_is_required = 1; - SHOW_TIME("fifo_stop > my_stop_is_required = 1\n"); - } - SHOW_TIME("fifo_stop > unlocking\n"); - a_status = pthread_mutex_unlock(&my_mutex); - if (a_status != 0) - { - return EE_INTERNAL_ERROR; - } - - if (a_command_is_running) - { - SHOW_TIME("fifo_stop > wait for my_sem_stop_is_acknowledged\n"); - while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) - { - continue; // Restart when interrupted by handler - } - SHOW_TIME("fifo_stop > get my_sem_stop_is_acknowledged\n"); - } - - SHOW_TIME("fifo_stop > my_stop_is_required = 0\n"); - my_stop_is_required = 0; - SHOW_TIME("LEAVE fifo_stop\n"); - - return EE_OK; -} - -//> - -//<fifo_is_speaking -int fifo_is_busy () -{ - // ENTER("isSpeaking"); - // int aResult = (int) (my_command_is_running || WaveIsPlaying()); - SHOW("fifo_is_busy > aResult = %d\n",my_command_is_running); - return my_command_is_running; -} - -// int pause () -// { -// ENTER("pause"); -// // TBD -// // if (espeakPause (espeakHandle, 1)) -// return true; -// } - -// int resume () -// { -// ENTER("resume"); -// // TBD -// // if (espeakPause (espeakHandle, 0)) -// return true; -// } -//> - - -//<sleep_until_start_request_or_inactivity - -static int sleep_until_start_request_or_inactivity() -{ - SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > ENTER"); - int a_start_is_required=0; - - // Wait for the start request (my_sem_start_is_required). - // Besides this, if the audio stream is still busy, - // check from time to time its end. - // The end of the stream is confirmed by several checks - // for filtering underflow. - // - int i=0; - while((i<= MAX_INACTIVITY_CHECK) && !a_start_is_required) - { - if (wave_is_busy( NULL) ) - { - i = 0; - } - else - { - i++; - } - - int err=0; - struct timespec ts, to; - struct timeval tv; - - clock_gettime2( &ts); - to.tv_sec = ts.tv_sec; - to.tv_nsec = ts.tv_nsec; - - add_time_in_ms( &ts, INACTIVITY_TIMEOUT); - - SHOW("fifo > sleep_until_start_request_or_inactivity > start sem_timedwait (start_is_required) from %d.%09lu to %d.%09lu \n", - to.tv_sec, to.tv_nsec, - ts.tv_sec, ts.tv_nsec); - - while ((err = sem_timedwait(&my_sem_start_is_required, &ts)) == -1 - && errno == EINTR) - { - continue; - } - - assert (gettimeofday(&tv, NULL) != -1); - SHOW("fifo > sleep_until_start_request_or_inactivity > stop sem_timedwait (start_is_required, err=%d) %d.%09lu \n", err, - tv.tv_sec, tv.tv_usec*1000); - - if (err==0) - { - a_start_is_required = 1; - } - } - SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > LEAVE"); - return a_start_is_required; -} - -//> -//<close_stream - -static void close_stream() -{ - SHOW_TIME("fifo > close_stream > ENTER\n"); - - // Warning: a wave_close can be already required by - // an external command (espeak_Cancel + fifo_stop), if so: - // my_stop_is_required = 1; - - int a_status = pthread_mutex_lock(&my_mutex); - assert (!a_status); - int a_stop_is_required = my_stop_is_required; - if (!a_stop_is_required) - { - my_command_is_running = 1; - } - a_status = pthread_mutex_unlock(&my_mutex); - - if (!a_stop_is_required) - { - wave_close(NULL); - - int a_status = pthread_mutex_lock(&my_mutex); - assert (!a_status); - my_command_is_running = 0; - - a_stop_is_required = my_stop_is_required; - a_status = pthread_mutex_unlock(&my_mutex); - - if (a_stop_is_required) - { - // acknowledge the stop request - SHOW_TIME("fifo > close_stream > post my_sem_stop_is_acknowledged\n"); - int a_status = sem_post(&my_sem_stop_is_acknowledged); - assert( a_status != -1); - } - } - - SHOW_TIME("fifo > close_stream > LEAVE\n"); -} - -//> -//<say_thread - -static void* say_thread(void*) -{ - ENTER("say_thread"); - - SHOW_TIME("say_thread > post my_sem_stop_is_acknowledged\n"); - - // announce that thread is started - sem_post(&my_sem_stop_is_acknowledged); - - int look_for_inactivity=0; - - while(1) - { - SHOW_TIME("say_thread > wait for my_sem_start_is_required\n"); - - int a_start_is_required = 0; - if (look_for_inactivity) - { - a_start_is_required = sleep_until_start_request_or_inactivity(); - if (!a_start_is_required) - { - close_stream(); - } - } - look_for_inactivity = 1; - - if (!a_start_is_required) - { - while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) - { - continue; // Restart when interrupted by handler - } - } - SHOW_TIME("say_thread > get my_sem_start_is_required\n"); - - SHOW_TIME("say_thread > my_command_is_running = 1\n"); - my_command_is_running = 1; - - while( my_command_is_running) - { - SHOW_TIME("say_thread > locking\n"); - int a_status = pthread_mutex_lock(&my_mutex); - assert (!a_status); - t_espeak_command* a_command = (t_espeak_command*)pop(); - - if (a_command == NULL) - { - SHOW_TIME("say_thread > text empty (talking=0) \n"); - a_status = pthread_mutex_unlock(&my_mutex); - SHOW_TIME("say_thread > unlocked\n"); - SHOW_TIME("say_thread > my_command_is_running = 0\n"); - my_command_is_running = 0; - } - else - { - display_espeak_command(a_command); - // purge start semaphore - SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); - while(0 == sem_trywait(&my_sem_start_is_required)) - { - }; - - if (my_stop_is_required) - { - SHOW_TIME("say_thread > my_command_is_running = 0\n"); - my_command_is_running = 0; - } - SHOW_TIME("say_thread > unlocking\n"); - a_status = pthread_mutex_unlock(&my_mutex); - - if (my_command_is_running) - { - process_espeak_command(a_command); - } - delete_espeak_command(a_command); - } - } - - if (my_stop_is_required) - { - // no mutex required since the stop command is synchronous - // and waiting for my_sem_stop_is_acknowledged - init(); - - // purge start semaphore - SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); - while(0==sem_trywait(&my_sem_start_is_required)) - { - }; - - // acknowledge the stop request - SHOW_TIME("say_thread > post my_sem_stop_is_acknowledged\n"); - int a_status = sem_post(&my_sem_stop_is_acknowledged); - assert( a_status != -1); - } - // and wait for the next start - SHOW_TIME("say_thread > wait for my_sem_start_is_required\n"); - } - - return NULL; -} - -int fifo_is_command_enabled() -{ - SHOW("ENTER fifo_is_command_enabled=%d\n",(int)(0 == my_stop_is_required)); - return (0 == my_stop_is_required); -} - -//> -//<fifo -typedef struct t_node -{ - t_espeak_command* data; - t_node *next; -} node; - -static node* head=NULL; -static node* tail=NULL; -// return 1 if ok, 0 otherwise -static espeak_ERROR push(t_espeak_command* the_command) -{ - ENTER("fifo > push"); - - assert((!head && !tail) || (head && tail)); - - if (the_command == NULL) - { - SHOW("push > command=0x%x\n", NULL); - return EE_INTERNAL_ERROR; - } - - if (node_counter >= MAX_NODE_COUNTER) - { - SHOW("push > %s\n", "EE_BUFFER_FULL"); - return EE_BUFFER_FULL; - } - - node *n = (node *)malloc(sizeof(node)); - if (n == NULL) - { - return EE_INTERNAL_ERROR; - } - - if (head == NULL) - { - head = n; - tail = n; - } - else - { - tail->next = n; - tail = n; - } - - tail->next = NULL; - tail->data = the_command; - - node_counter++; - SHOW("push > counter=%d\n",node_counter); - - the_command->state = CS_PENDING; - display_espeak_command(the_command); - - return EE_OK; -} - -static t_espeak_command* pop() -{ - ENTER("fifo > pop"); - t_espeak_command* the_command = NULL; - - assert((!head && !tail) || (head && tail)); - - if (head != NULL) - { - node* n = head; - the_command = n->data; - head = n->next; - free(n); - node_counter--; - SHOW("pop > command=0x%x (counter=%d)\n",the_command, node_counter); - } - - if(head == NULL) - { - tail = NULL; - } - - display_espeak_command(the_command); - - return the_command; -} - - -static void init() -{ - ENTER("fifo > init"); - while (delete_espeak_command( pop() )) - {} - node_counter = 0; -} - -//> -//<fifo_init -void fifo_terminate() -{ - ENTER("fifo_terminate"); - - pthread_cancel(my_thread); - pthread_join(my_thread,NULL); - pthread_mutex_destroy(&my_mutex); - sem_destroy(&my_sem_start_is_required); - sem_destroy(&my_sem_stop_is_acknowledged); - - init(); // purge fifo -} - -#endif -//> - diff --git a/navit/support/espeak/fifo.h b/navit/support/espeak/fifo.h deleted file mode 100644 index b3699ff9b..000000000 --- a/navit/support/espeak/fifo.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef FIFO_H -#define FIFO_H - -// Helps to add espeak commands in a first-in first-out queue -// and run them asynchronously. - -#include "espeak_command.h" -#include "speak_lib.h" - -// Initialize the fifo component. -// First function to be called. -void fifo_init(); - -// Add an espeak command. -// -// Note: this function fails if too many commands are already buffered. -// In such a case, the calling function could wait and then add again its command. -// -// Return: EE_OK: operation achieved -// EE_BUFFER_FULL: the command can not be buffered; -// you may try after a while to call the function again. -// EE_INTERNAL_ERROR. -espeak_ERROR fifo_add_command (t_espeak_command* c); - -// Add two espeak commands in a single transaction. -// -// Note: this function fails if too many commands are already buffered. -// In such a case, the calling function could wait and then add again these commands. -// -// Return: EE_OK: operation achieved -// EE_BUFFER_FULL: at least one command can not be buffered; -// you may try after a while to call the function again. -// EE_INTERNAL_ERROR. -espeak_ERROR fifo_add_commands (t_espeak_command* c1, t_espeak_command* c2); - -// The current running command must be stopped and the awaiting commands are cleared. -// Return: EE_OK: operation achieved -// EE_INTERNAL_ERROR. -espeak_ERROR fifo_stop (); - -// Is there a running command? -// Returns 1 if yes; 0 otherwise. -int fifo_is_busy (); - -// Terminate the fifo component. -// Last function to be called. -void fifo_terminate(); - -// Indicates if the running command is still enabled. -// -// Note: this function is mainly called by the SynthCallback (speak_lib.cpp) -// It indicates if the actual wave sample can still be played. It is helpful for -// stopping speech as soon as a cancel command is applied. -// -// Returns 1 if yes, or 0 otherwise. -int fifo_is_command_enabled(); - -#endif diff --git a/navit/support/espeak/intonation.c b/navit/support/espeak/intonation.c deleted file mode 100755 index 61b2ff282..000000000 --- a/navit/support/espeak/intonation.c +++ /dev/null @@ -1,1104 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <string.h> -#include <wctype.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" - - -/* Note this module is mostly old code that needs to be rewritten to - provide a more flexible intonation system. -*/ - -// bits in SYLLABLE.flags -#define SYL_RISE 1 -#define SYL_EMPHASIS 2 -#define SYL_END_CLAUSE 4 - -typedef struct { - char stress; - char env; - char flags; //bit 0=pitch rising, bit1=emnphasized, bit2=end of clause - char nextph_type; - short pitch1; - short pitch2; -} SYLLABLE; - -static SYLLABLE *syllable_tab; - - -static int tone_pitch_env; /* used to return pitch envelope */ - - - -/* Pitch data for tone types */ -/*****************************/ - - -#define PITCHfall 0 -#define PITCHrise 1 -#define PITCHfrise 2 // and 3 must be for the varient preceded by 'r' -#define PITCHfrise2 4 // and 5 must be the 'r' variant -#define PITCHrisefall 6 - -/* 0 fall */ -unsigned char env_fall[128] = { - 0xff, 0xfd, 0xfa, 0xf8, 0xf6, 0xf4, 0xf2, 0xf0, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, - 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xd0, 0xce, 0xcc, 0xca, 0xc8, 0xc6, 0xc4, 0xc2, 0xc0, - 0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0, 0xae, 0xac, 0xaa, 0xa8, 0xa6, 0xa4, 0xa2, 0xa0, - 0x9e, 0x9c, 0x9a, 0x98, 0x96, 0x94, 0x92, 0x90, 0x8e, 0x8c, 0x8a, 0x88, 0x86, 0x84, 0x82, 0x80, - 0x7e, 0x7c, 0x7a, 0x78, 0x76, 0x74, 0x72, 0x70, 0x6e, 0x6c, 0x6a, 0x68, 0x66, 0x64, 0x62, 0x60, - 0x5e, 0x5c, 0x5a, 0x58, 0x56, 0x54, 0x52, 0x50, 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x42, 0x40, - 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, - 0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0e, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x00 }; - -/* 1 rise */ -unsigned char env_rise[128] = { - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, - 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, - 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, - 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, - 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, - 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, - 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, - 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfd, 0xff }; - -unsigned char env_frise[128] = { - 0xff, 0xf4, 0xea, 0xe0, 0xd6, 0xcc, 0xc3, 0xba, 0xb1, 0xa8, 0x9f, 0x97, 0x8f, 0x87, 0x7f, 0x78, - 0x71, 0x6a, 0x63, 0x5c, 0x56, 0x50, 0x4a, 0x44, 0x3f, 0x39, 0x34, 0x2f, 0x2b, 0x26, 0x22, 0x1e, - 0x1a, 0x17, 0x13, 0x10, 0x0d, 0x0b, 0x08, 0x06, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x13, 0x15, 0x17, - 0x1a, 0x1d, 0x1f, 0x22, 0x25, 0x28, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x39, 0x3b, 0x3d, 0x40, - 0x42, 0x45, 0x47, 0x4a, 0x4c, 0x4f, 0x51, 0x54, 0x57, 0x5a, 0x5d, 0x5f, 0x62, 0x65, 0x68, 0x6b, - 0x6e, 0x71, 0x74, 0x78, 0x7b, 0x7e, 0x81, 0x85, 0x88, 0x8b, 0x8f, 0x92, 0x96, 0x99, 0x9d, 0xa0, - 0xa4, 0xa8, 0xac, 0xaf, 0xb3, 0xb7, 0xbb, 0xbf, 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7, 0xdb, 0xe0 }; - -static unsigned char env_r_frise[128] = { - 0xcf, 0xcc, 0xc9, 0xc6, 0xc3, 0xc0, 0xbd, 0xb9, 0xb4, 0xb0, 0xab, 0xa7, 0xa2, 0x9c, 0x97, 0x92, - 0x8c, 0x86, 0x81, 0x7b, 0x75, 0x6f, 0x69, 0x63, 0x5d, 0x57, 0x50, 0x4a, 0x44, 0x3e, 0x38, 0x33, - 0x2d, 0x27, 0x22, 0x1c, 0x17, 0x12, 0x0d, 0x08, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x0a, 0x0c, 0x0d, 0x0f, 0x12, 0x14, 0x16, - 0x19, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d, 0x30, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3f, 0x41, - 0x43, 0x46, 0x48, 0x4b, 0x4d, 0x50, 0x52, 0x55, 0x58, 0x5a, 0x5d, 0x60, 0x63, 0x66, 0x69, 0x6c, - 0x6f, 0x72, 0x75, 0x78, 0x7b, 0x7e, 0x81, 0x85, 0x88, 0x8b, 0x8f, 0x92, 0x96, 0x99, 0x9d, 0xa0, - 0xa4, 0xa8, 0xac, 0xaf, 0xb3, 0xb7, 0xbb, 0xbf, 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7, 0xdb, 0xe0 }; - -static unsigned char env_frise2[128] = { - 0xff, 0xf9, 0xf4, 0xee, 0xe9, 0xe4, 0xdf, 0xda, 0xd5, 0xd0, 0xcb, 0xc6, 0xc1, 0xbd, 0xb8, 0xb3, - 0xaf, 0xaa, 0xa6, 0xa1, 0x9d, 0x99, 0x95, 0x90, 0x8c, 0x88, 0x84, 0x80, 0x7d, 0x79, 0x75, 0x71, - 0x6e, 0x6a, 0x67, 0x63, 0x60, 0x5d, 0x59, 0x56, 0x53, 0x50, 0x4d, 0x4a, 0x47, 0x44, 0x41, 0x3e, - 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2f, 0x2d, 0x2b, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1e, 0x1c, 0x1a, - 0x19, 0x17, 0x15, 0x14, 0x12, 0x11, 0x0f, 0x0e, 0x0d, 0x0c, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, - 0x05, 0x04, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f, 0x10, 0x12, 0x13, 0x15, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20 }; - -static unsigned char env_r_frise2[128] = { - 0xd0, 0xce, 0xcd, 0xcc, 0xca, 0xc8, 0xc7, 0xc5, 0xc3, 0xc1, 0xc0, 0xbd, 0xbb, 0xb8, 0xb5, 0xb3, - 0xb0, 0xad, 0xaa, 0xa7, 0xa3, 0xa0, 0x9d, 0x99, 0x96, 0x92, 0x8f, 0x8b, 0x87, 0x84, 0x80, 0x7c, - 0x78, 0x74, 0x70, 0x6d, 0x69, 0x65, 0x61, 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x4a, 0x46, 0x42, 0x3e, - 0x3b, 0x37, 0x34, 0x31, 0x2f, 0x2d, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1e, 0x1c, 0x1a, 0x19, - 0x17, 0x15, 0x14, 0x12, 0x11, 0x0f, 0x0e, 0x0d, 0x0c, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x05, - 0x04, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f, 0x10, 0x12, 0x13, 0x15, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20 }; - -static unsigned char env_risefall[128] = { - 0x98, 0x99, 0x99, 0x9a, 0x9c, 0x9d, 0x9f, 0xa1, 0xa4, 0xa7, 0xa9, 0xac, 0xb0, 0xb3, 0xb6, 0xba, - 0xbe, 0xc1, 0xc5, 0xc9, 0xcd, 0xd1, 0xd4, 0xd8, 0xdc, 0xdf, 0xe3, 0xe6, 0xea, 0xed, 0xf0, 0xf2, - 0xf5, 0xf7, 0xf9, 0xfb, 0xfc, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfd, - 0xfb, 0xfa, 0xf8, 0xf6, 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe4, 0xe0, 0xdd, 0xda, 0xd7, 0xd3, - 0xd0, 0xcc, 0xc8, 0xc4, 0xc0, 0xbc, 0xb8, 0xb4, 0xb0, 0xac, 0xa7, 0xa3, 0x9f, 0x9a, 0x96, 0x91, - 0x8d, 0x88, 0x84, 0x7f, 0x7b, 0x76, 0x72, 0x6d, 0x69, 0x65, 0x60, 0x5c, 0x58, 0x54, 0x50, 0x4c, - 0x48, 0x44, 0x40, 0x3c, 0x39, 0x35, 0x32, 0x2f, 0x2b, 0x28, 0x26, 0x23, 0x20, 0x1d, 0x1a, 0x17, - 0x15, 0x12, 0x0f, 0x0d, 0x0a, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -static unsigned char env_rise2[128] = { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x06, 0x06, - 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1d, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2b, - 0x2d, 0x2f, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x47, 0x49, 0x4b, - 0x4e, 0x50, 0x52, 0x55, 0x57, 0x5a, 0x5d, 0x5f, 0x62, 0x65, 0x67, 0x6a, 0x6d, 0x70, 0x73, 0x76, - 0x79, 0x7c, 0x7f, 0x82, 0x86, 0x89, 0x8c, 0x90, 0x93, 0x96, 0x9a, 0x9d, 0xa0, 0xa3, 0xa6, 0xa9, - 0xac, 0xaf, 0xb2, 0xb5, 0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd, 0xd0, 0xd3, 0xd6, 0xd9, - 0xdc, 0xdf, 0xe2, 0xe4, 0xe7, 0xe9, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfb, 0xfd }; - -static unsigned char env_fall2[128] = { - 0xfe, 0xfe, 0xfd, 0xfd, 0xfc, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf6, - 0xf5, 0xf4, 0xf4, 0xf3, 0xf3, 0xf2, 0xf2, 0xf1, 0xf0, 0xf0, 0xef, 0xee, 0xee, 0xed, 0xec, 0xeb, - 0xea, 0xea, 0xe9, 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xde, 0xdd, 0xdc, 0xdb, - 0xd9, 0xd8, 0xd6, 0xd5, 0xd3, 0xd2, 0xd0, 0xce, 0xcc, 0xcb, 0xc9, 0xc7, 0xc5, 0xc3, 0xc0, 0xbe, - 0xbc, 0xb9, 0xb7, 0xb5, 0xb2, 0xaf, 0xad, 0xaa, 0xa7, 0xa4, 0xa1, 0x9e, 0x9a, 0x97, 0x94, 0x90, - 0x8d, 0x89, 0x85, 0x81, 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x68, 0x64, 0x61, 0x5e, 0x5b, 0x57, 0x54, - 0x51, 0x4d, 0x4a, 0x46, 0x43, 0x40, 0x3c, 0x39, 0x35, 0x32, 0x2e, 0x2a, 0x27, 0x23, 0x1f, 0x1c, - 0x18, 0x14, 0x11, 0x0d, 0x0b, 0x09, 0x07, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00 }; - -static unsigned char env_fallrise3[128] = { - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xfc, 0xfa, 0xf8, 0xf6, 0xf4, 0xf1, 0xee, 0xeb, - 0xe8, 0xe5, 0xe1, 0xde, 0xda, 0xd6, 0xd2, 0xcd, 0xc9, 0xc4, 0xbf, 0xba, 0xb6, 0xb0, 0xab, 0xa6, - 0xa1, 0x9c, 0x96, 0x91, 0x8b, 0x86, 0x80, 0x7b, 0x75, 0x6f, 0x6a, 0x64, 0x5f, 0x59, 0x54, 0x4f, - 0x49, 0x44, 0x3f, 0x3a, 0x35, 0x30, 0x2b, 0x26, 0x22, 0x1d, 0x19, 0x15, 0x11, 0x0d, 0x0a, 0x07, - 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x04, 0x05, - 0x07, 0x09, 0x0b, 0x0d, 0x10, 0x12, 0x15, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35, - 0x3a, 0x3e, 0x43, 0x48, 0x4c, 0x51, 0x57, 0x5b, 0x5e, 0x62, 0x65, 0x68, 0x6b, 0x6e, 0x71, 0x74, - 0x76, 0x78, 0x7b, 0x7c, 0x7e, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x83, 0x83, 0x82, 0x81 }; - -static unsigned char env_fallrise4[128] = { - 0x72, 0x72, 0x71, 0x71, 0x70, 0x6f, 0x6d, 0x6c, 0x6a, 0x68, 0x66, 0x64, 0x61, 0x5f, 0x5c, 0x5a, - 0x57, 0x54, 0x51, 0x4e, 0x4b, 0x48, 0x45, 0x42, 0x3f, 0x3b, 0x38, 0x35, 0x32, 0x2f, 0x2c, 0x29, - 0x26, 0x23, 0x20, 0x1d, 0x1b, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0e, 0x0c, 0x0b, 0x0a, 0x09, 0x08, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, - 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d, 0x0f, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1d, 0x20, - 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43, 0x47, 0x4c, 0x51, 0x56, 0x5b, 0x60, - 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7f, 0x84, 0x89, 0x8f, 0x95, 0x9b, 0xa1, 0xa7, 0xad, 0xb3, 0xba, - 0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1, 0xf5, 0xf7, 0xfa, 0xfc, 0xfd, 0xfe, 0xff, 0xff }; - -static unsigned char env_risefallrise[128] = { - 0x7f, 0x7f, 0x7f, 0x80, 0x81, 0x83, 0x84, 0x87, 0x89, 0x8c, 0x8f, 0x92, 0x96, 0x99, 0x9d, 0xa1, - 0xa5, 0xaa, 0xae, 0xb2, 0xb7, 0xbb, 0xc0, 0xc5, 0xc9, 0xcd, 0xd2, 0xd6, 0xda, 0xde, 0xe2, 0xe6, - 0xea, 0xed, 0xf0, 0xf3, 0xf5, 0xf8, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xfe, 0xfd, 0xfc, 0xfb, 0xf9, - 0xf7, 0xf4, 0xf0, 0xec, 0xe7, 0xe2, 0xdc, 0xd5, 0xce, 0xc6, 0xbd, 0xb4, 0xa9, 0x9e, 0x92, 0x88, - 0x82, 0x7d, 0x77, 0x72, 0x6c, 0x66, 0x60, 0x5a, 0x54, 0x4e, 0x49, 0x42, 0x3c, 0x37, 0x32, 0x2d, - 0x28, 0x24, 0x1f, 0x1b, 0x18, 0x14, 0x11, 0x0e, 0x0c, 0x09, 0x07, 0x06, 0x05, 0x04, 0x04, 0x04, - 0x04, 0x05, 0x06, 0x08, 0x0a, 0x0d, 0x10, 0x14, 0x18, 0x1d, 0x23, 0x29, 0x2f, 0x37, 0x3e, 0x47, - 0x50, 0x5a, 0x64, 0x70, 0x7c, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x93, 0x93 }; - - - - -unsigned char *envelope_data[18] = { - env_fall, - env_rise, - env_frise, env_r_frise, - env_frise2, env_r_frise2, - env_risefall, env_risefall, - - env_fallrise3, env_fallrise3, - env_fallrise4, env_fallrise4, - env_fall2, env_fall2, - env_rise2, env_rise2, - env_risefallrise, env_risefallrise - }; - - -/* all pitches given in Hz above pitch_base */ - -// pitch change during the main part of the clause -static int drops_0[8] = {0x400,0x400,0x700,0x700,0x700,0xa00,0x1800,0x0e00}; -//static int drops_1[8] = {0x400,0x400,0x600,0x600,0xc00,0xc00,0x0e00,0x0e00}; -//static int drops_2[8] = {0x400,0x400,0x600,0x600,-0x800,0xc00,0x0e00,0x0e00}; - -static short oflow[] = {0, 20, 12, 4, 0}; -static short oflow_emf[] = {5, 24, 15, 10, 5}; -static short oflow_less[] = {3, 19, 12, 7, 2}; -// static short oflow_test2[] = {20, 0, 20, 0, 20}; -// static short back_emf[] = {35, 32, 0}; - - -#define N_TONE_HEAD_TABLE 13 -#define N_TONE_NUCLEUS_TABLE 13 - - -typedef struct { - unsigned char pre_start; - unsigned char pre_end; - - unsigned char body_start; - unsigned char body_end; - - int *body_drops; - unsigned char body_max_steps; - char body_lower_u; - - char n_overflow; - short *overflow; -} TONE_HEAD; - - -typedef struct { - unsigned char pitch_env0; /* pitch envelope, tonic syllable at end */ - unsigned char tonic_max0; - unsigned char tonic_min0; - - unsigned char pitch_env1; /* followed by unstressed */ - unsigned char tonic_max1; - unsigned char tonic_min1; - - short *backwards; - - unsigned char tail_start; - unsigned char tail_end; - unsigned char flags; -} TONE_NUCLEUS; - -#define T_EMPH 1 - -static TONE_HEAD tone_head_table[N_TONE_HEAD_TABLE] = { - {20, 25, 34, 22, drops_0, 3, 3, 5, oflow}, // 0 statement - {20, 25, 34, 20, drops_0, 3, 3, 5, oflow}, // 1 comma - {20, 25, 34, 20, drops_0, 3, 3, 5, oflow}, // 2 question - {20, 25, 36, 22, drops_0, 3, 4, 5, oflow_emf}, // 3 exclamation - {20, 25, 34, 22, drops_0, 3, 3, 5, oflow}, // 4 statement, emphatic - {20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less}, // 5 statement, less intonation - {20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less}, // 6 comma, less intonation - {20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less}, // 7 comma, less intonation, less rise - {20, 25, 34, 22, drops_0, 3, 3, 5, oflow}, // 8 pitch raises at end of sentence - {20, 25, 34, 20, drops_0, 3, 3, 5, oflow}, // 9 comma - {20, 25, 34, 22, drops_0, 3, 3, 5, oflow}, // 10 question - {15, 18, 18, 14, drops_0, 3, 3, 5, oflow_less}, // 11 test - {20, 25, 24, 22, drops_0, 3, 3, 5, oflow_less}, // 12 test -}; - -static TONE_NUCLEUS tone_nucleus_table[N_TONE_NUCLEUS_TABLE] = { - {PITCHfall, 30, 5, PITCHfall, 32, 9, NULL, 12, 7, 0}, // 0 statement - {PITCHfrise, 35, 8, PITCHfrise2, 35,10, NULL, 15, 23, 0}, // 1 comma - {PITCHfrise, 39,10, PITCHfrise2, 36,10, NULL, 15, 28, 0}, // 2 question -// {PITCHfall, 41, 4, PITCHfall, 41,27, NULL, 16, 4, T_EMPH}, // 3 exclamation - {PITCHfall, 41, 4, PITCHfall, 41,35, NULL, 35, 4, T_EMPH}, // 3 exclamation - {PITCHfall, 38, 2, PITCHfall, 42,30, NULL, 15, 5, 0}, // 4 statement, emphatic - {PITCHfall, 28, 5, PITCHfall, 28, 9, NULL, 12, 7, 0}, // 5 statement, less intonation - {PITCHfrise, 30, 8, PITCHfrise2, 30,10, NULL, 13, 20, 0}, // 6 comma, less intonation - {PITCHfrise2, 28, 7, PITCHfall, 29,14, NULL, 14, 8, 0}, // 7 comma, less intonation, less rise - {PITCHrise, 30,20, PITCHfall, 19,14, NULL, 20, 26, 0}, // 8 pitch raises at end of sentence - {PITCHfrise, 35,11, PITCHfrise2, 32,10, NULL, 19, 24, 0}, // 9 comma - {PITCHfrise, 39,15, PITCHfall, 28,14, NULL, 20, 36, 0}, // 10 question - {PITCHfall, 28, 6, PITCHfall, 28,10, NULL, 12, 6, 0}, // 11 test - {PITCHfall, 35, 9, PITCHfall, 35,12, NULL, 16, 10, 0}, // 12 test -}; - - - -/* index by 0=. 1=, 2=?, 3=! 4=none, 5=emphasized */ -unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS] = { - {0,1,2,3,0,4}, - {0,1,2,3,0,4}, - {5,6,2,3,0,4}, - {5,7,1,3,0,4}, - {8,9,10,3,0,0}, - {8,8,10,3,0,0}, - {11,11,11,11,0,0}, // 6 test - {12,12,12,12,0,0} -}; - - - -/* indexed by stress */ -static int min_drop[] = {0x300,0x300,0x400,0x400,0x900,0x900,0x900,0xb00}; - - - - -#define SECONDARY 3 -#define PRIMARY 4 -#define PRIMARY_STRESSED 6 -#define PRIMARY_LAST 7 - - -static int number_pre; -static int number_body; -static int number_tail; -static int last_primary; -static int tone_posn; -static int tone_posn2; -static int no_tonic; - - -static void count_pitch_vowels(int start, int end, int clause_end) -/****************************************************************/ -{ - int ix; - int stress; - int max_stress = 0; - int max_stress_posn = 0; // last syllable ot the highest stress - int max_stress_posn2 = 0; // penuntimate syllable of the highest stress - - number_pre = -1; /* number of vowels before 1st primary stress */ - number_body = 0; - number_tail = 0; /* number between tonic syllable and next primary */ - last_primary = -1; - - for(ix=start; ix<end; ix++) - { - stress = syllable_tab[ix].stress; /* marked stress level */ - - if(stress >= max_stress) - { - if(stress > max_stress) - { - max_stress_posn2 = ix; - } - else - { - max_stress_posn2 = max_stress_posn; - } - max_stress_posn = ix; - max_stress = stress; - } - if(stress >= PRIMARY) - { - if(number_pre < 0) - number_pre = ix - start; - - last_primary = ix; - } - - } - - if(number_pre < 0) - number_pre = end; - - number_tail = end - max_stress_posn - 1; - tone_posn = max_stress_posn; - tone_posn2 = max_stress_posn2; - - if(no_tonic) - { - tone_posn = tone_posn2 = end; // next position after the end of the truncated clause - } - else - if(last_primary >= 0) - { - if(end == clause_end) - { - syllable_tab[last_primary].stress = PRIMARY_LAST; - } - } - else - { - // no primary stress. Use the highest stress - 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 */ -{ - int count = 0; - int stress; - - while(ix < end_ix) - { - stress = syllable_tab[ix++].stress; - if(stress >= PRIMARY_LAST) - break; - - if(stress >= min_stress) - 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. Base & drop are Hz * 256 -{ - int pitch1, pitch2; - int flags = 0; - - /* adjust experimentally */ - int pitch_range2 = 148; - int pitch_base2 = 72; - - if(base < 0) base = 0; - - pitch2 = ((base * pitch_range2 ) >> 15) + pitch_base2; - - if(drop < 0) - { - flags = SYL_RISE; - drop = -drop; - } - - pitch1 = pitch2 + ((drop * pitch_range2) >> 15); - - if(pitch1 > 511) pitch1 = 511; - if(pitch2 > 511) pitch2 = 511; - - syl->pitch1 = pitch1; - syl->pitch2 = pitch2; - syl->flags |= flags; -} /* end of set_pitch */ - - - -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. - Increment pitch if stress is >= min_stress. - Used for tonic segment */ -{ - int stress; - int pitch=0; - int increment=0; - int n_primary=0; - int n_steps=0; - int initial; - int overflow=0; - int n_overflow; - int *drops; - short *overflow_tab; - SYLLABLE *syl; - - static short continue_tab[5] = {-13, 16, 10, 4, 0}; - - drops = th->body_drops; - - if(continuing) - { - initial =0; - overflow = 0; - n_overflow = 5; - overflow_tab = continue_tab; - increment = (th->body_end - th->body_start) << 8; - increment = increment / (th->body_max_steps -1); - } - else - { - n_overflow = th->n_overflow; - overflow_tab = th->overflow; - initial = 1; - } - - while(ix < end_ix) - { - syl = &syllable_tab[ix]; - stress = syl->stress; - -// if(stress == PRIMARY_MARKED) -// initial = 1; // reset the intonation pattern - - if(initial || (stress >= min_stress)) - { - // a primary stress - - if((initial) || (stress == 5)) - { - initial = 0; - overflow = 0; - n_steps = n_primary = count_increments(ix,end_ix,min_stress); - - if(n_steps > th->body_max_steps) - n_steps = th->body_max_steps; - - if(n_steps > 1) - { - increment = (th->body_end - th->body_start) << 8; - increment = increment / (n_steps -1); - } - else - increment = 0; - - pitch = th->body_start << 8; - } - else - { - if(n_steps > 0) - pitch += increment; - else - { - pitch = (th->body_end << 8) - (increment * overflow_tab[overflow++])/16; - if(overflow >= n_overflow) - { - overflow = 0; - overflow_tab = th->overflow; - } - } - } - - n_steps--; - - n_primary--; - if((tn->backwards) && (n_primary < 2)) - { - pitch = tn->backwards[n_primary] << 8; - } - } - - if(stress >= PRIMARY) - { - syl->stress = PRIMARY_STRESSED; - set_pitch(syl,pitch,drops[stress]); - } - else - if(stress >= SECONDARY) - { - set_pitch(syl,pitch,drops[stress]); - } - else - { - /* unstressed, drop pitch if preceded by PRIMARY */ - if((syllable_tab[ix-1].stress & 0x3f) >= SECONDARY) - set_pitch(syl,pitch - (th->body_lower_u << 8), drops[stress]); - else - set_pitch(syl,pitch,drops[stress]); - } - - ix++; - } - return(ix); -} /* end of calc_pitch_segment */ - - - - - -static int calc_pitch_segment2(int ix, int end_ix, int start_p, int end_p, int min_stress) -/****************************************************************************************/ -/* Linear pitch rise/fall, change pitch at min_stress or stronger - Used for pre-head and tail */ -{ - int stress; - int pitch; - int increment; - int n_increments; - int drop; - SYLLABLE *syl; - - if(ix >= end_ix) - return(ix); - - n_increments = count_increments(ix,end_ix,min_stress); - increment = (end_p - start_p) << 8; - - if(n_increments > 1) - { - increment = increment / n_increments; - } - - - pitch = start_p << 8; - while(ix < end_ix) - { - syl = &syllable_tab[ix]; - stress = syl->stress; - - if(increment > 0) - { - set_pitch(syl,pitch,-increment); - pitch += increment; - } - else - { - drop = -increment; - if(drop < min_drop[stress]) - drop = min_drop[stress]; - - pitch += increment; - - if(drop > 0x900) - drop = 0x900; - set_pitch(syl, pitch, drop); - } - - ix++; - } - return(ix); -} /* end of calc_pitch_segment2 */ - - - - - - -static int calc_pitches(int start, int end, int head_tone, int nucleus_tone) -//=========================================================================== -// Calculate pitch values for the vowels in this tone group -{ - int ix; - TONE_HEAD *th; - TONE_NUCLEUS *tn; - int drop; - int continuing = 0; - - if(start > 0) - continuing = 1; - - th = &tone_head_table[head_tone]; - tn = &tone_nucleus_table[nucleus_tone]; - ix = start; - - /* vowels before the first primary stress */ - /******************************************/ - - if(number_pre > 0) - { - ix = calc_pitch_segment2(ix, ix+number_pre, th->pre_start, th->pre_end, 0); - } - - /* body of tonic segment */ - /*************************/ - - if(option_tone_flags & OPTION_EMPHASIZE_PENULTIMATE) - { - tone_posn = tone_posn2; // put tone on the penultimate stressed word - } - ix = calc_pitch_segment(ix,tone_posn, th, tn, PRIMARY, continuing); - - if(no_tonic) - return(0); - - /* tonic syllable */ - /******************/ - - if(tn->flags & T_EMPH) - { - syllable_tab[ix].flags |= SYL_EMPHASIS; - } - - if(number_tail == 0) - { - tone_pitch_env = tn->pitch_env0; - drop = tn->tonic_max0 - tn->tonic_min0; - set_pitch(&syllable_tab[ix++],tn->tonic_min0 << 8,drop << 8); - } - else - { - tone_pitch_env = tn->pitch_env1; - drop = tn->tonic_max1 - tn->tonic_min1; - set_pitch(&syllable_tab[ix++],tn->tonic_min1 << 8,drop << 8); - } - - syllable_tab[tone_posn].env = tone_pitch_env; - if(syllable_tab[tone_posn].stress == PRIMARY) - syllable_tab[tone_posn].stress = PRIMARY_STRESSED; - - /* tail, after the tonic syllable */ - /**********************************/ - - calc_pitch_segment2(ix, end, tn->tail_start, tn->tail_end, 0); - - return(tone_pitch_env); -} /* end of calc_pitches */ - - - - - - -static void CalcPitches_Tone(Translator *tr, int clause_tone) -{//========================================================== -// clause_tone: 0=. 1=, 2=?, 3=! 4=none - PHONEME_LIST *p; - int ix; - int count_stressed=0; - int final_stressed=0; - - int tone_ph; - int pause; - int tone_promoted; - PHONEME_TAB *tph; - PHONEME_TAB *prev_tph; // forget across word boundary - PHONEME_TAB *prevw_tph; // remember across word boundary - PHONEME_TAB *prev2_tph; // 2 tones previous - PHONEME_LIST *prev_p; - - int pitch_adjust = 0; // pitch gradient through the clause - inital value - int pitch_decrement = 0; // decrease by this for each stressed syllable - int pitch_low = 0; // until it drops to this - int pitch_high = 0; // then reset to this - - p = &phoneme_list[0]; - - // count number of stressed syllables - p = &phoneme_list[0]; - for(ix=0; ix<n_phoneme_list; ix++, p++) - { - if((p->type == phVOWEL) && (p->stresslevel >= 4)) - { - if(count_stressed == 0) - final_stressed = ix; - - if(p->stresslevel >= 4) - { - final_stressed = ix; - count_stressed++; - } - } - } - - phoneme_list[final_stressed].stresslevel = 7; - - // language specific, changes to tones - if(tr->translator_name == L('v','i')) - { - // LANG=vi - p = &phoneme_list[final_stressed]; - if(p->tone_ph == 0) - p->tone_ph = PhonemeCode('7'); // change default tone (tone 1) to falling tone at end of clause - } - - - pause = 1; - tone_promoted = 0; - - prev_p = p = &phoneme_list[0]; - prev_tph = prevw_tph = phoneme_tab[phonPAUSE]; - - // perform tone sandhi - for(ix=0; ix<n_phoneme_list; ix++, p++) - { - if((p->type == phPAUSE) && (p->ph->std_length > 50)) - { - pause = 1; // there is a pause since the previous vowel - prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone - } - - if(p->newword) - { - prev_tph = phoneme_tab[phonPAUSE]; // forget across word boundaries - } - - if(p->synthflags & SFLAG_SYLLABLE) - { - tone_ph = p->tone_ph; - tph = phoneme_tab[tone_ph]; - - // Mandarin - if(tr->translator_name == L('z','h')) - { - if(tone_ph == 0) - { - if(pause || tone_promoted) - { - tone_ph = PhonemeCode2('5','5'); // no previous vowel, use tone 1 - tone_promoted = 1; - } - else - { - tone_ph = PhonemeCode2('1','1'); // default tone 5 - } - - p->tone_ph = tone_ph; - tph = phoneme_tab[tone_ph]; - - } - else - { - tone_promoted = 0; - } - - if(ix == final_stressed) - { - if((tph->mnemonic == 0x3535 ) || (tph->mnemonic == 0x3135)) - { - // change sentence final tone 1 or 4 to stress 6, not 7 - phoneme_list[final_stressed].stresslevel = 6; - } - } - - if(prevw_tph->mnemonic == 0x343132) // [214] - { - if(tph->mnemonic == 0x343132) // [214] - prev_p->tone_ph = PhonemeCode2('3','5'); - else - prev_p->tone_ph = PhonemeCode2('2','1'); - } - if((prev_tph->mnemonic == 0x3135) && (tph->mnemonic == 0x3135)) // [51] + [51] - { - prev_p->tone_ph = PhonemeCode2('5','3'); - } - - if(tph->mnemonic == 0x3131) // [11] Tone 5 - { - // tone 5, change its level depending on the previous tone (across word boundaries) - if(prevw_tph->mnemonic == 0x3535) - p->tone_ph = PhonemeCode2('2','2'); - if(prevw_tph->mnemonic == 0x3533) - p->tone_ph = PhonemeCode2('3','3'); - if(prevw_tph->mnemonic == 0x343132) - p->tone_ph = PhonemeCode2('4','4'); - - // tone 5 is unstressed (shorter) - p->stresslevel = 1; // diminished stress - } - } - - prev_p = p; - prev2_tph = prevw_tph; - prevw_tph = prev_tph = tph; - pause = 0; - } - } - - // convert tone numbers to pitch - p = &phoneme_list[0]; - for(ix=0; ix<n_phoneme_list; ix++, p++) - { - if(p->synthflags & SFLAG_SYLLABLE) - { - tone_ph = p->tone_ph; - - if(p->stresslevel != 1) // TEST, consider all syllables as stressed - { - if(ix == final_stressed) - { - // the last stressed syllable - pitch_adjust = pitch_low; - } - else - { - pitch_adjust -= pitch_decrement; - if(pitch_adjust <= pitch_low) - pitch_adjust = pitch_high; - } - } - - if(tone_ph ==0) - { - tone_ph = phonDEFAULTTONE; // no tone specified, use default tone 1 - p->tone_ph = tone_ph; - } - p->pitch1 = pitch_adjust + phoneme_tab[tone_ph]->start_type; - p->pitch2 = pitch_adjust + phoneme_tab[tone_ph]->end_type; - } - } - - -} // end of Translator::CalcPitches_Tone - - - -void CalcPitches(Translator *tr, int clause_type) -{//============================================== -// clause_type: 0=. 1=, 2=?, 3=! 4=none - PHONEME_LIST *p; - SYLLABLE *syl; - int ix; - int x; - int st_ix; - int n_st; - int option; - int group_tone; - int group_tone_emph; - int group_tone_comma; - int ph_start=0; - int st_start; - int st_clause_end; - int count; - int n_primary; - int count_primary; - PHONEME_TAB *ph; - int ph_end=n_phoneme_list; - - SYLLABLE syllable_tab2[N_PHONEME_LIST]; - - syllable_tab = syllable_tab2; // don't use permanent storage. it's only needed during the call of CalcPitches() - n_st = 0; - n_primary = 0; - for(ix=0; ix<(n_phoneme_list-1); ix++) - { - p = &phoneme_list[ix]; - if(p->synthflags & SFLAG_SYLLABLE) - { - syllable_tab[n_st].flags = 0; - syllable_tab[n_st].env = PITCHfall; - syllable_tab[n_st].nextph_type = phoneme_list[ix+1].type; - syllable_tab[n_st++].stress = p->stresslevel; - - if(p->stresslevel >= 4) - n_primary++; - } - else - if((p->ph->code == phonPAUSE_CLAUSE) && (n_st > 0)) - { - syllable_tab[n_st-1].flags |= SYL_END_CLAUSE; - } - } - syllable_tab[n_st].stress = 0; // extra 0 entry at the end - - if(n_st == 0) - return; // nothing to do - - - - if(tr->langopts.tone_language == 1) - { - CalcPitches_Tone(tr,clause_type); - return; - } - - - option = tr->langopts.intonation_group; - if(option >= INTONATION_TYPES) - option = 0; - - group_tone = tr->punct_to_tone[option][clause_type]; - group_tone_emph = tr->punct_to_tone[option][5]; // emphatic form of statement - group_tone_comma = tr->punct_to_tone[option][1]; // emphatic form of statement - - if(clause_type == 4) - no_tonic = 1; /* incomplete clause, used for abbreviations such as Mr. Dr. Mrs. */ - else - no_tonic = 0; - - st_start = 0; - count_primary=0; - for(st_ix=0; st_ix<n_st; st_ix++) - { - syl = &syllable_tab[st_ix]; - - if(syl->stress >= 4) - count_primary++; - - if(syl->stress == 6) - { - // reduce the stress of the previous stressed syllable (review only the previous few syllables) - for(ix=st_ix-1; ix>=st_start && ix>=(st_ix-3); ix--) - { - if(syllable_tab[ix].stress == 6) - break; - if(syllable_tab[ix].stress == 4) - { - syllable_tab[ix].stress = 3; - break; - } - } - - // are the next primary syllables also emphasized ? - for(ix=st_ix+1; ix<n_st; ix++) - { - if(syllable_tab[ix].stress == 4) - break; - if(syllable_tab[ix].stress == 6) - { - // emphasize this syllable, but don't end the current tone group - syllable_tab[st_ix].flags = SYL_EMPHASIS; - syl->stress = 5; - break; - } - } - } - - if(syl->stress == 6) - { - // an emphasized syllable, end the tone group after the next primary stress - syllable_tab[st_ix].flags = SYL_EMPHASIS; - - count = 0; - if((n_primary - count_primary) > 1) - count =1; - - for(ix=st_ix+1; ix<n_st; ix++) - { - if(syllable_tab[ix].stress > 4) - break; - if(syllable_tab[ix].stress == 4) - { - count++; - if(count > 1) - break; - } - } - - count_pitch_vowels(st_start, ix, n_st); - if((ix < n_st) || (clause_type == 0)) - calc_pitches(st_start, ix, group_tone_emph, group_tone_emph); // split into > 1 tone groups, use emphatic tone - else - calc_pitches(st_start, ix, group_tone, group_tone); - - st_start = ix; - } - if((st_start < st_ix) && (syl->flags & SYL_END_CLAUSE)) - { - // end of clause after this syllable, indicated by a phonPAUSE_CLAUSE phoneme - st_clause_end = st_ix+1; - count_pitch_vowels(st_start, st_clause_end, st_clause_end); - calc_pitches(st_start, st_clause_end, group_tone_comma, group_tone_comma); - st_start = st_clause_end; - } - } - - if(st_start < st_ix) - { - count_pitch_vowels(st_start, st_ix, n_st); - calc_pitches(st_start, st_ix, group_tone, group_tone); - } - - - // unpack pitch data - st_ix=0; - for(ix=ph_start; ix < ph_end; ix++) - { - p = &phoneme_list[ix]; - p->stresslevel = syllable_tab[st_ix].stress; - - if(p->synthflags & SFLAG_SYLLABLE) - { - syl = &syllable_tab[st_ix]; - - x = syl->pitch1 - 72; - if(x < 0) x = 0; - p->pitch1 = x; - - x = syl->pitch2 - 72; - if(x < 0) x = 0; - p->pitch2 = x; - - p->env = PITCHfall; - if(syl->flags & SYL_RISE) - { - p->env = PITCHrise; - } - else - if(p->stresslevel > 5) - p->env = syl->env; - - if(p->pitch1 > p->pitch2) - { - // swap so that pitch2 is the higher - x = p->pitch1; - p->pitch1 = p->pitch2; - p->pitch2 = x; - } - -if(p->tone_ph) -{ - ph = phoneme_tab[p->tone_ph]; - x = (p->pitch1 + p->pitch2)/2; - p->pitch2 = x + ph->end_type; - p->pitch1 = x + ph->start_type; -} - - if(syl->flags & SYL_EMPHASIS) - { - p->stresslevel |= 8; // emphasized - } - - st_ix++; - } - } - -} // end of Translator::CalcPitches - - diff --git a/navit/support/espeak/klatt.c b/navit/support/espeak/klatt.c deleted file mode 100644 index 8cdbf782b..000000000 --- a/navit/support/espeak/klatt.c +++ /dev/null @@ -1,1303 +0,0 @@ - -/*************************************************************************** - * Copyright (C) 2008 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * Based on a re-implementation by: * - * (c) 1993,94 Jon Iles and Nick Ing-Simmons * - * of the Klatt cascade-parallel formant synthesizer * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -// See URL: ftp://svr-ftp.eng.cam.ac.uk/pub/comp.speech/synthesis/klatt.3.04.tar.gz - -#include "StdAfx.h" - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include <string.h> - -#include "speak_lib.h" -#include "speech.h" -#include "klatt.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" - -#ifdef INCLUDE_KLATT // conditional compilation for the whole file - -extern unsigned char *out_ptr; // **JSD -extern unsigned char *out_start; -extern unsigned char *out_end; -extern WGEN_DATA wdata; -static int nsamples; -static int sample_count; - - -#ifdef _MSC_VER -#define getrandom(min,max) ((rand()%(int)(((max)+1)-(min)))+(min)) -#else -#define getrandom(min,max) ((rand()%(long)(((max)+1)-(min)))+(min)) -#endif - - -/* function prototypes for functions private to this file */ - -static void flutter(klatt_frame_ptr); -static double sampled_source (void); -static double impulsive_source (void); -static double natural_source (void); -static void pitch_synch_par_reset (klatt_frame_ptr); -static double gen_noise (double); -static double DBtoLIN (long); -static void frame_init (klatt_frame_ptr); -static void setabc (long,long,resonator_ptr); -static void setzeroabc (long,long,resonator_ptr); - -static klatt_frame_t kt_frame; -static klatt_global_t kt_globals; - -/* -function RESONATOR - -This is a generic resonator function. Internal memory for the resonator -is stored in the globals structure. -*/ - -static double resonator(resonator_ptr r, double input) -{ - double x; - - x = (double) ((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2); - r->p2 = (double)r->p1; - r->p1 = (double)x; - - return (double)x; -} - -static double resonator2(resonator_ptr r, double input) -{ - double x; - - x = (double) ((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2); - r->p2 = (double)r->p1; - r->p1 = (double)x; - - r->a += r->a_inc; - r->b += r->b_inc; - r->c += r->c_inc; - return (double)x; -} - - - -/* -function ANTIRESONATOR - -This is a generic anti-resonator function. The code is the same as resonator -except that a,b,c need to be set with setzeroabc() and we save inputs in -p1/p2 rather than outputs. There is currently only one of these - "rnz" -Output = (rnz.a * input) + (rnz.b * oldin1) + (rnz.c * oldin2) -*/ - -#ifdef deleted -static double antiresonator(resonator_ptr r, double input) -{ - register double x = (double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2; - r->p2 = (double)r->p1; - r->p1 = (double)input; - return (double)x; -} -#endif - -static double antiresonator2(resonator_ptr r, double input) -{ - register double x = (double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2; - r->p2 = (double)r->p1; - r->p1 = (double)input; - - r->a += r->a_inc; - r->b += r->b_inc; - r->c += r->c_inc; - return (double)x; -} - - - -/* -function FLUTTER - -This function adds F0 flutter, as specified in: - -"Analysis, synthesis and perception of voice quality variations among -female and male talkers" D.H. Klatt and L.C. Klatt JASA 87(2) February 1990. - -Flutter is added by applying a quasi-random element constructed from three -slowly varying sine waves. -*/ - -static void flutter(klatt_frame_ptr frame) -{ - static int time_count; - double delta_f0; - double fla,flb,flc,fld,fle; - - fla = (double) kt_globals.f0_flutter / 50; - flb = (double) kt_globals.original_f0 / 100; -// flc = sin(2*PI*12.7*time_count); -// fld = sin(2*PI*7.1*time_count); -// fle = sin(2*PI*4.7*time_count); - flc = sin(PI*12.7*time_count); // because we are calling flutter() more frequently, every 2.9mS - fld = sin(PI*7.1*time_count); - fle = sin(PI*4.7*time_count); - delta_f0 = fla * flb * (flc + fld + fle) * 10; - frame->F0hz10 = frame->F0hz10 + (long) delta_f0; - time_count++; -} - - - -/* -function SAMPLED_SOURCE - -Allows the use of a glottal excitation waveform sampled from a real -voice. -*/ - -static double sampled_source() -{ - int itemp; - double ftemp; - double result; - double diff_value; - int current_value; - int next_value; - double temp_diff; - - if(kt_globals.T0!=0) - { - ftemp = (double) kt_globals.nper; - ftemp = ftemp / kt_globals.T0; - ftemp = ftemp * kt_globals.num_samples; - itemp = (int) ftemp; - - temp_diff = ftemp - (double) itemp; - - current_value = kt_globals.natural_samples[itemp]; - next_value = kt_globals.natural_samples[itemp+1]; - - diff_value = (double) next_value - (double) current_value; - diff_value = diff_value * temp_diff; - - result = kt_globals.natural_samples[itemp] + diff_value; - result = result * kt_globals.sample_factor; - } - else - { - result = 0; - } - return(result); -} - - - - -/* -function PARWAVE - -Converts synthesis parameters to a waveform. -*/ - - -static int parwave(klatt_frame_ptr frame) -{ - double temp; - double outbypas; - double out; - long n4; - double frics; - double glotout; - double aspiration; - double casc_next_in; - double par_glotout; - static double noise; - static double voice; - static double vlast; - static double glotlast; - static double sourc; - int ix; - - frame_init(frame); /* get parameters for next frame of speech */ - - flutter(frame); /* add f0 flutter */ - -#ifdef deleted -{ - FILE *f; - f=fopen("klatt_log","a"); - fprintf(f,"%4dhz %2dAV %4d %3d, %4d %3d, %4d %3d, %4d %3d, %4d, %3d, %4d %3d TLT=%2d\n",frame->F0hz10,frame->AVdb, - frame->F1hz,frame->B1hz,frame->F2hz,frame->B2hz,frame->F3hz,frame->B3hz,frame->F4hz,frame->B4hz,frame->F5hz,frame->B5hz,frame->F6hz,frame->B6hz,frame->TLTdb); - fclose(f); -} -#endif - - /* MAIN LOOP, for each output sample of current frame: */ - - for (kt_globals.ns=0; kt_globals.ns<kt_globals.nspfr; kt_globals.ns++) - { - /* Get low-passed random number for aspiration and frication noise */ - noise = gen_noise(noise); - - /* - Amplitude modulate noise (reduce noise amplitude during - second half of glottal period) if voicing simultaneously present. - */ - - if (kt_globals.nper > kt_globals.nmod) - { - noise *= (double) 0.5; - } - - /* Compute frication noise */ - frics = kt_globals.amp_frica * noise; - - /* - Compute voicing waveform. Run glottal source simulation at 4 - times normal sample rate to minimize quantization noise in - period of female voice. - */ - - for (n4=0; n4<4; n4++) - { - switch(kt_globals.glsource) - { - case IMPULSIVE: - voice = impulsive_source(); - break; - case NATURAL: - voice = natural_source(); - break; - case SAMPLED: - voice = sampled_source(); - break; - } - - /* Reset period when counter 'nper' reaches T0 */ - if (kt_globals.nper >= kt_globals.T0) - { - kt_globals.nper = 0; - pitch_synch_par_reset(frame); - } - - /* - Low-pass filter voicing waveform before downsampling from 4*samrate - to samrate samples/sec. Resonator f=.09*samrate, bw=.06*samrate - */ - - voice = resonator(&(kt_globals.rsn[RLP]),voice); - - /* Increment counter that keeps track of 4*samrate samples per sec */ - kt_globals.nper++; - } - - /* - Tilt spectrum of voicing source down by soft low-pass filtering, amount - of tilt determined by TLTdb - */ - - voice = (voice * kt_globals.onemd) + (vlast * kt_globals.decay); - vlast = voice; - - /* - Add breathiness during glottal open phase. Amount of breathiness - determined by parameter Aturb Use nrand rather than noise because - noise is low-passed. - */ - - - if (kt_globals.nper < kt_globals.nopen) - { - voice += kt_globals.amp_breth * kt_globals.nrand; - } - - /* Set amplitude of voicing */ - glotout = kt_globals.amp_voice * voice; - par_glotout = kt_globals.par_amp_voice * voice; - - /* Compute aspiration amplitude and add to voicing source */ - aspiration = kt_globals.amp_aspir * noise; - glotout += aspiration; - - par_glotout += aspiration; - - /* - Cascade vocal tract, excited by laryngeal sources. - Nasal antiresonator, then formants FNP, F5, F4, F3, F2, F1 - */ - - out=0; - if(kt_globals.synthesis_model != ALL_PARALLEL) - { - casc_next_in = antiresonator2(&(kt_globals.rsn[Rnz]),glotout); - casc_next_in = resonator(&(kt_globals.rsn[Rnpc]),casc_next_in); - casc_next_in = resonator(&(kt_globals.rsn[R8c]),casc_next_in); - casc_next_in = resonator(&(kt_globals.rsn[R7c]),casc_next_in); - casc_next_in = resonator(&(kt_globals.rsn[R6c]),casc_next_in); - casc_next_in = resonator2(&(kt_globals.rsn[R5c]),casc_next_in); - casc_next_in = resonator2(&(kt_globals.rsn[R4c]),casc_next_in); - casc_next_in = resonator2(&(kt_globals.rsn[R3c]),casc_next_in); - casc_next_in = resonator2(&(kt_globals.rsn[R2c]),casc_next_in); - out = resonator2(&(kt_globals.rsn[R1c]),casc_next_in); - } - - /* Excite parallel F1 and FNP by voicing waveform */ - sourc = par_glotout; /* Source is voicing plus aspiration */ - - /* - Standard parallel vocal tract Formants F6,F5,F4,F3,F2, - outputs added with alternating sign. Sound source for other - parallel resonators is frication plus first difference of - voicing waveform. - */ - - out += resonator(&(kt_globals.rsn[R1p]),sourc); - out += resonator(&(kt_globals.rsn[Rnpp]),sourc); - - sourc = frics + par_glotout - glotlast; - glotlast = par_glotout; - - for(ix=R2p; ix<=R6p; ix++) - { - out = resonator(&(kt_globals.rsn[ix]),sourc) - out; - } - - outbypas = kt_globals.amp_bypas * sourc; - - out = outbypas - out; - -#ifdef deleted -// for testing - if (kt_globals.outsl != 0) - { - switch(kt_globals.outsl) - { - case 1: - out = voice; - break; - case 2: - out = aspiration; - break; - case 3: - out = frics; - break; - case 4: - out = glotout; - break; - case 5: - out = par_glotout; - break; - case 6: - out = outbypas; - break; - case 7: - out = sourc; - break; - } - } -#endif - - out = resonator(&(kt_globals.rsn[Rout]),out); - temp = (out * wdata.amplitude * kt_globals.amp_gain0) ; /* Convert back to integer */ - - - // mix with a recorded WAV if required for this phoneme - { - int z2; - signed char c; - int sample; - - z2 = 0; - if(wdata.mix_wavefile_ix < wdata.n_mix_wavefile) - { - if(wdata.mix_wave_scale == 0) - { - // a 16 bit sample - c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1]; - sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256); - wdata.mix_wavefile_ix += 2; - } - else - { - // a 8 bit sample, scaled - sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale; - } - z2 = sample * wdata.amplitude_v / 1024; - z2 = (z2 * wdata.mix_wave_amp)/40; - temp += z2; - } - } - - // if fadeout is set, fade to zero over 64 samples, to avoid clicks at end of synthesis - if(kt_globals.fadeout > 0) - { - kt_globals.fadeout--; - temp = (temp * kt_globals.fadeout) / 64; - } - - if (temp < -32768.0) - { - temp = -32768.0; - } - - if (temp > 32767.0) - { - temp = 32767.0; - } - - *out_ptr++ = (int)(temp); // **JSD - *out_ptr++ = (int)(temp) >> 8; - sample_count++; - if(out_ptr >= out_end) - { - return(1); - } - } - return(0); -} // end of parwave - - - - -/* -function PARWAVE_INIT - -Initialises all parameters used in parwave, sets resonator internal memory -to zero. -*/ - -static void reset_resonators() -{ - int r_ix; - - for(r_ix=0; r_ix < N_RSN; r_ix++) - { - kt_globals.rsn[r_ix].p1 = 0; - kt_globals.rsn[r_ix].p2 = 0; - } -} - -static void parwave_init() -{ - kt_globals.FLPhz = (950 * kt_globals.samrate) / 10000; - kt_globals.BLPhz = (630 * kt_globals.samrate) / 10000; - kt_globals.minus_pi_t = -PI / kt_globals.samrate; - kt_globals.two_pi_t = -2.0 * kt_globals.minus_pi_t; - setabc(kt_globals.FLPhz,kt_globals.BLPhz,&(kt_globals.rsn[RLP])); - kt_globals.nper = 0; - kt_globals.T0 = 0; - kt_globals.nopen = 0; - kt_globals.nmod = 0; - - reset_resonators(); -} - - -/* -function FRAME_INIT - -Use parameters from the input frame to set up resonator coefficients. -*/ - -static void frame_init(klatt_frame_ptr frame) -{ - double amp_par[7]; - static double amp_par_factor[7] = {0.6, 0.4, 0.15, 0.06, 0.04, 0.022, 0.03}; - long Gain0_tmp; - int ix; - - kt_globals.original_f0 = frame->F0hz10 / 10; - - frame->AVdb_tmp = frame->AVdb - 7; - if (frame->AVdb_tmp < 0) - { - frame->AVdb_tmp = 0; - } - - kt_globals.amp_aspir = DBtoLIN(frame->ASP) * 0.05; - kt_globals.amp_frica = DBtoLIN(frame->AF) * 0.25; - kt_globals.par_amp_voice = DBtoLIN(frame->AVpdb); - kt_globals.amp_bypas = DBtoLIN(frame->AB) * 0.05; - - for(ix=0; ix <= 6; ix++) - { - // parallel amplitudes F1 to F6, and parallel nasal pole - amp_par[ix] = DBtoLIN(frame->Ap[ix]) * amp_par_factor[ix]; - } - - Gain0_tmp = frame->Gain0 - 3; - if (Gain0_tmp <= 0) - { - Gain0_tmp = 57; - } - kt_globals.amp_gain0 = DBtoLIN(Gain0_tmp) / kt_globals.scale_wav; - - /* Set coefficients of variable cascade resonators */ - for(ix=0; ix<=8; ix++) - { - // formants 1 to 8, plus nasal pole - setabc(frame->Fhz[ix],frame->Bhz[ix],&(kt_globals.rsn[ix])); - - if(ix <= 5) - { - setabc(frame->Fhz_next[ix],frame->Bhz_next[ix],&(kt_globals.rsn_next[ix])); - - kt_globals.rsn[ix].a_inc = (kt_globals.rsn_next[ix].a - kt_globals.rsn[ix].a) / 64.0; - kt_globals.rsn[ix].b_inc = (kt_globals.rsn_next[ix].b - kt_globals.rsn[ix].b) / 64.0; - kt_globals.rsn[ix].c_inc = (kt_globals.rsn_next[ix].c - kt_globals.rsn[ix].c) / 64.0; - } - } - - // nasal zero anti-resonator - setzeroabc(frame->Fhz[F_NZ],frame->Bhz[F_NZ],&(kt_globals.rsn[Rnz])); - setzeroabc(frame->Fhz_next[F_NZ],frame->Bhz_next[F_NZ],&(kt_globals.rsn_next[Rnz])); - kt_globals.rsn[F_NZ].a_inc = (kt_globals.rsn_next[F_NZ].a - kt_globals.rsn[F_NZ].a) / 64.0; - kt_globals.rsn[F_NZ].b_inc = (kt_globals.rsn_next[F_NZ].b - kt_globals.rsn[F_NZ].b) / 64.0; - kt_globals.rsn[F_NZ].c_inc = (kt_globals.rsn_next[F_NZ].c - kt_globals.rsn[F_NZ].c) / 64.0; - - - /* Set coefficients of parallel resonators, and amplitude of outputs */ - - for(ix=0; ix<=6; ix++) - { - setabc(frame->Fhz[ix],frame->Bphz[ix],&(kt_globals.rsn[Rparallel+ix])); - kt_globals.rsn[Rparallel+ix].a *= amp_par[ix]; - } - - /* output low-pass filter */ - - setabc((long)0.0,(long)(kt_globals.samrate/2),&(kt_globals.rsn[Rout])); - -} - - - -/* -function IMPULSIVE_SOURCE - -Generate a low pass filtered train of impulses as an approximation of -a natural excitation waveform. Low-pass filter the differentiated impulse -with a critically-damped second-order filter, time constant proportional -to Kopen. -*/ - - -static double impulsive_source() -{ - static double doublet[] = {0.0,13000000.0,-13000000.0}; - static double vwave; - - if (kt_globals.nper < 3) - { - vwave = doublet[kt_globals.nper]; - } - else - { - vwave = 0.0; - } - - return(resonator(&(kt_globals.rsn[RGL]),vwave)); -} - - - -/* -function NATURAL_SOURCE - -Vwave is the differentiated glottal flow waveform, there is a weak -spectral zero around 800 Hz, magic constants a,b reset pitch synchronously. -*/ - -static double natural_source() -{ - double lgtemp; - static double vwave; - - if (kt_globals.nper < kt_globals.nopen) - { - kt_globals.pulse_shape_a -= kt_globals.pulse_shape_b; - vwave += kt_globals.pulse_shape_a; - lgtemp=vwave * 0.028; - - return(lgtemp); - } - else - { - vwave = 0.0; - return(0.0); - } -} - - - - - -/* -function PITCH_SYNC_PAR_RESET - -Reset selected parameters pitch-synchronously. - - -Constant B0 controls shape of glottal pulse as a function -of desired duration of open phase N0 -(Note that N0 is specified in terms of 40,000 samples/sec of speech) - -Assume voicing waveform V(t) has form: k1 t**2 - k2 t**3 - - If the radiation characterivative, a temporal derivative - is folded in, and we go from continuous time to discrete - integers n: dV/dt = vwave[n] - = sum over i=1,2,...,n of { a - (i * b) } - = a n - b/2 n**2 - - where the constants a and b control the detailed shape - and amplitude of the voicing waveform over the open - potion of the voicing cycle "nopen". - - Let integral of dV/dt have no net dc flow --> a = (b * nopen) / 3 - - Let maximum of dUg(n)/dn be constant --> b = gain / (nopen * nopen) - meaning as nopen gets bigger, V has bigger peak proportional to n - - Thus, to generate the table below for 40 <= nopen <= 263: - - B0[nopen - 40] = 1920000 / (nopen * nopen) -*/ - -static void pitch_synch_par_reset(klatt_frame_ptr frame) -{ - long temp; - double temp1; - static long skew; - static short B0[224] = - { - 1200,1142,1088,1038, 991, 948, 907, 869, 833, 799, 768, 738, 710, 683, 658, - 634, 612, 590, 570, 551, 533, 515, 499, 483, 468, 454, 440, 427, 415, 403, - 391, 380, 370, 360, 350, 341, 332, 323, 315, 307, 300, 292, 285, 278, 272, - 265, 259, 253, 247, 242, 237, 231, 226, 221, 217, 212, 208, 204, 199, 195, - 192, 188, 184, 180, 177, 174, 170, 167, 164, 161, 158, 155, 153, 150, 147, - 145, 142, 140, 137, 135, 133, 131, 128, 126, 124, 122, 120, 119, 117, 115, - 113,111, 110, 108, 106, 105, 103, 102, 100, 99, 97, 96, 95, 93, 92, 91, 90, - 88, 87, 86, 85, 84, 83, 82, 80, 79, 78, 77, 76, 75, 75, 74, 73, 72, 71, - 70, 69, 68, 68, 67, 66, 65, 64, 64, 63, 62, 61, 61, 60, 59, 59, 58, 57, - 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, - 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 41, 41, 40, 40, - 39, 39, 38, 38, 38, 38, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34,33, - 33, 33, 33, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, - 28, 28, 28, 28, 27, 27 - }; - - if (frame->F0hz10 > 0) - { - /* T0 is 4* the number of samples in one pitch period */ - - kt_globals.T0 = (40 * kt_globals.samrate) / frame->F0hz10; - - - kt_globals.amp_voice = DBtoLIN(frame->AVdb_tmp); - - /* Duration of period before amplitude modulation */ - - kt_globals.nmod = kt_globals.T0; - if (frame->AVdb_tmp > 0) - { - kt_globals.nmod >>= 1; - } - - /* Breathiness of voicing waveform */ - - kt_globals.amp_breth = DBtoLIN(frame->Aturb) * 0.1; - - /* Set open phase of glottal period where 40 <= open phase <= 263 */ - - kt_globals.nopen = 4 * frame->Kopen; - - if ((kt_globals.glsource == IMPULSIVE) && (kt_globals.nopen > 263)) - { - kt_globals.nopen = 263; - } - - if (kt_globals.nopen >= (kt_globals.T0-1)) - { -// printf("Warning: glottal open period cannot exceed T0, truncated\n"); - kt_globals.nopen = kt_globals.T0 - 2; - } - - if (kt_globals.nopen < 40) - { - /* F0 max = 1000 Hz */ -// printf("Warning: minimum glottal open period is 10 samples.\n"); -// printf("truncated, nopen = %d\n",kt_globals.nopen); - kt_globals.nopen = 40; - } - - - /* Reset a & b, which determine shape of "natural" glottal waveform */ - - kt_globals.pulse_shape_b = B0[kt_globals.nopen-40]; - kt_globals.pulse_shape_a = (kt_globals.pulse_shape_b * kt_globals.nopen) * 0.333; - - /* Reset width of "impulsive" glottal pulse */ - - temp = kt_globals.samrate / kt_globals.nopen; - - setabc((long)0,temp,&(kt_globals.rsn[RGL])); - - /* Make gain at F1 about constant */ - - temp1 = kt_globals.nopen *.00833; - kt_globals.rsn[RGL].a *= temp1 * temp1; - - /* - Truncate skewness so as not to exceed duration of closed phase - of glottal period. - */ - - - temp = kt_globals.T0 - kt_globals.nopen; - if (frame->Kskew > temp) - { -// printf("Kskew duration=%d > glottal closed period=%d, truncate\n", frame->Kskew, kt_globals.T0 - kt_globals.nopen); - frame->Kskew = temp; - } - if (skew >= 0) - { - skew = frame->Kskew; - } - else - { - skew = - frame->Kskew; - } - - /* Add skewness to closed portion of voicing period */ - kt_globals.T0 = kt_globals.T0 + skew; - skew = - skew; - } - else - { - kt_globals.T0 = 4; /* Default for f0 undefined */ - kt_globals.amp_voice = 0.0; - kt_globals.nmod = kt_globals.T0; - kt_globals.amp_breth = 0.0; - kt_globals.pulse_shape_a = 0.0; - kt_globals.pulse_shape_b = 0.0; - } - - /* Reset these pars pitch synchronously or at update rate if f0=0 */ - - if ((kt_globals.T0 != 4) || (kt_globals.ns == 0)) - { - /* Set one-pole low-pass filter that tilts glottal source */ - - kt_globals.decay = (0.033 * frame->TLTdb); - - if (kt_globals.decay > 0.0) - { - kt_globals.onemd = 1.0 - kt_globals.decay; - } - else - { - kt_globals.onemd = 1.0; - } - } -} - - - -/* -function SETABC - -Convert formant freqencies and bandwidth into resonator difference -equation constants. -*/ - - -static void setabc(long int f, long int bw, resonator_ptr rp) -{ - double r; - double arg; - - /* Let r = exp(-pi bw t) */ - arg = kt_globals.minus_pi_t * bw; - r = exp(arg); - - /* Let c = -r**2 */ - rp->c = -(r * r); - - /* Let b = r * 2*cos(2 pi f t) */ - arg = kt_globals.two_pi_t * f; - rp->b = r * cos(arg) * 2.0; - - /* Let a = 1.0 - b - c */ - rp->a = 1.0 - rp->b - rp->c; -} - - -/* -function SETZEROABC - -Convert formant freqencies and bandwidth into anti-resonator difference -equation constants. -*/ - -static void setzeroabc(long int f, long int bw, resonator_ptr rp) -{ - double r; - double arg; - - f = -f; - - if(f>=0) - { - f = -1; - } - - /* First compute ordinary resonator coefficients */ - /* Let r = exp(-pi bw t) */ - arg = kt_globals.minus_pi_t * bw; - r = exp(arg); - - /* Let c = -r**2 */ - rp->c = -(r * r); - - /* Let b = r * 2*cos(2 pi f t) */ - arg = kt_globals.two_pi_t * f; - rp->b = r * cos(arg) * 2.; - - /* Let a = 1.0 - b - c */ - rp->a = 1.0 - rp->b - rp->c; - - /* Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) */ - rp->a = 1.0 / rp->a; - rp->c *= -rp->a; - rp->b *= -rp->a; -} - - -/* -function GEN_NOISE - -Random number generator (return a number between -8191 and +8191) -Noise spectrum is tilted down by soft low-pass filter having a pole near -the origin in the z-plane, i.e. output = input + (0.75 * lastoutput) -*/ - - -static double gen_noise(double noise) -{ - long temp; - static double nlast; - - temp = (long) getrandom(-8191,8191); - kt_globals.nrand = (long) temp; - - noise = kt_globals.nrand + (0.75 * nlast); - nlast = noise; - - return(noise); -} - - -/* -function DBTOLIN - -Convert from decibels to a linear scale factor - - -Conversion table, db to linear, 87 dB --> 32767 - 86 dB --> 29491 (1 dB down = 0.5**1/6) - ... - 81 dB --> 16384 (6 dB down = 0.5) - ... - 0 dB --> 0 - -The just noticeable difference for a change in intensity of a vowel -is approximately 1 dB. Thus all amplitudes are quantized to 1 dB -steps. -*/ - - -static double DBtoLIN(long dB) -{ - static short amptable[88] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, - 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, 32, - 35, 40, 45, 51, 57, 64, 71, 80, 90, 101, 114, 128, - 142, 159, 179, 202, 227, 256, 284, 318, 359, 405, - 455, 512, 568, 638, 719, 881, 911, 1024, 1137, 1276, - 1438, 1622, 1823, 2048, 2273, 2552, 2875, 3244, 3645, - 4096, 4547, 5104, 5751, 6488, 7291, 8192, 9093, 10207, - 11502, 12976, 14582, 16384, 18350, 20644, 23429, - 26214, 29491, 32767 }; - - if ((dB < 0) || (dB > 87)) - { - return(0); - } - - return((double)(amptable[dB]) * 0.001); -} - - - - - -extern voice_t *wvoice; -static klatt_peaks_t peaks[N_PEAKS]; -static int end_wave; -static int klattp[N_KLATTP]; -static double klattp1[N_KLATTP]; -static double klattp_inc[N_KLATTP]; - -static int scale_wav_tab[] = {45,38,45,45}; // scale output from different voicing sources - - - -int Wavegen_Klatt(int resume) -{//========================== - int pk; - int x; - int ix; - - if(resume==0) - { - sample_count = 0; - } - - while(sample_count < nsamples) - { - kt_frame.F0hz10 = (wdata.pitch * 10) / 4096; - - // formants F6,F7,F8 are fixed values for cascade resonators, set in KlattInit() - // but F6 is used for parallel resonator - // F0 is used for the nasal zero - for(ix=0; ix < 6; ix++) - { - kt_frame.Fhz[ix] = peaks[ix].freq; - if(ix < 4) - { - kt_frame.Bhz[ix] = peaks[ix].bw; - } - } - for(ix=1; ix < 7; ix++) - { - kt_frame.Ap[ix] = 0; - } - - kt_frame.AVdb = klattp[KLATT_AV]; - kt_frame.AVpdb = klattp[KLATT_AVp]; - kt_frame.AF = klattp[KLATT_Fric]; - kt_frame.AB = klattp[KLATT_FricBP]; - kt_frame.ASP = klattp[KLATT_Aspr]; - kt_frame.Aturb = klattp[KLATT_Turb]; - kt_frame.Kskew = klattp[KLATT_Skew]; - kt_frame.TLTdb = klattp[KLATT_Tilt]; - kt_frame.Kopen = klattp[KLATT_Kopen]; - - // advance formants - for(pk=0; pk<N_PEAKS; pk++) - { - peaks[pk].freq1 += peaks[pk].freq_inc; - peaks[pk].freq = (int)peaks[pk].freq1; - peaks[pk].bw1 += peaks[pk].bw_inc; - peaks[pk].bw = (int)peaks[pk].bw1; - peaks[pk].bp1 += peaks[pk].bp_inc; - peaks[pk].bp = (int)peaks[pk].bp1; - peaks[pk].ap1 += peaks[pk].ap_inc; - peaks[pk].ap = (int)peaks[pk].ap1; - } - - // advance other parameters - for(ix=0; ix < N_KLATTP; ix++) - { - klattp1[ix] += klattp_inc[ix]; - klattp[ix] = (int)(klattp1[ix]); - } - - for(ix=0; ix<=6; ix++) - { - kt_frame.Fhz_next[ix] = peaks[ix].freq; - if(ix < 4) - { - kt_frame.Bhz_next[ix] = peaks[ix].bw; - } - } - - // advance the pitch - wdata.pitch_ix += wdata.pitch_inc; - if((ix = wdata.pitch_ix>>8) > 127) ix = 127; - x = wdata.pitch_env[ix] * wdata.pitch_range; - wdata.pitch = (x>>8) + wdata.pitch_base; - - kt_globals.nspfr = (nsamples - sample_count); - if(kt_globals.nspfr > STEPSIZE) - kt_globals.nspfr = STEPSIZE; - - if(parwave(&kt_frame) == 1) - { - return(1); - } - } - - if(end_wave == 1) - { - // fade out to avoid a click - kt_globals.fadeout = 64; - end_wave = 0; - sample_count -= 64; - kt_globals.nspfr = 64; - if(parwave(&kt_frame) == 1) - { - return(1); - } - } - - return(0); -} - - -void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v, int control) -{//=========================================================================================== - int ix; - DOUBLEX next; - int qix; - int cmd; - static frame_t prev_fr; - - if(wvoice != NULL) - { - if((wvoice->klattv[0] > 0) && (wvoice->klattv[0] <=3 )) - { - kt_globals.glsource = wvoice->klattv[0]; - kt_globals.scale_wav = scale_wav_tab[kt_globals.glsource]; - } - kt_globals.f0_flutter = wvoice->flutter/32; - } - - end_wave = 0; - if(control & 2) - { - end_wave = 1; // fadeout at the end - } - if(control & 1) - { - end_wave = 1; - for(qix=wcmdq_head+1;;qix++) - { - if(qix >= N_WCMDQ) qix = 0; - if(qix == wcmdq_tail) break; - - cmd = wcmdq[qix][0]; - if(cmd==WCMD_KLATT) - { - end_wave = 0; // next wave generation is from another spectrum - break; - } - if((cmd==WCMD_WAVE) || (cmd==WCMD_PAUSE)) - break; // next is not from spectrum, so continue until end of wave cycle - } - } - -{ -//FILE *f; -//f=fopen("klatt_log","a"); -//fprintf(f,"len %4d (%3d %4d %4d) (%3d %4d %4d)\n",length,fr1->ffreq[1],fr1->ffreq[2],fr1->ffreq[3],fr2->ffreq[1],fr2->ffreq[2],fr2->ffreq[3]); -//fclose(f); -} - - if(control & 1) - { - if(wdata.prev_was_synth == 0) - { - // A break, not following on from another synthesized sound. - // Reset the synthesizer - //reset_resonators(&kt_globals); - parwave_init(); - } - else - { - if((prev_fr.ffreq[1] != fr1->ffreq[1]) || (prev_fr.ffreq[2] != fr1->ffreq[2])) - { - - // fade out to avoid a click, but only up to the end of output buffer - ix = (out_end - out_ptr)/2; - if(ix > 64) - ix = 64; - kt_globals.fadeout = ix; - kt_globals.nspfr = ix; - parwave(&kt_frame); - - //reset_resonators(&kt_globals); - parwave_init(); - } - } - wdata.prev_was_synth = 1; - memcpy(&prev_fr,fr2,sizeof(prev_fr)); - } - if(fr2->frflags & FRFLAG_BREAK) - { -// fr2 = fr1; -// reset_resonators(&kt_globals); - } - - for(ix=0; ix<N_KLATTP; ix++) - { - if((ix >= 5) && ((fr1->frflags & FRFLAG_KLATT) == 0)) - { - klattp1[ix] = klattp[ix] = 0; - klattp_inc[ix] = 0; - } - else - { - klattp1[ix] = klattp[ix] = fr1->klattp[ix]; - klattp_inc[ix] = (double)((fr2->klattp[ix] - klattp[ix]) * STEPSIZE)/length; - } - - // get klatt parameter adjustments for the voice -// if((ix>0) && (ix < KLATT_AVp)) -// klattp1[ix] = klattp[ix] = (klattp[ix] + wvoice->klattv[ix]); - } - - nsamples = length; - - for(ix=1; ix < 6; ix++) - { - peaks[ix].freq1 = (fr1->ffreq[ix] * v->freq[ix] / 256.0) + v->freqadd[ix]; - peaks[ix].freq = (int)(peaks[ix].freq1); - next = (fr2->ffreq[ix] * v->freq[ix] / 256.0) + v->freqadd[ix]; - peaks[ix].freq_inc = ((next - peaks[ix].freq1) * STEPSIZE) / length; - - if(ix < 4) - { - // klatt bandwidth for f1, f2, f3 (others are fixed) - peaks[ix].bw1 = fr1->bw[ix] * 2; - peaks[ix].bw = (int)(peaks[ix].bw1); - next = fr2->bw[ix] * 2; - peaks[ix].bw_inc = ((next - peaks[ix].bw1) * STEPSIZE) / length; - } - } - - // nasal zero frequency - peaks[0].freq1 = fr1->klattp[KLATT_FNZ] * 2; - peaks[0].freq = (int)(peaks[0].freq1); - next = fr2->klattp[KLATT_FNZ] * 2; - peaks[0].freq_inc = ((next - peaks[0].freq1) * STEPSIZE) / length; - - peaks[0].bw1 = 89; - peaks[0].bw = 89; - peaks[0].bw_inc = 0; - - if(fr1->frflags & FRFLAG_KLATT) - { - // the frame contains additional parameters for parallel resonators - for(ix=1; ix < 7; ix++) - { - peaks[ix].bp1 = fr1->klatt_bp[ix] * 4; // parallel bandwidth - peaks[ix].bp = (int)(peaks[ix].bp1); - next = fr2->klatt_bp[ix] * 2; - peaks[ix].bp_inc = ((next - peaks[ix].bp1) * STEPSIZE) / length; - - peaks[ix].ap1 = fr1->klatt_ap[ix]; // parallal amplitude - peaks[ix].ap = (int)(peaks[ix].ap1); - next = fr2->klatt_ap[ix] * 2; - 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) -{//=================================================================================== - if(resume==0) - SetSynth_Klatt(length, modulation, fr1, fr2, wvoice, 1); - - return(Wavegen_Klatt(resume)); -} - - - -void KlattInit() -{ -#define NUMBER_OF_SAMPLES 100 - - static short natural_samples[NUMBER_OF_SAMPLES]= - { - -310,-400,530,356,224,89,23,-10,-58,-16,461,599,536,701,770, - 605,497,461,560,404,110,224,131,104,-97,155,278,-154,-1165, - -598,737,125,-592,41,11,-247,-10,65,92,80,-304,71,167,-1,122, - 233,161,-43,278,479,485,407,266,650,134,80,236,68,260,269,179, - 53,140,275,293,296,104,257,152,311,182,263,245,125,314,140,44, - 203,230,-235,-286,23,107,92,-91,38,464,443,176,98,-784,-2449, - -1891,-1045,-1600,-1462,-1384,-1261,-949,-730 - }; - static short formant_hz[10] = {280,688,1064,2806,3260,3700,6500,7000,8000,280}; - static short bandwidth[10] = {89,160,70,160,200,200,500,500,500,89}; - static short parallel_amp[10] = { 0,59,59,59,59,59,59,0,0,0}; - static short parallel_bw[10] = {59,59,89,149,200,200,500,0,0,0}; - - int ix; - - sample_count=0; - - kt_globals.synthesis_model = CASCADE_PARALLEL; - kt_globals.samrate = 22050; - - kt_globals.glsource = IMPULSIVE; // IMPULSIVE, NATURAL, SAMPLED - kt_globals.scale_wav = scale_wav_tab[kt_globals.glsource]; - kt_globals.natural_samples = natural_samples; - kt_globals.num_samples = NUMBER_OF_SAMPLES; - kt_globals.sample_factor = 3.0; - kt_globals.nspfr = (kt_globals.samrate * 10) / 1000; - kt_globals.outsl = 0; - kt_globals.f0_flutter = 20; - - parwave_init(); - - // set default values for frame parameters - for(ix=0; ix<=9; ix++) - { - kt_frame.Fhz[ix] = formant_hz[ix]; - kt_frame.Bhz[ix] = bandwidth[ix]; - kt_frame.Ap[ix] = parallel_amp[ix]; - kt_frame.Bphz[ix] = parallel_bw[ix]; - } - kt_frame.Bhz_next[F_NZ] = bandwidth[F_NZ]; - - kt_frame.F0hz10 = 1000; - kt_frame.AVdb = 59; // 59 - kt_frame.ASP = 0; - kt_frame.Kopen = 40; // 40 - kt_frame.Aturb = 0; - kt_frame.TLTdb = 0; - kt_frame.AF =50; - kt_frame.Kskew = 0; - kt_frame.AB = 0; - kt_frame.AVpdb = 0; - kt_frame.Gain0 = 60; // 62 -} // end of KlattInit - -#endif // INCLUDE_KLATT diff --git a/navit/support/espeak/klatt.h b/navit/support/espeak/klatt.h deleted file mode 100644 index 5583b178a..000000000 --- a/navit/support/espeak/klatt.h +++ /dev/null @@ -1,153 +0,0 @@ - - -#define CASCADE_PARALLEL 1 /* Type of synthesis model */ -#define ALL_PARALLEL 2 - -#define IMPULSIVE 1 /* Type of voicing source */ -#define NATURAL 2 -#define SAMPLED 3 - -#define PI 3.1415927 - - -/* typedef's that need to be exported */ - -typedef long flag; - -/* Resonator Structure */ - -typedef struct -{ - double a; - double b; - double c; - double p1; - double p2; - double a_inc; - double b_inc; - double c_inc; -} resonator_t, *resonator_ptr; - -/* Structure for Klatt Globals */ - -typedef struct -{ - flag synthesis_model; /* cascade-parallel or all-parallel */ - flag outsl; /* Output waveform selector */ - long samrate; /* Number of output samples per second */ - long FLPhz ; /* Frequeny of glottal downsample low-pass filter */ - long BLPhz ; /* Bandwidth of glottal downsample low-pass filter */ - flag glsource; /* Type of glottal source */ - int f0_flutter; /* Percentage of f0 flutter 0-100 */ - long nspfr; /* number of samples per frame */ - long nper; /* Counter for number of samples in a pitch period */ - long ns; - long T0; /* Fundamental period in output samples times 4 */ - long nopen; /* Number of samples in open phase of period */ - long nmod; /* Position in period to begin noise amp. modul */ - long nrand; /* Varible used by random number generator */ - double pulse_shape_a; /* Makes waveshape of glottal pulse when open */ - double pulse_shape_b; /* Makes waveshape of glottal pulse when open */ - double minus_pi_t; - double two_pi_t; - double onemd; - double decay; - double amp_bypas; /* AB converted to linear gain */ - double amp_voice; /* AVdb converted to linear gain */ - double par_amp_voice; /* AVpdb converted to linear gain */ - double amp_aspir; /* AP converted to linear gain */ - double amp_frica; /* AF converted to linear gain */ - double amp_breth; /* ATURB converted to linear gain */ - double amp_gain0; /* G0 converted to linear gain */ - int num_samples; /* number of glottal samples */ - double sample_factor; /* multiplication factor for glottal samples */ - short *natural_samples; /* pointer to an array of glottal samples */ - long original_f0; /* original value of f0 not modified by flutter */ - - int fadeout; // set to 64 to cause fadeout over 64 samples - int scale_wav; // depends on the voicing source - -#define N_RSN 20 -#define Rnpc 0 -#define R1c 1 -#define R2c 2 -#define R3c 3 -#define R4c 4 -#define R5c 5 -#define R6c 6 -#define R7c 7 -#define R8c 8 -#define Rnz 9 - -#define Rparallel 10 -#define Rnpp 10 -#define R1p 11 -#define R2p 12 -#define R3p 13 -#define R4p 14 -#define R5p 15 -#define R6p 16 - -#define RGL 17 -#define RLP 18 -#define Rout 19 - - resonator_t rsn[N_RSN]; // internal storage for resonators - resonator_t rsn_next[N_RSN]; - -} klatt_global_t, *klatt_global_ptr; - -/* Structure for Klatt Parameters */ - -#define F_NZ 0 // nasal zero formant -#define F1 1 -#define F2 2 -#define F3 3 -#define F4 4 -#define F5 5 -#define F6 6 -#define F_NP 9 // nasal pole formant - - -typedef struct -{ - long F0hz10; /* Voicing fund freq in Hz */ - long AVdb; /* Amp of voicing in dB, 0 to 70 */ - int Fhz[10]; // formant Hz, F_NZ to F6 to F_NP - int Bhz[10]; - int Ap[10]; /* Amp of parallel formants in dB, 0 to 80 */ - int Bphz[10]; /* Parallel formants bw in Hz, 40 to 1000 */ - - long ASP; /* Amp of aspiration in dB, 0 to 70 */ - long Kopen; /* # of samples in open period, 10 to 65 */ - long Aturb; /* Breathiness in voicing, 0 to 80 */ - long TLTdb; /* Voicing spectral tilt in dB, 0 to 24 */ - long AF; /* Amp of frication in dB, 0 to 80 */ - long Kskew; /* Skewness of alternate periods, 0 to 40 in sample#/2 */ - - long AB; /* Amp of bypass fric. in dB, 0 to 80 */ - long AVpdb; /* Amp of voicing, par in dB, 0 to 70 */ - long Gain0; /* Overall gain, 60 dB is unity, 0 to 60 */ - - long AVdb_tmp; //copy of AVdb, which is changed within parwave() - int Fhz_next[10]; // Fhz for the next chunk, so we can do interpolation of resonator (a,b,c) parameters - int Bhz_next[10]; - } klatt_frame_t, *klatt_frame_ptr; - - -typedef struct { - int freq; // Hz - int bw; // klatt bandwidth - int ap; // parallel amplitude - int bp; // parallel bandwidth - DOUBLEX freq1; // floating point versions of the above - DOUBLEX bw1; - DOUBLEX ap1; - DOUBLEX bp1; - DOUBLEX freq_inc; // increment by this every 64 samples - DOUBLEX bw_inc; - DOUBLEX ap_inc; - DOUBLEX bp_inc; -} klatt_peaks_t; - - diff --git a/navit/support/espeak/mbrolib.h b/navit/support/espeak/mbrolib.h deleted file mode 100644 index 0616b464b..000000000 --- a/navit/support/espeak/mbrolib.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef MBROLIB_H -#define MBROLIB_H - -/* - * mbrolib: mbrola wrapper. - * - * Copyright (C) 2007 Gilles Casse <gcasse@oralux.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/* < types */ - -/** Parameters */ - -typedef struct { - int ignore_error; /* 1=Ignore any fatal error or unknown diphone */ - char comment_char; /* Comment character */ - float volume_ratio; /* Volume ratio */ - float frequency_ratio; /* Applied to pitch points */ - float time_ratio; /* Applied to phone durations */ -} mbrolib_parameter; - - -/** Returned errors */ - -typedef enum { - MBROLIB_OK=0, - MBROLIB_DATABASE_NOT_INSTALLED, - MBROLIB_INVAL, - MBROLIB_OUT_OF_MEMORY, - MBROLIB_OUT_OF_RANGE, - MBROLIB_READ_ERROR, - MBROLIB_WRITE_ERROR -} MBROLIB_ERROR; - - - -/** Gender */ - -typedef enum { - MBROLIB_FEMALE, - MBROLIB_MALE -} MBROLIB_GENDER; - - - -/** Voice descriptor */ - -typedef struct { - char *name; /* name (for example: "en1") */ - char *filename; /* database pathname (for example: "/usr/share/mbrola/voices/en1) */ - int rate; /* database sample rate */ - MBROLIB_GENDER gender; - const char *language; /* Language and optional dialect qualifier in ascii (e.g. en, fr_ca). */ -} mbrolib_voice; - -/* > */ - - -/** Initialization, returns a new handle. - First function. - - @param the_sample_rate: output rate in Hz (for example 22050). If 0, keep the original database rate. - - @return handle (or NULL if error). -*/ -void* mbrolib_init( int sample_rate); -typedef void* (t_mbrolib_init)(int); - - -/** Returns the list of the installed mbrola databases. - The databases are searched according to the MBROLA_PATH environment variable if set, - or under a default path otherwise (see MBROLA_PATH in mbrolib.c). - - An array of voices is returned. The last item is set to NULL. - The caller must not free the returned items or the array. - - @param the_handle previously given by mbrolib_init. - - @return An array of voices. -*/ -const mbrolib_voice ** mbrolib_list_voices( void* the_handle); -typedef const mbrolib_voice ** (t_mbrolib_list_voices)(void*); - - - -/** Set voice - - @param the_handle. - - @param the_database (for example, "en1"). - - @return error code (MBROLIB_OK, MBROLIB_DATABASE_NOT_INSTALLED, MBROLIB_INVAL). - -*/ -MBROLIB_ERROR mbrolib_set_voice( void* the_handle, const char* the_name); -typedef MBROLIB_ERROR (t_mbrolib_set_voice)( void*, const char*); - - - -/** Get the current database parameters. - The caller supplies a pointer to an already allocated structure. - - @param the_handle previously given by mbrolib_init. - - @param the_parameters: pointer to the structure. - - @return error code (MBROLIB_OK, MBROLIB_INVAL). -*/ -MBROLIB_ERROR mbrolib_get_parameter(void* the_handle, mbrolib_parameter* the_parameter); -typedef MBROLIB_ERROR (t_mbrolib_get_parameter)(void*, mbrolib_parameter*); - - - -/** Set the database parameters using the supplied data. - - @param the_handle previously given by mbrolib_init. - - @param the_parameters: pointer to the wished parameters. - - @return error code (MBROLIB_OK, MBROLIB_INVAL). -*/ -MBROLIB_ERROR mbrolib_set_parameter(void* the_handle, const mbrolib_parameter* the_parameter); -typedef MBROLIB_ERROR (t_mbrolib_set_parameter)(void*, const mbrolib_parameter*); - - - -/** Write the mbrola phonemes in the internal buffer. - - @param the_handle. - - @param the_mbrola_phonemes. - - @param the_size in bytes. - - @return error code (MBROLIB_OK, MBROLIB_INVAL, MBROLIB_WRITE_ERROR, MBROLIB_READ_ERROR). -*/ -MBROLIB_ERROR mbrolib_write(void* the_handle, const char* the_mbrola_phonemes, size_t the_size); -typedef MBROLIB_ERROR (t_mbrolib_write)(void*, const char*, size_t); - - - -/** Read n bytes of the output samples. - - @param the_handle. - - @param the_samples (raw audio data, 16bits, mono). - - @param the_size max number of int16 to read. - - @param the_size number of int16 read. - - @return error code (MBROLIB_OK, MBROLIB_INVAL, MBROLIB_READ_ERROR). - -*/ -MBROLIB_ERROR mbrolib_read(void* the_handle, short* the_samples, int the_max_size, int* the_read_size); -typedef MBROLIB_ERROR (t_mbrolib_read)(void*, short*, int, int*); - - - -/** Flush - - @param the_handle. - -*/ -void mbrolib_flush(void* the_handle); -typedef void (t_mbrolib_flush)(void*); - - - -/** Release the handle - - @param the_handle. - - @return error code (MBROLIB_OK, MBROLIB_INVAL). - -*/ -MBROLIB_ERROR mbrolib_terminate(void* the_handle); -typedef MBROLIB_ERROR (t_mbrolib_terminate)(void*); - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/navit/support/espeak/numbers.c b/navit/support/espeak/numbers.c deleted file mode 100644 index 9c74eaca3..000000000 --- a/navit/support/espeak/numbers.c +++ /dev/null @@ -1,1507 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#include <wctype.h> -#include <wchar.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" - - - -#define M_NAME 0 -#define M_SMALLCAP 1 -#define M_TURNED 2 -#define M_REVERSED 3 -#define M_CURL 4 - -#define M_ACUTE 5 -#define M_BREVE 6 -#define M_CARON 7 -#define M_CEDILLA 8 -#define M_CIRCUMFLEX 9 -#define M_DIAERESIS 10 -#define M_DOUBLE_ACUTE 11 -#define M_DOT_ABOVE 12 -#define M_GRAVE 13 -#define M_MACRON 14 -#define M_OGONEK 15 -#define M_RING 16 -#define M_STROKE 17 -#define M_TILDE 18 - -#define M_BAR 19 -#define M_RETROFLEX 20 -#define M_HOOK 21 - - -#define M_MIDDLE_DOT M_DOT_ABOVE // duplicate of M_DOT_ABOVE -#define M_IMPLOSIVE M_HOOK - -typedef struct { -const char *name; -int flags; -} ACCENTS; - -// these are tokens to look up in the *_list file. -static ACCENTS accents_tab[] = { -{"_lig", 1}, -{"_smc", 1}, // smallcap -{"_tur", 1}, // turned -{"_rev", 1}, // reversed -{"_crl", 0}, // curl - -{"_acu", 0}, // acute -{"_brv", 0}, // breve -{"_hac", 0}, // caron/hacek -{"_ced", 0}, // cedilla -{"_cir", 0}, // circumflex -{"_dia", 0}, // diaeresis -{"_ac2", 0}, // double acute -{"_dot", 0}, // dot -{"_grv", 0}, // grave -{"_mcn", 0}, // macron -{"_ogo", 0}, // ogonek -{"_rng", 0}, // ring -{"_stk", 0}, // stroke -{"_tld", 0}, // tilde - -{"_bar", 0}, // bar -{"_rfx", 0}, // retroflex -{"_hok", 0}, // hook -}; - - -#define CAPITAL 0 -#define LETTER(ch,mod1,mod2) (ch-59)+(mod1 << 6)+(mod2 << 11) -#define LIGATURE(ch1,ch2,mod1) (ch1-59)+((ch2-59) << 6)+(mod1 << 12)+0x8000 - - -#define L_ALPHA 60 // U+3B1 -#define L_SCHWA 61 // U+259 -#define L_OPEN_E 62 // U+25B -#define L_GAMMA 63 // U+3B3 -#define L_IOTA 64 // U+3B9 -#define L_OE 65 // U+153 -#define L_OMEGA 66 // U+3C9 - -#define L_PHI 67 // U+3C6 -#define L_ESH 68 // U+283 -#define L_UPSILON 69 // U+3C5 -#define L_EZH 70 // U+292 -#define L_GLOTTAL 71 // U+294 -#define L_RTAP 72 // U+27E - - -static const short non_ascii_tab[] = { - 0, 0x3b1, 0x259, 0x25b, 0x3b3, 0x3b9, 0x153, 0x3c9, -0x3c6, 0x283, 0x3c5, 0x292, 0x294, 0x27e }; - - -// characters U+00e0 to U+017f -static const unsigned short letter_accents_0e0[] = { -LETTER('a',M_GRAVE,0), // U+00e0 -LETTER('a',M_ACUTE,0), -LETTER('a',M_CIRCUMFLEX,0), -LETTER('a',M_TILDE,0), -LETTER('a',M_DIAERESIS,0), -LETTER('a',M_RING,0), -LIGATURE('a','e',0), -LETTER('c',M_CEDILLA,0), -LETTER('e',M_GRAVE,0), -LETTER('e',M_ACUTE,0), -LETTER('e',M_CIRCUMFLEX,0), -LETTER('e',M_DIAERESIS,0), -LETTER('i',M_GRAVE,0), -LETTER('i',M_ACUTE,0), -LETTER('i',M_CIRCUMFLEX,0), -LETTER('i',M_DIAERESIS,0), -LETTER('d',M_NAME,0), // eth // U+00f0 -LETTER('n',M_TILDE,0), -LETTER('o',M_GRAVE,0), -LETTER('o',M_ACUTE,0), -LETTER('o',M_CIRCUMFLEX,0), -LETTER('o',M_TILDE,0), -LETTER('o',M_DIAERESIS,0), -0, // division sign -LETTER('o',M_STROKE,0), -LETTER('u',M_GRAVE,0), -LETTER('u',M_ACUTE,0), -LETTER('u',M_CIRCUMFLEX,0), -LETTER('u',M_DIAERESIS,0), -LETTER('y',M_ACUTE,0), -LETTER('t',M_NAME,0), // thorn -LETTER('y',M_DIAERESIS,0), -CAPITAL, // U+0100 -LETTER('a',M_MACRON,0), -CAPITAL, -LETTER('a',M_BREVE,0), -CAPITAL, -LETTER('a',M_OGONEK,0), -CAPITAL, -LETTER('c',M_ACUTE,0), -CAPITAL, -LETTER('c',M_CIRCUMFLEX,0), -CAPITAL, -LETTER('c',M_DOT_ABOVE,0), -CAPITAL, -LETTER('c',M_CARON,0), -CAPITAL, -LETTER('d',M_CARON,0), -CAPITAL, // U+0110 -LETTER('d',M_STROKE,0), -CAPITAL, -LETTER('e',M_MACRON,0), -CAPITAL, -LETTER('e',M_BREVE,0), -CAPITAL, -LETTER('e',M_DOT_ABOVE,0), -CAPITAL, -LETTER('e',M_OGONEK,0), -CAPITAL, -LETTER('e',M_CARON,0), -CAPITAL, -LETTER('g',M_CIRCUMFLEX,0), -CAPITAL, -LETTER('g',M_BREVE,0), -CAPITAL, // U+0120 -LETTER('g',M_DOT_ABOVE,0), -CAPITAL, -LETTER('g',M_CEDILLA,0), -CAPITAL, -LETTER('h',M_CIRCUMFLEX,0), -CAPITAL, -LETTER('h',M_STROKE,0), -CAPITAL, -LETTER('i',M_TILDE,0), -CAPITAL, -LETTER('i',M_MACRON,0), -CAPITAL, -LETTER('i',M_BREVE,0), -CAPITAL, -LETTER('i',M_OGONEK,0), -CAPITAL, // U+0130 -LETTER('i',M_NAME,0), // dotless i -CAPITAL, -LIGATURE('i','j',0), -CAPITAL, -LETTER('j',M_CIRCUMFLEX,0), -CAPITAL, -LETTER('k',M_CEDILLA,0), -LETTER('k',M_NAME,0), // kra -CAPITAL, -LETTER('l',M_ACUTE,0), -CAPITAL, -LETTER('l',M_CEDILLA,0), -CAPITAL, -LETTER('l',M_CARON,0), -CAPITAL, -LETTER('l',M_MIDDLE_DOT,0), // U+0140 -CAPITAL, -LETTER('l',M_STROKE,0), -CAPITAL, -LETTER('n',M_ACUTE,0), -CAPITAL, -LETTER('n',M_CEDILLA,0), -CAPITAL, -LETTER('n',M_CARON,0), -LETTER('n',M_NAME,0), // apostrophe n -CAPITAL, -LETTER('n',M_NAME,0), // eng -CAPITAL, -LETTER('o',M_MACRON,0), -CAPITAL, -LETTER('o',M_BREVE,0), -CAPITAL, // U+0150 -LETTER('o',M_DOUBLE_ACUTE,0), -CAPITAL, -LIGATURE('o','e',0), -CAPITAL, -LETTER('r',M_ACUTE,0), -CAPITAL, -LETTER('r',M_CEDILLA,0), -CAPITAL, -LETTER('r',M_CARON,0), -CAPITAL, -LETTER('s',M_ACUTE,0), -CAPITAL, -LETTER('s',M_CIRCUMFLEX,0), -CAPITAL, -LETTER('s',M_CEDILLA,0), -CAPITAL, // U+0160 -LETTER('s',M_CARON,0), -CAPITAL, -LETTER('t',M_CEDILLA,0), -CAPITAL, -LETTER('t',M_CARON,0), -CAPITAL, -LETTER('t',M_STROKE,0), -CAPITAL, -LETTER('u',M_TILDE,0), -CAPITAL, -LETTER('u',M_MACRON,0), -CAPITAL, -LETTER('u',M_BREVE,0), -CAPITAL, -LETTER('u',M_RING,0), -CAPITAL, // U+0170 -LETTER('u',M_DOUBLE_ACUTE,0), -CAPITAL, -LETTER('u',M_OGONEK,0), -CAPITAL, -LETTER('w',M_CIRCUMFLEX,0), -CAPITAL, -LETTER('y',M_CIRCUMFLEX,0), -CAPITAL, // Y-DIAERESIS -CAPITAL, -LETTER('z',M_ACUTE,0), -CAPITAL, -LETTER('z',M_DOT_ABOVE,0), -CAPITAL, -LETTER('z',M_CARON,0), -LETTER('s',M_NAME,0), // long-s // U+17f -}; - - -// characters U+0250 to U+029F -static const unsigned short letter_accents_250[] = { -LETTER('a',M_TURNED,0), // U+250 -LETTER(L_ALPHA,0,0), -LETTER(L_ALPHA,M_TURNED,0), -LETTER('b',M_IMPLOSIVE,0), -0, // open-o -LETTER('c',M_CURL,0), -LETTER('d',M_RETROFLEX,0), -LETTER('d',M_IMPLOSIVE,0), -LETTER('e',M_REVERSED,0), // U+258 -0, // schwa -LETTER(L_SCHWA,M_HOOK,0), -0, // open-e -LETTER(L_OPEN_E,M_REVERSED,0), -LETTER(L_OPEN_E,M_HOOK,M_REVERSED), -0,//LETTER(L_OPEN_E,M_CLOSED,M_REVERSED), -LETTER('j',M_BAR,0), -LETTER('g',M_IMPLOSIVE,0), // U+260 -LETTER('g',0,0), -LETTER('g',M_SMALLCAP,0), -LETTER(L_GAMMA,0,0), -0, // ramshorn -LETTER('h',M_TURNED,0), -LETTER('h',M_HOOK,0), -0,//LETTER(L_HENG,M_HOOK,0), -LETTER('i',M_BAR,0), // U+268 -LETTER(L_IOTA,0,0), -LETTER('i',M_SMALLCAP,0), -LETTER('l',M_TILDE,0), -LETTER('l',M_BAR,0), -LETTER('l',M_RETROFLEX,0), -LIGATURE('l','z',0), -LETTER('m',M_TURNED,0), -0,//LETTER('m',M_TURNED,M_LEG), // U+270 -LETTER('m',M_HOOK,0), -0,//LETTER('n',M_LEFTHOOK,0), -LETTER('n',M_RETROFLEX,0), -LETTER('n',M_SMALLCAP,0), -LETTER('o',M_BAR,0), -LIGATURE('o','e',M_SMALLCAP), -0,//LETTER(L_OMEGA,M_CLOSED,0), -LETTER(L_PHI,0,0), // U+278 -LETTER('r',M_TURNED,0), -0,//LETTER('r',M_TURNED,M_LEG), -LETTER('r',M_RETROFLEX,M_TURNED), -0,//LETTER('r',M_LEG,0), -LETTER('r',M_RETROFLEX,0), -0, // r-tap -LETTER(L_RTAP,M_REVERSED,0), -LETTER('r',M_SMALLCAP,0), // U+280 -LETTER('r',M_TURNED,M_SMALLCAP), -LETTER('s',M_RETROFLEX,0), -0, // esh -0,//LETTER('j',M_BAR,L_IMPLOSIVE), -LETTER(L_ESH,M_REVERSED,0), -LETTER(L_ESH,M_CURL,0), -LETTER('t',M_TURNED,0), -LETTER('t',M_RETROFLEX,0), // U+288 -LETTER('u',M_BAR,0), -LETTER(L_UPSILON,0,0), -LETTER('v',M_HOOK,0), -LETTER('v',M_TURNED,0), -LETTER('w',M_TURNED,0), -LETTER('y',M_TURNED,0), -LETTER('y',M_SMALLCAP,0), -LETTER('z',M_RETROFLEX,0), // U+290 -LETTER('z',M_CURL,0), -0, // ezh -LETTER(L_EZH,M_CURL,0), -0, // glottal stop -LETTER(L_GLOTTAL,M_REVERSED,0), -LETTER(L_GLOTTAL,M_TURNED,0), -0,//LETTER('c',M_LONG,0), -0, // bilabial click // U+298 -LETTER('b',M_SMALLCAP,0), -0,//LETTER(L_OPEN_E,M_CLOSED,0), -LETTER('g',M_IMPLOSIVE,M_SMALLCAP), -LETTER('h',M_SMALLCAP,0), -LETTER('j',M_CURL,0), -LETTER('k',M_TURNED,0), -LETTER('l',M_SMALLCAP,0), -LETTER('q',M_HOOK,0), // U+2a0 -LETTER(L_GLOTTAL,M_STROKE,0), -LETTER(L_GLOTTAL,M_STROKE,M_REVERSED), -LIGATURE('d','z',0), -0, // dezh -LIGATURE('d','z',M_CURL), -LIGATURE('t','s',0), -0, // tesh -LIGATURE('t','s',M_CURL), -}; - -static int LookupLetter2(Translator *tr, unsigned int letter, char *ph_buf) -{//======================================================================== - int len; - char single_letter[10]; - - single_letter[0] = 0; - single_letter[1] = '_'; - len = utf8_out(letter, &single_letter[2]); - single_letter[len+2] = ' '; - single_letter[len+3] = 0; - - if(Lookup(tr, &single_letter[1], ph_buf) == 0) - { - single_letter[1] = ' '; - if(Lookup(tr, &single_letter[2], ph_buf) == 0) - { - TranslateRules(tr, &single_letter[2], ph_buf, 20, NULL,0,NULL); - } - } - return(ph_buf[0]); -} - - -void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf) -{//========================================================================= - // lookup the character in the accents table - int accent_data = 0; - int accent1 = 0; - int accent2 = 0; - int basic_letter; - int letter2=0; - char ph_letter1[30]; - char ph_letter2[30]; - char ph_accent1[30]; - char ph_accent2[30]; - - ph_accent2[0] = 0; - - if((letter >= 0xe0) && (letter < 0x17f)) - { - accent_data = letter_accents_0e0[letter - 0xe0]; - } - else - if((letter >= 0x250) && (letter <= 0x2a8)) - { - accent_data = letter_accents_250[letter - 0x250]; - } - - if(accent_data != 0) - { - basic_letter = (accent_data & 0x3f) + 59; - if(basic_letter < 'a') - basic_letter = non_ascii_tab[basic_letter-59]; - - if(accent_data & 0x8000) - { - letter2 = (accent_data >> 6) & 0x3f; - letter2 += 59; - accent2 = (accent_data >> 12) & 0x7; - } - else - { - accent1 = (accent_data >> 6) & 0x1f; - accent2 = (accent_data >> 11) & 0xf; - } - - - if(Lookup(tr, accents_tab[accent1].name, ph_accent1) != 0) - { - - if(LookupLetter2(tr, basic_letter, ph_letter1) != 0) - { - if(accent2 != 0) - { - if(Lookup(tr, accents_tab[accent2].name, ph_accent2) == 0) - { -// break; - } - - if(accents_tab[accent2].flags & 1) - { - strcpy(ph_buf,ph_accent2); - ph_buf += strlen(ph_buf); - ph_accent2[0] = 0; - } - } - if(letter2 != 0) - { - //ligature - LookupLetter2(tr, letter2, ph_letter2); - sprintf(ph_buf,"%s%c%s%c%s%s",ph_accent1, phonPAUSE_VSHORT, ph_letter1, phonSTRESS_P, ph_letter2, ph_accent2); - } - else - { - if(accent1 == 0) - strcpy(ph_buf, ph_letter1); - else - if((tr->langopts.accents & 1) || (accents_tab[accent1].flags & 1)) - sprintf(ph_buf,"%s%c%c%s", ph_accent1, phonPAUSE_VSHORT, phonSTRESS_P, ph_letter1); - else - sprintf(ph_buf,"%c%s%c%s%c", phonSTRESS_2, ph_letter1, phonPAUSE_VSHORT, ph_accent1, phonPAUSE_VSHORT); - } - } - } - } -} // end of LookupAccentedLetter - - - -void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1) -{//================================================================================= - int len; - unsigned char *p; - static char single_letter[10] = {0,0}; - char ph_stress[2]; - unsigned int dict_flags[2]; - char ph_buf3[40]; - char *ptr; - - ph_buf1[0] = 0; - len = utf8_out(letter,&single_letter[2]); - single_letter[len+2] = ' '; - - if(next_byte == -1) - { - // speaking normal text, not individual characters - if(Lookup(tr, &single_letter[2], ph_buf1) != 0) - return; - - single_letter[1] = '_'; - if(Lookup(tr, &single_letter[1], ph_buf3) != 0) - return; // the character is specified as _* so ignore it when speaking normal text - - // check whether this character is specified for English - if(tr->translator_name == L('e','n')) - return; // we are already using English - - SetTranslator2("en"); - if(Lookup(translator2, &single_letter[2], ph_buf3) != 0) - { - // yes, switch to English and re-translate the word - sprintf(ph_buf1,"%c",phonSWITCH); - } - SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table - return; - } - - if((letter <= 32) || iswspace(letter)) - { - // lookup space as _&32 etc. - sprintf(&single_letter[1],"_#%d ",letter); - Lookup(tr, &single_letter[1], ph_buf1); - return; - } - - if(next_byte != ' ') - next_byte = RULE_SPELLING; - single_letter[3+len] = next_byte; // follow by space-space if the end of the word, or space-0x31 - - single_letter[1] = '_'; - - // if the $accent flag is set for this letter, use the accents table (below) - dict_flags[1] = 0; - ptr = &single_letter[1]; - - if(Lookup(tr, &single_letter[1], ph_buf3) == 0) - { - single_letter[1] = ' '; - if(Lookup(tr, &single_letter[2], ph_buf3) == 0) - { - TranslateRules(tr, &single_letter[2], ph_buf3, sizeof(ph_buf3), NULL,FLAG_NO_TRACE,NULL); - } - } - - if(ph_buf3[0] == 0) - { - LookupAccentedLetter(tr, letter, ph_buf3); - } - - if(ph_buf3[0] == 0) - { - ph_buf1[0] = 0; - return; - } - if(ph_buf3[0] == phonSWITCH) - { - strcpy(ph_buf1,ph_buf3); - return; - } - // at a stress marker at the start of the letter name, unless one is already marked - ph_stress[0] = phonSTRESS_P; - ph_stress[1] = 0; - - for(p=(unsigned char *)ph_buf3; *p != 0; p++) - { - if(phoneme_tab[*p]->type == phSTRESS) - ph_stress[0] = 0; // stress is already marked - } - sprintf(ph_buf1,"%s%s",ph_stress,ph_buf3); -} - - - -int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, int word_length) -{//====================================================================================== -// get pronunciation for an isolated letter -// return number of bytes used by the letter -// control 2=say-as glyphs, 3-say-as chars - int n_bytes; - int letter; - int len; - int save_option_phonemes; - char *p2; - char *pbuf; - char capital[20]; - char ph_buf[60]; - char ph_buf2[60]; - char hexbuf[6]; - - ph_buf[0] = 0; - capital[0] = 0; - - n_bytes = utf8_in(&letter,word); - - if((letter & 0xfff00) == 0x0e000) - { - letter &= 0xff; // uncode private usage area - } - - if(control > 2) - { - // include CAPITAL information - if(iswupper(letter)) - { - Lookup(tr, "_cap", capital); - } - } - letter = towlower2(letter); - - LookupLetter(tr, letter, word[n_bytes], ph_buf); - - if(ph_buf[0] == phonSWITCH) - { - strcpy(phonemes,ph_buf); - return(0); - } - - if((ph_buf[0] == 0) && (tr->translator_name != L('e','n'))) - { - // speak as English, check whether there is a translation for this character - SetTranslator2("en"); - save_option_phonemes = option_phonemes; - option_phonemes = 0; - LookupLetter(translator2, letter, word[n_bytes], ph_buf); - SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table - option_phonemes = save_option_phonemes; - - if(ph_buf[0] != 0) - { - sprintf(phonemes,"%cen",phonSWITCH); - return(0); - } - } - - if(ph_buf[0] == 0) - { - // character name not found - if(iswalpha(letter)) - Lookup(tr, "_?A", ph_buf); - - if((ph_buf[0]==0) && !iswspace(letter)) - Lookup(tr, "_??", ph_buf); - - if(ph_buf[0] != 0) - { - // speak the hexadecimal number of the character code - sprintf(hexbuf,"%x",letter); - pbuf = ph_buf; - for(p2 = hexbuf; *p2 != 0; p2++) - { - pbuf += strlen(pbuf); - *pbuf++ = phonPAUSE_VSHORT; - LookupLetter(tr, *p2, 0, pbuf); - } - } - } - - len = strlen(phonemes); - if(tr->langopts.accents & 2) - sprintf(ph_buf2,"%c%s%s",0xff,ph_buf,capital); - else - sprintf(ph_buf2,"%c%s%s",0xff,capital,ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress() - if((len + strlen(ph_buf2)) < N_WORD_PHONEMES) - { - strcpy(&phonemes[len],ph_buf2); - } - return(n_bytes); -} // end of TranslateLetter - - - -void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) -{//============================================================================= -// Individual letter names, reduce the stress of some. - int ix; - unsigned int c; - int n_stress=0; - int count; - unsigned char buf[N_WORD_PHONEMES]; - - for(ix=0; (c = phonemes[ix]) != 0; ix++) - { - if(c == phonSTRESS_P) - { - n_stress++; - } - buf[ix] = c; - } - buf[ix] = 0; - - count = 0; - for(ix=0; (c = buf[ix]) != 0; ix++) - { - if((c == phonSTRESS_P) && (n_chars > 1)) - { - count++; - - if(tr->langopts.spelling_stress == 1) - { - // stress on initial letter when spelling - if(count > 1) - c = phonSTRESS_3; - } - else - { - if(count != n_stress) - { - if(((count % 3) != 0) || (count == n_stress-1)) - c = phonSTRESS_3; // reduce to secondary stress - } - } - } - else - if(c == 0xff) - { - if((control < 2) || (ix==0)) - continue; // don't insert pauses - - if(control == 4) - c = phonPAUSE; // pause after each character - if(((count % 3) == 0) || (control > 2)) - c = phonPAUSE_SHORT; // pause following a primary stress - else - continue; // remove marker - } - *phonemes++ = c; - } - if(control >= 2) - *phonemes++ = phonPAUSE_NOLINK; - *phonemes = 0; -} // end of SetSpellingStress - - - -// Numbers - -static char ph_ordinal2[12]; - -int TranslateRoman(Translator *tr, char *word, char *ph_out) -{//===================================================== - int c; - char *p; - const char *p2; - int acc; - int prev; - int value; - int subtract; - int repeat = 0; - unsigned int flags; - char ph_roman[30]; - char number_chars[N_WORD_BYTES]; - - static const char *roman_numbers = "ixcmvld"; - static int roman_values[] = {1,10,100,1000,5,50,500}; - - acc = 0; - prev = 0; - subtract = 0x7fff; - - while((c = *word++) != ' ') - { - if((p2 = strchr(roman_numbers,c)) == NULL) - return(0); - - value = roman_values[p2 - roman_numbers]; - if(value == prev) - { - repeat++; - if(repeat >= 3) - return(0); - } - else - repeat = 0; - - if((prev > 1) && (prev != 10) && (prev != 100)) - { - if(value >= prev) - return(0); - } - if((prev != 0) && (prev < value)) - { - if(((acc % 10) != 0) || ((prev*10) < value)) - return(0); - subtract = prev; - value -= subtract; - } - else - if(value >= subtract) - return(0); - else - acc += prev; - prev = value; - } - acc += prev; - if(acc < 2) - return(0); - - if(acc > tr->langopts.max_roman) - return(0); - - Lookup(tr, "_roman",ph_roman); // precede by "roman" if _rom is defined in *_list - p = &ph_out[0]; - - if((tr->langopts.numbers & NUM_ROMAN_AFTER) == 0) - { - strcpy(ph_out,ph_roman); - p = &ph_out[strlen(ph_out)]; - } - - sprintf(number_chars," %d ",acc); - TranslateNumber(tr, &number_chars[1], p, &flags, 0); - - if(tr->langopts.numbers & NUM_ROMAN_AFTER) - strcat(ph_out,ph_roman); - return(1); -} // end of TranslateRoman - - -static const char *M_Variant(int value) -{//==================================== - // returns M, or perhaps MA for some cases - - if((translator->langopts.numbers2 & 0x100) && (value >= 2) && (value <= 4)) - return("0MA"); // Czech, Slovak - else - if(((value % 100) < 10) || ((value % 100) > 20)) // but not teens, 10 to 19 - { - if ((translator->langopts.numbers2 & 0x40) && - ((value % 10)>=2) && - ((value % 10)<=4)) - { - // for Polish language - two forms of plural! - return("0MA"); - } - - if((translator->langopts.numbers2 & 0x80) && - ((value % 10)==1)) - { - return("1MA"); - } - - } - return("0M"); -} - - -static int LookupThousands(Translator *tr, int value, int thousandplex, char *ph_out) -{//================================================================================== - int found; - char string[12]; - char ph_of[12]; - char ph_thousands[40]; - - ph_of[0] = 0; - - // first look fora match with the exact value of thousands - sprintf(string,"_%dM%d",value,thousandplex); - - if((found = Lookup(tr, string, ph_thousands)) == 0) - { - if((value % 100) >= 20) - { - Lookup(tr, "_0of", ph_of); - } - - sprintf(string,"_%s%d",M_Variant(value),thousandplex); - - if(Lookup(tr, string, ph_thousands) == 0) - { - // repeat "thousand" if higher order names are not available - sprintf(string,"_%dM1",value); - if((found = Lookup(tr, string, ph_thousands)) == 0) - Lookup(tr, "_0M1", ph_thousands); - } - } - sprintf(ph_out,"%s%s",ph_of,ph_thousands); - return(found); -} - - -static int LookupNum2(Translator *tr, int value, int control, char *ph_out) -{//======================================================================== -// Lookup a 2 digit number -// control bit 0: tens and units (use special form of '1') -// control bit 1: ordinal number -// control bit 2: use feminine form of '2' -// control bit 3: speak zero tens - - int found; - int ix; - int units; - int used_and=0; - int found_ordinal = 0; - int next_phtype; - char string[12]; // for looking up entries in *_list - char ph_ordinal[20]; - char ph_tens[50]; - char ph_digits[50]; - char ph_and[12]; - - // is there a special pronunciation for this 2-digit number - found = 0; - ph_ordinal[0] = 0; - - if(control & 4) - { - sprintf(string,"_%df",value); - found = Lookup(tr, string, ph_digits); - } - if(control & 2) - { - strcpy(ph_ordinal, ph_ordinal2); - - sprintf(string,"_%do",value); - if((found = Lookup(tr, string, ph_digits)) != 0) - { - found_ordinal = 1; - } - } - - if(found == 0) - { - if((value == 1) && (control & 1)) - { - if(Lookup(tr, "_1a", ph_out) != 0) - return(0); - } - sprintf(string,"_%d",value); - found = Lookup(tr, string, ph_digits); - } - - // no, speak as tens+units - - if((control & 8) && (value < 10)) - { - // speak leading zero - Lookup(tr, "_0", ph_tens); - } - else - { - if(found) - { - ph_tens[0] = 0; - } - else - { - units = (value % 10); - - if((control & 2) && ((units == 0) || (tr->langopts.numbers & 0x10))) - { - sprintf(string,"_%dXo",value / 10); - if(Lookup(tr, string, ph_tens) != 0) - { - found_ordinal = 1; - } - } - if(found_ordinal == 0) - { - sprintf(string,"_%dX",value / 10); - Lookup(tr, string, ph_tens); - } - - if((ph_tens[0] == 0) && (tr->langopts.numbers & NUM_VIGESIMAL)) - { - // tens not found, (for example) 73 is 60+13 - units = (value % 20); - sprintf(string,"_%dX",(value / 10) & 0xfe); - Lookup(tr, string, ph_tens); - } - - ph_digits[0] = 0; - if(units > 0) - { - found = 0; - if(control & 4) - { - // is there a variant form of this number? - sprintf(string,"_%df",units); - found = Lookup(tr, string, ph_digits); - } - if((control & 2) && ((tr->langopts.numbers & 0x10) == 0)) - { - // ordinal - sprintf(string,"_%do",units); - if((found = Lookup(tr, string, ph_digits)) != 0) - { - found_ordinal = 1; - } - } - if(found == 0) - { - sprintf(string,"_%d",units); - Lookup(tr, string, ph_digits); - } - } - } - } - - if((control & 2) && (found_ordinal == 0) && (ph_ordinal[0] == 0)) - { - if((value >= 20) && (((value % 10) == 0) || (tr->langopts.numbers & 0x10))) - Lookup(tr, "_ord20", ph_ordinal); - if(ph_ordinal[0] == 0) - Lookup(tr, "_ord", ph_ordinal); - } - - if((tr->langopts.numbers & 0x30) && (ph_tens[0] != 0) && (ph_digits[0] != 0)) - { - Lookup(tr, "_0and", ph_and); - if(tr->langopts.numbers & 0x10) - sprintf(ph_out,"%s%s%s%s",ph_digits, ph_and, ph_tens, ph_ordinal); - else - sprintf(ph_out,"%s%s%s%s",ph_tens, ph_and, ph_digits, ph_ordinal); - used_and = 1; - } - else - { - if(tr->langopts.numbers & 0x200) - { - // remove vowel from the end of tens if units starts with a vowel (LANG=Italian) - if(((ix = strlen(ph_tens)-1) >= 0) && (ph_digits[0] != 0)) - { - if((next_phtype = phoneme_tab[(unsigned int)(ph_digits[0])]->type) == phSTRESS) - next_phtype = phoneme_tab[(unsigned int)(ph_digits[1])]->type; - - if((phoneme_tab[(unsigned int)(ph_tens[ix])]->type == phVOWEL) && (next_phtype == phVOWEL)) - ph_tens[ix] = 0; - } - } - sprintf(ph_out,"%s%s%s",ph_tens, ph_digits, ph_ordinal); - } - - if(tr->langopts.numbers & 0x100) - { - // only one primary stress - found = 0; - for(ix=strlen(ph_out)-1; ix>=0; ix--) - { - if(ph_out[ix] == phonSTRESS_P) - { - if(found) - ph_out[ix] = phonSTRESS_3; - else - found = 1; - } - } - } - return(used_and); -} // end of LookupNum2 - - -static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int control) -{//============================================================================================================= -// Translate a 3 digit number -// control bit 0, previous thousands -// bit 1, ordinal number - int found; - int hundreds; - int x; - char string[12]; // for looking up entries in **_list - char buf1[100]; - char buf2[100]; - char ph_100[20]; - char ph_10T[20]; - char ph_digits[50]; - char ph_thousands[50]; - char ph_hundred_and[12]; - char ph_thousand_and[12]; - - hundreds = value / 100; - buf1[0] = 0; - - if(hundreds > 0) - { - ph_thousands[0] = 0; - ph_thousand_and[0] = 0; - - found = 0; - if((control & 2) && ((value % 100) == 0)) - { - // ordinal number, with no tens or units - found = Lookup(tr, "_0Co", ph_100); - } - if(found == 0) - { - Lookup(tr, "_0C", ph_100); - } - - if(((tr->langopts.numbers & 0x0800) != 0) && (hundreds == 19)) - { - // speak numbers such as 1984 as years: nineteen-eighty-four -// ph_100[0] = 0; // don't say "hundred", we also need to surpess "and" - } - else - if(hundreds >= 10) - { - ph_digits[0] = 0; - - if(LookupThousands(tr, hundreds / 10, thousandplex+1, ph_10T) == 0) - { - x = 0; - if(tr->langopts.numbers2 & (1 << (thousandplex+1))) - x = 4; - LookupNum2(tr, hundreds/10, x, ph_digits); - } - - if(tr->langopts.numbers2 & 0x200) - sprintf(ph_thousands,"%s%s%c",ph_10T,ph_digits,phonPAUSE_NOLINK); // say "thousands" before its number, not after - else - sprintf(ph_thousands,"%s%s%c",ph_digits,ph_10T,phonPAUSE_NOLINK); - - hundreds %= 10; - if(hundreds == 0) - ph_100[0] = 0; - suppress_null = 1; - } - - ph_digits[0] = 0; - if(hundreds > 0) - { - if((tr->langopts.numbers & 0x100000) && ((control & 1) || (ph_thousands[0] != 0))) - { - Lookup(tr, "_0and", ph_thousand_and); - } - - suppress_null = 1; - - found = 0; - if((value % 1000) == 100) - { - // is there a special pronunciation for exactly 100 ? - found = Lookup(tr, "_1C0", ph_digits); - } - if(!found) - { - sprintf(string,"_%dC",hundreds); - found = Lookup(tr, string, ph_digits); // is there a specific pronunciation for n-hundred ? - } - - if(found) - { - ph_100[0] = 0; - } - else - { - if((hundreds > 1) || ((tr->langopts.numbers & 0x400) == 0)) - { - LookupNum2(tr, hundreds, 0, ph_digits); - } - } - } - - sprintf(buf1,"%s%s%s%s",ph_thousands,ph_thousand_and,ph_digits,ph_100); - } - - ph_hundred_and[0] = 0; - if((tr->langopts.numbers & 0x40) && ((value % 100) != 0)) - { - if((value > 100) || ((control & 1) && (thousandplex==0))) - { - Lookup(tr, "_0and", ph_hundred_and); - } - } - - - buf2[0] = 0; - value = value % 100; - - if((value != 0) || (suppress_null == 0)) - { - x = 0; - if(thousandplex==0) - { - x = 1; // allow "eins" for 1 rather than "ein" - if(control & 2) - x = 3; // ordinal number - } - else - { - if(tr->langopts.numbers2 & (1 << thousandplex)) - x = 4; // use variant (feminine) for before thousands and millions - } - - if(LookupNum2(tr, value, x, buf2) != 0) - { - if(tr->langopts.numbers & 0x80) - ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units - } - } - - sprintf(ph_out,"%s%s%s",buf1,ph_hundred_and,buf2); - - return(0); -} // end of LookupNum3 - - -static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, int wflags) -{//==================================================================================================== -// Number translation with various options -// the "word" may be up to 4 digits -// "words" of 3 digits may be preceded by another number "word" for thousands or millions - - int n_digits; - int value; - unsigned int ix; - unsigned char c; - int suppress_null = 0; - int decimal_point = 0; - int thousandplex = 0; - int thousands_inc = 0; - int prev_thousands = 0; - int ordinal = 0; - int this_value; - static int prev_value; - int decimal_count; - int max_decimal_count; - int decimal_mode; - int hyphen; - char *p; - char string[20]; // for looking up entries in **_list - char buf1[100]; - char ph_append[50]; - char ph_buf[200]; - char ph_buf2[50]; - char suffix[20]; - - static const char str_pause[2] = {phonPAUSE_NOLINK,0}; - - *flags = 0; - - for(ix=0; isdigit(word[ix]); ix++) ; - n_digits = ix; - value = this_value = atoi(word); - - ph_ordinal2[0] = 0; - if((tr->langopts.numbers & 0x10000) && (word[ix] == '.') && !isdigit(word[ix+2])) - { - // ordinal number is indicated by dot after the number - ordinal = 2; - word[ix] = ' '; - } - else - { - // look for an ordinal number suffix after the number - ix++; - hyphen = 0; - p = suffix; - if(word[ix] == '-') - { - *p++ = '-'; - hyphen = 1; - ix += 2; - } - while((word[ix] != 0) && (word[ix] != ' ') && (ix < (sizeof(suffix)-1))) - { - *p++ = word[ix++]; - } - *p = 0; - - if(suffix[0] != 0) - { - sprintf(string,"_0%s",suffix); - if(Lookup(tr, string, ph_ordinal2)) - { - // this is an ordinal suffix - ordinal = 2; - flags[0] |= FLAG_SKIPWORDS; - dictionary_skipwords = 1 + hyphen; - } - } - } - - ph_append[0] = 0; - ph_buf2[0] = 0; - - // is there a previous thousands part (as a previous "word") ? - if((n_digits == 3) && (word[-2] == tr->langopts.thousands_sep) && isdigit(word[-3])) - { - prev_thousands = 1; - } - else - if((tr->langopts.thousands_sep == ' ') || (tr->langopts.numbers & 0x1000)) - { - // thousands groups can be separated by spaces - if((n_digits == 3) && isdigit(word[-2])) - { - prev_thousands = 1; - } - } - - if((word[0] == '0') && (prev_thousands == 0) && (word[1] != ' ') && (word[1] != tr->langopts.decimal_sep)) - { - if((n_digits == 2) && (word[3] == ':') && isdigit(word[5]) && isspace(word[7])) - { - // looks like a time 02:30, omit the leading zero - } - else - { - return(0); // number string with leading zero, speak as individual digits - } - } - - if((tr->langopts.numbers & 0x1000) && (word[n_digits] == ' ')) - thousands_inc = 1; - else - if(word[n_digits] == tr->langopts.thousands_sep) - thousands_inc = 2; - - if(thousands_inc > 0) - { - // if the following "words" are three-digit groups, count them and add - // a "thousand"/"million" suffix to this one - - ix = n_digits + thousands_inc; - while(isdigit(word[ix]) && isdigit(word[ix+1]) && isdigit(word[ix+2])) - { - thousandplex++; - if(word[ix+3] == tr->langopts.thousands_sep) - ix += (3 + thousands_inc); - else - break; - } - } - - if((value == 0) && prev_thousands) - { - suppress_null = 1; - } - - if((word[n_digits] == tr->langopts.decimal_sep) && isdigit(word[n_digits+1])) - { - // this "word" ends with a decimal point - Lookup(tr, "_dpt", ph_append); - decimal_point = 1; - } - else - if(suppress_null == 0) - { - if(thousands_inc > 0) - { - if((thousandplex > 0) && (value < 1000)) - { - if((suppress_null == 0) && (LookupThousands(tr,value,thousandplex,ph_append))) - { - // found an exact match for N thousand - value = 0; - suppress_null = 1; - } - } - } - } - else - if((thousandplex > 1) && prev_thousands && (prev_value > 0)) - { - sprintf(string,"_%s%d",M_Variant(value),thousandplex+1); - if(Lookup(tr, string, buf1)==0) - { - // speak this thousandplex if there was no word for the previous thousandplex - sprintf(string,"_0M%d",thousandplex); - Lookup(tr, string, ph_append); - } - } - - if((ph_append[0] == 0) && (word[n_digits] == '.') && (thousandplex == 0)) - { - Lookup(tr, "_.", ph_append); - } - - LookupNum3(tr, value, ph_buf, suppress_null, thousandplex, prev_thousands | ordinal); - if((thousandplex > 0) && (tr->langopts.numbers2 & 0x200)) - sprintf(ph_out,"%s%s%s",ph_append,ph_buf2,ph_buf); // say "thousands" before its number - else - sprintf(ph_out,"%s%s%s",ph_buf2,ph_buf,ph_append); - - - while(decimal_point) - { - n_digits++; - - decimal_count = 0; - while(isdigit(word[n_digits+decimal_count])) - decimal_count++; - - if(decimal_count > 1) - { - max_decimal_count = 2; - switch(decimal_mode = (tr->langopts.numbers & 0xe000)) - { - case 0x8000: - max_decimal_count = 5; - case 0x4000: - // French/Polish decimal fraction - while(word[n_digits] == '0') - { - Lookup(tr, "_0", buf1); - strcat(ph_out,buf1); - decimal_count--; - n_digits++; - } - if((decimal_count <= max_decimal_count) && isdigit(word[n_digits])) - { - LookupNum3(tr, atoi(&word[n_digits]), buf1, 0,0,0); - strcat(ph_out,buf1); - n_digits += decimal_count; - } - break; - - case 0x2000: - case 0xa000: - // Italian decimal fractions - if(decimal_count <= 4) - { - LookupNum3(tr, atoi(&word[n_digits]), ph_buf, 0,0,0); - if((word[n_digits]=='0') || (decimal_mode == 0xa000)) - { - // decimal part has leading zeros, so add a "hundredths" or "thousandths" suffix - sprintf(string,"_0Z%d",decimal_count); - if(Lookup(tr, string, buf1) == 0) - break; // revert to speaking single digits - - strcat(ph_buf,buf1); - } - strcat(ph_out,ph_buf); - n_digits += decimal_count; - } - break; - - case 0x6000: - // Romanian decimal fractions - if((decimal_count <= 4) && (word[n_digits] != '0')) - { - LookupNum3(tr, atoi(&word[n_digits]), buf1, 0,0,0); - strcat(ph_out,buf1); - n_digits += decimal_count; - } - break; - } - } - - while(isdigit(c = word[n_digits]) && (strlen(ph_out) < (N_WORD_PHONEMES - 10))) - { - value = word[n_digits++] - '0'; - LookupNum2(tr, value, 1, buf1); - strcat(ph_out,buf1); - } - - // something after the decimal part ? - if(Lookup(tr, "_dpt2", buf1)) - strcat(ph_out,buf1); - - if((c == tr->langopts.decimal_sep) && isdigit(word[n_digits+1])) - { - Lookup(tr, "_dpt", buf1); - strcat(ph_out,buf1); - } - else - { - decimal_point = 0; - } - } - if((ph_out[0] != 0) && (ph_out[0] != phonSWITCH)) - { - int next_char; - char *p; - p = &word[n_digits+1]; - - p += utf8_in(&next_char,p); - if((tr->langopts.numbers & NUM_NOPAUSE) && (next_char == ' ')) - utf8_in(&next_char,p); - - if(!iswalpha(next_char)) - strcat(ph_out,str_pause); // don't add pause for 100s, 6th, etc. - } - - *flags |= FLAG_FOUND; - prev_value = this_value; - return(1); -} // end of TranslateNumber_1 - - - -int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, int wflags) -{//============================================================================================ - if(option_sayas == SAYAS_DIGITS1) - return(0); // speak digits individually - - if((tr->langopts.numbers & 0x3) == 1) - return(TranslateNumber_1(tr, word1, ph_out, flags, wflags)); - - return(0); -} // end of TranslateNumber - diff --git a/navit/support/espeak/phoneme.h b/navit/support/espeak/phoneme.h deleted file mode 100755 index 596f457ef..000000000 --- a/navit/support/espeak/phoneme.h +++ /dev/null @@ -1,168 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - - - -// phoneme types -#define phPAUSE 0 -#define phSTRESS 1 -#define phVOWEL 2 -#define phLIQUID 3 -#define phSTOP 4 -#define phVSTOP 5 -#define phFRICATIVE 6 -#define phVFRICATIVE 7 -#define phNASAL 8 -#define phVIRTUAL 9 -#define phDELETED 14 -#define phINVALID 15 - - -// phoneme properties -// bits 16-19 give place of articulation (not currently used) -#define phWAVE 0x01 -#define phUNSTRESSED 0x02 -#define phFORTIS 0x08 -#define phVOICED 0x10 -#define phSIBILANT 0x20 -#define phNOLINK 0x40 -#define phTRILL 0x80 -#define phVOWEL2 0x100 // liquid that is considered a vowel -#define phPALATAL 0x200 -#define phAPPENDPH 0x2000 // always insert another phoneme (link_out) after this one -#define phBRKAFTER 0x4000 // [*] add a post-pause -#define phBEFOREPAUSE 0x8000 // replace with the link_out phoneme if the next phoneme is a pause - -#define phALTERNATIVE 0x1c00 // bits 10,11,12 specifying use of alternative_ph -#define phBEFOREVOWEL 0x0000 -#define phBEFOREVOWELPAUSE 0x0400 -#define phBEFORENOTVOWEL 0x0c00 -#define phBEFORENOTVOWEL2 0x1000 -#define phSWITCHVOICING 0x0800 -#define phBEFORE_R 0x1400 - -#define phNONSYLLABIC 0x100000 // don't count this vowel as a syllable when finding the stress position -#define phLONG 0x200000 -#define phLENGTHENSTOP 0x400000 // make the pre-pause slightly longer -#define phRHOTIC 0x800000 - -// fixed phoneme code numbers, these can be used from the program code -#define phonCONTROL 1 -#define phonSTRESS_U 2 -#define phonSTRESS_D 3 -#define phonSTRESS_2 4 -#define phonSTRESS_3 5 -#define phonSTRESS_P 6 -#define phonSTRESS_P2 7 // priority stress within a word -#define phonSTRESS_PREV 8 -#define phonPAUSE 9 -#define phonPAUSE_SHORT 10 -#define phonPAUSE_NOLINK 11 -#define phonLENGTHEN 12 -#define phonSCHWA 13 -#define phonSCHWA_SHORT 14 -#define phonEND_WORD 15 -#define phonSONORANT 16 -#define phonDEFAULTTONE 17 -#define phonCAPITAL 18 -#define phonGLOTTALSTOP 19 -#define phonSYLLABIC 20 -#define phonSWITCH 21 -#define phonX1 22 // a language specific action -#define phonPAUSE_VSHORT 23 -#define phonPAUSE_LONG 24 -#define phonT_REDUCED 25 -#define phonSTRESS_TONIC 26 -#define phonPAUSE_CLAUSE 27 - -extern const unsigned char pause_phonemes[8]; // 0, vshort, short, pause, long, glottalstop - -// place of articulation -#define phPLACE 0xf0000 -#define phPLACE_pla 0x60000 - -#define N_PHONEME_TABS 100 // number of phoneme tables -#define N_PHONEME_TAB 256 // max phonemes in a phoneme table -#define N_PHONEME_TAB_NAME 32 // must be multiple of 4 - -// main table of phonemes, index by phoneme number (1-254) -typedef struct { - unsigned int mnemonic; // 1st char is in the l.s.byte - unsigned int phflags; // bits 28-30 reduce_to level, bits 16-19 place of articulation - // bits 10-11 alternative ph control - - unsigned short std_length; // for vowels, in mS; for phSTRESS, the stress/tone type - unsigned short spect; - unsigned short before; - unsigned short after; - - unsigned char code; // the phoneme number - unsigned char type; // phVOWEL, phPAUSE, phSTOP etc - unsigned char start_type; - unsigned char end_type; - - unsigned char length_mod; // a length_mod group number, used to access length_mod_tab - unsigned char reduce_to; // change to this phoneme if unstressed - unsigned char alternative_ph; // change to this phoneme if a vowel follows/doesn't follow - unsigned char link_out; // insert linking phoneme if a vowel follows - -} PHONEME_TAB; - - -// Several phoneme tables may be loaded into memory. phoneme_tab points to -// one for the current voice -extern int n_phoneme_tab; -extern int current_phoneme_table; -extern PHONEME_TAB *phoneme_tab[N_PHONEME_TAB]; -extern unsigned char phoneme_tab_flags[N_PHONEME_TAB]; // bit 0: not inherited - -typedef struct { - char name[N_PHONEME_TAB_NAME]; - PHONEME_TAB *phoneme_tab_ptr; - int n_phonemes; - int includes; // also include the phonemes from this other phoneme table -} PHONEME_TAB_LIST; - - - -// table of phonemes to be replaced with different phonemes, for the current voice -#define N_REPLACE_PHONEMES 60 -typedef struct { - unsigned char old_ph; - unsigned char new_ph; - char type; // 0=always replace, 1=only at end of word -} REPLACE_PHONEMES; - -extern int n_replace_phonemes; -extern REPLACE_PHONEMES replace_phonemes[N_REPLACE_PHONEMES]; - - -#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name -#define PH3(c1,c2,c3) (c3<<16)+(c2<<8)+c1 -#define PhonemeCode2(c1,c2) PhonemeCode((c2<<8)+c1) -int LookupPhonemeString(const char *string); -int PhonemeCode(unsigned int mnem); - -char *EncodePhonemes(char *p, char *outptr, unsigned char *bad_phoneme); -void DecodePhonemes(const char *inptr, char *outptr); - -extern const char *WordToString(unsigned int word); - -extern PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; -extern int phoneme_tab_number; diff --git a/navit/support/espeak/phonemelist.c b/navit/support/espeak/phonemelist.c deleted file mode 100755 index d663e2e94..000000000 --- a/navit/support/espeak/phonemelist.c +++ /dev/null @@ -1,686 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "translate.h" - - -const unsigned char pause_phonemes[8] = {0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG}; - - -extern int n_ph_list2; -extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes - - - -static int ChangePhonemes(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) -{//================================================================================================================= -// Called for each phoneme in the phoneme list, to allow a language to make changes -// ph The current phoneme - - if(tr->translator_name == L('r','u')) - return(ChangePhonemes_ru(tr, phlist, n_ph, index, ph, ch)); - - return(0); -} - - -static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out) -{//==================================================================== -// Copy the phonemes list and perform any substitutions that are required for the -// current voice - int ix; - int k; - int replace_flags; - int n_plist_out = 0; - int word_end; - int max_stress = -1; - int switched_language = 0; - int max_stress_posn=0; - int n_syllables = 0; - int syllable = 0; - int syllable_stressed = 0; - PHONEME_LIST2 *plist2; - PHONEME_LIST2 *pl; - PHONEME_TAB *next=NULL; - - for(ix=0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++) - { - plist2 = &ph_list2[ix]; - - if(plist2->phcode == phonSWITCH) - switched_language ^= 1; - - // don't do any substitution if the language has been temporarily changed - if(switched_language == 0) - { - if(ix < (n_ph_list2 -1)) - next = phoneme_tab[ph_list2[ix+1].phcode]; - - word_end = 0; - if((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE))) - word_end = 1; // this phoneme is the end of a word - - if(tr->langopts.phoneme_change != 0) - { - // this language does changes to phonemes after translation - int flags; - CHANGEPH ch; - if(plist2->sourceix) - { - // start of a word, find the stressed vowel - syllable = 0; - syllable_stressed = 0; - n_syllables = 0; - - max_stress = -1; - max_stress_posn = ix; - for(k=ix; k < n_ph_list2; k++) - { - if(((pl = &ph_list2[k])->sourceix != 0) && (k > ix)) - break; - - pl->stress &= 0xf; - - if(phoneme_tab[pl->phcode]->type == phVOWEL) - { - n_syllables++; - - if(pl->stress > max_stress) - { - syllable_stressed = n_syllables; - max_stress = pl->stress; - max_stress_posn = k; - } - } - } - } - - if(phoneme_tab[plist2->phcode]->type == phVOWEL) - { - syllable++; - } - - // make any language specific changes - flags = 0; - if(ix == max_stress_posn) - flags |= 2; - if(ix > max_stress_posn) - flags |= 4; - if(ph_list2[ix].synthflags & SFLAG_DICTIONARY) - flags |= 8; - ch.flags = flags | word_end; - - ch.stress = plist2->stress; - ch.stress_highest = max_stress; - ch.n_vowels = n_syllables; - ch.vowel_this = syllable; - ch.vowel_stressed = syllable_stressed; - - ChangePhonemes(tr, ph_list2, n_ph_list2, ix, phoneme_tab[ph_list2[ix].phcode], &ch); - } - - // check whether a Voice has specified that we should replace this phoneme - for(k=0; k<n_replace_phonemes; k++) - { - if(plist2->phcode == replace_phonemes[k].old_ph) - { - replace_flags = replace_phonemes[k].type; - - if((replace_flags & 1) && (word_end == 0)) - continue; // this replacement only occurs at the end of a word - - if((replace_flags & 2) && ((plist2->stress & 0x7) > 3)) - continue; // this replacement doesn't occur in stressed syllables - - // substitute the replacement phoneme - plist2->phcode = replace_phonemes[k].new_ph; - if((plist2->stress > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED)) - plist2->stress = 0; // the replacement must be unstressed - break; - } - } - - if(plist2->phcode == 0) - { - continue; // phoneme has been replaced by NULL, so don't copy it - } - } - - // copy phoneme into the output list - memcpy(&plist_out[n_plist_out++],plist2,sizeof(PHONEME_LIST2)); - } - return(n_plist_out); -} // end of SubstitutePhonemes - - - -void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) -{//===================================================================== - - int ix=0; - int j; - int insert_ph = 0; - PHONEME_LIST *phlist; - PHONEME_TAB *ph; - PHONEME_TAB *prev, *next, *next2; - int unstress_count = 0; - int word_stress = 0; - int switched_language = 0; - int max_stress; - int voicing; - int regression; - int end_sourceix; - int alternative; - int first_vowel=0; // first vowel in a word - PHONEME_LIST2 ph_list3[N_PHONEME_LIST]; - - static PHONEME_LIST2 ph_list2_null = {0,0,0,0,0}; - PHONEME_LIST2 *plist2 = &ph_list2_null; - PHONEME_LIST2 *plist2_inserted = NULL; - - plist2 = ph_list2; - phlist = phoneme_list; - end_sourceix = plist2[n_ph_list2-1].sourceix; - - // is the last word of the clause unstressed ? - max_stress = 0; - for(j = n_ph_list2-3; j>=0; j--) - { - // start with the last phoneme (before the terminating pauses) and move forwards - if((plist2[j].stress & 0x7f) > max_stress) - max_stress = plist2[j].stress & 0x7f; - if(plist2[j].sourceix != 0) - break; - } - if(max_stress < 4) - { - // the last word is unstressed, look for a previous word that can be stressed - while(--j >= 0) - { - if(plist2[j].synthflags & SFLAG_PROMOTE_STRESS) // dictionary flags indicated that this stress can be promoted - { - plist2[j].stress = 4; // promote to stressed - break; - } - if(plist2[j].stress >= 4) - { - // found a stressed syllable, so stop looking - break; - } - } - } - - if((regression = tr->langopts.param[LOPT_REGRESSIVE_VOICING]) != 0) - { - // set consonant clusters to all voiced or all unvoiced - // Regressive - int type; - voicing = 0; - - for(j=n_ph_list2-1; j>=0; j--) - { - ph = phoneme_tab[plist2[j].phcode]; - if(ph == NULL) - continue; - - if(ph->code == phonSWITCH) - switched_language ^= 1; - if(switched_language) - continue; - - type = ph->type; - - if(regression & 0x2) - { - // LANG=Russian, [v] amd [v;] don't cause regression, or [R^] - if((ph->mnemonic == 'v') || (ph->mnemonic == ((';'<<8)+'v')) || ((ph->mnemonic & 0xff)== 'R')) - type = phLIQUID; - } - - if((type==phSTOP) || type==(phFRICATIVE)) - { - if(voicing==0) - { - voicing = 1; - } - else - if((voicing==2) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING)) - { - plist2[j].phcode = ph->alternative_ph; // change to voiced equivalent - } - } - else - if((type==phVSTOP) || type==(phVFRICATIVE)) - { - if(voicing==0) - { - voicing = 2; - } - else - if((voicing==1) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING)) - { - plist2[j].phcode = ph->alternative_ph; // change to unvoiced equivalent - } - } - else - { - if(regression & 0x8) - { - // LANG=Polish, propagate through liquids and nasals - if((type == phPAUSE) || (type == phVOWEL)) - voicing = 0; - } - else - { - voicing = 0; - } - } - if((regression & 0x4) && (plist2[j].sourceix)) - { - // stop propagation at a word boundary - voicing = 0; - } - } - } - - n_ph_list2 = SubstitutePhonemes(tr,ph_list3) - 2; - - // transfer all the phonemes of the clause into phoneme_list - ph = phoneme_tab[phonPAUSE]; - switched_language = 0; - - for(j=0; insert_ph || ((j < n_ph_list2) && (ix < N_PHONEME_LIST-3)); j++) - { - prev = ph; - - plist2 = &ph_list3[j]; - - if(insert_ph != 0) - { - // we have a (linking) phoneme which we need to insert here - next = phoneme_tab[plist2->phcode]; // this phoneme, i.e. after the insert - - // re-use the previous entry for the inserted phoneme. - // That's OK because we don't look backwards from plist2 - j--; - plist2 = plist2_inserted = &ph_list3[j]; - memset(plist2, 0, sizeof(*plist2)); - plist2->phcode = insert_ph; - ph = phoneme_tab[insert_ph]; - insert_ph = 0; - } - else - { - // otherwise get the next phoneme from the list - ph = phoneme_tab[plist2->phcode]; - - if(plist2->phcode == phonSWITCH) - { - // change phoneme table - SelectPhonemeTable(plist2->tone_number); - switched_language ^= SFLAG_SWITCHED_LANG; - } - next = phoneme_tab[(plist2+1)->phcode]; // the phoneme after this one - } - - if(plist2->sourceix) - { - // start of a word - int k; - word_stress = 0; - first_vowel = 1; - - // find the highest stress level in this word - for(k=j+1; k < n_ph_list2; k++) - { - if(ph_list3[k].sourceix) - break; // start of the next word - - if(ph_list3[k].stress > word_stress) - word_stress = ph_list3[k].stress; - } - } - - if(ph == NULL) continue; - - if(ph->type == phVOWEL) - { - // check for consecutive unstressed syllables - if(plist2->stress == 0) - { - // an unstressed vowel - unstress_count++; - if((unstress_count > 1) && ((unstress_count & 1)==0)) - { - // in a sequence of unstressed syllables, reduce alternate syllables to 'diminished' - // stress. But not for the last phoneme of a stressed word - if((tr->langopts.stress_flags & 0x2) || ((word_stress > 3) && ((plist2+1)->sourceix!=0))) - { - // An unstressed final vowel of a stressed word - unstress_count=1; // try again for next syllable - } - else - { - plist2->stress = 1; // change stress to 'diminished' - } - } - } - else - { - unstress_count = 0; - } - } - - alternative = 0; - - if(ph->alternative_ph > 0) - { - switch(ph->phflags & phALTERNATIVE) - { - // This phoneme changes if vowel follows, or doesn't follow, depending on its phNOTFOLLOWS flag - case phBEFORENOTVOWEL: - if(next->type != phVOWEL) - alternative = ph->alternative_ph; - break; - - case phBEFORENOTVOWEL2: // LANG=tr - if(((plist2+1)->sourceix != 0) || - ((next->type != phVOWEL) && ((phoneme_tab[(plist2+2)->phcode]->type != phVOWEL) || ((plist2+2)->sourceix != 0)))) - { - alternative = ph->alternative_ph; - } - break; - - case phBEFOREVOWELPAUSE: - if((next->type == phVOWEL) || (next->type == phPAUSE)) - alternative = ph->alternative_ph; - break; - - case phBEFOREVOWEL: - if(next->type == phVOWEL) - alternative = ph->alternative_ph; - break; - - case phBEFORE_R: - if(next->phflags & phRHOTIC) - { - alternative = ph->alternative_ph; - } - break; - } - } - if(ph->phflags & phBEFOREPAUSE) - { - if(next->type == phPAUSE) - alternative = ph->link_out; // replace with the link_out phoneme - } - - if(alternative == 1) - continue; // NULL phoneme, discard - - if(alternative > 1) - { - PHONEME_TAB *ph2; - ph2 = ph; - ph = phoneme_tab[alternative]; - - if(ph->type == phVOWEL) - { - plist2->synthflags |= SFLAG_SYLLABLE; - if(ph2->type != phVOWEL) - plist2->stress = 0; // change from non-vowel to vowel, make sure it's unstressed - } - else - plist2->synthflags &= ~SFLAG_SYLLABLE; - } - - if(tr->langopts.param[LOPT_REDUCE_T]) - { - if((ph->mnemonic == 't') && (plist2->sourceix == 0) && ((prev->type == phVOWEL) || (prev->mnemonic == 'n'))) - { - if(((plist2+1)->sourceix == 0) && ((plist2+1)->stress < 3) && (next->type == phVOWEL)) - { - ph = phoneme_tab[phonT_REDUCED]; - } - } - } - - - while((ph->reduce_to != 0) && (!(plist2->synthflags & SFLAG_DICTIONARY) || (tr->langopts.param[LOPT_REDUCE] & 1))) - { - int reduce_level; - int stress_level; - int reduce = 0; - - reduce_level = (ph->phflags >> 28) & 7; - - if(ph->type == phVOWEL) - { - stress_level = plist2->stress; - } - else - { - // consonant, get stress from the following vowel - if(next->type == phVOWEL) - stress_level = (plist2+1)->stress; - else - break; - } - - if((stress_level == 1) && (first_vowel)) - stress_level = 0; // ignore 'dimished' stress on first syllable - - if(stress_level == 1) - reduce = 1; // stress = 'reduced' - - if(stress_level < reduce_level) - reduce =1; - - if((word_stress < 4) && (tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= word_stress)) - { - // don't reduce the most stressed syllable in an unstressed word - reduce = 0; - } - - if(reduce) - ph = phoneme_tab[ph->reduce_to]; - else - break; - } - - if(ph->type == phVOWEL) - first_vowel = 0; - - if((plist2+1)->synthflags & SFLAG_LENGTHEN) - { - static char types_double[] = {phFRICATIVE,phVFRICATIVE,phNASAL,phLIQUID,0}; - if(strchr(types_double,next->type)) - { - // lengthen this consonant by doubling it - insert_ph = next->code; - (plist2+1)->synthflags ^= SFLAG_LENGTHEN; - } - } - - if((plist2+1)->sourceix != 0) - { - int x; - - if(tr->langopts.vowel_pause && (ph->type != phPAUSE)) - { - - if((ph->type != phVOWEL) && (tr->langopts.vowel_pause & 0x200)) - { - // add a pause after a word which ends in a consonant - insert_ph = phonPAUSE_NOLINK; - } - - if(next->type == phVOWEL) - { - if((x = tr->langopts.vowel_pause & 0x0c) != 0) - { - // break before a word which starts with a vowel - if(x == 0xc) - insert_ph = phonPAUSE_NOLINK; - else - insert_ph = phonPAUSE_VSHORT; - } - - if((ph->type == phVOWEL) && ((x = tr->langopts.vowel_pause & 0x03) != 0)) - { - // adjacent vowels over a word boundary - if(x == 2) - insert_ph = phonPAUSE_SHORT; - else - insert_ph = phonPAUSE_VSHORT; - } - - if(((plist2+1)->stress >= 4) && (tr->langopts.vowel_pause & 0x100)) - { - // pause before a words which starts with a stressed vowel - insert_ph = phonPAUSE_SHORT; - } - } - } - - if(plist2 != plist2_inserted) - { - if((x = (tr->langopts.word_gap & 0x7)) != 0) - { - if((x > 1) || ((insert_ph != phonPAUSE_SHORT) && (insert_ph != phonPAUSE_NOLINK))) - { - // don't reduce the pause - insert_ph = pause_phonemes[x]; - } - } - if(option_wordgap > 0) - { - insert_ph = phonPAUSE_LONG; - } - } - } - - next2 = phoneme_tab[(plist2+2)->phcode]; - - if((insert_ph == 0) && (ph->link_out != 0) && !(ph->phflags & phBEFOREPAUSE) && (((plist2+1)->synthflags & SFLAG_EMBEDDED)==0)) - { - if(ph->phflags & phAPPENDPH) - { - // always append the specified phoneme, unless it already is the next phoneme - if((ph->link_out != (plist2+1)->phcode) && (next->type == phVOWEL)) -// if(ph->link_out != (plist2+1)->phcode) - { - insert_ph = ph->link_out; - } - } - else - if(((tr->langopts.word_gap & 8)==0) || ((plist2+1)->sourceix == 0)) - { - // This phoneme can be linked to a following vowel by inserting a linking phoneme - if(next->type == phVOWEL) - insert_ph = ph->link_out; - else - if(next->code == phonPAUSE_SHORT) - { - // Pause followed by Vowel, replace the Short Pause with the linking phoneme, - if(next2->type == phVOWEL) - (plist2+1)->phcode = ph->link_out; // replace pause by linking phoneme - } - } - } - - if(ph->phflags & phVOICED) - { - // check that a voiced consonant is preceded or followed by a vowel or liquid - // and if not, add a short schwa - - // not yet implemented - } - - phlist[ix].ph = ph; - phlist[ix].type = ph->type; - phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module - phlist[ix].synthflags = plist2->synthflags | switched_language; - phlist[ix].stresslevel = plist2->stress & 0xf; - phlist[ix].tone_ph = plist2->tone_number; - phlist[ix].sourceix = 0; - - if(plist2->sourceix != 0) - { - phlist[ix].sourceix = plist2->sourceix; - phlist[ix].newword = 1; // this phoneme is the start of a word - - if(start_sentence) - { - phlist[ix].newword = 5; // start of sentence + start of word - start_sentence = 0; - } - } - else - { - phlist[ix].newword = 0; - } - - phlist[ix].length = ph->std_length; - if((ph->code == phonPAUSE_LONG) && (option_wordgap > 0)) - { - phlist[ix].ph = phoneme_tab[phonPAUSE_SHORT]; - phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed - } - - if(ph->type==phVOWEL || ph->type==phLIQUID || ph->type==phNASAL || ph->type==phVSTOP || ph->type==phVFRICATIVE) - { - phlist[ix].length = 128; // length_mod - phlist[ix].env = PITCHfall; - } - - phlist[ix].prepause = 0; - phlist[ix].amp = 20; // default, will be changed later - phlist[ix].pitch1 = 0x400; - phlist[ix].pitch2 = 0x400; - ix++; - } - phlist[ix].newword = 2; // end of clause - - phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes - phlist[ix].length = post_pause; // length of the pause, depends on the punctuation - phlist[ix].sourceix = end_sourceix; - phlist[ix].synthflags = 0; - - phlist[ix++].ph = phoneme_tab[phonPAUSE]; - phlist[ix].type = phPAUSE; - phlist[ix].length = 0; - phlist[ix].sourceix=0; - phlist[ix].synthflags = 0; - phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT]; - - n_phoneme_list = ix; -} // end of MakePhonemeList - - diff --git a/navit/support/espeak/portaudio.h b/navit/support/espeak/portaudio.h deleted file mode 100755 index 2ab8e02a4..000000000 --- a/navit/support/espeak/portaudio.h +++ /dev/null @@ -1,466 +0,0 @@ -// NOTE: Copy this file to portaudio.h in order to compile with V18 portaudio - - -#ifndef PORT_AUDIO_H -#define PORT_AUDIO_H - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/* - * $Id: portaudio.h,v 1.5 2002/03/26 18:04:22 philburk Exp $ - * PortAudio Portable Real-Time Audio Library - * PortAudio API Header File - * Latest version available at: http://www.audiomulch.com/portaudio/ - * - * Copyright (c) 1999-2000 Ross Bencina and Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -typedef int PaError; -typedef enum { - paNoError = 0, - - paHostError = -10000, - paInvalidChannelCount, - paInvalidSampleRate, - paInvalidDeviceId, - paInvalidFlag, - paSampleFormatNotSupported, - paBadIODeviceCombination, - paInsufficientMemory, - paBufferTooBig, - paBufferTooSmall, - paNullCallback, - paBadStreamPtr, - paTimedOut, - paInternalError, - paDeviceUnavailable -} PaErrorNum; - -/* - Pa_Initialize() is the library initialisation function - call this before - using the library. - -*/ - -PaError Pa_Initialize( void ); - -/* - Pa_Terminate() is the library termination function - call this after - using the library. - -*/ - -PaError Pa_Terminate( void ); - -/* - Pa_GetHostError() returns a host specific error code. - This can be called after receiving a PortAudio error code of paHostError. - -*/ - -long Pa_GetHostError( void ); - -/* - Pa_GetErrorText() translates the supplied PortAudio error number - into a human readable message. - -*/ - -const char *Pa_GetErrorText( PaError errnum ); - -/* - Sample formats - - These are formats used to pass sound data between the callback and the - stream. Each device has a "native" format which may be used when optimum - efficiency or control over conversion is required. - - Formats marked "always available" are supported (emulated) by all - PortAudio implementations. - - The floating point representation (paFloat32) uses +1.0 and -1.0 as the - maximum and minimum respectively. - - paUInt8 is an unsigned 8 bit format where 128 is considered "ground" - -*/ - -typedef unsigned long PaSampleFormat; -#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/ -#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/ -#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/ -#define paInt24 ((PaSampleFormat) (1<<3)) -#define paPackedInt24 ((PaSampleFormat) (1<<4)) -#define paInt8 ((PaSampleFormat) (1<<5)) -#define paUInt8 ((PaSampleFormat) (1<<6)) -#define paCustomFormat ((PaSampleFormat) (1<<16)) - -/* - Device enumeration mechanism. - - Device ids range from 0 to Pa_CountDevices()-1. - - Devices may support input, output or both. - -*/ - -typedef int PaDeviceID; -#define paNoDevice -1 - -int Pa_CountDevices( void ); - -typedef struct -{ - int structVersion; - const char *name; - int maxInputChannels; - int maxOutputChannels; - /* Number of discrete rates, or -1 if range supported. */ - int numSampleRates; - /* Array of supported sample rates, or {min,max} if range supported. */ - const double *sampleRates; - PaSampleFormat nativeSampleFormats; -} -PaDeviceInfo; - -/* - Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID() return the - default device ids for input and output respectively, or paNoDevice if - no device is available. - The result can be passed to Pa_OpenStream(). - - On the PC, the user can specify a default device by - setting an environment variable. For example, to use device #1. - - set PA_RECOMMENDED_OUTPUT_DEVICE=1 - - The user should first determine the available device ids by using - the supplied application "pa_devs". - -*/ - -PaDeviceID Pa_GetDefaultInputDeviceID( void ); -PaDeviceID Pa_GetDefaultOutputDeviceID( void ); - - - -/* - Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure - for the device specified. - If the device parameter is out of range the function returns NULL. - - PortAudio manages the memory referenced by the returned pointer, the client - must not manipulate or free the memory. The pointer is only guaranteed to be - valid between calls to Pa_Initialize() and Pa_Terminate(). - -*/ - -const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID device ); - -/* - PaTimestamp is used to represent a continuous sample clock with arbitrary - start time that can be used for syncronization. The type is used for the - outTime argument to the PortAudioCallback and as the result of Pa_StreamTime() - -*/ - -typedef double PaTimestamp; - -/* - PortAudioCallback is implemented by PortAudio clients. - - inputBuffer and outputBuffer are arrays of interleaved samples, - the format, packing and number of channels used by the buffers are - determined by parameters to Pa_OpenStream() (see below). - - framesPerBuffer is the number of sample frames to be processed by the callback. - - outTime is the time in samples when the buffer(s) processed by - this callback will begin being played at the audio output. - See also Pa_StreamTime() - - userData is the value of a user supplied pointer passed to Pa_OpenStream() - intended for storing synthesis data etc. - - return value: - The callback can return a non-zero value to stop the stream. This may be - useful in applications such as soundfile players where a specific duration - of output is required. However, it is not necessary to utilise this mechanism - as StopStream() will also terminate the stream. A callback returning a - non-zero value must fill the entire outputBuffer. - - NOTE: None of the other stream functions may be called from within the - callback function except for Pa_GetCPULoad(). - -*/ - -typedef int (PortAudioCallback)( - void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, - PaTimestamp outTime, void *userData ); - - -/* - Stream flags - - These flags may be supplied (ored together) in the streamFlags argument to - the Pa_OpenStream() function. - -*/ - -#define paNoFlag (0) -#define paClipOff (1<<0) /* disable default clipping of out of range samples */ -#define paDitherOff (1<<1) /* disable default dithering */ -#define paPlatformSpecificFlags (0x00010000) -typedef unsigned long PaStreamFlags; - -/* - A single PortAudioStream provides multiple channels of real-time - input and output audio streaming to a client application. - Pointers to PortAudioStream objects are passed between PortAudio functions. -*/ - -typedef void PortAudioStream; -#define PaStream PortAudioStream - -/* - Pa_OpenStream() opens a stream for either input, output or both. - - stream is the address of a PortAudioStream pointer which will receive - a pointer to the newly opened stream. - - inputDevice is the id of the device used for input (see PaDeviceID above.) - inputDevice may be paNoDevice to indicate that an input device is not required. - - numInputChannels is the number of channels of sound to be delivered to the - callback. It can range from 1 to the value of maxInputChannels in the - PaDeviceInfo record for the device specified by the inputDevice parameter. - If inputDevice is paNoDevice numInputChannels is ignored. - - inputSampleFormat is the sample format of inputBuffer provided to the callback - function. inputSampleFormat may be any of the formats described by the - PaSampleFormat enumeration (see above). PortAudio guarantees support for - the device's native formats (nativeSampleFormats in the device info record) - and additionally 16 and 32 bit integer and 32 bit floating point formats. - Support for other formats is implementation defined. - - inputDriverInfo is a pointer to an optional driver specific data structure - containing additional information for device setup or stream processing. - inputDriverInfo is never required for correct operation. If not used - inputDriverInfo should be NULL. - - outputDevice is the id of the device used for output (see PaDeviceID above.) - outputDevice may be paNoDevice to indicate that an output device is not required. - - numOutputChannels is the number of channels of sound to be supplied by the - callback. See the definition of numInputChannels above for more details. - - outputSampleFormat is the sample format of the outputBuffer filled by the - callback function. See the definition of inputSampleFormat above for more - details. - - outputDriverInfo is a pointer to an optional driver specific data structure - containing additional information for device setup or stream processing. - outputDriverInfo is never required for correct operation. If not used - outputDriverInfo should be NULL. - - sampleRate is the desired sampleRate. For full-duplex streams it is the - sample rate for both input and output - - framesPerBuffer is the length in sample frames of all internal sample buffers - used for communication with platform specific audio routines. Wherever - possible this corresponds to the framesPerBuffer parameter passed to the - callback function. - - numberOfBuffers is the number of buffers used for multibuffered communication - with the platform specific audio routines. If you pass zero, then an optimum - value will be chosen for you internally. This parameter is provided only - as a guide - and does not imply that an implementation must use multibuffered - i/o when reliable double buffering is available (such as SndPlayDoubleBuffer() - on the Macintosh.) - - streamFlags may contain a combination of flags ORed together. - These flags modify the behaviour of the streaming process. Some flags may only - be relevant to certain buffer formats. - - callback is a pointer to a client supplied function that is responsible - for processing and filling input and output buffers (see above for details.) - - userData is a client supplied pointer which is passed to the callback - function. It could for example, contain a pointer to instance data necessary - for processing the audio buffers. - - return value: - Upon success Pa_OpenStream() returns PaNoError and places a pointer to a - valid PortAudioStream in the stream argument. The stream is inactive (stopped). - If a call to Pa_OpenStream() fails a non-zero error code is returned (see - PaError above) and the value of stream is invalid. - -*/ - -PaError Pa_OpenStream( PortAudioStream** stream, - PaDeviceID inputDevice, - int numInputChannels, - PaSampleFormat inputSampleFormat, - void *inputDriverInfo, - PaDeviceID outputDevice, - int numOutputChannels, - PaSampleFormat outputSampleFormat, - void *outputDriverInfo, - double sampleRate, - unsigned long framesPerBuffer, - unsigned long numberOfBuffers, - PaStreamFlags streamFlags, - PortAudioCallback *callback, - void *userData ); - - -/* - Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that opens - the default input and/or output devices. Most parameters have identical meaning - to their Pa_OpenStream() counterparts, with the following exceptions: - - If either numInputChannels or numOutputChannels is 0 the respective device - is not opened. This has the same effect as passing paNoDevice in the device - arguments to Pa_OpenStream(). - - sampleFormat applies to both the input and output buffers. - -*/ - -PaError Pa_OpenDefaultStream( PortAudioStream** stream, - int numInputChannels, - int numOutputChannels, - PaSampleFormat sampleFormat, - double sampleRate, - unsigned long framesPerBuffer, - unsigned long numberOfBuffers, - PortAudioCallback *callback, - void *userData ); - -/* - Pa_CloseStream() closes an audio stream, flushing any pending buffers. - -*/ - -PaError Pa_CloseStream( PortAudioStream* ); - -/* - Pa_StartStream() and Pa_StopStream() begin and terminate audio processing. - Pa_StopStream() waits until all pending audio buffers have been played. - Pa_AbortStream() stops playing immediately without waiting for pending - buffers to complete. - -*/ - -PaError Pa_StartStream( PortAudioStream *stream ); - -PaError Pa_StopStream( PortAudioStream *stream ); - -PaError Pa_AbortStream( PortAudioStream *stream ); - -/* - Pa_StreamActive() returns one (1) when the stream is active (ie playing - or recording audio), zero (0) when not playing, or a negative error number - if the stream is invalid. - The stream is active between calls to Pa_StartStream() and Pa_StopStream(), - but may also become inactive if the callback returns a non-zero value. - In the latter case, the stream is considered inactive after the last - buffer has finished playing. - -*/ - -PaError Pa_StreamActive( PortAudioStream *stream ); - -/* - Pa_StreamTime() returns the current output time in samples for the stream. - This time may be used as a time reference (for example synchronizing audio to - MIDI). - -*/ - -PaTimestamp Pa_StreamTime( PortAudioStream *stream ); - -/* - Pa_GetCPULoad() returns the CPU Load for the stream. - The "CPU Load" is a fraction of total CPU time consumed by the stream's - audio processing routines including, but not limited to the client supplied - callback. - A value of 0.5 would imply that PortAudio and the sound generating - callback was consuming roughly 50% of the available CPU time. - This function may be called from the callback function or the application. - -*/ - -double Pa_GetCPULoad( PortAudioStream* stream ); - -/* - Pa_GetMinNumBuffers() returns the minimum number of buffers required by - the current host based on minimum latency. - On the PC, for the DirectSound implementation, latency can be optionally set - by user by setting an environment variable. - For example, to set latency to 200 msec, put: - - set PA_MIN_LATENCY_MSEC=200 - - in the AUTOEXEC.BAT file and reboot. - If the environment variable is not set, then the latency will be determined - based on the OS. Windows NT has higher latency than Win95. - -*/ - -int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate ); - -/* - Pa_Sleep() puts the caller to sleep for at least 'msec' milliseconds. - You may sleep longer than the requested time so don't rely on this for - accurate musical timing. - - Pa_Sleep() is provided as a convenience for authors of portable code (such as - the tests and examples in the PortAudio distribution.) - -*/ - -void Pa_Sleep( long msec ); - -/* - Pa_GetSampleSize() returns the size in bytes of a single sample in the - supplied PaSampleFormat, or paSampleFormatNotSupported if the format is - no supported. - -*/ - -PaError Pa_GetSampleSize( PaSampleFormat format ); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* PORT_AUDIO_H */ diff --git a/navit/support/espeak/portaudio18.h b/navit/support/espeak/portaudio18.h deleted file mode 100755 index 2ab8e02a4..000000000 --- a/navit/support/espeak/portaudio18.h +++ /dev/null @@ -1,466 +0,0 @@ -// NOTE: Copy this file to portaudio.h in order to compile with V18 portaudio - - -#ifndef PORT_AUDIO_H -#define PORT_AUDIO_H - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/* - * $Id: portaudio.h,v 1.5 2002/03/26 18:04:22 philburk Exp $ - * PortAudio Portable Real-Time Audio Library - * PortAudio API Header File - * Latest version available at: http://www.audiomulch.com/portaudio/ - * - * Copyright (c) 1999-2000 Ross Bencina and Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -typedef int PaError; -typedef enum { - paNoError = 0, - - paHostError = -10000, - paInvalidChannelCount, - paInvalidSampleRate, - paInvalidDeviceId, - paInvalidFlag, - paSampleFormatNotSupported, - paBadIODeviceCombination, - paInsufficientMemory, - paBufferTooBig, - paBufferTooSmall, - paNullCallback, - paBadStreamPtr, - paTimedOut, - paInternalError, - paDeviceUnavailable -} PaErrorNum; - -/* - Pa_Initialize() is the library initialisation function - call this before - using the library. - -*/ - -PaError Pa_Initialize( void ); - -/* - Pa_Terminate() is the library termination function - call this after - using the library. - -*/ - -PaError Pa_Terminate( void ); - -/* - Pa_GetHostError() returns a host specific error code. - This can be called after receiving a PortAudio error code of paHostError. - -*/ - -long Pa_GetHostError( void ); - -/* - Pa_GetErrorText() translates the supplied PortAudio error number - into a human readable message. - -*/ - -const char *Pa_GetErrorText( PaError errnum ); - -/* - Sample formats - - These are formats used to pass sound data between the callback and the - stream. Each device has a "native" format which may be used when optimum - efficiency or control over conversion is required. - - Formats marked "always available" are supported (emulated) by all - PortAudio implementations. - - The floating point representation (paFloat32) uses +1.0 and -1.0 as the - maximum and minimum respectively. - - paUInt8 is an unsigned 8 bit format where 128 is considered "ground" - -*/ - -typedef unsigned long PaSampleFormat; -#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/ -#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/ -#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/ -#define paInt24 ((PaSampleFormat) (1<<3)) -#define paPackedInt24 ((PaSampleFormat) (1<<4)) -#define paInt8 ((PaSampleFormat) (1<<5)) -#define paUInt8 ((PaSampleFormat) (1<<6)) -#define paCustomFormat ((PaSampleFormat) (1<<16)) - -/* - Device enumeration mechanism. - - Device ids range from 0 to Pa_CountDevices()-1. - - Devices may support input, output or both. - -*/ - -typedef int PaDeviceID; -#define paNoDevice -1 - -int Pa_CountDevices( void ); - -typedef struct -{ - int structVersion; - const char *name; - int maxInputChannels; - int maxOutputChannels; - /* Number of discrete rates, or -1 if range supported. */ - int numSampleRates; - /* Array of supported sample rates, or {min,max} if range supported. */ - const double *sampleRates; - PaSampleFormat nativeSampleFormats; -} -PaDeviceInfo; - -/* - Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID() return the - default device ids for input and output respectively, or paNoDevice if - no device is available. - The result can be passed to Pa_OpenStream(). - - On the PC, the user can specify a default device by - setting an environment variable. For example, to use device #1. - - set PA_RECOMMENDED_OUTPUT_DEVICE=1 - - The user should first determine the available device ids by using - the supplied application "pa_devs". - -*/ - -PaDeviceID Pa_GetDefaultInputDeviceID( void ); -PaDeviceID Pa_GetDefaultOutputDeviceID( void ); - - - -/* - Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure - for the device specified. - If the device parameter is out of range the function returns NULL. - - PortAudio manages the memory referenced by the returned pointer, the client - must not manipulate or free the memory. The pointer is only guaranteed to be - valid between calls to Pa_Initialize() and Pa_Terminate(). - -*/ - -const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID device ); - -/* - PaTimestamp is used to represent a continuous sample clock with arbitrary - start time that can be used for syncronization. The type is used for the - outTime argument to the PortAudioCallback and as the result of Pa_StreamTime() - -*/ - -typedef double PaTimestamp; - -/* - PortAudioCallback is implemented by PortAudio clients. - - inputBuffer and outputBuffer are arrays of interleaved samples, - the format, packing and number of channels used by the buffers are - determined by parameters to Pa_OpenStream() (see below). - - framesPerBuffer is the number of sample frames to be processed by the callback. - - outTime is the time in samples when the buffer(s) processed by - this callback will begin being played at the audio output. - See also Pa_StreamTime() - - userData is the value of a user supplied pointer passed to Pa_OpenStream() - intended for storing synthesis data etc. - - return value: - The callback can return a non-zero value to stop the stream. This may be - useful in applications such as soundfile players where a specific duration - of output is required. However, it is not necessary to utilise this mechanism - as StopStream() will also terminate the stream. A callback returning a - non-zero value must fill the entire outputBuffer. - - NOTE: None of the other stream functions may be called from within the - callback function except for Pa_GetCPULoad(). - -*/ - -typedef int (PortAudioCallback)( - void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, - PaTimestamp outTime, void *userData ); - - -/* - Stream flags - - These flags may be supplied (ored together) in the streamFlags argument to - the Pa_OpenStream() function. - -*/ - -#define paNoFlag (0) -#define paClipOff (1<<0) /* disable default clipping of out of range samples */ -#define paDitherOff (1<<1) /* disable default dithering */ -#define paPlatformSpecificFlags (0x00010000) -typedef unsigned long PaStreamFlags; - -/* - A single PortAudioStream provides multiple channels of real-time - input and output audio streaming to a client application. - Pointers to PortAudioStream objects are passed between PortAudio functions. -*/ - -typedef void PortAudioStream; -#define PaStream PortAudioStream - -/* - Pa_OpenStream() opens a stream for either input, output or both. - - stream is the address of a PortAudioStream pointer which will receive - a pointer to the newly opened stream. - - inputDevice is the id of the device used for input (see PaDeviceID above.) - inputDevice may be paNoDevice to indicate that an input device is not required. - - numInputChannels is the number of channels of sound to be delivered to the - callback. It can range from 1 to the value of maxInputChannels in the - PaDeviceInfo record for the device specified by the inputDevice parameter. - If inputDevice is paNoDevice numInputChannels is ignored. - - inputSampleFormat is the sample format of inputBuffer provided to the callback - function. inputSampleFormat may be any of the formats described by the - PaSampleFormat enumeration (see above). PortAudio guarantees support for - the device's native formats (nativeSampleFormats in the device info record) - and additionally 16 and 32 bit integer and 32 bit floating point formats. - Support for other formats is implementation defined. - - inputDriverInfo is a pointer to an optional driver specific data structure - containing additional information for device setup or stream processing. - inputDriverInfo is never required for correct operation. If not used - inputDriverInfo should be NULL. - - outputDevice is the id of the device used for output (see PaDeviceID above.) - outputDevice may be paNoDevice to indicate that an output device is not required. - - numOutputChannels is the number of channels of sound to be supplied by the - callback. See the definition of numInputChannels above for more details. - - outputSampleFormat is the sample format of the outputBuffer filled by the - callback function. See the definition of inputSampleFormat above for more - details. - - outputDriverInfo is a pointer to an optional driver specific data structure - containing additional information for device setup or stream processing. - outputDriverInfo is never required for correct operation. If not used - outputDriverInfo should be NULL. - - sampleRate is the desired sampleRate. For full-duplex streams it is the - sample rate for both input and output - - framesPerBuffer is the length in sample frames of all internal sample buffers - used for communication with platform specific audio routines. Wherever - possible this corresponds to the framesPerBuffer parameter passed to the - callback function. - - numberOfBuffers is the number of buffers used for multibuffered communication - with the platform specific audio routines. If you pass zero, then an optimum - value will be chosen for you internally. This parameter is provided only - as a guide - and does not imply that an implementation must use multibuffered - i/o when reliable double buffering is available (such as SndPlayDoubleBuffer() - on the Macintosh.) - - streamFlags may contain a combination of flags ORed together. - These flags modify the behaviour of the streaming process. Some flags may only - be relevant to certain buffer formats. - - callback is a pointer to a client supplied function that is responsible - for processing and filling input and output buffers (see above for details.) - - userData is a client supplied pointer which is passed to the callback - function. It could for example, contain a pointer to instance data necessary - for processing the audio buffers. - - return value: - Upon success Pa_OpenStream() returns PaNoError and places a pointer to a - valid PortAudioStream in the stream argument. The stream is inactive (stopped). - If a call to Pa_OpenStream() fails a non-zero error code is returned (see - PaError above) and the value of stream is invalid. - -*/ - -PaError Pa_OpenStream( PortAudioStream** stream, - PaDeviceID inputDevice, - int numInputChannels, - PaSampleFormat inputSampleFormat, - void *inputDriverInfo, - PaDeviceID outputDevice, - int numOutputChannels, - PaSampleFormat outputSampleFormat, - void *outputDriverInfo, - double sampleRate, - unsigned long framesPerBuffer, - unsigned long numberOfBuffers, - PaStreamFlags streamFlags, - PortAudioCallback *callback, - void *userData ); - - -/* - Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that opens - the default input and/or output devices. Most parameters have identical meaning - to their Pa_OpenStream() counterparts, with the following exceptions: - - If either numInputChannels or numOutputChannels is 0 the respective device - is not opened. This has the same effect as passing paNoDevice in the device - arguments to Pa_OpenStream(). - - sampleFormat applies to both the input and output buffers. - -*/ - -PaError Pa_OpenDefaultStream( PortAudioStream** stream, - int numInputChannels, - int numOutputChannels, - PaSampleFormat sampleFormat, - double sampleRate, - unsigned long framesPerBuffer, - unsigned long numberOfBuffers, - PortAudioCallback *callback, - void *userData ); - -/* - Pa_CloseStream() closes an audio stream, flushing any pending buffers. - -*/ - -PaError Pa_CloseStream( PortAudioStream* ); - -/* - Pa_StartStream() and Pa_StopStream() begin and terminate audio processing. - Pa_StopStream() waits until all pending audio buffers have been played. - Pa_AbortStream() stops playing immediately without waiting for pending - buffers to complete. - -*/ - -PaError Pa_StartStream( PortAudioStream *stream ); - -PaError Pa_StopStream( PortAudioStream *stream ); - -PaError Pa_AbortStream( PortAudioStream *stream ); - -/* - Pa_StreamActive() returns one (1) when the stream is active (ie playing - or recording audio), zero (0) when not playing, or a negative error number - if the stream is invalid. - The stream is active between calls to Pa_StartStream() and Pa_StopStream(), - but may also become inactive if the callback returns a non-zero value. - In the latter case, the stream is considered inactive after the last - buffer has finished playing. - -*/ - -PaError Pa_StreamActive( PortAudioStream *stream ); - -/* - Pa_StreamTime() returns the current output time in samples for the stream. - This time may be used as a time reference (for example synchronizing audio to - MIDI). - -*/ - -PaTimestamp Pa_StreamTime( PortAudioStream *stream ); - -/* - Pa_GetCPULoad() returns the CPU Load for the stream. - The "CPU Load" is a fraction of total CPU time consumed by the stream's - audio processing routines including, but not limited to the client supplied - callback. - A value of 0.5 would imply that PortAudio and the sound generating - callback was consuming roughly 50% of the available CPU time. - This function may be called from the callback function or the application. - -*/ - -double Pa_GetCPULoad( PortAudioStream* stream ); - -/* - Pa_GetMinNumBuffers() returns the minimum number of buffers required by - the current host based on minimum latency. - On the PC, for the DirectSound implementation, latency can be optionally set - by user by setting an environment variable. - For example, to set latency to 200 msec, put: - - set PA_MIN_LATENCY_MSEC=200 - - in the AUTOEXEC.BAT file and reboot. - If the environment variable is not set, then the latency will be determined - based on the OS. Windows NT has higher latency than Win95. - -*/ - -int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate ); - -/* - Pa_Sleep() puts the caller to sleep for at least 'msec' milliseconds. - You may sleep longer than the requested time so don't rely on this for - accurate musical timing. - - Pa_Sleep() is provided as a convenience for authors of portable code (such as - the tests and examples in the PortAudio distribution.) - -*/ - -void Pa_Sleep( long msec ); - -/* - Pa_GetSampleSize() returns the size in bytes of a single sample in the - supplied PaSampleFormat, or paSampleFormatNotSupported if the format is - no supported. - -*/ - -PaError Pa_GetSampleSize( PaSampleFormat format ); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* PORT_AUDIO_H */ diff --git a/navit/support/espeak/portaudio19.h b/navit/support/espeak/portaudio19.h deleted file mode 100644 index 5c060b711..000000000 --- a/navit/support/espeak/portaudio19.h +++ /dev/null @@ -1,1127 +0,0 @@ -// NOTE: Copy this file to portaudio.h in order to compile with V19 portaudio - -#ifndef PORTAUDIO_H -#define PORTAUDIO_H -/* - * $Id: portaudio.h 1061 2006-06-19 22:46:41Z lschwardt $ - * PortAudio Portable Real-Time Audio Library - * PortAudio API Header File - * Latest version available at: http://www.portaudio.com/ - * - * Copyright (c) 1999-2002 Ross Bencina and Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** @file - @brief The PortAudio API. -*/ - - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - - -/** Retrieve the release number of the currently running PortAudio build, - eg 1900. -*/ -int Pa_GetVersion( void ); - - -/** Retrieve a textual description of the current PortAudio build, - eg "PortAudio V19-devel 13 October 2002". -*/ -const char* Pa_GetVersionText( void ); - - -/** Error codes returned by PortAudio functions. - Note that with the exception of paNoError, all PaErrorCodes are negative. -*/ - -typedef int PaError; -typedef enum PaErrorCode -{ - paNoError = 0, - - paNotInitialized = -10000, - paUnanticipatedHostError, - paInvalidChannelCount, - paInvalidSampleRate, - paInvalidDevice, - paInvalidFlag, - paSampleFormatNotSupported, - paBadIODeviceCombination, - paInsufficientMemory, - paBufferTooBig, - paBufferTooSmall, - paNullCallback, - paBadStreamPtr, - paTimedOut, - paInternalError, - paDeviceUnavailable, - paIncompatibleHostApiSpecificStreamInfo, - paStreamIsStopped, - paStreamIsNotStopped, - paInputOverflowed, - paOutputUnderflowed, - paHostApiNotFound, - paInvalidHostApi, - paCanNotReadFromACallbackStream, /**< @todo review error code name */ - paCanNotWriteToACallbackStream, /**< @todo review error code name */ - paCanNotReadFromAnOutputOnlyStream, /**< @todo review error code name */ - paCanNotWriteToAnInputOnlyStream, /**< @todo review error code name */ - paIncompatibleStreamHostApi, - paBadBufferPtr -} PaErrorCode; - - -/** Translate the supplied PortAudio error code into a human readable - message. -*/ -const char *Pa_GetErrorText( PaError errorCode ); - - -/** Library initialization function - call this before using PortAudio. - This function initialises internal data structures and prepares underlying - host APIs for use. This function MUST be called before using any other - PortAudio API functions. - - If Pa_Initialize() is called multiple times, each successful - call must be matched with a corresponding call to Pa_Terminate(). - Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not - required to be fully nested. - - Note that if Pa_Initialize() returns an error code, Pa_Terminate() should - NOT be called. - - @return paNoError if successful, otherwise an error code indicating the cause - of failure. - - @see Pa_Terminate -*/ -PaError Pa_Initialize( void ); - - -/** Library termination function - call this when finished using PortAudio. - This function deallocates all resources allocated by PortAudio since it was - initializied by a call to Pa_Initialize(). In cases where Pa_Initialise() has - been called multiple times, each call must be matched with a corresponding call - to Pa_Terminate(). The final matching call to Pa_Terminate() will automatically - close any PortAudio streams that are still open. - - Pa_Terminate() MUST be called before exiting a program which uses PortAudio. - Failure to do so may result in serious resource leaks, such as audio devices - not being available until the next reboot. - - @return paNoError if successful, otherwise an error code indicating the cause - of failure. - - @see Pa_Initialize -*/ -PaError Pa_Terminate( void ); - - - -/** The type used to refer to audio devices. Values of this type usually - range from 0 to (Pa_DeviceCount-1), and may also take on the PaNoDevice - and paUseHostApiSpecificDeviceSpecification values. - - @see Pa_DeviceCount, paNoDevice, paUseHostApiSpecificDeviceSpecification -*/ -typedef int PaDeviceIndex; - - -/** A special PaDeviceIndex value indicating that no device is available, - or should be used. - - @see PaDeviceIndex -*/ -#define paNoDevice ((PaDeviceIndex)-1) - - -/** A special PaDeviceIndex value indicating that the device(s) to be used - are specified in the host api specific stream info structure. - - @see PaDeviceIndex -*/ -#define paUseHostApiSpecificDeviceSpecification ((PaDeviceIndex)-2) - - -/* Host API enumeration mechanism */ - -/** The type used to enumerate to host APIs at runtime. Values of this type - range from 0 to (Pa_GetHostApiCount()-1). - - @see Pa_GetHostApiCount -*/ -typedef int PaHostApiIndex; - - -/** Retrieve the number of available host APIs. Even if a host API is - available it may have no devices available. - - @return A non-negative value indicating the number of available host APIs - or, a PaErrorCode (which are always negative) if PortAudio is not initialized - or an error is encountered. - - @see PaHostApiIndex -*/ -PaHostApiIndex Pa_GetHostApiCount( void ); - - -/** Retrieve the index of the default host API. The default host API will be - the lowest common denominator host API on the current platform and is - unlikely to provide the best performance. - - @return A non-negative value ranging from 0 to (Pa_GetHostApiCount()-1) - indicating the default host API index or, a PaErrorCode (which are always - negative) if PortAudio is not initialized or an error is encountered. -*/ -PaHostApiIndex Pa_GetDefaultHostApi( void ); - - -/** Unchanging unique identifiers for each supported host API. This type - is used in the PaHostApiInfo structure. The values are guaranteed to be - unique and to never change, thus allowing code to be written that - conditionally uses host API specific extensions. - - New type ids will be allocated when support for a host API reaches - "public alpha" status, prior to that developers should use the - paInDevelopment type id. - - @see PaHostApiInfo -*/ -typedef enum PaHostApiTypeId -{ - paInDevelopment=0, /* use while developing support for a new host API */ - paDirectSound=1, - paMME=2, - paASIO=3, - paSoundManager=4, - paCoreAudio=5, - paOSS=7, - paALSA=8, - paAL=9, - paBeOS=10, - paWDMKS=11, - paJACK=12, - paWASAPI=13, - paAudioScienceHPI=14 -} PaHostApiTypeId; - - -/** A structure containing information about a particular host API. */ - -typedef struct PaHostApiInfo -{ - /** this is struct version 1 */ - int structVersion; - /** The well known unique identifier of this host API @see PaHostApiTypeId */ - PaHostApiTypeId type; - /** A textual description of the host API for display on user interfaces. */ - const char *name; - - /** The number of devices belonging to this host API. This field may be - used in conjunction with Pa_HostApiDeviceIndexToDeviceIndex() to enumerate - all devices for this host API. - @see Pa_HostApiDeviceIndexToDeviceIndex - */ - int deviceCount; - - /** The default input device for this host API. The value will be a - device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice - if no default input device is available. - */ - PaDeviceIndex defaultInputDevice; - - /** The default output device for this host API. The value will be a - device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice - if no default output device is available. - */ - PaDeviceIndex defaultOutputDevice; - -} PaHostApiInfo; - - -/** Retrieve a pointer to a structure containing information about a specific - host Api. - - @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1) - - @return A pointer to an immutable PaHostApiInfo structure describing - a specific host API. If the hostApi parameter is out of range or an error - is encountered, the function returns NULL. - - The returned structure is owned by the PortAudio implementation and must not - be manipulated or freed. The pointer is only guaranteed to be valid between - calls to Pa_Initialize() and Pa_Terminate(). -*/ -const PaHostApiInfo * Pa_GetHostApiInfo( PaHostApiIndex hostApi ); - - -/** Convert a static host API unique identifier, into a runtime - host API index. - - @param type A unique host API identifier belonging to the PaHostApiTypeId - enumeration. - - @return A valid PaHostApiIndex ranging from 0 to (Pa_GetHostApiCount()-1) or, - a PaErrorCode (which are always negative) if PortAudio is not initialized - or an error is encountered. - - The paHostApiNotFound error code indicates that the host API specified by the - type parameter is not available. - - @see PaHostApiTypeId -*/ -PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type ); - - -/** Convert a host-API-specific device index to standard PortAudio device index. - This function may be used in conjunction with the deviceCount field of - PaHostApiInfo to enumerate all devices for the specified host API. - - @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1) - - @param hostApiDeviceIndex A valid per-host device index in the range - 0 to (Pa_GetHostApiInfo(hostApi)->deviceCount-1) - - @return A non-negative PaDeviceIndex ranging from 0 to (Pa_GetDeviceCount()-1) - or, a PaErrorCode (which are always negative) if PortAudio is not initialized - or an error is encountered. - - A paInvalidHostApi error code indicates that the host API index specified by - the hostApi parameter is out of range. - - A paInvalidDevice error code indicates that the hostApiDeviceIndex parameter - is out of range. - - @see PaHostApiInfo -*/ -PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, - int hostApiDeviceIndex ); - - - -/** Structure used to return information about a host error condition. -*/ -typedef struct PaHostErrorInfo{ - PaHostApiTypeId hostApiType; /**< the host API which returned the error code */ - long errorCode; /**< the error code returned */ - const char *errorText; /**< a textual description of the error if available, otherwise a zero-length string */ -}PaHostErrorInfo; - - -/** Return information about the last host error encountered. The error - information returned by Pa_GetLastHostErrorInfo() will never be modified - asyncronously by errors occurring in other PortAudio owned threads - (such as the thread that manages the stream callback.) - - This function is provided as a last resort, primarily to enhance debugging - by providing clients with access to all available error information. - - @return A pointer to an immutable structure constaining information about - the host error. The values in this structure will only be valid if a - PortAudio function has previously returned the paUnanticipatedHostError - error code. -*/ -const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void ); - - - -/* Device enumeration and capabilities */ - -/** Retrieve the number of available devices. The number of available devices - may be zero. - - @return A non-negative value indicating the number of available devices or, - a PaErrorCode (which are always negative) if PortAudio is not initialized - or an error is encountered. -*/ -PaDeviceIndex Pa_GetDeviceCount( void ); - - -/** Retrieve the index of the default input device. The result can be - used in the inputDevice parameter to Pa_OpenStream(). - - @return The default input device index for the default host API, or paNoDevice - if no default input device is available or an error was encountered. -*/ -PaDeviceIndex Pa_GetDefaultInputDevice( void ); - - -/** Retrieve the index of the default output device. The result can be - used in the outputDevice parameter to Pa_OpenStream(). - - @return The default output device index for the defualt host API, or paNoDevice - if no default output device is available or an error was encountered. - - @note - On the PC, the user can specify a default device by - setting an environment variable. For example, to use device #1. -<pre> - set PA_RECOMMENDED_OUTPUT_DEVICE=1 -</pre> - The user should first determine the available device ids by using - the supplied application "pa_devs". -*/ -PaDeviceIndex Pa_GetDefaultOutputDevice( void ); - - -/** The type used to represent monotonic time in seconds that can be used - for syncronisation. The type is used for the outTime argument to the - PaStreamCallback and as the result of Pa_GetStreamTime(). - - @see PaStreamCallback, Pa_GetStreamTime -*/ -typedef double PaTime; - - -/** A type used to specify one or more sample formats. Each value indicates - a possible format for sound data passed to and from the stream callback, - Pa_ReadStream and Pa_WriteStream. - - The standard formats paFloat32, paInt16, paInt32, paInt24, paInt8 - and aUInt8 are usually implemented by all implementations. - - The floating point representation (paFloat32) uses +1.0 and -1.0 as the - maximum and minimum respectively. - - paUInt8 is an unsigned 8 bit format where 128 is considered "ground" - - The paNonInterleaved flag indicates that a multichannel buffer is passed - as a set of non-interleaved pointers. - - @see Pa_OpenStream, Pa_OpenDefaultStream, PaDeviceInfo - @see paFloat32, paInt16, paInt32, paInt24, paInt8 - @see paUInt8, paCustomFormat, paNonInterleaved -*/ -typedef unsigned long PaSampleFormat; - - -#define paFloat32 ((PaSampleFormat) 0x00000001) /**< @see PaSampleFormat */ -#define paInt32 ((PaSampleFormat) 0x00000002) /**< @see PaSampleFormat */ -#define paInt24 ((PaSampleFormat) 0x00000004) /**< Packed 24 bit format. @see PaSampleFormat */ -#define paInt16 ((PaSampleFormat) 0x00000008) /**< @see PaSampleFormat */ -#define paInt8 ((PaSampleFormat) 0x00000010) /**< @see PaSampleFormat */ -#define paUInt8 ((PaSampleFormat) 0x00000020) /**< @see PaSampleFormat */ -#define paCustomFormat ((PaSampleFormat) 0x00010000)/**< @see PaSampleFormat */ - -#define paNonInterleaved ((PaSampleFormat) 0x80000000) - -/** A structure providing information and capabilities of PortAudio devices. - Devices may support input, output or both input and output. -*/ -typedef struct PaDeviceInfo -{ - int structVersion; /* this is struct version 2 */ - const char *name; - PaHostApiIndex hostApi; /* note this is a host API index, not a type id*/ - - int maxInputChannels; - int maxOutputChannels; - - /* Default latency values for interactive performance. */ - PaTime defaultLowInputLatency; - PaTime defaultLowOutputLatency; - /* Default latency values for robust non-interactive applications (eg. playing sound files). */ - PaTime defaultHighInputLatency; - PaTime defaultHighOutputLatency; - - double defaultSampleRate; -} PaDeviceInfo; - - -/** Retrieve a pointer to a PaDeviceInfo structure containing information - about the specified device. - @return A pointer to an immutable PaDeviceInfo structure. If the device - parameter is out of range the function returns NULL. - - @param device A valid device index in the range 0 to (Pa_GetDeviceCount()-1) - - @note PortAudio manages the memory referenced by the returned pointer, - the client must not manipulate or free the memory. The pointer is only - guaranteed to be valid between calls to Pa_Initialize() and Pa_Terminate(). - - @see PaDeviceInfo, PaDeviceIndex -*/ -const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device ); - - -/** Parameters for one direction (input or output) of a stream. -*/ -typedef struct PaStreamParameters -{ - /** A valid device index in the range 0 to (Pa_GetDeviceCount()-1) - specifying the device to be used or the special constant - paUseHostApiSpecificDeviceSpecification which indicates that the actual - device(s) to use are specified in hostApiSpecificStreamInfo. - This field must not be set to paNoDevice. - */ - PaDeviceIndex device; - - /** The number of channels of sound to be delivered to the - stream callback or accessed by Pa_ReadStream() or Pa_WriteStream(). - It can range from 1 to the value of maxInputChannels in the - PaDeviceInfo record for the device specified by the device parameter. - */ - int channelCount; - - /** The sample format of the buffer provided to the stream callback, - a_ReadStream() or Pa_WriteStream(). It may be any of the formats described - by the PaSampleFormat enumeration. - */ - PaSampleFormat sampleFormat; - - /** The desired latency in seconds. Where practical, implementations should - configure their latency based on these parameters, otherwise they may - choose the closest viable latency instead. Unless the suggested latency - is greater than the absolute upper limit for the device implementations - should round the suggestedLatency up to the next practial value - ie to - provide an equal or higher latency than suggestedLatency wherever possibe. - Actual latency values for an open stream may be retrieved using the - inputLatency and outputLatency fields of the PaStreamInfo structure - returned by Pa_GetStreamInfo(). - @see default*Latency in PaDeviceInfo, *Latency in PaStreamInfo - */ - PaTime suggestedLatency; - - /** An optional pointer to a host api specific data structure - containing additional information for device setup and/or stream processing. - hostApiSpecificStreamInfo is never required for correct operation, - if not used it should be set to NULL. - */ - void *hostApiSpecificStreamInfo; - -} PaStreamParameters; - - -/** Return code for Pa_IsFormatSupported indicating success. */ -#define paFormatIsSupported (0) - -/** Determine whether it would be possible to open a stream with the specified - parameters. - - @param inputParameters A structure that describes the input parameters used to - open a stream. The suggestedLatency field is ignored. See PaStreamParameters - for a description of these parameters. inputParameters must be NULL for - output-only streams. - - @param outputParameters A structure that describes the output parameters used - to open a stream. The suggestedLatency field is ignored. See PaStreamParameters - for a description of these parameters. outputParameters must be NULL for - input-only streams. - - @param sampleRate The required sampleRate. For full-duplex streams it is the - sample rate for both input and output - - @return Returns 0 if the format is supported, and an error code indicating why - the format is not supported otherwise. The constant paFormatIsSupported is - provided to compare with the return value for success. - - @see paFormatIsSupported, PaStreamParameters -*/ -PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters, - const PaStreamParameters *outputParameters, - double sampleRate ); - - - -/* Streaming types and functions */ - - -/** - A single PaStream can provide multiple channels of real-time - streaming audio input and output to a client application. A stream - provides access to audio hardware represented by one or more - PaDevices. Depending on the underlying Host API, it may be possible - to open multiple streams using the same device, however this behavior - is implementation defined. Portable applications should assume that - a PaDevice may be simultaneously used by at most one PaStream. - - Pointers to PaStream objects are passed between PortAudio functions that - operate on streams. - - @see Pa_OpenStream, Pa_OpenDefaultStream, Pa_OpenDefaultStream, Pa_CloseStream, - Pa_StartStream, Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive, - Pa_GetStreamTime, Pa_GetStreamCpuLoad - -*/ -typedef void PaStream; - - -/** Can be passed as the framesPerBuffer parameter to Pa_OpenStream() - or Pa_OpenDefaultStream() to indicate that the stream callback will - accept buffers of any size. -*/ -#define paFramesPerBufferUnspecified (0) - - -/** Flags used to control the behavior of a stream. They are passed as - parameters to Pa_OpenStream or Pa_OpenDefaultStream. Multiple flags may be - ORed together. - - @see Pa_OpenStream, Pa_OpenDefaultStream - @see paNoFlag, paClipOff, paDitherOff, paNeverDropInput, - paPrimeOutputBuffersUsingStreamCallback, paPlatformSpecificFlags -*/ -typedef unsigned long PaStreamFlags; - -/** @see PaStreamFlags */ -#define paNoFlag ((PaStreamFlags) 0) - -/** Disable default clipping of out of range samples. - @see PaStreamFlags -*/ -#define paClipOff ((PaStreamFlags) 0x00000001) - -/** Disable default dithering. - @see PaStreamFlags -*/ -#define paDitherOff ((PaStreamFlags) 0x00000002) - -/** Flag requests that where possible a full duplex stream will not discard - overflowed input samples without calling the stream callback. This flag is - only valid for full duplex callback streams and only when used in combination - with the paFramesPerBufferUnspecified (0) framesPerBuffer parameter. Using - this flag incorrectly results in a paInvalidFlag error being returned from - Pa_OpenStream and Pa_OpenDefaultStream. - - @see PaStreamFlags, paFramesPerBufferUnspecified -*/ -#define paNeverDropInput ((PaStreamFlags) 0x00000004) - -/** Call the stream callback to fill initial output buffers, rather than the - default behavior of priming the buffers with zeros (silence). This flag has - no effect for input-only and blocking read/write streams. - - @see PaStreamFlags -*/ -#define paPrimeOutputBuffersUsingStreamCallback ((PaStreamFlags) 0x00000008) - -/** A mask specifying the platform specific bits. - @see PaStreamFlags -*/ -#define paPlatformSpecificFlags ((PaStreamFlags)0xFFFF0000) - -/** - Timing information for the buffers passed to the stream callback. -*/ -typedef struct PaStreamCallbackTimeInfo{ - PaTime inputBufferAdcTime; - PaTime currentTime; - PaTime outputBufferDacTime; -} PaStreamCallbackTimeInfo; - - -/** - Flag bit constants for the statusFlags to PaStreamCallback. - - @see paInputUnderflow, paInputOverflow, paOutputUnderflow, paOutputOverflow, - paPrimingOutput -*/ -typedef unsigned long PaStreamCallbackFlags; - -/** In a stream opened with paFramesPerBufferUnspecified, indicates that - input data is all silence (zeros) because no real data is available. In a - stream opened without paFramesPerBufferUnspecified, it indicates that one or - more zero samples have been inserted into the input buffer to compensate - for an input underflow. - @see PaStreamCallbackFlags -*/ -#define paInputUnderflow ((PaStreamCallbackFlags) 0x00000001) - -/** In a stream opened with paFramesPerBufferUnspecified, indicates that data - prior to the first sample of the input buffer was discarded due to an - overflow, possibly because the stream callback is using too much CPU time. - Otherwise indicates that data prior to one or more samples in the - input buffer was discarded. - @see PaStreamCallbackFlags -*/ -#define paInputOverflow ((PaStreamCallbackFlags) 0x00000002) - -/** Indicates that output data (or a gap) was inserted, possibly because the - stream callback is using too much CPU time. - @see PaStreamCallbackFlags -*/ -#define paOutputUnderflow ((PaStreamCallbackFlags) 0x00000004) - -/** Indicates that output data will be discarded because no room is available. - @see PaStreamCallbackFlags -*/ -#define paOutputOverflow ((PaStreamCallbackFlags) 0x00000008) - -/** Some of all of the output data will be used to prime the stream, input - data may be zero. - @see PaStreamCallbackFlags -*/ -#define paPrimingOutput ((PaStreamCallbackFlags) 0x00000010) - -/** - Allowable return values for the PaStreamCallback. - @see PaStreamCallback -*/ -typedef enum PaStreamCallbackResult -{ - paContinue=0, - paComplete=1, - paAbort=2 -} PaStreamCallbackResult; - - -/** - Functions of type PaStreamCallback are implemented by PortAudio clients. - They consume, process or generate audio in response to requests from an - active PortAudio stream. - - @param input and @param output are arrays of interleaved samples, - the format, packing and number of channels used by the buffers are - determined by parameters to Pa_OpenStream(). - - @param frameCount The number of sample frames to be processed by - the stream callback. - - @param timeInfo The time in seconds when the first sample of the input - buffer was received at the audio input, the time in seconds when the first - sample of the output buffer will begin being played at the audio output, and - the time in seconds when the stream callback was called. - See also Pa_GetStreamTime() - - @param statusFlags Flags indicating whether input and/or output buffers - have been inserted or will be dropped to overcome underflow or overflow - conditions. - - @param userData The value of a user supplied pointer passed to - Pa_OpenStream() intended for storing synthesis data etc. - - @return - The stream callback should return one of the values in the - PaStreamCallbackResult enumeration. To ensure that the callback continues - to be called, it should return paContinue (0). Either paComplete or paAbort - can be returned to finish stream processing, after either of these values is - returned the callback will not be called again. If paAbort is returned the - stream will finish as soon as possible. If paComplete is returned, the stream - will continue until all buffers generated by the callback have been played. - This may be useful in applications such as soundfile players where a specific - duration of output is required. However, it is not necessary to utilise this - mechanism as Pa_StopStream(), Pa_AbortStream() or Pa_CloseStream() can also - be used to stop the stream. The callback must always fill the entire output - buffer irrespective of its return value. - - @see Pa_OpenStream, Pa_OpenDefaultStream - - @note With the exception of Pa_GetStreamCpuLoad() it is not permissable to call - PortAudio API functions from within the stream callback. -*/ -typedef int PaStreamCallback( - const void *input, void *output, - unsigned long frameCount, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void *userData ); - - -/** Opens a stream for either input, output or both. - - @param stream The address of a PaStream pointer which will receive - a pointer to the newly opened stream. - - @param inputParameters A structure that describes the input parameters used by - the opened stream. See PaStreamParameters for a description of these parameters. - inputParameters must be NULL for output-only streams. - - @param outputParameters A structure that describes the output parameters used by - the opened stream. See PaStreamParameters for a description of these parameters. - outputParameters must be NULL for input-only streams. - - @param sampleRate The desired sampleRate. For full-duplex streams it is the - sample rate for both input and output - - @param framesPerBuffer The number of frames passed to the stream callback - function, or the preferred block granularity for a blocking read/write stream. - The special value paFramesPerBufferUnspecified (0) may be used to request that - the stream callback will recieve an optimal (and possibly varying) number of - frames based on host requirements and the requested latency settings. - Note: With some host APIs, the use of non-zero framesPerBuffer for a callback - stream may introduce an additional layer of buffering which could introduce - additional latency. PortAudio guarantees that the additional latency - will be kept to the theoretical minimum however, it is strongly recommended - that a non-zero framesPerBuffer value only be used when your algorithm - requires a fixed number of frames per stream callback. - - @param streamFlags Flags which modify the behaviour of the streaming process. - This parameter may contain a combination of flags ORed together. Some flags may - only be relevant to certain buffer formats. - - @param streamCallback A pointer to a client supplied function that is responsible - for processing and filling input and output buffers. If this parameter is NULL - the stream will be opened in 'blocking read/write' mode. In blocking mode, - the client can receive sample data using Pa_ReadStream and write sample data - using Pa_WriteStream, the number of samples that may be read or written - without blocking is returned by Pa_GetStreamReadAvailable and - Pa_GetStreamWriteAvailable respectively. - - @param userData A client supplied pointer which is passed to the stream callback - function. It could for example, contain a pointer to instance data necessary - for processing the audio buffers. This parameter is ignored if streamCallback - is NULL. - - @return - Upon success Pa_OpenStream() returns paNoError and places a pointer to a - valid PaStream in the stream argument. The stream is inactive (stopped). - If a call to Pa_OpenStream() fails, a non-zero error code is returned (see - PaError for possible error codes) and the value of stream is invalid. - - @see PaStreamParameters, PaStreamCallback, Pa_ReadStream, Pa_WriteStream, - Pa_GetStreamReadAvailable, Pa_GetStreamWriteAvailable -*/ -PaError Pa_OpenStream( PaStream** stream, - const PaStreamParameters *inputParameters, - const PaStreamParameters *outputParameters, - double sampleRate, - unsigned long framesPerBuffer, - PaStreamFlags streamFlags, - PaStreamCallback *streamCallback, - void *userData ); - - -/** A simplified version of Pa_OpenStream() that opens the default input - and/or output devices. - - @param stream The address of a PaStream pointer which will receive - a pointer to the newly opened stream. - - @param numInputChannels The number of channels of sound that will be supplied - to the stream callback or returned by Pa_ReadStream. It can range from 1 to - the value of maxInputChannels in the PaDeviceInfo record for the default input - device. If 0 the stream is opened as an output-only stream. - - @param numOutputChannels The number of channels of sound to be delivered to the - stream callback or passed to Pa_WriteStream. It can range from 1 to the value - of maxOutputChannels in the PaDeviceInfo record for the default output dvice. - If 0 the stream is opened as an output-only stream. - - @param sampleFormat The sample format of both the input and output buffers - provided to the callback or passed to and from Pa_ReadStream and Pa_WriteStream. - sampleFormat may be any of the formats described by the PaSampleFormat - enumeration. - - @param sampleRate Same as Pa_OpenStream parameter of the same name. - @param framesPerBuffer Same as Pa_OpenStream parameter of the same name. - @param streamCallback Same as Pa_OpenStream parameter of the same name. - @param userData Same as Pa_OpenStream parameter of the same name. - - @return As for Pa_OpenStream - - @see Pa_OpenStream, PaStreamCallback -*/ -PaError Pa_OpenDefaultStream( PaStream** stream, - int numInputChannels, - int numOutputChannels, - PaSampleFormat sampleFormat, - double sampleRate, - unsigned long framesPerBuffer, - PaStreamCallback *streamCallback, - void *userData ); - - -/** Closes an audio stream. If the audio stream is active it - discards any pending buffers as if Pa_AbortStream() had been called. -*/ -PaError Pa_CloseStream( PaStream *stream ); - - -/** Functions of type PaStreamFinishedCallback are implemented by PortAudio - clients. They can be registered with a stream using the Pa_SetStreamFinishedCallback - function. Once registered they are called when the stream becomes inactive - (ie once a call to Pa_StopStream() will not block). - A stream will become inactive after the stream callback returns non-zero, - or when Pa_StopStream or Pa_AbortStream is called. For a stream providing audio - output, if the stream callback returns paComplete, or Pa_StopStream is called, - the stream finished callback will not be called until all generated sample data - has been played. - - @param userData The userData parameter supplied to Pa_OpenStream() - - @see Pa_SetStreamFinishedCallback -*/ -typedef void PaStreamFinishedCallback( void *userData ); - - -/** Register a stream finished callback function which will be called when the - stream becomes inactive. See the description of PaStreamFinishedCallback for - further details about when the callback will be called. - - @param stream a pointer to a PaStream that is in the stopped state - if the - stream is not stopped, the stream's finished callback will remain unchanged - and an error code will be returned. - - @param streamFinishedCallback a pointer to a function with the same signature - as PaStreamFinishedCallback, that will be called when the stream becomes - inactive. Passing NULL for this parameter will un-register a previously - registered stream finished callback function. - - @return on success returns paNoError, otherwise an error code indicating the cause - of the error. - - @see PaStreamFinishedCallback -*/ -PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback ); - - -/** Commences audio processing. -*/ -PaError Pa_StartStream( PaStream *stream ); - - -/** Terminates audio processing. It waits until all pending - audio buffers have been played before it returns. -*/ -PaError Pa_StopStream( PaStream *stream ); - - -/** Terminates audio processing immediately without waiting for pending - buffers to complete. -*/ -PaError Pa_AbortStream( PaStream *stream ); - - -/** Determine whether the stream is stopped. - A stream is considered to be stopped prior to a successful call to - Pa_StartStream and after a successful call to Pa_StopStream or Pa_AbortStream. - If a stream callback returns a value other than paContinue the stream is NOT - considered to be stopped. - - @return Returns one (1) when the stream is stopped, zero (0) when - the stream is running or, a PaErrorCode (which are always negative) if - PortAudio is not initialized or an error is encountered. - - @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive -*/ -PaError Pa_IsStreamStopped( PaStream *stream ); - - -/** Determine whether the stream is active. - A stream is active after a successful call to Pa_StartStream(), until it - becomes inactive either as a result of a call to Pa_StopStream() or - Pa_AbortStream(), or as a result of a return value other than paContinue from - the stream callback. In the latter case, the stream is considered inactive - after the last buffer has finished playing. - - @return Returns one (1) when the stream is active (ie playing or recording - audio), zero (0) when not playing or, a PaErrorCode (which are always negative) - if PortAudio is not initialized or an error is encountered. - - @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamStopped -*/ -PaError Pa_IsStreamActive( PaStream *stream ); - - - -/** A structure containing unchanging information about an open stream. - @see Pa_GetStreamInfo -*/ - -typedef struct PaStreamInfo -{ - /** this is struct version 1 */ - int structVersion; - - /** The input latency of the stream in seconds. This value provides the most - accurate estimate of input latency available to the implementation. It may - differ significantly from the suggestedLatency value passed to Pa_OpenStream(). - The value of this field will be zero (0.) for output-only streams. - @see PaTime - */ - PaTime inputLatency; - - /** The output latency of the stream in seconds. This value provides the most - accurate estimate of output latency available to the implementation. It may - differ significantly from the suggestedLatency value passed to Pa_OpenStream(). - The value of this field will be zero (0.) for input-only streams. - @see PaTime - */ - PaTime outputLatency; - - /** The sample rate of the stream in Hertz (samples per second). In cases - where the hardware sample rate is inaccurate and PortAudio is aware of it, - the value of this field may be different from the sampleRate parameter - passed to Pa_OpenStream(). If information about the actual hardware sample - rate is not available, this field will have the same value as the sampleRate - parameter passed to Pa_OpenStream(). - */ - double sampleRate; - -} PaStreamInfo; - - -/** Retrieve a pointer to a PaStreamInfo structure containing information - about the specified stream. - @return A pointer to an immutable PaStreamInfo structure. If the stream - parameter invalid, or an error is encountered, the function returns NULL. - - @param stream A pointer to an open stream previously created with Pa_OpenStream. - - @note PortAudio manages the memory referenced by the returned pointer, - the client must not manipulate or free the memory. The pointer is only - guaranteed to be valid until the specified stream is closed. - - @see PaStreamInfo -*/ -const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream ); - - -/** Determine the current time for the stream according to the same clock used - to generate buffer timestamps. This time may be used for syncronising other - events to the audio stream, for example synchronizing audio to MIDI. - - @return The stream's current time in seconds, or 0 if an error occurred. - - @see PaTime, PaStreamCallback -*/ -PaTime Pa_GetStreamTime( PaStream *stream ); - - -/** Retrieve CPU usage information for the specified stream. - The "CPU Load" is a fraction of total CPU time consumed by a callback stream's - audio processing routines including, but not limited to the client supplied - stream callback. This function does not work with blocking read/write streams. - - This function may be called from the stream callback function or the - application. - - @return - A floating point value, typically between 0.0 and 1.0, where 1.0 indicates - that the stream callback is consuming the maximum number of CPU cycles possible - to maintain real-time operation. A value of 0.5 would imply that PortAudio and - the stream callback was consuming roughly 50% of the available CPU time. The - return value may exceed 1.0. A value of 0.0 will always be returned for a - blocking read/write stream, or if an error occurrs. -*/ -double Pa_GetStreamCpuLoad( PaStream* stream ); - - -/** Read samples from an input stream. The function doesn't return until - the entire buffer has been filled - this may involve waiting for the operating - system to supply the data. - - @param stream A pointer to an open stream previously created with Pa_OpenStream. - - @param buffer A pointer to a buffer of sample frames. The buffer contains - samples in the format specified by the inputParameters->sampleFormat field - used to open the stream, and the number of channels specified by - inputParameters->numChannels. If non-interleaved samples were requested, - buffer is a pointer to the first element of an array of non-interleaved - buffer pointers, one for each channel. - - @param frames The number of frames to be read into buffer. This parameter - is not constrained to a specific range, however high performance applications - will want to match this parameter to the framesPerBuffer parameter used - when opening the stream. - - @return On success PaNoError will be returned, or PaInputOverflowed if input - data was discarded by PortAudio after the previous call and before this call. -*/ -PaError Pa_ReadStream( PaStream* stream, - void *buffer, - unsigned long frames ); - - -/** Write samples to an output stream. This function doesn't return until the - entire buffer has been consumed - this may involve waiting for the operating - system to consume the data. - - @param stream A pointer to an open stream previously created with Pa_OpenStream. - - @param buffer A pointer to a buffer of sample frames. The buffer contains - samples in the format specified by the outputParameters->sampleFormat field - used to open the stream, and the number of channels specified by - outputParameters->numChannels. If non-interleaved samples were requested, - buffer is a pointer to the first element of an array of non-interleaved - buffer pointers, one for each channel. - - @param frames The number of frames to be written from buffer. This parameter - is not constrained to a specific range, however high performance applications - will want to match this parameter to the framesPerBuffer parameter used - when opening the stream. - - @return On success PaNoError will be returned, or paOutputUnderflowed if - additional output data was inserted after the previous call and before this - call. -*/ -PaError Pa_WriteStream( PaStream* stream, - const void *buffer, - unsigned long frames ); - - -/** Retrieve the number of frames that can be read from the stream without - waiting. - - @return Returns a non-negative value representing the maximum number of frames - that can be read from the stream without blocking or busy waiting or, a - PaErrorCode (which are always negative) if PortAudio is not initialized or an - error is encountered. -*/ -signed long Pa_GetStreamReadAvailable( PaStream* stream ); - - -/** Retrieve the number of frames that can be written to the stream without - waiting. - - @return Returns a non-negative value representing the maximum number of frames - that can be written to the stream without blocking or busy waiting or, a - PaErrorCode (which are always negative) if PortAudio is not initialized or an - error is encountered. -*/ -signed long Pa_GetStreamWriteAvailable( PaStream* stream ); - - -/* Miscellaneous utilities */ - - -/** Retrieve the size of a given sample format in bytes. - - @return The size in bytes of a single sample in the specified format, - or paSampleFormatNotSupported if the format is not supported. -*/ -PaError Pa_GetSampleSize( PaSampleFormat format ); - - -/** Put the caller to sleep for at least 'msec' milliseconds. This function is - provided only as a convenience for authors of portable code (such as the tests - and examples in the PortAudio distribution.) - - The function may sleep longer than requested so don't rely on this for accurate - musical timing. -*/ -void Pa_Sleep( long msec ); - - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* PORTAUDIO_H */ diff --git a/navit/support/espeak/readclause.c b/navit/support/espeak/readclause.c deleted file mode 100644 index b8d302a27..000000000 --- a/navit/support/espeak/readclause.c +++ /dev/null @@ -1,2440 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <wctype.h> -#include <wchar.h> -#include <math.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" - -#ifdef PLATFORM_POSIX -#include <unistd.h> -#endif - -#include <locale.h> -#define N_XML_BUF 256 - -#define double(x) ((double)(x)) -static const char *xmlbase = ""; // base URL from <speak> - -static int namedata_ix=0; -static int n_namedata = 0; -char *namedata = NULL; - - -static FILE *f_input = NULL; -static int ungot_char2 = 0; -unsigned char *p_textinput; -wchar_t *p_wchar_input; -static int ungot_char; -static const char *ungot_word = NULL; -static int end_of_input; - -static int ignore_text=0; // set during <sub> ... </sub> to ignore text which has been replaced by an alias -static int clear_skipping_text = 0; // next clause should clear the skipping_text flag -int count_characters = 0; -static int sayas_mode; -static int ssml_ignore_l_angle = 0; - -static const char *punct_stop = ".:!?"; // pitch fall if followed by space -static const char *punct_close = ")]}>;'\""; // always pitch fall unless followed by alnum - -// alter tone for announce punctuation or capitals -static const char *tone_punct_on = "\0016T"; // add reverberation, lower pitch -static const char *tone_punct_off = "\001T"; - -// punctuations symbols that can end a clause -static const unsigned short punct_chars[] = {',','.','?','!',':',';', - 0x2013, // en-dash - 0x2014, // em-dash - 0x2026, // elipsis - - 0x037e, // Greek question mark (looks like semicolon) - 0x0387, // Greek semicolon, ano teleia - 0x0964, // Devanagari Danda (fullstop) - - 0x0589, // Armenian period - 0x055d, // Armenian comma - 0x055c, // Armenian exclamation - 0x055e, // Armenian question - 0x055b, // Armenian emphasis mark - - 0x1362, // Ethiopic period - 0x1363, - 0x1364, - 0x1365, - 0x1366, - 0x1367, - 0x1368, - - 0x3001, // ideograph comma - 0x3002, // ideograph period - - 0xff01, // fullwidth exclamation - 0xff0c, // fullwidth comma - 0xff0e, // fullwidth period - 0xff1a, // fullwidth colon - 0xff1b, // fullwidth semicolon - 0xff1f, // fullwidth question mark - - 0}; - - -// indexed by (entry num. in punct_chars) + 1 -// bits 0-7 pause x 10mS, bits 12-14 intonation type, bit 15 don't need following space or bracket -static const unsigned int punct_attributes [] = { 0, - CLAUSE_COMMA, CLAUSE_PERIOD, CLAUSE_QUESTION, CLAUSE_EXCLAMATION, CLAUSE_COLON, CLAUSE_SEMICOLON, - CLAUSE_SEMICOLON, // en-dash - CLAUSE_SEMICOLON, // em-dash - CLAUSE_SEMICOLON, // elipsis - - CLAUSE_QUESTION, // Greek question mark - CLAUSE_SEMICOLON, // Greek semicolon - CLAUSE_PERIOD+0x8000, // Devanagari Danda (fullstop) - - CLAUSE_PERIOD+0x8000, // Armenian period - CLAUSE_COMMA, // Armenian comma - CLAUSE_EXCLAMATION + PUNCT_IN_WORD, // Armenian exclamation - CLAUSE_QUESTION + PUNCT_IN_WORD, // Armenian question - CLAUSE_PERIOD + PUNCT_IN_WORD, // Armenian emphasis mark - - CLAUSE_PERIOD, // Ethiopic period - CLAUSE_COMMA, // Ethiopic comma - CLAUSE_SEMICOLON, // Ethiopic semicolon - CLAUSE_COLON, // Ethiopic colon - CLAUSE_COLON, // Ethiopic preface colon - CLAUSE_QUESTION, // Ethiopic question mark - CLAUSE_PERIOD, // Ethiopic paragraph - - CLAUSE_COMMA+0x8000, // ideograph comma - CLAUSE_PERIOD+0x8000, // ideograph period - - CLAUSE_EXCLAMATION+0x8000, // fullwidth - CLAUSE_COMMA+0x8000, - CLAUSE_PERIOD+0x8000, - CLAUSE_COLON+0x8000, - CLAUSE_SEMICOLON+0x8000, - CLAUSE_QUESTION+0x8000, - - CLAUSE_SEMICOLON, // spare - 0 }; - - -// stack for language and voice properties -// frame 0 is for the defaults, before any ssml tags. -typedef struct { - int tag_type; - int voice_variant; - int voice_gender; - int voice_age; - char voice_name[40]; - char language[20]; -} SSML_STACK; - -#define N_SSML_STACK 20 -static int n_ssml_stack; -static SSML_STACK ssml_stack[N_SSML_STACK]; - -static char current_voice_id[40] = {0}; - - -#define N_PARAM_STACK 20 -static int n_param_stack; -PARAM_STACK param_stack[N_PARAM_STACK]; - -static int speech_parameters[N_SPEECH_PARAM]; // current values, from param_stack - -const int param_defaults[N_SPEECH_PARAM] = { - 0, // silence (internal use) - 170, // rate wpm - 100, // volume - 50, // pitch - 50, // range - 0, // punctuation - 0, // capital letters - 0, // wordgap - 0, // options - 0, // intonation - 0, - 0, - 0, // emphasis - 0, // line length - 0, // voice type -}; - - -#ifdef NEED_WCHAR_FUNCTIONS - -// additional Latin characters beyond the Latin1 character set -#define MAX_WALPHA 0x233 -// indexed by character - 0x100 -// 0=not alphabetic, 0xff=lower case, other=value to add to upper case to convert to lower case -static unsigned char walpha_tab[MAX_WALPHA-0xff] = { - 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 100 - 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 110 - 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 120 - 0xff,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, 1, // 130 - 0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, // 140 - 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 150 - 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 160 - 1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, // 170 - 0xff, 210, 1,0xff, 1,0xff, 206, 1,0xff, 205, 205, 1,0xff,0xff, 79, 202, // 180 - 203, 1,0xff, 205, 207,0xff, 211, 209, 1,0xff,0xff,0xff, 211, 213,0xff, 214, // 190 - 1,0xff, 1,0xff, 1,0xff, 218, 1,0xff, 218,0xff,0xff, 1,0xff, 218, 1, // 1a0 - 0xff, 217, 217, 1,0xff, 1,0xff, 219, 1,0xff,0xff,0xff, 1,0xff,0xff,0xff, // 1b0 - 0xff,0xff,0xff,0xff, 2, 1,0xff, 2, 1,0xff, 2, 1,0xff, 1,0xff, 1, // 1c0 - 0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, // 1d0 - 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 1e0 - 0xff, 2, 1,0xff, 1,0xff,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 1f0 - 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 200 - 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 210 - 0xff, 0, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 220 - 1,0xff, 1,0xff }; // 230 - -// use ctype.h functions for Latin1 (character < 0x100) -int iswalpha(int c) -{ - if(c < 0x100) - return(isalpha(c)); - if((c > 0x3040) && (c <= 0xa700)) - return(1); // japanese, chinese characters - if(c > MAX_WALPHA) - return(0); - return(walpha_tab[c-0x100]); -} - -int iswdigit(int c) -{ - if(c < 0x100) - return(isdigit(c)); - return(0); -} - -int iswalnum(int c) -{ - if(iswdigit(c)) - return(1); - return(iswalpha(c)); -} - -int towlower(int c) -{ - int x; - if(c < 0x100) - return(tolower(c)); - if((c > MAX_WALPHA) || ((x = walpha_tab[c-0x100])==0xff)) - return(c); // already lower case - return(c + x); // convert to lower case -} - -int towupper(int c) -{ - // check whether the previous character code is the upper-case equivalent of this character - if(tolower(c-1) == c) - return(c-1); // yes, use it - return(c); // no -} - -int iswupper(int c) -{ - int x; - if(c < 0x100) - return(isupper(c)); - if(((c > MAX_WALPHA) || (x = walpha_tab[c-0x100])==0) || (x == 0xff)) - return(0); - return(1); -} - -int iswlower(int c) -{ - if(c < 0x100) - return(islower(c)); - if((c > MAX_WALPHA) || (walpha_tab[c-0x100] != 0xff)) - return(0); - return(1); -} - -int iswspace(int c) -{ - if(c < 0x100) - return(isspace(c)); - return(0); -} - -int iswpunct(int c) -{ - if(c < 0x100) - return(ispunct(c)); - return(0); -} - -const wchar_t *wcschr(const wchar_t *str, int c) -{ - while(*str != 0) - { - if(*str == c) - return(str); - str++; - } - return(NULL); -} - -#ifndef WINCE -// wcslen() is provided by WINCE, but not the other wchar functions -const int wcslen(const wchar_t *str) -{ - int ix=0; - - while(*str != 0) - { - ix++; - } - return(ix); -} -#endif - -float wcstod(const wchar_t *str, wchar_t **tailptr) -{ - int ix; - char buf[80]; - while(isspace(*str)) str++; - for(ix=0; ix<80; ix++) - { - buf[ix] = str[ix]; - if(isspace(buf[ix])) - break; - } - *tailptr = (wchar_t *)&str[ix]; - return(atof(buf)); -} -#endif - -int towlower2(unsigned int c) -{ - // check for non-standard upper to lower case conversions - if(c == 'I') - { - if(translator->translator_name == L('t','r')) - { - c = 0x131; // I -> ı - } - } - return(towlower(c)); -} - -static void GetC_unget(int c) -{//========================== -// This is only called with UTF8 input, not wchar input - if(f_input != NULL) - ungetc(c,f_input); - else - { - p_textinput--; - *p_textinput = c; - end_of_input = 0; - } -} - -int Eof(void) -{//========== - if(ungot_char != 0) - return(0); - - if(f_input != 0) - return(feof(f_input)); - - return(end_of_input); -} - - -static int GetC_get(void) -{//====================== - unsigned int c; - unsigned int c2; - - if(f_input != NULL) - { - c = fgetc(f_input); - if(feof(f_input)) c = ' '; - - if(option_multibyte == espeakCHARS_16BIT) - { - c2 = fgetc(f_input); - if(feof(f_input)) c2 = 0; - c = c + (c2 << 8); - } - return(c); - } - - if(option_multibyte == espeakCHARS_WCHAR) - { - if(*p_wchar_input == 0) - { - end_of_input = 1; - return(0); - } - - if(!end_of_input) - return(*p_wchar_input++); - } - else - { - if(*p_textinput == 0) - { - end_of_input = 1; - return(0); - } - - if(!end_of_input) - { - if(option_multibyte == espeakCHARS_16BIT) - { - c = p_textinput[0] + (p_textinput[1] << 8); - p_textinput += 2; - return(c); - } - return(*p_textinput++ & 0xff); - } - } - return(0); -} - - -static int GetC(void) -{//================== -// Returns a unicode wide character -// Performs UTF8 checking and conversion - - int c; - int c1; - int c2; - int cbuf[4]; - int ix; - int n_bytes; - unsigned char m; - static int ungot2 = 0; - static const unsigned char mask[4] = {0xff,0x1f,0x0f,0x07}; - static const unsigned char mask2[4] = {0,0x80,0x20,0x30}; - - if((c1 = ungot_char) != 0) - { - ungot_char = 0; - return(c1); - } - - if(ungot2 != 0) - { - c1 = ungot2; - ungot2 = 0; - } - else - { - c1 = GetC_get(); - } - - if((option_multibyte == espeakCHARS_WCHAR) || (option_multibyte == espeakCHARS_16BIT)) - { - count_characters++; - return(c1); // wchar_t text - } - - if((option_multibyte < 2) && (c1 & 0x80)) - { - // multi-byte utf8 encoding, convert to unicode - n_bytes = 0; - - if(((c1 & 0xe0) == 0xc0) && ((c1 & 0x1e) != 0)) - n_bytes = 1; - else - if((c1 & 0xf0) == 0xe0) - n_bytes = 2; - else - if(((c1 & 0xf8) == 0xf0) && ((c1 & 0x0f) <= 4)) - n_bytes = 3; - - if((ix = n_bytes) > 0) - { - c = c1 & mask[ix]; - m = mask2[ix]; - while(ix > 0) - { - if((c2 = cbuf[ix] = GetC_get()) == 0) - { - if(option_multibyte==espeakCHARS_AUTO) - option_multibyte=espeakCHARS_8BIT; // change "auto" option to "no" - GetC_unget(' '); - break; - } - - if((c2 & 0xc0) != 0x80) - { - // This is not UTF8. Change to 8-bit characterset. - if((n_bytes == 2) && (ix == 1)) - ungot2 = cbuf[2]; - GetC_unget(c2); - break; - } - m = 0x80; - c = (c << 6) + (c2 & 0x3f); - ix--; - } - if(ix == 0) - { - count_characters++; - return(c); - } - } - // top-bit-set character is not utf8, drop through to 8bit charset case - if((option_multibyte==espeakCHARS_AUTO) && !Eof()) - option_multibyte=espeakCHARS_8BIT; // change "auto" option to "no" - } - - // 8 bit character set, convert to unicode if - count_characters++; - if(c1 >= 0xa0) - return(translator->charset_a0[c1-0xa0]); - return(c1); -} // end of GetC - - -static void UngetC(int c) -{//====================== - ungot_char = c; -} - - -static const char *WordToString2(unsigned int word) -{//================================================ -// Convert a language mnemonic word into a string - int ix; - static char buf[5]; - char *p; - - p = buf; - for(ix=3; ix>=0; ix--) - { - if((*p = word >> (ix*8)) != 0) - p++; - } - *p = 0; - return(buf); -} - - -static const char *LookupSpecial(Translator *tr, const char *string, char* text_out) -{//================================================================================= - unsigned int flags[2]; - char phonemes[55]; - char phonemes2[55]; - char *string1 = (char *)string; - - if(LookupDictList(tr,&string1,phonemes,flags,0,NULL)) - { - SetWordStress(tr, phonemes, &flags[0], -1, 0); - DecodePhonemes(phonemes,phonemes2); - sprintf(text_out,"[[%s]]",phonemes2); - option_phoneme_input |= 2; - return(text_out); - } - return(NULL); -} - - -static const char *LookupCharName(Translator *tr, int c) -{//===================================================== -// Find the phoneme string (in ascii) to speak the name of character c -// Used for punctuation characters and symbols - - int ix; - unsigned int flags[2]; - char single_letter[24]; - char phonemes[60]; - char phonemes2[60]; - const char *lang_name = NULL; - char *string; - static char buf[60]; - - buf[0] = 0; - flags[0] = 0; - flags[1] = 0; - single_letter[0] = 0; - single_letter[1] = '_'; - ix = utf8_out(c,&single_letter[2]); - single_letter[2+ix]=0; - - string = &single_letter[1]; - if(LookupDictList(tr, &string, phonemes, flags, 0, NULL) == 0) - { - // try _* then * - string = &single_letter[2]; - if(LookupDictList(tr, &string, phonemes, flags, 0, NULL) == 0) - { - // now try the rules - single_letter[1] = ' '; - TranslateRules(tr, &single_letter[2], phonemes, sizeof(phonemes), NULL,0,NULL); - } - } - - if((phonemes[0] == 0) && (tr->translator_name != L('e','n'))) - { - // not found, try English - SetTranslator2("en"); - string = &single_letter[1]; - single_letter[1] = '_'; - if(LookupDictList(translator2, &string, phonemes, flags, 0, NULL) == 0) - { - string = &single_letter[2]; - LookupDictList(translator2, &string, phonemes, flags, 0, NULL); - } - if(phonemes[0]) - { - lang_name = "en"; - } - else - { - SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table - } - } - - if(phonemes[0]) - { - if(lang_name) - { - SetWordStress(translator2, phonemes, &flags[0], -1, 0); - DecodePhonemes(phonemes,phonemes2); - sprintf(buf,"[[_^_%s %s _^_%s]]","en",phonemes2,WordToString2(tr->translator_name)); - SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table - } - else - { - SetWordStress(tr, phonemes, &flags[0], -1, 0); - DecodePhonemes(phonemes,phonemes2); - sprintf(buf,"[[%s]] ",phonemes2); - } - option_phoneme_input |= 2; - } - else - { - strcpy(buf,"[[(X1)(X1)(X1)]]"); - option_phoneme_input |= 2; - } - - return(buf); -} - -int Read4Bytes(FILE *f) -{//==================== -// Read 4 bytes (least significant first) into a word - int ix; - unsigned char c; - int acc=0; - - for(ix=0; ix<4; ix++) - { - c = fgetc(f) & 0xff; - acc += (c << (ix*8)); - } - return(acc); -} - - -static int LoadSoundFile(const char *fname, int index) -{//=================================================== - FILE *f; - char *p; - int *ip; - int length; - char fname_temp[100]; - char fname2[sizeof(path_home)+13+40]; - - if(fname == NULL) - { - // filename is already in the table - fname = soundicon_tab[index].filename; - } - - if(fname==NULL) - return(1); - - if(fname[0] != '/') - { - // a relative path, look in espeak-data/soundicons - sprintf(fname2,"%s%csoundicons%c%s",path_home,PATHSEP,PATHSEP,fname); - fname = fname2; - } - - f = NULL; -#ifdef PLATFORM_POSIX - if((f = fopen(fname,"rb")) != NULL) - { - int ix; - int fd_temp; - const char *resample; - int header[3]; - char command[sizeof(fname2)+sizeof(fname2)+40]; - - fseek(f,20,SEEK_SET); - for(ix=0; ix<3; ix++) - header[ix] = Read4Bytes(f); - - // if the sound file is not mono, 16 bit signed, at the correct sample rate, then convert it - if((header[0] != 0x10001) || (header[1] != samplerate) || (header[2] != samplerate*2)) - { - fclose(f); - f = NULL; - - if(header[2] == samplerate) - resample = ""; - else - resample = "polyphase"; - - strcpy(fname_temp,"/tmp/espeakXXXXXX"); - if((fd_temp = mkstemp(fname_temp)) >= 0) - { - close(fd_temp); -// sprintf(fname_temp,"%s.wav",tmpnam(NULL)); - sprintf(command,"sox \"%s\" -r %d -w -s -c1 %s %s\n", fname, samplerate, fname_temp, resample); - if(system(command) == 0) - { - fname = fname_temp; - } - } - } - } -#endif - - if(f == NULL) - { - f = fopen(fname,"rb"); - if(f == NULL) - { - fprintf(stderr,"Can't read temp file: %s\n",fname); - return(3); - } - } - - length = GetFileLength(fname); - fseek(f,0,SEEK_SET); - if((p = (char *)realloc(soundicon_tab[index].data, length)) == NULL) - { - fclose(f); - return(4); - } - fread(p,length,1,f); - fclose(f); -#if 0 - remove(fname_temp); -#endif - - ip = (int *)(&p[40]); - soundicon_tab[index].length = (*ip) / 2; // length in samples - soundicon_tab[index].data = p; - return(0); -} // end of LoadSoundFile - - -static int LookupSoundicon(int c) -{//============================== -// Find the sound icon number for a punctuation chatacter - int ix; - - for(ix=N_SOUNDICON_SLOTS; ix<n_soundicon_tab; ix++) - { - if(soundicon_tab[ix].name == c) - { - if(soundicon_tab[ix].length == 0) - { - if(LoadSoundFile(NULL,ix)!=0) - return(-1); // sound file is not available - } - return(ix); - } - } - return(-1); -} - - -static int LoadSoundFile2(const char *fname) -{//========================================= -// Load a sound file into one of the reserved slots in the sound icon table -// (if it'snot already loaded) - - int ix; - static int slot = -1; - - for(ix=0; ix<n_soundicon_tab; ix++) - { - if(((soundicon_tab[ix].filename != NULL) && strcmp(fname, soundicon_tab[ix].filename) == 0)) - return(ix); // already loaded - } - - // load the file into the next slot - slot++; - if(slot >= N_SOUNDICON_SLOTS) - slot = 0; - - if(LoadSoundFile(fname, slot) != 0) - return(-1); - - soundicon_tab[slot].filename = (char *)realloc(soundicon_tab[ix].filename, strlen(fname)+1); - strcpy(soundicon_tab[slot].filename, fname); - return(slot); -} - - - -static int AnnouncePunctuation(Translator *tr, int c1, int c2, char *buf, int bufix) -{//================================================================================= - // announce punctuation names - // c1: the punctuation character - // c2: the following character - - int punct_count; - const char *punctname; - int found = 0; - int soundicon; - char *p; - - if((soundicon = LookupSoundicon(c1)) >= 0) - { - // add an embedded command to play the soundicon - sprintf(&buf[bufix],"\001%dI ",soundicon); - UngetC(c2); - found = 1; - } - else - if((punctname = LookupCharName(tr, c1)) != NULL) - { - found = 1; - if(bufix==0) - { - punct_count=1; - while(c2 == c1) - { - punct_count++; - c2 = GetC(); - } - UngetC(c2); - - p = &buf[bufix]; - if(punct_count==1) - { - sprintf(p,"%s %s %s",tone_punct_on,punctname,tone_punct_off); - } - else - if(punct_count < 4) - { - sprintf(p,"\001+10S%s",tone_punct_on); - while(punct_count-- > 0) - sprintf(buf,"%s %s",buf,punctname); - sprintf(p,"%s %s\001-10S",buf,tone_punct_off); - } - else - { - sprintf(p,"%s %s %d %s %s", - tone_punct_on,punctname,punct_count,punctname,tone_punct_off); - return(CLAUSE_COMMA); - } - } - else - { - // end the clause now and pick up the punctuation next time - UngetC(c2); - if(option_ssml) - { - if((c1 == '<') || (c1 == '&')) - ssml_ignore_l_angle = c1; // this was < which was converted to <, don't pick it up again as < - } - ungot_char2 = c1; - buf[bufix] = ' '; - buf[bufix+1] = 0; - } - } - - if(found == 0) - return(-1); - - if(c1 == '-') - return(CLAUSE_NONE); // no pause - if(bufix > 0) - return(CLAUSE_SHORTCOMMA); - if((strchr_w(punct_close,c1) != NULL) && !iswalnum(c2)) - return(CLAUSE_SHORTFALL+4); - if(iswspace(c2) && strchr_w(punct_stop,c1)!=NULL) - return(punct_attributes[lookupwchar(punct_chars,c1)]); - - return(CLAUSE_SHORTCOMMA); -} // end of AnnouncePunctuation - -#define SSML_SPEAK 1 -#define SSML_VOICE 2 -#define SSML_PROSODY 3 -#define SSML_SAYAS 4 -#define SSML_MARK 5 -#define SSML_SENTENCE 6 -#define SSML_PARAGRAPH 7 -#define SSML_PHONEME 8 -#define SSML_SUB 9 -#define SSML_STYLE 10 -#define SSML_AUDIO 11 -#define SSML_EMPHASIS 12 -#define SSML_BREAK 13 -#define SSML_IGNORE_TEXT 14 -#define HTML_BREAK 15 -#define SSML_CLOSE 0x10 // for a closing tag, OR this with the tag type - -// these tags have no effect if they are self-closing, eg. <voice /> -static char ignore_if_self_closing[] = {0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,0,0}; - - -static MNEM_TAB ssmltags[] = { - {"speak", SSML_SPEAK}, - {"voice", SSML_VOICE}, - {"prosody", SSML_PROSODY}, - {"say-as", SSML_SAYAS}, - {"mark", SSML_MARK}, - {"s", SSML_SENTENCE}, - {"p", SSML_PARAGRAPH}, - {"phoneme", SSML_PHONEME}, - {"sub", SSML_SUB}, - {"tts:style", SSML_STYLE}, - {"audio", SSML_AUDIO}, - {"emphasis", SSML_EMPHASIS}, - {"break", SSML_BREAK}, - {"metadata", SSML_IGNORE_TEXT}, - - {"br", HTML_BREAK}, - {"li", HTML_BREAK}, - {"img", HTML_BREAK}, - {"td", HTML_BREAK}, - {"h1", SSML_PARAGRAPH}, - {"h2", SSML_PARAGRAPH}, - {"h3", SSML_PARAGRAPH}, - {"h4", SSML_PARAGRAPH}, - {"hr", SSML_PARAGRAPH}, - {"script", SSML_IGNORE_TEXT}, - {"style", SSML_IGNORE_TEXT}, - {NULL,0}}; - - - - -static const char *VoiceFromStack() -{//================================ -// Use the voice properties from the SSML stack to choose a voice, and switch -// to that voice if it's not the current voice - int ix; - SSML_STACK *sp; - const char *v_id; - int voice_name_specified; - int voice_found; - espeak_VOICE voice_select; - char voice_name[40]; - char language[40]; - - strcpy(voice_name,ssml_stack[0].voice_name); - strcpy(language,ssml_stack[0].language); - voice_select.age = ssml_stack[0].voice_age; - voice_select.gender = ssml_stack[0].voice_gender; - voice_select.variant = ssml_stack[0].voice_variant; - voice_select.identifier = NULL; - - for(ix=0; ix<n_ssml_stack; ix++) - { - sp = &ssml_stack[ix]; - voice_name_specified = 0; - - if((sp->voice_name[0] != 0) && (SelectVoiceByName(NULL,sp->voice_name) != NULL)) - { - voice_name_specified = 1; - strcpy(voice_name, sp->voice_name); - language[0] = 0; - voice_select.gender = 0; - voice_select.age = 0; - voice_select.variant = 0; - } - if(sp->language[0] != 0) - { - strcpy(language, sp->language); - if(voice_name_specified == 0) - voice_name[0] = 0; // forget a previous voice name if a language is specified - } - if(sp->voice_gender != 0) - voice_select.gender = sp->voice_gender; - if(sp->voice_age != 0) - voice_select.age = sp->voice_age; - if(sp->voice_variant != 0) - voice_select.variant = sp->voice_variant; - } - - voice_select.name = voice_name; - voice_select.languages = language; - v_id = SelectVoice(&voice_select, &voice_found); - if(v_id == NULL) - return("default"); - return(v_id); -} // end of VoiceFromStack - - - -static void ProcessParamStack(char *outbuf, int *outix) -{//==================================================== -// Set the speech parameters from the parameter stack - int param; - int ix; - int value; - char buf[20]; - int new_parameters[N_SPEECH_PARAM]; - static char cmd_letter[N_SPEECH_PARAM] = {0, 'S','A','P','R', 0, 0, 0, 0, 0, 0, 0, 'F'}; // embedded command letters - - - for(param=0; param<N_SPEECH_PARAM; param++) - new_parameters[param] = -1; - - for(ix=0; ix<n_param_stack; ix++) - { - for(param=0; param<N_SPEECH_PARAM; param++) - { - if(param_stack[ix].parameter[param] >= 0) - new_parameters[param] = param_stack[ix].parameter[param]; - } - } - - for(param=0; param<N_SPEECH_PARAM; param++) - { - if((value = new_parameters[param]) != speech_parameters[param]) - { - buf[0] = 0; - - switch(param) - { - case espeakPUNCTUATION: - option_punctuation = value-1; - break; - - case espeakCAPITALS: - option_capitals = value; - break; - - case espeakRATE: - case espeakVOLUME: - case espeakPITCH: - case espeakRANGE: - case espeakEMPHASIS: - sprintf(buf,"%c%d%c",CTRL_EMBEDDED,value,cmd_letter[param]); - break; - } - - speech_parameters[param] = new_parameters[param]; - strcpy(&outbuf[*outix],buf); - (*outix) += strlen(buf); - } - } -} // end of ProcessParamStack - - -static PARAM_STACK *PushParamStack(int tag_type) -{//============================================= - int ix; - PARAM_STACK *sp; - - sp = ¶m_stack[n_param_stack]; - if(n_param_stack < (N_PARAM_STACK-1)) - n_param_stack++; - - sp->type = tag_type; - for(ix=0; ix<N_SPEECH_PARAM; ix++) - { - sp->parameter[ix] = -1; - } - return(sp); -} // end of PushParamStack - - -static void PopParamStack(int tag_type, char *outbuf, int *outix) -{//============================================================== - // unwind the stack up to and including the previous tag of this type - int ix; - int top = 0; - - if(tag_type >= SSML_CLOSE) - tag_type -= SSML_CLOSE; - - for(ix=0; ix<n_param_stack; ix++) - { - if(param_stack[ix].type == tag_type) - { - top = ix; - } - } - if(top > 0) - { - n_param_stack = top; - } - ProcessParamStack(outbuf, outix); -} // end of PopParamStack - - - -static wchar_t *GetSsmlAttribute(wchar_t *pw, const char *name) -{//============================================================ -// Gets the value string for an attribute. -// Returns NULL if the attribute is not present - int ix; - static wchar_t empty[1] = {0}; - - while(*pw != 0) - { - if(iswspace(pw[-1])) - { - ix = 0; - while(*pw == name[ix]) - { - pw++; - ix++; - } - if(name[ix]==0) - { - // found the attribute, now get the value - while(iswspace(*pw)) pw++; - if(*pw == '=') pw++; - while(iswspace(*pw)) pw++; - if(*pw == '"') - return(pw+1); - else - return(empty); - } - } - pw++; - } - return(NULL); -} // end of GetSsmlAttribute - - -static int attrcmp(const wchar_t *string1, const char *string2) -{//============================================================ - int ix; - - if(string1 == NULL) - return(1); - - for(ix=0; (string1[ix] == string2[ix]) && (string1[ix] != 0); ix++) - { - } - if((string1[ix]=='"') && (string2[ix]==0)) - return(0); - return(1); -} - - -static int attrlookup(const wchar_t *string1, const MNEM_TAB *mtab) -{//================================================================ - int ix; - - for(ix=0; mtab[ix].mnem != NULL; ix++) - { - if(attrcmp(string1,mtab[ix].mnem) == 0) - return(mtab[ix].value); - } - return(mtab[ix].value); -} - - -static int attrnumber(const wchar_t *pw, int default_value, int type) -{//================================================================== - int value = 0; - - if((pw == NULL) || !isdigit(*pw)) - return(default_value); - - while(isdigit(*pw)) - { - value = value*10 + *pw++ - '0'; - } - if((type==1) && (towlower(*pw)=='s')) - { - // time: seconds rather than ms - value *= 1000; - } - return(value); -} // end of attrnumber - - - -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 - unsigned int c; - int ix = 0; - int n; - int prev_c = 0; - - if(pw != NULL) - { - while((ix < (len-4)) && ((c = *pw++) != 0)) - { - if((c=='"') && (prev_c != '\\')) - break; // " indicates end of attribute, unless preceded by backstroke - n = utf8_out(c,&buf[ix]); - ix += n; - prev_c = c; - } - } - buf[ix] = 0; - return(ix); -} // end of attrcopy_utf8 - - - -static int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out) -{//============================================================================= - int sign = 0; - wchar_t *tail; - float value; - - while(iswspace(*pw)) pw++; - if(*pw == '+') - { - pw++; - sign = 1; - } - if(*pw == '-') - { - pw++; - sign = -1; - } - value = (float)wcstod(pw,&tail); - if(tail == pw) - { - // failed to find a number, return 100% - *value_out = 100; - return(2); - } - - if(*tail == '%') - { - if(sign != 0) - value = 100 + (sign * value); - *value_out = (int)value; - return(2); // percentage - } - - if((tail[0]=='s') && (tail[1]=='t')) - { - double x; - // convert from semitones to a frequency percentage - x = pow(double(2.0),double((value*sign)/12)) * 100; - *value_out = (int)x; - return(2); // percentage - } - - if(param_type == espeakRATE) - { - *value_out = (int)(value * 100); - return(2); // percentage - } - - *value_out = (int)value; - return(sign); // -1, 0, or 1 -} // end of attr_prosody_value - - -int AddNameData(const char *name, int wide) -{//======================================== -// Add the name to the namedata and return its position -// (Used by the Windows SAPI wrapper) - int ix; - int len; - void *vp; - - if(wide) - { - len = (wcslen((const wchar_t *)name)+1)*sizeof(wchar_t); - n_namedata = (n_namedata + sizeof(wchar_t) - 1) % sizeof(wchar_t); // round to wchar_t boundary - } - else - { - len = strlen(name)+1; - } - - if(namedata_ix+len >= n_namedata) - { - // allocate more space for marker names - if((vp = realloc(namedata, namedata_ix+len + 300)) == NULL) - return(-1); // failed to allocate, original data is unchanged but ignore this new name - - namedata = (char *)vp; - n_namedata = namedata_ix+len + 300; - } - memcpy(&namedata[ix = namedata_ix],name,len); - namedata_ix += len; - return(ix); -} // end of AddNameData - - -void SetVoiceStack(espeak_VOICE *v) -{//================================ - SSML_STACK *sp; - sp = &ssml_stack[0]; - - if(v == NULL) - { - memset(sp,0,sizeof(ssml_stack[0])); - return; - } - if(v->languages != NULL) - strcpy(sp->language,v->languages); - if(v->name != NULL) - strcpy(sp->voice_name,v->name); - sp->voice_variant = v->variant; - sp->voice_age = v->age; - sp->voice_gender = v->gender; -} - - -static int GetVoiceAttributes(wchar_t *pw, int tag_type) -{//===================================================== -// Determines whether voice attribute are specified in this tag, and if so, whether this means -// a voice change. -// If it's a closing tag, delete the top frame of the stack and determine whether this implies -// a voice change. -// Returns CLAUSE_BIT_VOICE if there is a voice change - - wchar_t *lang; - wchar_t *gender; - wchar_t *name; - wchar_t *age; - wchar_t *variant; - const char *new_voice_id; - SSML_STACK *ssml_sp; - - static const MNEM_TAB mnem_gender[] = { - {"male", 1}, - {"female", 2}, - {"neutral", 3}, - {NULL, 0}}; - - if(tag_type & SSML_CLOSE) - { - // delete a stack frame - if(n_ssml_stack > 1) - { - n_ssml_stack--; - } - } - else - { - // add a stack frame if any voice details are specified - lang = GetSsmlAttribute(pw,"xml:lang"); - - if(tag_type != SSML_VOICE) - { - // only expect an xml:lang attribute - name = NULL; - variant = NULL; - age = NULL; - gender = NULL; - } - else - { - name = GetSsmlAttribute(pw,"name"); - variant = GetSsmlAttribute(pw,"variant"); - age = GetSsmlAttribute(pw,"age"); - gender = GetSsmlAttribute(pw,"gender"); - } - - if((tag_type != SSML_VOICE) && (lang==NULL)) - return(0); // <s> or <p> without language spec, nothing to do - - ssml_sp = &ssml_stack[n_ssml_stack++]; - - attrcopy_utf8(ssml_sp->language,lang,sizeof(ssml_sp->language)); - attrcopy_utf8(ssml_sp->voice_name,name,sizeof(ssml_sp->voice_name)); - ssml_sp->voice_variant = attrnumber(variant,1,0)-1; - ssml_sp->voice_age = attrnumber(age,0,0); - ssml_sp->voice_gender = attrlookup(gender,mnem_gender); - ssml_sp->tag_type = tag_type; - } - - new_voice_id = VoiceFromStack(); - if(strcmp(new_voice_id,current_voice_id) != 0) - { - // add an embedded command to change the voice - strcpy(current_voice_id,new_voice_id); - return(CLAUSE_BIT_VOICE); // change of voice - } - - return(0); -} // end of GetVoiceAttributes - - -static void SetProsodyParameter(int param_type, wchar_t *attr1, PARAM_STACK *sp) -{//============================================================================= - int value; - int sign; - - static const MNEM_TAB mnem_volume[] = { - {"default",100}, - {"silent",0}, - {"x-soft",30}, - {"soft",65}, - {"medium",100}, - {"loud",150}, - {"x-loud",230}, - {NULL, -1}}; - - static const MNEM_TAB mnem_rate[] = { - {"default",100}, - {"x-slow",60}, - {"slow",80}, - {"medium",100}, - {"fast",120}, - {"x-fast",150}, - {NULL, -1}}; - - static const MNEM_TAB mnem_pitch[] = { - {"default",100}, - {"x-low",70}, - {"low",85}, - {"medium",100}, - {"high",110}, - {"x-high",120}, - {NULL, -1}}; - - static const MNEM_TAB mnem_range[] = { - {"default",100}, - {"x-low",20}, - {"low",50}, - {"medium",100}, - {"high",140}, - {"x-high",180}, - {NULL, -1}}; - - static const MNEM_TAB *mnem_tabs[5] = { - NULL, mnem_rate, mnem_volume, mnem_pitch, mnem_range }; - - - if((value = attrlookup(attr1,mnem_tabs[param_type])) >= 0) - { - // mnemonic specifies a value as a percentage of the base pitch/range/rate/volume - sp->parameter[param_type] = (param_stack[0].parameter[param_type] * value)/100; - } - else - { - sign = attr_prosody_value(param_type,attr1,&value); - - if(sign == 0) - sp->parameter[param_type] = value; // absolute value in Hz - else - if(sign == 2) - { - // change specified as percentage or in semitones - sp->parameter[param_type] = (speech_parameters[param_type] * value)/100; - } - else - { - // change specified as plus or minus Hz - sp->parameter[param_type] = speech_parameters[param_type] + (value*sign); - } - } -} // end of SetProsodyParemeter - - - -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 '>' -// returns a clause terminator value. - - unsigned int ix; - int index; - int c; - int tag_type; - int value; - int value2; - int value3; - int voice_change_flag; - wchar_t *px; - wchar_t *attr1; - wchar_t *attr2; - wchar_t *attr3; - int terminator; - char *uri; - int param_type; - char tag_name[40]; - char buf[80]; - PARAM_STACK *sp; - SSML_STACK *ssml_sp; - - static const MNEM_TAB mnem_punct[] = { - {"none", 1}, - {"all", 2}, - {"some", 3}, - {NULL, -1}}; - - static const MNEM_TAB mnem_capitals[] = { - {"no", 0}, - {"spelling", 2}, - {"icon", 1}, - {"pitch", 20}, // this is the amount by which to raise the pitch - {NULL, -1}}; - - static const MNEM_TAB mnem_interpret_as[] = { - {"characters",SAYAS_CHARS}, - {"tts:char",SAYAS_SINGLE_CHARS}, - {"tts:key",SAYAS_KEY}, - {"tts:digits",SAYAS_DIGITS}, - {"telephone",SAYAS_DIGITS1}, - {NULL, -1}}; - - static const MNEM_TAB mnem_sayas_format[] = { - {"glyphs",1}, - {NULL, -1}}; - - static const MNEM_TAB mnem_break[] = { - {"none",0}, - {"x-weak",1}, - {"weak",2}, - {"medium",3}, - {"strong",4}, - {"x-strong",5}, - {NULL,-1}}; - - static const MNEM_TAB mnem_emphasis[] = { - {"none",1}, - {"reduced",2}, - {"moderate",3}, - {"strong",4}, - {NULL,-1}}; - - static const char *prosody_attr[5] = { - NULL, "rate", "volume", "pitch", "range" }; - - for(ix=0; ix<(sizeof(tag_name)-1); ix++) - { - if(((c = xml_buf[ix]) == 0) || iswspace(c)) - break; - tag_name[ix] = tolower((char)c); - } - tag_name[ix] = 0; - - px = &xml_buf[ix]; // the tag's attributes - - if(tag_name[0] == '/') - { - tag_type = LookupMnem(ssmltags,&tag_name[1]) + SSML_CLOSE; // closing tag - } - else - { - tag_type = LookupMnem(ssmltags,tag_name); - - if(self_closing && ignore_if_self_closing[tag_type]) - return(0); - } - - voice_change_flag = 0; - terminator = CLAUSE_NONE; - ssml_sp = &ssml_stack[n_ssml_stack-1]; - - switch(tag_type) - { - case SSML_STYLE: - sp = PushParamStack(tag_type); - attr1 = GetSsmlAttribute(px,"field"); - attr2 = GetSsmlAttribute(px,"mode"); - - - if(attrcmp(attr1,"punctuation")==0) - { - value = attrlookup(attr2,mnem_punct); - sp->parameter[espeakPUNCTUATION] = value; - } - else - if(attrcmp(attr1,"capital_letters")==0) - { - value = attrlookup(attr2,mnem_capitals); - sp->parameter[espeakCAPITALS] = value; - } - ProcessParamStack(outbuf, outix); - break; - - case SSML_PROSODY: - sp = PushParamStack(tag_type); - - // look for attributes: rate, volume, pitch, range - for(param_type=espeakRATE; param_type <= espeakRANGE; param_type++) - { - if((attr1 = GetSsmlAttribute(px,prosody_attr[param_type])) != NULL) - { - SetProsodyParameter(param_type, attr1, sp); - } - } - - ProcessParamStack(outbuf, outix); - break; - - case SSML_EMPHASIS: - sp = PushParamStack(tag_type); - value = 3; // default is "moderate" - if((attr1 = GetSsmlAttribute(px,"level")) != NULL) - { - value = attrlookup(attr1,mnem_emphasis); - } - - if(translator->langopts.tone_language == 1) - { - static unsigned char emphasis_to_pitch_range[] = {50,50,40,70,90,90}; - static unsigned char emphasis_to_volume[] = {100,100,70,110,140,140}; - // tone language (eg.Chinese) do emphasis by increasing the pitch range. - sp->parameter[espeakRANGE] = emphasis_to_pitch_range[value]; - sp->parameter[espeakVOLUME] = emphasis_to_volume[value]; - } - else - { - sp->parameter[espeakEMPHASIS] = value; - } - ProcessParamStack(outbuf, outix); - break; - - case SSML_STYLE + SSML_CLOSE: - case SSML_PROSODY + SSML_CLOSE: - case SSML_EMPHASIS + SSML_CLOSE: - PopParamStack(tag_type, outbuf, outix); - break; - - case SSML_SAYAS: - attr1 = GetSsmlAttribute(px,"interpret-as"); - attr2 = GetSsmlAttribute(px,"format"); - attr3 = GetSsmlAttribute(px,"detail"); - value = attrlookup(attr1,mnem_interpret_as); - value2 = attrlookup(attr2,mnem_sayas_format); - if(value2 == 1) - value = SAYAS_GLYPHS; - - value3 = attrnumber(attr3,0,0); - - if(value == SAYAS_DIGITS) - { - if(value3 <= 1) - value = SAYAS_DIGITS1; - else - value = SAYAS_DIGITS + value3; - } - - sprintf(buf,"%c%dY",CTRL_EMBEDDED,value); - strcpy(&outbuf[*outix],buf); - (*outix) += strlen(buf); - - sayas_mode = value; // punctuation doesn't end clause during SAY-AS - break; - - case SSML_SAYAS + SSML_CLOSE: - outbuf[(*outix)++] = CTRL_EMBEDDED; - outbuf[(*outix)++] = 'Y'; - sayas_mode = 0; - break; - - case SSML_SUB: - if((attr1 = GetSsmlAttribute(px,"alias")) != NULL) - { - // use the alias rather than the text - ignore_text = 1; - (*outix) += attrcopy_utf8(&outbuf[*outix],attr1,n_outbuf-*outix); - } - break; - - case SSML_IGNORE_TEXT: - ignore_text = 1; - break; - - case SSML_SUB + SSML_CLOSE: - case SSML_IGNORE_TEXT + SSML_CLOSE: - ignore_text = 0; - break; - - case SSML_MARK: - if((attr1 = GetSsmlAttribute(px,"name")) != NULL) - { - // add name to circular buffer of marker names - attrcopy_utf8(buf,attr1,sizeof(buf)); - - if(strcmp(skip_marker,buf)==0) - { - // This is the marker we are waiting for before starting to speak - clear_skipping_text = 1; - skip_marker[0] = 0; - return(CLAUSE_NONE); - } - - if((index = AddNameData(buf,0)) >= 0) - { - sprintf(buf,"%c%dM",CTRL_EMBEDDED,index); - strcpy(&outbuf[*outix],buf); - (*outix) += strlen(buf); - } - } - break; - - case SSML_AUDIO: - sp = PushParamStack(tag_type); - - if((attr1 = GetSsmlAttribute(px,"src")) != NULL) - { - char fname[256]; - attrcopy_utf8(buf,attr1,sizeof(buf)); - - if(uri_callback == NULL) - { - if((xmlbase != NULL) && (buf[0] != '/')) - { - sprintf(fname,"%s/%s",xmlbase,buf); - index = LoadSoundFile2(fname); - } - else - { - index = LoadSoundFile2(buf); - } - if(index >= 0) - { - sprintf(buf,"%c%dI",CTRL_EMBEDDED,index); - strcpy(&outbuf[*outix],buf); - (*outix) += strlen(buf); - sp->parameter[espeakSILENCE] = 1; - } - } - else - { - if((index = AddNameData(buf,0)) >= 0) - { - uri = &namedata[index]; - if(uri_callback(1,uri,xmlbase) == 0) - { - sprintf(buf,"%c%dU",CTRL_EMBEDDED,index); - strcpy(&outbuf[*outix],buf); - (*outix) += strlen(buf); - sp->parameter[espeakSILENCE] = 1; - } - } - } - } - ProcessParamStack(outbuf, outix); - - if(self_closing) - PopParamStack(tag_type, outbuf, outix); - return(CLAUSE_NONE); - - case SSML_AUDIO + SSML_CLOSE: - PopParamStack(tag_type, outbuf, outix); - return(CLAUSE_NONE); - - case SSML_BREAK: - value = 21; - terminator = CLAUSE_NONE; - - if((attr1 = GetSsmlAttribute(px,"strength")) != NULL) - { - static int break_value[6] = {0,7,14,21,40,80}; // *10mS - value = attrlookup(attr1,mnem_break); - if(value < 3) - { - // adjust prepause on the following word - sprintf(&outbuf[*outix],"%c%dB",CTRL_EMBEDDED,value); - (*outix) += 3; - terminator = 0; - } - value = break_value[value]; - } - if((attr2 = GetSsmlAttribute(px,"time")) != NULL) - { - value = (attrnumber(attr2,0,1) * 25) / speed.speed_factor1; // compensate for speaking speed to keep constant pause length - - if(terminator == 0) - terminator = CLAUSE_NONE; - } - if(terminator) - { - if(value > 0xfff) - value = 0xfff; - return(terminator + value); - } - break; - - case SSML_SPEAK: - if((attr1 = GetSsmlAttribute(px,"xml:base")) != NULL) - { - attrcopy_utf8(buf,attr1,sizeof(buf)); - if((index = AddNameData(buf,0)) >= 0) - { - xmlbase = &namedata[index]; - } - } - if(GetVoiceAttributes(px, tag_type) == 0) - return(0); // no voice change - return(CLAUSE_VOICE); - - case SSML_VOICE: - if(GetVoiceAttributes(px, tag_type) == 0) - return(0); // no voice change - return(CLAUSE_VOICE); - - case SSML_SPEAK + SSML_CLOSE: - // unwind stack until the previous <voice> or <speak> tag - while((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_SPEAK)) - { - n_ssml_stack--; - } - return(CLAUSE_PERIOD + GetVoiceAttributes(px, tag_type)); - - case SSML_VOICE + SSML_CLOSE: - // unwind stack until the previous <voice> or <speak> tag - while((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_VOICE)) - { - n_ssml_stack--; - } - -terminator=0; // ?? Sentence intonation, but no pause ?? - return(terminator + GetVoiceAttributes(px, tag_type)); - - case HTML_BREAK: - case HTML_BREAK + SSML_CLOSE: - return(CLAUSE_COLON); - - case SSML_SENTENCE: - if(ssml_sp->tag_type == SSML_SENTENCE) - { - // new sentence implies end-of-sentence - voice_change_flag = GetVoiceAttributes(px, SSML_SENTENCE+SSML_CLOSE); - } - voice_change_flag |= GetVoiceAttributes(px, tag_type); - return(CLAUSE_PARAGRAPH + voice_change_flag); - - - case SSML_PARAGRAPH: - if(ssml_sp->tag_type == SSML_SENTENCE) - { - // new paragraph implies end-of-sentence or end-of-paragraph - voice_change_flag = GetVoiceAttributes(px, SSML_SENTENCE+SSML_CLOSE); - } - if(ssml_sp->tag_type == SSML_PARAGRAPH) - { - // new paragraph implies end-of-sentence or end-of-paragraph - voice_change_flag |= GetVoiceAttributes(px, SSML_PARAGRAPH+SSML_CLOSE); - } - voice_change_flag |= GetVoiceAttributes(px, tag_type); - return(CLAUSE_PARAGRAPH + voice_change_flag); - - - case SSML_SENTENCE + SSML_CLOSE: - if(ssml_sp->tag_type == SSML_SENTENCE) - { - // end of a sentence which specified a language - voice_change_flag = GetVoiceAttributes(px, tag_type); - } - return(CLAUSE_PERIOD + voice_change_flag); - - - case SSML_PARAGRAPH + SSML_CLOSE: - if((ssml_sp->tag_type == SSML_SENTENCE) || (ssml_sp->tag_type == SSML_PARAGRAPH)) - { - // End of a paragraph which specified a language. - // (End-of-paragraph also implies end-of-sentence) - return(GetVoiceAttributes(px, tag_type) + CLAUSE_PARAGRAPH); - } - return(CLAUSE_PARAGRAPH); - } - return(0); -} // end of ProcessSsmlTag - - -static MNEM_TAB xml_char_mnemonics[] = { - {"gt",'>'}, - {"lt",'<'}, - {"amp", '&'}, - {"quot", '"'}, - {"nbsp", ' '}, - {"apos", '\''}, - {NULL,-1}}; - - -int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix_top, int n_buf, int *tone_type) -{//============================================================================================================= -/* Find the end of the current clause. - Write the clause into buf - - returns: clause type (bits 0-7: pause x10mS, bits 8-11 intonation type) - - Also checks for blank line (paragraph) as end-of-clause indicator. - - Does not end clause for: - punctuation immediately followed by alphanumeric eg. 1.23 !Speak :path - repeated punctuation, eg. ... !!! -*/ - int c1=' '; // current character - int c2; // next character - int cprev=' '; // previous character - int parag; - int ix = 0; - int j; - int nl_count; - int linelength = 0; - int phoneme_mode = 0; - int n_xml_buf; - int terminator; - int punct; - int found; - int any_alnum = 0; - int self_closing; - int punct_data; - int stressed_word = 0; - const char *p; - wchar_t xml_buf[N_XML_BUF+1]; - -#define N_XML_BUF2 20 - char xml_buf2[N_XML_BUF2+2]; // for &<name> and &<number> sequences - static char ungot_string[N_XML_BUF2+4]; - static int ungot_string_ix = -1; - - if(clear_skipping_text) - { - skipping_text = 0; - clear_skipping_text = 0; - } - - tr->clause_upper_count = 0; - tr->clause_lower_count = 0; - end_of_input = 0; - *tone_type = 0; - -f_input = f_in; // for GetC etc - - if(ungot_word != NULL) - { - strcpy(buf,ungot_word); - ix += strlen(ungot_word); - ungot_word = NULL; - } - - if(ungot_char2 != 0) - { - c2 = ungot_char2; - } - else - { - c2 = GetC(); - } - - while(!Eof() || (ungot_char != 0) || (ungot_char2 != 0) || (ungot_string_ix >= 0)) - { - if(!iswalnum(c1)) - { - if((end_character_position > 0) && (count_characters > end_character_position)) - { - end_of_input = 1; - return(CLAUSE_EOF); - } - - if((skip_characters > 0) && (count_characters > skip_characters)) - { - // reached the specified start position - // don't break a word - clear_skipping_text = 1; - skip_characters = 0; - UngetC(c2); - return(CLAUSE_NONE); - } - } - - cprev = c1; - c1 = c2; - - if(ungot_string_ix >= 0) - { - if(ungot_string[ungot_string_ix] == 0) - ungot_string_ix = -1; - } - - if((ungot_string_ix == 0) && (ungot_char2 == 0)) - { - c1 = ungot_string[ungot_string_ix++]; - } - if(ungot_string_ix >= 0) - { - c2 = ungot_string[ungot_string_ix++]; - } - else - { - c2 = GetC(); - - if(Eof()) - { - c2 = ' '; - } - } - ungot_char2 = 0; - - if((option_ssml) && (phoneme_mode==0)) - { - if((ssml_ignore_l_angle != '&') && (c1 == '&') && ((c2=='#') || ((c2 >= 'a') && (c2 <= 'z')))) - { - n_xml_buf = 0; - c1 = c2; - while(!Eof() && (iswalnum(c1) || (c1=='#')) && (n_xml_buf < N_XML_BUF2)) - { - xml_buf2[n_xml_buf++] = c1; - c1 = GetC(); - } - xml_buf2[n_xml_buf] = 0; - c2 = GetC(); - sprintf(ungot_string,"%s%c%c",&xml_buf2[0],c1,c2); - - if(c1 == ';') - { - if(xml_buf2[0] == '#') - { - // character code number - if(xml_buf2[1] == 'x') - found = sscanf(&xml_buf2[2],"%x",(unsigned int *)(&c1)); - else - found = sscanf(&xml_buf2[1],"%d",&c1); - } - else - { - if((found = LookupMnem(xml_char_mnemonics,xml_buf2)) != -1) - { - c1 = found; - if(c2 == 0) - c2 = ' '; - } - } - } - else - { - found = -1; - } - - if(found <= 0) - { - ungot_string_ix = 0; - c1 = '&'; - c2 = ' '; - } - - if((c1 <= 0x20) && ((sayas_mode == SAYAS_SINGLE_CHARS) || (sayas_mode == SAYAS_KEY))) - { - c1 += 0xe000; // move into unicode private usage area - } - } - else - if((c1 == '<') && (ssml_ignore_l_angle != '<')) - { - if(c2 == '!') - { - // a comment, ignore until closing '<' - while(!Eof() && (c1 != '>')) - { - c1 = GetC(); - } - c2 = ' '; - } - else - if((c2 == '/') || iswalpha(c2)) - { - // SSML Tag - n_xml_buf = 0; - c1 = c2; - while(!Eof() && (c1 != '>') && (n_xml_buf < N_XML_BUF)) - { - xml_buf[n_xml_buf++] = c1; - c1 = GetC(); - } - xml_buf[n_xml_buf] = 0; - c2 = ' '; - - buf[ix++] = ' '; - - self_closing = 0; - if(xml_buf[n_xml_buf-1] == '/') - { - // a self-closing tag - xml_buf[n_xml_buf-1] = ' '; - self_closing = 1; - } - - terminator = ProcessSsmlTag(xml_buf,buf,ix,n_buf,self_closing); - - if(terminator != 0) - { - buf[ix] = ' '; - buf[ix++] = 0; - - if(terminator & CLAUSE_BIT_VOICE) - { - // a change in voice, write the new voice name to the end of the buf - p = current_voice_id; - while((*p != 0) && (ix < (n_buf-1))) - { - buf[ix++] = *p++; - } - buf[ix++] = 0; - } - return(terminator); - } - continue; - } - } - } - ssml_ignore_l_angle=0; - - if(ignore_text) - continue; - - if((c2=='\n') && (option_linelength == -1)) - { - // single-line mode, return immediately on NL - if((punct = lookupwchar(punct_chars,c1)) == 0) - { - charix[ix] = count_characters - clause_start_char; - *charix_top = ix; - ix += utf8_out(c1,&buf[ix]); - terminator = CLAUSE_PERIOD; // line doesn't end in punctuation, assume period - } - else - { - terminator = punct_attributes[punct]; - } - buf[ix] = ' '; - buf[ix+1] = 0; - return(terminator); - } - - if((c1 == CTRL_EMBEDDED) || (c1 == ctrl_embedded)) - { - // an embedded command. If it's a voice change, end the clause - if(c2 == 'V') - { - buf[ix++] = 0; // end the clause at this point - while(!iswspace(c1 = GetC()) && !Eof() && (ix < (n_buf-1))) - buf[ix++] = c1; // add voice name to end of buffer, after the text - buf[ix++] = 0; - return(CLAUSE_VOICE); - } - else - if(c2 == 'B') - { - // set the punctuation option from an embedded command - // B0 B1 B<punct list><space> - strcpy(&buf[ix]," "); - ix += 3; - - if((c2 = GetC()) == '0') - option_punctuation = 0; - else - { - option_punctuation = 1; - option_punctlist[0] = 0; - if(c2 != '1') - { - // a list of punctuation characters to be spoken, terminated by space - j = 0; - while(!iswspace(c2) && !Eof()) - { - option_punctlist[j++] = c2; - c2 = GetC(); - buf[ix++] = ' '; - } - option_punctlist[j] = 0; // terminate punctuation list - option_punctuation = 2; - } - } - c2 = GetC(); - continue; - } - } - - linelength++; - - if(iswalnum(c1)) - any_alnum = 1; - else - { - if(stressed_word) - { - stressed_word = 0; - c1 = CHAR_EMPHASIS; // indicate this word is stressed - UngetC(c2); - c2 = ' '; - } - - if(iswspace(c1)) - { - char *p_word; - - if(tr->translator_name == 0x6a626f) - { - // language jbo : lojban - // treat "i" or ".i" as end-of-sentence - p_word = &buf[ix-1]; - if(p_word[0] == 'i') - { - if(p_word[-1] == '.') - p_word--; - if(p_word[-1] == ' ') - { - ungot_word = "i "; - UngetC(c2); - p_word[0] = 0; - return(CLAUSE_PERIOD); - } - } - } - } - } - - if(iswupper(c1)) - { - tr->clause_upper_count++; - if((option_capitals == 2) && (sayas_mode == 0) && !iswupper(cprev)) - { - char text_buf[40]; - char text_buf2[30]; - if(LookupSpecial(tr, "_cap", text_buf2) != NULL) - { - sprintf(text_buf,"%s%s%s",tone_punct_on,text_buf2,tone_punct_off); - j = strlen(text_buf); - if((ix + j) < n_buf) - { - strcpy(&buf[ix],text_buf); - ix += j; - } - } - } - } - else - if(iswalpha(c1)) - tr->clause_lower_count++; - - if(option_phoneme_input) - { - if(phoneme_mode > 0) - phoneme_mode--; - else - if((c1 == '[') && (c2 == '[')) - phoneme_mode = -1; // input is phoneme mnemonics, so don't look for punctuation - else - if((c1 == ']') && (c2 == ']')) - phoneme_mode = 2; // set phoneme_mode to zero after the next two characters - } - - if(c1 == '\n') - { - parag = 0; - - // count consecutive newlines, ignoring other spaces - while(!Eof() && iswspace(c2)) - { - if(c2 == '\n') - parag++; - c2 = GetC(); - } - if(parag > 0) - { - // 2nd newline, assume paragraph - UngetC(c2); - - buf[ix] = ' '; - buf[ix+1] = 0; - if(parag > 3) - parag = 3; -if(option_ssml) parag=1; - return((CLAUSE_PARAGRAPH-30) + 30*parag); // several blank lines, longer pause - } - - if(linelength <= option_linelength) - { - // treat lines shorter than a specified length as end-of-clause - UngetC(c2); - buf[ix] = ' '; - buf[ix+1] = 0; - return(CLAUSE_COLON); - } - - linelength = 0; - } - - if(option_punctuation && (phoneme_mode==0) && (sayas_mode==0) && iswpunct(c1)) - { - // option is set to explicitly speak punctuation characters - // if a list of allowed punctuation has been set up, check whether the character is in it - if((option_punctuation == 1) || (wcschr(option_punctlist,c1) != NULL)) - { - if((terminator = AnnouncePunctuation(tr, c1, c2, buf, ix)) >= 0) - return(terminator); - } - } - - if((phoneme_mode==0) && (sayas_mode==0) && ((punct = lookupwchar(punct_chars,c1)) != 0)) - { - punct_data = punct_attributes[punct]; - - if(punct_data & PUNCT_IN_WORD) - { - // Armenian punctuation inside a word - stressed_word = 1; - *tone_type = punct_data >> 12 & 0xf; // override the end-of-sentence type - continue; - } - - if((iswspace(c2) || (punct_data & 0x8000) || IsBracket(c2) || (c2=='?') || (c2=='-') || Eof())) - { - // note: (c2='?') is for when a smart-quote has been replaced by '?' - buf[ix] = ' '; - buf[ix+1] = 0; - - if((c1 == '.') && (cprev == '.')) - { - c1 = 0x2026; - punct = 9; // elipsis - } - - nl_count = 0; - while(!Eof() && iswspace(c2)) - { - if(c2 == '\n') - nl_count++; - c2 = GetC(); // skip past space(s) - } - if(!Eof()) - { - UngetC(c2); - } - - if((nl_count==0) && (c1 == '.')) - { - if(iswdigit(cprev) && (tr->langopts.numbers & 0x10000) && islower(c2)) - { - // dot after a number indicates an ordinal number - c2 = '.'; - continue; - } - if(iswlower(c2)) - { - c2 = ' '; - continue; // next word has no capital letter, this dot is probably from an abbreviation - } - if(any_alnum==0) - { - c2 = ' '; // no letters or digits yet, so probably not a sentence terminator - continue; - } - } - - punct_data = punct_attributes[punct]; - if(nl_count > 1) - { - if((punct_data == CLAUSE_QUESTION) || (punct_data == CLAUSE_EXCLAMATION)) - return(punct_data + 35); // with a longer pause - return(CLAUSE_PARAGRAPH); - } - return(punct_data); // only recognise punctuation if followed by a blank or bracket/quote - } - } - - if(speech_parameters[espeakSILENCE]==1) - continue; - - j = ix+1; - ix += utf8_out(c1,&buf[ix]); // buf[ix++] = c1; - if(!iswspace(c1) && !IsBracket(c1)) - { - charix[ix] = count_characters - clause_start_char; - while(j < ix) - charix[j++] = -1; // subsequent bytes of a multibyte character - } - *charix_top = ix; - - if(((ix > (n_buf-20)) && !IsAlpha(c1) && !iswdigit(c1)) || (ix >= (n_buf-2))) - { - // clause too long, getting near end of buffer, so break here - // try to break at a word boundary (unless we actually reach the end of buffer). - buf[ix] = ' '; - buf[ix+1] = 0; - UngetC(c2); - return(CLAUSE_NONE); - } - } - - if(stressed_word) - { - ix += utf8_out(CHAR_EMPHASIS, &buf[ix]); - } - buf[ix] = ' '; - buf[ix+1] = 0; - return(CLAUSE_EOF); // end of file -} // end of ReadClause - - -void InitNamedata(void) -{//==================== - namedata_ix = 0; - if(namedata != NULL) - { - free(namedata); - namedata = NULL; - n_namedata = 0; - } -} - - -void InitText2(void) -{//================= - int param; - - ungot_char = 0; - - n_ssml_stack =1; - n_param_stack = 1; - ssml_stack[0].tag_type = 0; - - for(param=0; param<N_SPEECH_PARAM; param++) - speech_parameters[param] = param_stack[0].parameter[param]; // set all speech parameters to defaults - - option_punctuation = speech_parameters[espeakPUNCTUATION]; - option_capitals = speech_parameters[espeakCAPITALS]; - - current_voice_id[0] = 0; - - ignore_text = 0; - clear_skipping_text = 0; - count_characters = -1; - sayas_mode = 0; - - xmlbase = NULL; -} - diff --git a/navit/support/espeak/setlengths.c b/navit/support/espeak/setlengths.c deleted file mode 100755 index ed4421bf9..000000000 --- a/navit/support/espeak/setlengths.c +++ /dev/null @@ -1,673 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdlib.h> -#include <stdio.h> -#include <wctype.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" - -extern int GetAmplitude(void); - - -// convert from words-per-minute to internal speed factor -static unsigned char speed_lookup[290] = { - 250, 246, 243, 239, 236, // 80 - 233, 229, 226, 223, 220, // 85 - 217, 214, 211, 208, 205, // 90 - 202, 197, 194, 192, 190, // 95 - 187, 185, 183, 180, 178, // 100 - 176, 174, 172, 170, 168, // 105 - 166, 164, 161, 159, 158, // 110 - 156, 154, 152, 150, 148, // 115 - 146, 145, 143, 141, 137, // 120 - 136, 135, 133, 132, 131, // 125 - 129, 128, 127, 126, 125, // 130 - 124, 122, 121, 120, 119, // 135 - 117, 116, 115, 114, 113, // 140 - 112, 111, 110, 108, 107, // 145 - 106, 105, 104, 103, 102, // 150 - 101, 100, 99, 98, 97, // 155 - 96, 95, 93, 92, 92, // 160 - 91, 90, 89, 89, 88, // 165 - 87, 87, 86, 85, 85, // 170 - 84, 83, 83, 82, 81, // 175 - 80, 80, 79, 78, 78, // 180 - 77, 76, 76, 75, 73, // 185 - 72, 72, 71, 71, 70, // 190 - 70, 69, 69, 68, 67, // 195 - 67, 66, 66, 65, 65, // 200 - 64, 64, 63, 63, 62, // 205 - 62, 61, 60, 60, 59, // 210 - 59, 58, 58, 57, 57, // 215 - 56, 56, 55, 55, 55, // 220 - 54, 54, 53, 53, 52, // 225 - 52, 51, 51, 50, 50, // 230 - 49, 49, 49, 48, 48, // 235 - 47, 47, 46, 46, 46, // 240 - 45, 45, 44, 44, 43, // 245 - 43, 43, 42, 42, 41, // 250 - 41, 41, 40, 40, 39, // 255 - 39, 39, 38, 38, 38, // 260 - 37, 37, 37, 36, 36, // 265 - 35, 35, 35, 34, 34, // 270 - 34, 33, 33, 33, 32, // 275 - 32, 32, 32, 31, 31, // 280 - 31, 30, 30, 30, 29, // 285 - 29, 29, 29, 28, 28, // 290 - 28, 28, 27, 27, 27, // 295 - 26, 26, 26, 26, 25, // 300 - 25, 25, 22, 22, 22, // 305 - 22, 22, 22, 22, 22, // 310 - 21, 21, 21, 21, 21, // 315 - 21, 20, 20, 20, 20, // 320 - 20, 15, 15, 15, 15, // 325 - 15, 15, 15, 15, 16, // 330 - 16, 16, 16, 15, 15, // 335 - 15, 15, 15, 15, 15, // 340 - 15, 17, 17, 16, 16, // 345 - 15, 15, 14, 14, 13, // 350 - 13, 12, 12, 11, 11, // 355 - 10, 10, 9, 8, 8, // 360 - 7, 6, 5, 5, 4, // 365 -}; - -// speed_factor2 adjustments for speeds 370 to 390 -static unsigned char faster[] = { -114,112,110,109,107,105,104,102,100,98, // 370-379 -96,94,92,90,88,85,83,80,78,75,72 }; //380-390 - -static int speed1 = 130; -static int speed2 = 121; -static int speed3 = 118; - - - -void SetSpeed(int control) -{//======================= - int x; - int s1; - int wpm; - int wpm2; - - wpm = embedded_value[EMBED_S]; - if(control == 2) - wpm = embedded_value[EMBED_S2]; - wpm2 = wpm; - - if(wpm > 369) wpm = 369; - if(wpm < 80) wpm = 80; - - x = speed_lookup[wpm-80]; - - if(control & 1) - { - // set speed factors for different syllable positions within a word - // these are used in CalcLengths() - speed1 = (x * voice->speedf1)/256; - speed2 = (x * voice->speedf2)/256; - speed3 = (x * voice->speedf3)/256; - } - - if(control & 2) - { - // these are used in synthesis file - s1 = (x * voice->speedf1)/256; - speed.speed_factor1 = (256 * s1)/115; // full speed adjustment, used for pause length -if(speed.speed_factor1 < 15) - speed.speed_factor1 = 15; - if(wpm >= 170) -// speed_factor2 = 100 + (166*s1)/128; // reduced speed adjustment, used for playing recorded sounds - speed.speed_factor2 = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds - else - speed.speed_factor2 = 128 + (128*s1)/130; // = 215 at 170 wpm - - if(wpm2 > 369) - { - if(wpm2 > 390) - wpm2 = 390; - speed.speed_factor2 = faster[wpm2 - 370]; - } - } - - speed.min_sample_len = 450; - speed.speed_factor3 = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change - - if(wpm2 >= 370) - { - // TESTING - // use experimental fast settings if they have been specified in the Voice - if(speed.fast_settings[0] > 0) - speed.speed_factor1 = speed.fast_settings[0]; - if(speed.fast_settings[1] > 0) - speed.speed_factor2 = speed.fast_settings[1]; - if(speed.fast_settings[2] > 0) - speed.speed_factor3 = speed.fast_settings[2]; - } -} // end of SetSpeed - - -#ifdef deleted -void SetAmplitude(int amp) -{//======================= - static unsigned char amplitude_factor[] = {0,5,6,7,9,11,14,17,21,26, 32, 38,44,50,56,63,70,77,84,91,100 }; - - if((amp >= 0) && (amp <= 20)) - { - option_amplitude = (amplitude_factor[amp] * 480)/256; - } -} -#endif - - - -void SetParameter(int parameter, int value, int relative) -{//====================================================== -// parameter: reset-all, amp, pitch, speed, linelength, expression, capitals, number grouping -// relative 0=absolute 1=relative - - int new_value = value; - int default_value; - - if(relative) - { - if(parameter < 5) - { - default_value = param_defaults[parameter]; - new_value = default_value + (default_value * value)/100; - } - } - param_stack[0].parameter[parameter] = new_value; - - switch(parameter) - { - case espeakRATE: - embedded_value[EMBED_S] = new_value; - embedded_value[EMBED_S2] = new_value; - SetSpeed(3); - break; - - case espeakVOLUME: - embedded_value[EMBED_A] = new_value; - GetAmplitude(); - break; - - case espeakPITCH: - if(new_value > 99) new_value = 99; - if(new_value < 0) new_value = 0; - embedded_value[EMBED_P] = new_value; - break; - - case espeakRANGE: - if(new_value > 99) new_value = 99; - embedded_value[EMBED_R] = new_value; - break; - - case espeakLINELENGTH: - option_linelength = new_value; - break; - - case espeakWORDGAP: - option_wordgap = new_value; - break; - - case espeakINTONATION: - if((new_value & 0xff) != 0) - translator->langopts.intonation_group = new_value & 0xff; - option_tone_flags = new_value; - break; - - default: - break; - } -} // end of SetParameter - - - -static void DoEmbedded2(int *embix) -{//================================ - // There were embedded commands in the text at this point - - unsigned int word; - - do { - word = embedded_list[(*embix)++]; - - if((word & 0x1f) == EMBED_S) - { - // speed - SetEmbedded(word & 0x7f, word >> 8); // adjusts embedded_value[EMBED_S] - SetSpeed(1); - } - } while((word & 0x80) == 0); -} - - -void CalcLengths(Translator *tr) -{//============================== - int ix; - int ix2; - PHONEME_LIST *prev; - PHONEME_LIST *next; - PHONEME_LIST *next2; - PHONEME_LIST *next3; - PHONEME_LIST *p; - PHONEME_LIST *p2; - - int stress; - int type; - static int more_syllables=0; - int pre_sonorant=0; - int pre_voiced=0; - int last_pitch = 0; - int pitch_start; - int length_mod; - int len; - int env2; - int end_of_clause; - int embedded_ix = 0; - int min_drop; - int emphasized; - int tone_mod; - unsigned char *pitch_env=NULL; - - for(ix=1; ix<n_phoneme_list; ix++) - { - prev = &phoneme_list[ix-1]; - p = &phoneme_list[ix]; - stress = p->stresslevel & 0x7; - emphasized = p->stresslevel & 0x8; - - next = &phoneme_list[ix+1]; - - if(p->synthflags & SFLAG_EMBEDDED) - { - DoEmbedded2(&embedded_ix); - } - - type = p->type; - if(p->synthflags & SFLAG_SYLLABLE) - type = phVOWEL; - - switch(type) - { - case phPAUSE: - last_pitch = 0; - break; - - case phSTOP: - last_pitch = 0; - if(prev->type == phFRICATIVE) - p->prepause = 20; - else - if((more_syllables > 0) || (stress < 4)) - p->prepause = 40; - else - p->prepause = 60; - - if(prev->type == phSTOP) - p->prepause = 60; - - if((tr->langopts.word_gap & 0x10) && (p->newword)) - p->prepause = 60; - - if(p->ph->phflags & phLENGTHENSTOP) - p->prepause += 30; - - if(p->synthflags & SFLAG_LENGTHEN) - p->prepause += tr->langopts.long_stop; - break; - - case phVFRICATIVE: - if(next->type==phVOWEL) - { - pre_voiced = 1; - } // drop through - case phFRICATIVE: - if(p->newword) - p->prepause = 15; - - if(next->type==phPAUSE && prev->type==phNASAL && !(p->ph->phflags&phFORTIS)) - p->prepause = 25; - - if(prev->ph->phflags & phBRKAFTER) - p->prepause = 30; - - if((p->ph->phflags & phSIBILANT) && next->type==phSTOP && !next->newword) - { - if(prev->type == phVOWEL) - p->length = 200; // ?? should do this if it's from a prefix - else - p->length = 150; - } - else - p->length = 256; - - if((tr->langopts.word_gap & 0x10) && (p->newword)) - p->prepause = 30; - - break; - - case phVSTOP: - if(prev->type==phVFRICATIVE || prev->type==phFRICATIVE || (prev->ph->phflags & phSIBILANT) || (prev->type == phLIQUID)) - p->prepause = 30; - - if(next->type==phVOWEL || next->type==phLIQUID) - { - if((next->type==phVOWEL) || !next->newword) - pre_voiced = 1; - - p->prepause = 40; - - if((prev->type == phPAUSE) || (prev->type == phVOWEL)) // || (prev->ph->mnemonic == ('/'*256+'r'))) - p->prepause = 0; - else - if(p->newword==0) - { - if(prev->type==phLIQUID) - p->prepause = 20; - if(prev->type==phNASAL) - p->prepause = 12; - - if(prev->type==phSTOP && !(prev->ph->phflags & phFORTIS)) - p->prepause = 0; - } - } - if((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20)) - p->prepause = 20; - - break; - - case phLIQUID: - case phNASAL: - p->amp = tr->stress_amps[1]; // unless changed later - p->length = 256; // TEMPORARY - min_drop = 0; - - if(p->newword) - { - if(prev->type==phLIQUID) - p->prepause = 25; - if(prev->type==phVOWEL) - p->prepause = 12; - } - - if(next->type==phVOWEL) - { - pre_sonorant = 1; - } - else - if((prev->type==phVOWEL) || (prev->type == phLIQUID)) - { - p->length = prev->length; - p->pitch2 = last_pitch; - if(p->pitch2 < 7) - p->pitch2 = 7; - p->pitch1 = p->pitch2 - 8; - p->env = PITCHfall; - pre_voiced = 0; - - if(p->type == phLIQUID) - { - p->length = speed1; -//p->pitch1 = p->pitch2 - 20; // post vocalic [r/] - } - - if(next->type == phVSTOP) - { - p->length = (p->length * 160)/100; - } - if(next->type == phVFRICATIVE) - { - p->length = (p->length * 120)/100; - } - } - else - { - p->pitch2 = last_pitch; - for(ix2=ix; ix2<n_phoneme_list; ix2++) - { - if(phoneme_list[ix2].type == phVOWEL) - { - p->pitch2 = phoneme_list[ix2].pitch2; - break; - } - } - p->pitch1 = p->pitch2-8; - p->env = PITCHfall; - pre_voiced = 0; - } - break; - - case phVOWEL: - min_drop = 0; - next2 = &phoneme_list[ix+2]; - next3 = &phoneme_list[ix+3]; - - if(stress > 7) stress = 7; - - if(pre_sonorant) - p->amp = tr->stress_amps[stress]-1; - else - p->amp = tr->stress_amps[stress]; - - if(emphasized) - p->amp = 25; - - if(ix >= (n_phoneme_list-3)) - { - // last phoneme of a clause, limit its amplitude - if(p->amp > tr->langopts.param[LOPT_MAXAMP_EOC]) - p->amp = tr->langopts.param[LOPT_MAXAMP_EOC]; - } - - // is the last syllable of a word ? - more_syllables=0; - end_of_clause = 0; - for(p2 = p+1; p2->newword== 0; p2++) - { - if((p2->type == phVOWEL) && !(p2->ph->phflags & phNONSYLLABIC)) - more_syllables++; - - if(p2->ph->code == phonPAUSE_CLAUSE) - end_of_clause = 2; - } - if(p2->ph->code == phonPAUSE_CLAUSE) - end_of_clause = 2; - - if((p2->newword & 2) && (more_syllables==0)) - { - end_of_clause = 2; - } - - // calc length modifier - if((next->ph->code == phonPAUSE_VSHORT) && (next2->type == phPAUSE)) - { - // if PAUSE_VSHORT is followed by a pause, then use that - next = next2; - next2 = next3; - next3 = &phoneme_list[ix+4]; - } - - if(more_syllables==0) - { - len = tr->langopts.length_mods0[next2->ph->length_mod *10+ next->ph->length_mod]; - - if((next->newword) && (tr->langopts.word_gap & 0x20)) - { - // consider as a pause + first phoneme of the next word - length_mod = (len + tr->langopts.length_mods0[next->ph->length_mod *10+ 1])/2; - } - else - length_mod = len; - } - else - { - length_mod = tr->langopts.length_mods[next2->ph->length_mod *10+ next->ph->length_mod]; - - if((next->type == phNASAL) && (next2->type == phSTOP || next2->type == phVSTOP) && (next3->ph->phflags & phFORTIS)) - length_mod -= 15; - } - - if(more_syllables==0) - length_mod *= speed1; - else - if(more_syllables==1) - length_mod *= speed2; - else - length_mod *= speed3; - - length_mod = length_mod / 128; - - if(length_mod < 8) - length_mod = 8; // restrict how much lengths can be reduced - - if(stress >= 7) - { - // tonic syllable, include a constant component so it doesn't decrease directly with speed - length_mod += 20; - if(emphasized) - length_mod += 10; - } - else - if(emphasized) - { - length_mod += 20; - } - - if((len = tr->stress_lengths[stress]) == 0) - len = tr->stress_lengths[6]; - - length_mod = (length_mod * len)/128; - - if(p->tone_ph != 0) - { - if((tone_mod = phoneme_tab[p->tone_ph]->std_length) > 0) - { - // a tone phoneme specifies a percentage change to the length - length_mod = (length_mod * tone_mod) / 100; - } - } - - if(end_of_clause == 2) - { - // this is the last syllable in the clause, lengthen it - more for short vowels - len = p->ph->std_length; - if(tr->langopts.stress_flags & 0x40000) - len=200; // don't lengthen short vowels more than long vowels at end-of-clause - length_mod = length_mod * (256 + (280 - len)/3)/256; - } - -if(p->type != phVOWEL) -{ - length_mod = 256; // syllabic consonant - min_drop = 8; -} - p->length = length_mod; - - // pre-vocalic part - // set last-pitch - env2 = p->env; - if(env2 > 1) env2++; // version for use with preceding semi-vowel - - if(p->tone_ph != 0) - { - pitch_env = LookupEnvelope(phoneme_tab[p->tone_ph]->spect); - } - else - { - pitch_env = envelope_data[env2]; - } - - pitch_start = p->pitch1 + ((p->pitch2-p->pitch1)*pitch_env[0])/256; - - if(pre_sonorant || pre_voiced) - { - // set pitch for pre-vocalic part - if(pitch_start == 1024) - last_pitch = pitch_start; // pitch is not set - - if(pitch_start - last_pitch > 8) // was 9 - last_pitch = pitch_start - 8; - - prev->pitch1 = last_pitch; - prev->pitch2 = pitch_start; - if(last_pitch < pitch_start) - { - prev->env = PITCHrise; - p->env = env2; - } - else - { - prev->env = PITCHfall; - } - - prev->length = length_mod; - - prev->amp = p->amp; - if((prev->type != phLIQUID) && (prev->amp > 18)) - prev->amp = 18; - } - - // vowel & post-vocalic part - next->synthflags &= ~SFLAG_SEQCONTINUE; - if(next->type == phNASAL && next2->type != phVOWEL) - next->synthflags |= SFLAG_SEQCONTINUE; - - if(next->type == phLIQUID) - { - next->synthflags |= SFLAG_SEQCONTINUE; - - if(next2->type == phVOWEL) - { - next->synthflags &= ~SFLAG_SEQCONTINUE; - } - - if(next2->type != phVOWEL) - { - if(next->ph->mnemonic == ('/'*256+'r')) - { - next->synthflags &= ~SFLAG_SEQCONTINUE; -// min_drop = 15; - } - } - } - - if((min_drop > 0) && ((p->pitch2 - p->pitch1) < min_drop)) - { - p->pitch1 = p->pitch2 - min_drop; - if(p->pitch1 < 0) - p->pitch1 = 0; - } - - last_pitch = p->pitch1 + ((p->pitch2-p->pitch1)*envelope_data[p->env][127])/256; - pre_sonorant = 0; - pre_voiced = 0; - break; - } - } -} // end of CalcLengths - diff --git a/navit/support/espeak/sintab.h b/navit/support/espeak/sintab.h deleted file mode 100755 index 08fc18f31..000000000 --- a/navit/support/espeak/sintab.h +++ /dev/null @@ -1,258 +0,0 @@ -short int sin_tab[2048] = { - 0, -25, -50, -75, -100, -125, -150, -175, - -201, -226, -251, -276, -301, -326, -351, -376, - -401, -427, -452, -477, -502, -527, -552, -577, - -602, -627, -652, -677, -702, -727, -752, -777, - -802, -827, -852, -877, -902, -927, -952, -977, - -1002, -1027, -1052, -1077, -1102, -1127, -1152, -1177, - -1201, -1226, -1251, -1276, -1301, -1326, -1350, -1375, - -1400, -1425, -1449, -1474, -1499, -1523, -1548, -1573, - -1597, -1622, -1647, -1671, -1696, -1721, -1745, -1770, - -1794, -1819, -1843, -1868, -1892, -1917, -1941, -1965, - -1990, -2014, -2038, -2063, -2087, -2111, -2136, -2160, - -2184, -2208, -2233, -2257, -2281, -2305, -2329, -2353, - -2377, -2401, -2425, -2449, -2473, -2497, -2521, -2545, - -2569, -2593, -2617, -2640, -2664, -2688, -2712, -2735, - -2759, -2783, -2806, -2830, -2853, -2877, -2900, -2924, - -2947, -2971, -2994, -3018, -3041, -3064, -3088, -3111, - -3134, -3157, -3180, -3204, -3227, -3250, -3273, -3296, - -3319, -3342, -3365, -3388, -3410, -3433, -3456, -3479, - -3502, -3524, -3547, -3570, -3592, -3615, -3637, -3660, - -3682, -3705, -3727, -3749, -3772, -3794, -3816, -3839, - -3861, -3883, -3905, -3927, -3949, -3971, -3993, -4015, - -4037, -4059, -4080, -4102, -4124, -4146, -4167, -4189, - -4211, -4232, -4254, -4275, -4296, -4318, -4339, -4360, - -4382, -4403, -4424, -4445, -4466, -4487, -4508, -4529, - -4550, -4571, -4592, -4613, -4633, -4654, -4675, -4695, - -4716, -4736, -4757, -4777, -4798, -4818, -4838, -4859, - -4879, -4899, -4919, -4939, -4959, -4979, -4999, -5019, - -5039, -5059, -5078, -5098, -5118, -5137, -5157, -5176, - -5196, -5215, -5235, -5254, -5273, -5292, -5311, -5331, - -5350, -5369, -5388, -5406, -5425, -5444, -5463, -5482, - -5500, -5519, -5537, -5556, -5574, -5593, -5611, -5629, - -5648, -5666, -5684, -5702, -5720, -5738, -5756, -5774, - -5791, -5809, -5827, -5844, -5862, -5880, -5897, -5914, - -5932, -5949, -5966, -5984, -6001, -6018, -6035, -6052, - -6069, -6085, -6102, -6119, -6136, -6152, -6169, -6185, - -6202, -6218, -6235, -6251, -6267, -6283, -6299, -6315, - -6331, -6347, -6363, -6379, -6395, -6410, -6426, -6441, - -6457, -6472, -6488, -6503, -6518, -6533, -6549, -6564, - -6579, -6594, -6608, -6623, -6638, -6653, -6667, -6682, - -6696, -6711, -6725, -6739, -6754, -6768, -6782, -6796, - -6810, -6824, -6838, -6852, -6865, -6879, -6893, -6906, - -6920, -6933, -6946, -6960, -6973, -6986, -6999, -7012, - -7025, -7038, -7051, -7064, -7076, -7089, -7101, -7114, - -7126, -7139, -7151, -7163, -7175, -7187, -7199, -7211, - -7223, -7235, -7247, -7259, -7270, -7282, -7293, -7305, - -7316, -7327, -7338, -7349, -7361, -7372, -7382, -7393, - -7404, -7415, -7425, -7436, -7446, -7457, -7467, -7478, - -7488, -7498, -7508, -7518, -7528, -7538, -7548, -7557, - -7567, -7577, -7586, -7596, -7605, -7614, -7623, -7633, - -7642, -7651, -7660, -7668, -7677, -7686, -7695, -7703, - -7712, -7720, -7728, -7737, -7745, -7753, -7761, -7769, - -7777, -7785, -7793, -7800, -7808, -7816, -7823, -7830, - -7838, -7845, -7852, -7859, -7866, -7873, -7880, -7887, - -7894, -7900, -7907, -7914, -7920, -7926, -7933, -7939, - -7945, -7951, -7957, -7963, -7969, -7975, -7980, -7986, - -7991, -7997, -8002, -8008, -8013, -8018, -8023, -8028, - -8033, -8038, -8043, -8047, -8052, -8057, -8061, -8066, - -8070, -8074, -8078, -8082, -8086, -8090, -8094, -8098, - -8102, -8105, -8109, -8113, -8116, -8119, -8123, -8126, - -8129, -8132, -8135, -8138, -8141, -8143, -8146, -8149, - -8151, -8153, -8156, -8158, -8160, -8162, -8164, -8166, - -8168, -8170, -8172, -8174, -8175, -8177, -8178, -8179, - -8181, -8182, -8183, -8184, -8185, -8186, -8187, -8187, - -8188, -8189, -8189, -8190, -8190, -8190, -8190, -8190, - -8191, -8190, -8190, -8190, -8190, -8190, -8189, -8189, - -8188, -8187, -8187, -8186, -8185, -8184, -8183, -8182, - -8181, -8179, -8178, -8177, -8175, -8174, -8172, -8170, - -8168, -8166, -8164, -8162, -8160, -8158, -8156, -8153, - -8151, -8149, -8146, -8143, -8141, -8138, -8135, -8132, - -8129, -8126, -8123, -8119, -8116, -8113, -8109, -8105, - -8102, -8098, -8094, -8090, -8086, -8082, -8078, -8074, - -8070, -8066, -8061, -8057, -8052, -8047, -8043, -8038, - -8033, -8028, -8023, -8018, -8013, -8008, -8002, -7997, - -7991, -7986, -7980, -7975, -7969, -7963, -7957, -7951, - -7945, -7939, -7933, -7926, -7920, -7914, -7907, -7900, - -7894, -7887, -7880, -7873, -7866, -7859, -7852, -7845, - -7838, -7830, -7823, -7816, -7808, -7800, -7793, -7785, - -7777, -7769, -7761, -7753, -7745, -7737, -7728, -7720, - -7712, -7703, -7695, -7686, -7677, -7668, -7660, -7651, - -7642, -7633, -7623, -7614, -7605, -7596, -7586, -7577, - -7567, -7557, -7548, -7538, -7528, -7518, -7508, -7498, - -7488, -7478, -7467, -7457, -7446, -7436, -7425, -7415, - -7404, -7393, -7382, -7372, -7361, -7349, -7338, -7327, - -7316, -7305, -7293, -7282, -7270, -7259, -7247, -7235, - -7223, -7211, -7199, -7187, -7175, -7163, -7151, -7139, - -7126, -7114, -7101, -7089, -7076, -7064, -7051, -7038, - -7025, -7012, -6999, -6986, -6973, -6960, -6946, -6933, - -6920, -6906, -6893, -6879, -6865, -6852, -6838, -6824, - -6810, -6796, -6782, -6768, -6754, -6739, -6725, -6711, - -6696, -6682, -6667, -6653, -6638, -6623, -6608, -6594, - -6579, -6564, -6549, -6533, -6518, -6503, -6488, -6472, - -6457, -6441, -6426, -6410, -6395, -6379, -6363, -6347, - -6331, -6315, -6299, -6283, -6267, -6251, -6235, -6218, - -6202, -6185, -6169, -6152, -6136, -6119, -6102, -6085, - -6069, -6052, -6035, -6018, -6001, -5984, -5966, -5949, - -5932, -5914, -5897, -5880, -5862, -5844, -5827, -5809, - -5791, -5774, -5756, -5738, -5720, -5702, -5684, -5666, - -5648, -5629, -5611, -5593, -5574, -5556, -5537, -5519, - -5500, -5482, -5463, -5444, -5425, -5406, -5388, -5369, - -5350, -5331, -5311, -5292, -5273, -5254, -5235, -5215, - -5196, -5176, -5157, -5137, -5118, -5098, -5078, -5059, - -5039, -5019, -4999, -4979, -4959, -4939, -4919, -4899, - -4879, -4859, -4838, -4818, -4798, -4777, -4757, -4736, - -4716, -4695, -4675, -4654, -4633, -4613, -4592, -4571, - -4550, -4529, -4508, -4487, -4466, -4445, -4424, -4403, - -4382, -4360, -4339, -4318, -4296, -4275, -4254, -4232, - -4211, -4189, -4167, -4146, -4124, -4102, -4080, -4059, - -4037, -4015, -3993, -3971, -3949, -3927, -3905, -3883, - -3861, -3839, -3816, -3794, -3772, -3749, -3727, -3705, - -3682, -3660, -3637, -3615, -3592, -3570, -3547, -3524, - -3502, -3479, -3456, -3433, -3410, -3388, -3365, -3342, - -3319, -3296, -3273, -3250, -3227, -3204, -3180, -3157, - -3134, -3111, -3088, -3064, -3041, -3018, -2994, -2971, - -2947, -2924, -2900, -2877, -2853, -2830, -2806, -2783, - -2759, -2735, -2712, -2688, -2664, -2640, -2617, -2593, - -2569, -2545, -2521, -2497, -2473, -2449, -2425, -2401, - -2377, -2353, -2329, -2305, -2281, -2257, -2233, -2208, - -2184, -2160, -2136, -2111, -2087, -2063, -2038, -2014, - -1990, -1965, -1941, -1917, -1892, -1868, -1843, -1819, - -1794, -1770, -1745, -1721, -1696, -1671, -1647, -1622, - -1597, -1573, -1548, -1523, -1499, -1474, -1449, -1425, - -1400, -1375, -1350, -1326, -1301, -1276, -1251, -1226, - -1201, -1177, -1152, -1127, -1102, -1077, -1052, -1027, - -1002, -977, -952, -927, -902, -877, -852, -827, - -802, -777, -752, -727, -702, -677, -652, -627, - -602, -577, -552, -527, -502, -477, -452, -427, - -401, -376, -351, -326, -301, -276, -251, -226, - -201, -175, -150, -125, -100, -75, -50, -25, - 0, 25, 50, 75, 100, 125, 150, 175, - 201, 226, 251, 276, 301, 326, 351, 376, - 401, 427, 452, 477, 502, 527, 552, 577, - 602, 627, 652, 677, 702, 727, 752, 777, - 802, 827, 852, 877, 902, 927, 952, 977, - 1002, 1027, 1052, 1077, 1102, 1127, 1152, 1177, - 1201, 1226, 1251, 1276, 1301, 1326, 1350, 1375, - 1400, 1425, 1449, 1474, 1499, 1523, 1548, 1573, - 1597, 1622, 1647, 1671, 1696, 1721, 1745, 1770, - 1794, 1819, 1843, 1868, 1892, 1917, 1941, 1965, - 1990, 2014, 2038, 2063, 2087, 2111, 2136, 2160, - 2184, 2208, 2233, 2257, 2281, 2305, 2329, 2353, - 2377, 2401, 2425, 2449, 2473, 2497, 2521, 2545, - 2569, 2593, 2617, 2640, 2664, 2688, 2712, 2735, - 2759, 2783, 2806, 2830, 2853, 2877, 2900, 2924, - 2947, 2971, 2994, 3018, 3041, 3064, 3088, 3111, - 3134, 3157, 3180, 3204, 3227, 3250, 3273, 3296, - 3319, 3342, 3365, 3388, 3410, 3433, 3456, 3479, - 3502, 3524, 3547, 3570, 3592, 3615, 3637, 3660, - 3682, 3705, 3727, 3749, 3772, 3794, 3816, 3839, - 3861, 3883, 3905, 3927, 3949, 3971, 3993, 4015, - 4037, 4059, 4080, 4102, 4124, 4146, 4167, 4189, - 4211, 4232, 4254, 4275, 4296, 4318, 4339, 4360, - 4382, 4403, 4424, 4445, 4466, 4487, 4508, 4529, - 4550, 4571, 4592, 4613, 4633, 4654, 4675, 4695, - 4716, 4736, 4757, 4777, 4798, 4818, 4838, 4859, - 4879, 4899, 4919, 4939, 4959, 4979, 4999, 5019, - 5039, 5059, 5078, 5098, 5118, 5137, 5157, 5176, - 5196, 5215, 5235, 5254, 5273, 5292, 5311, 5331, - 5350, 5369, 5388, 5406, 5425, 5444, 5463, 5482, - 5500, 5519, 5537, 5556, 5574, 5593, 5611, 5629, - 5648, 5666, 5684, 5702, 5720, 5738, 5756, 5774, - 5791, 5809, 5827, 5844, 5862, 5880, 5897, 5914, - 5932, 5949, 5966, 5984, 6001, 6018, 6035, 6052, - 6069, 6085, 6102, 6119, 6136, 6152, 6169, 6185, - 6202, 6218, 6235, 6251, 6267, 6283, 6299, 6315, - 6331, 6347, 6363, 6379, 6395, 6410, 6426, 6441, - 6457, 6472, 6488, 6503, 6518, 6533, 6549, 6564, - 6579, 6594, 6608, 6623, 6638, 6653, 6667, 6682, - 6696, 6711, 6725, 6739, 6754, 6768, 6782, 6796, - 6810, 6824, 6838, 6852, 6865, 6879, 6893, 6906, - 6920, 6933, 6946, 6960, 6973, 6986, 6999, 7012, - 7025, 7038, 7051, 7064, 7076, 7089, 7101, 7114, - 7126, 7139, 7151, 7163, 7175, 7187, 7199, 7211, - 7223, 7235, 7247, 7259, 7270, 7282, 7293, 7305, - 7316, 7327, 7338, 7349, 7361, 7372, 7382, 7393, - 7404, 7415, 7425, 7436, 7446, 7457, 7467, 7478, - 7488, 7498, 7508, 7518, 7528, 7538, 7548, 7557, - 7567, 7577, 7586, 7596, 7605, 7614, 7623, 7633, - 7642, 7651, 7660, 7668, 7677, 7686, 7695, 7703, - 7712, 7720, 7728, 7737, 7745, 7753, 7761, 7769, - 7777, 7785, 7793, 7800, 7808, 7816, 7823, 7830, - 7838, 7845, 7852, 7859, 7866, 7873, 7880, 7887, - 7894, 7900, 7907, 7914, 7920, 7926, 7933, 7939, - 7945, 7951, 7957, 7963, 7969, 7975, 7980, 7986, - 7991, 7997, 8002, 8008, 8013, 8018, 8023, 8028, - 8033, 8038, 8043, 8047, 8052, 8057, 8061, 8066, - 8070, 8074, 8078, 8082, 8086, 8090, 8094, 8098, - 8102, 8105, 8109, 8113, 8116, 8119, 8123, 8126, - 8129, 8132, 8135, 8138, 8141, 8143, 8146, 8149, - 8151, 8153, 8156, 8158, 8160, 8162, 8164, 8166, - 8168, 8170, 8172, 8174, 8175, 8177, 8178, 8179, - 8181, 8182, 8183, 8184, 8185, 8186, 8187, 8187, - 8188, 8189, 8189, 8190, 8190, 8190, 8190, 8190, - 8191, 8190, 8190, 8190, 8190, 8190, 8189, 8189, - 8188, 8187, 8187, 8186, 8185, 8184, 8183, 8182, - 8181, 8179, 8178, 8177, 8175, 8174, 8172, 8170, - 8168, 8166, 8164, 8162, 8160, 8158, 8156, 8153, - 8151, 8149, 8146, 8143, 8141, 8138, 8135, 8132, - 8129, 8126, 8123, 8119, 8116, 8113, 8109, 8105, - 8102, 8098, 8094, 8090, 8086, 8082, 8078, 8074, - 8070, 8066, 8061, 8057, 8052, 8047, 8043, 8038, - 8033, 8028, 8023, 8018, 8013, 8008, 8002, 7997, - 7991, 7986, 7980, 7975, 7969, 7963, 7957, 7951, - 7945, 7939, 7933, 7926, 7920, 7914, 7907, 7900, - 7894, 7887, 7880, 7873, 7866, 7859, 7852, 7845, - 7838, 7830, 7823, 7816, 7808, 7800, 7793, 7785, - 7777, 7769, 7761, 7753, 7745, 7737, 7728, 7720, - 7712, 7703, 7695, 7686, 7677, 7668, 7660, 7651, - 7642, 7633, 7623, 7614, 7605, 7596, 7586, 7577, - 7567, 7557, 7548, 7538, 7528, 7518, 7508, 7498, - 7488, 7478, 7467, 7457, 7446, 7436, 7425, 7415, - 7404, 7393, 7382, 7372, 7361, 7349, 7338, 7327, - 7316, 7305, 7293, 7282, 7270, 7259, 7247, 7235, - 7223, 7211, 7199, 7187, 7175, 7163, 7151, 7139, - 7126, 7114, 7101, 7089, 7076, 7064, 7051, 7038, - 7025, 7012, 6999, 6986, 6973, 6960, 6946, 6933, - 6920, 6906, 6893, 6879, 6865, 6852, 6838, 6824, - 6810, 6796, 6782, 6768, 6754, 6739, 6725, 6711, - 6696, 6682, 6667, 6653, 6638, 6623, 6608, 6594, - 6579, 6564, 6549, 6533, 6518, 6503, 6488, 6472, - 6457, 6441, 6426, 6410, 6395, 6379, 6363, 6347, - 6331, 6315, 6299, 6283, 6267, 6251, 6235, 6218, - 6202, 6185, 6169, 6152, 6136, 6119, 6102, 6085, - 6069, 6052, 6035, 6018, 6001, 5984, 5966, 5949, - 5932, 5914, 5897, 5880, 5862, 5844, 5827, 5809, - 5791, 5774, 5756, 5738, 5720, 5702, 5684, 5666, - 5648, 5629, 5611, 5593, 5574, 5556, 5537, 5519, - 5500, 5482, 5463, 5444, 5425, 5406, 5388, 5369, - 5350, 5331, 5311, 5292, 5273, 5254, 5235, 5215, - 5196, 5176, 5157, 5137, 5118, 5098, 5078, 5059, - 5039, 5019, 4999, 4979, 4959, 4939, 4919, 4899, - 4879, 4859, 4838, 4818, 4798, 4777, 4757, 4736, - 4716, 4695, 4675, 4654, 4633, 4613, 4592, 4571, - 4550, 4529, 4508, 4487, 4466, 4445, 4424, 4403, - 4382, 4360, 4339, 4318, 4296, 4275, 4254, 4232, - 4211, 4189, 4167, 4146, 4124, 4102, 4080, 4059, - 4037, 4015, 3993, 3971, 3949, 3927, 3905, 3883, - 3861, 3839, 3816, 3794, 3772, 3749, 3727, 3705, - 3682, 3660, 3637, 3615, 3592, 3570, 3547, 3524, - 3502, 3479, 3456, 3433, 3410, 3388, 3365, 3342, - 3319, 3296, 3273, 3250, 3227, 3204, 3180, 3157, - 3134, 3111, 3088, 3064, 3041, 3018, 2994, 2971, - 2947, 2924, 2900, 2877, 2853, 2830, 2806, 2783, - 2759, 2735, 2712, 2688, 2664, 2640, 2617, 2593, - 2569, 2545, 2521, 2497, 2473, 2449, 2425, 2401, - 2377, 2353, 2329, 2305, 2281, 2257, 2233, 2208, - 2184, 2160, 2136, 2111, 2087, 2063, 2038, 2014, - 1990, 1965, 1941, 1917, 1892, 1868, 1843, 1819, - 1794, 1770, 1745, 1721, 1696, 1671, 1647, 1622, - 1597, 1573, 1548, 1523, 1499, 1474, 1449, 1425, - 1400, 1375, 1350, 1326, 1301, 1276, 1251, 1226, - 1201, 1177, 1152, 1127, 1102, 1077, 1052, 1027, - 1002, 977, 952, 927, 902, 877, 852, 827, - 802, 777, 752, 727, 702, 677, 652, 627, - 602, 577, 552, 527, 502, 477, 452, 427, - 401, 376, 351, 326, 301, 276, 251, 226, - 201, 175, 150, 125, 100, 75, 50, 25, - }; diff --git a/navit/support/espeak/speak.c b/navit/support/espeak/speak.c deleted file mode 100755 index ab33a867b..000000000 --- a/navit/support/espeak/speak.c +++ /dev/null @@ -1,898 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include "speech.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifndef PLATFORM_DOS -#ifdef PLATFORM_WINDOWS -#include <windows.h> -#include <winreg.h> -#else -#include <unistd.h> -#endif -#endif - -#ifndef NEED_GETOPT -#include <getopt.h> -#endif -#include <time.h> -#include <signal.h> -#include <locale.h> -#include <sys/stat.h> - -#include "speak_lib.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" - - - -extern void Write4Bytes(FILE *f, int value); -char path_home[N_PATH_HOME]; // this is the espeak-data directory - -char filetype[5]; -char wavefile[200]; -int (* uri_callback)(int, const char *, const char *) = NULL; -int (* phoneme_callback)(const char *) = NULL; - -FILE *f_wave = NULL; -int quiet = 0; -unsigned int samples_total = 0; -unsigned int samples_split = 0; -unsigned int wavefile_count = 0; -int end_of_sentence = 0; - -static const char *help_text = -"\nspeak [options] [\"<words>\"]\n\n" -"-f <text file> Text file to speak\n" -"--stdin Read text input from stdin instead of a file\n\n" -"If neither -f nor --stdin, <words> are spoken, or if none then text is\n" -"spoken from stdin, each line separately.\n\n" -"-a <integer>\n" -"\t Amplitude, 0 to 200, default is 100\n" -"-g <integer>\n" -"\t Word gap. Pause between words, units of 10mS at the default speed\n" -"-l <integer>\n" -"\t Line length. If not zero (which is the default), consider\n" -"\t lines less than this length as end-of-clause\n" -"-p <integer>\n" -"\t Pitch adjustment, 0 to 99, default is 50\n" -"-s <integer>\n" -"\t Speed in words per minute 80 to 390, default is 170\n" -"-v <voice name>\n" -"\t Use voice file of this name from espeak-data/voices\n" -"-w <wave file name>\n" -"\t Write output to this WAV file, rather than speaking it directly\n" -"-b\t Input text encoding, 1=UTF8, 2=8 bit, 4=16 bit \n" -"-m\t Interpret SSML markup, and ignore other < > tags\n" -"-q\t Quiet, don't produce any speech (may be useful with -x)\n" -"-x\t Write phoneme mnemonics to stdout\n" -"-X\t Write phonemes mnemonics and translation trace to stdout\n" -"-z\t No final sentence pause at the end of the text\n" -"--stdout Write speech output to stdout\n" -"--compile=<voice name>\n" -"\t Compile the pronunciation rules and dictionary in the current\n" -"\t directory. =<voice name> is optional and specifies which language\n" -"--path=\"<path>\"\n" -"\t Specifies the directory containing the espeak-data directory\n" -"--phonout=\"<filename>\"\n" -"\t Write output from -x -X commands and mbrola phoneme data to this file\n" -"--punct=\"<characters>\"\n" -"\t Speak the names of punctuation characters during speaking. If\n" -"\t =<characters> is omitted, all punctuation is spoken.\n" -"--split=\"<minutes>\"\n" -"\t Starts a new WAV file every <minutes>. Used with -w\n" -"--voices=<language>\n" -"\t List the available voices for the specified language.\n" -"\t If <language> is omitted, then list all voices.\n" -"-k <integer>\n" -"\t Indicate capital letters with: 1=sound, 2=the word \"capitals\",\n" -"\t higher values = a pitch increase (try -k20).\n"; - - -void DisplayVoices(FILE *f_out, char *language); - -USHORT voice_pcnt[N_PEAKS+1][3]; - - - -int GetFileLength(const char *filename) -{//==================================== - struct stat statbuf; - - if(stat(filename,&statbuf) != 0) - return(0); - - if((statbuf.st_mode & S_IFMT) == S_IFDIR) -// if(S_ISDIR(statbuf.st_mode)) - return(-2); // a directory - - return(statbuf.st_size); -} // end of GetFileLength - - -char *Alloc(int size) -{//================== - char *p; - if((p = (char *)malloc(size)) == NULL) - fprintf(stderr,"Can't allocate memory\n"); - return(p); -} - -void Free(void *ptr) -{//================= - if(ptr != NULL) - free(ptr); -} - - -void DisplayVoices(FILE *f_out, char *language) -{//============================================ - int ix; - const char *p; - int len; - int count; - int scores = 0; - const espeak_VOICE *v; - const char *lang_name; - char age_buf[12]; - const espeak_VOICE **voices; - espeak_VOICE voice_select; - - static char genders[4] = {' ','M','F',' '}; - - if((language != NULL) && (language[0] != 0)) - { - // display only voices for the specified language, in order of priority - voice_select.languages = language; - voice_select.age = 0; - voice_select.gender = 0; - voice_select.name = NULL; - voices = espeak_ListVoices(&voice_select); - scores = 1; - } - else - { - voices = espeak_ListVoices(NULL); - } - - fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Langs\n"); - - for(ix=0; (v = voices[ix]) != NULL; ix++) - { - count = 0; - p = v->languages; - while(*p != 0) - { - len = strlen(p+1); - lang_name = p+1; - - if(v->age == 0) - strcpy(age_buf," "); - else - sprintf(age_buf,"%3d",v->age); - - if(count==0) - { - fprintf(f_out,"%2d %-12s%s%c %-17s %-11s ", - p[0],lang_name,age_buf,genders[v->gender],v->name,v->identifier); - } - else - { - fprintf(f_out,"(%s %d)",lang_name,p[0]); - } - count++; - p += len+2; - } -// if(scores) -// fprintf(f_out,"%3d ",v->score); - fputc('\n',f_out); - } -} // end of DisplayVoices - - - - -static int OpenWaveFile(const char *path, int rate) -//================================================= -{ - // Set the length of 0x7ffff000 for --stdout - // This will be changed to the correct length for -w (write to file) - static unsigned char wave_hdr[44] = { - 'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ', - 0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0, - 2,0,0x10,0,'d','a','t','a', 0x00,0xf0,0xff,0x7f}; - - if(path == NULL) - return(2); - - if(strcmp(path,"stdout")==0) - f_wave = stdout; - else - f_wave = fopen(path,"wb"); - - if(f_wave != NULL) - { - fwrite(wave_hdr,1,24,f_wave); - Write4Bytes(f_wave,rate); - Write4Bytes(f_wave,rate * 2); - fwrite(&wave_hdr[32],1,12,f_wave); - return(0); - } - return(1); -} // end of OpenWaveFile - - - - -static void CloseWaveFile() -//========================= -{ - unsigned int pos; - - if((f_wave == NULL) || (f_wave == stdout)) - return; - - fflush(f_wave); - pos = ftell(f_wave); - - fseek(f_wave,4,SEEK_SET); - Write4Bytes(f_wave,pos - 8); - - fseek(f_wave,40,SEEK_SET); - Write4Bytes(f_wave,pos - 44); - - - fclose(f_wave); - f_wave = NULL; - -} // end of CloseWaveFile - - - - -void MarkerEvent(int type, unsigned int char_position, int value, unsigned char *out_ptr) -{//====================================================================================== -// Do nothing in the command-line version. - if(type == 2) - end_of_sentence = 1; -} // end of MarkerEvent - - -static int WavegenFile(void) -{//========================= - int finished; - unsigned char wav_outbuf[512]; - char fname[210]; - - out_ptr = out_start = wav_outbuf; - out_end = wav_outbuf + sizeof(wav_outbuf); - - finished = WavegenFill(0); - - if(quiet) - return(finished); - - if(f_wave == NULL) - { - sprintf(fname,"%s_%.2d%s",wavefile,++wavefile_count,filetype); - if(OpenWaveFile(fname, samplerate) != 0) - return(1); - } - - if(end_of_sentence) - { - end_of_sentence = 0; - if((samples_split > 0 ) && (samples_total > samples_split)) - { - CloseWaveFile(); - samples_total = 0; - } - } - - if(f_wave != NULL) - { - samples_total += (out_ptr - wav_outbuf)/2; - fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave); - } - return(finished); -} // end of WavegenFile - - - -static void init_path(char *argv0, char *path_specified) -{//===================================================== - - if(path_specified) - { - sprintf(path_home,"%s/espeak-data",path_specified); - return; - } - -#ifdef PLATFORM_WINDOWS - HKEY RegKey; - unsigned long size; - unsigned long var_type; - char *p; - char *env; - unsigned char buf[sizeof(path_home)-12]; - -#if 0 - if(((env = getenv("ESPEAK_DATA_PATH")) != NULL) && ((strlen(env)+12) < sizeof(path_home))) - { - sprintf(path_home,"%s\\espeak-data",env); - if(GetFileLength(path_home) == -2) - return; // an espeak-data directory exists in the directory specified by environment variable - } -#endif - - strcpy(path_home,argv0); - if((p = strrchr(path_home,'\\')) != NULL) - { - strcpy(&p[1],"espeak-data"); - if(GetFileLength(path_home) == -2) - return; // an espeak-data directory exists in the same directory as the espeak program - } - - // otherwise, look in the Windows Registry - buf[0] = 0; - RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Speech\\Voices\\Tokens\\eSpeak", 0, KEY_READ, &RegKey); - size = sizeof(buf); - var_type = REG_SZ; - RegQueryValueEx(RegKey, "path", 0, &var_type, buf, &size); - - sprintf(path_home,"%s\\espeak-data",buf); -#else -#ifdef PLATFORM_DOS - strcpy(path_home,PATH_ESPEAK_DATA); -#else - char *env; -#if 0 - if((env = getenv("ESPEAK_DATA_PATH")) != NULL) - { - snprintf(path_home,sizeof(path_home),"%s/espeak-data",env); - if(GetFileLength(path_home) == -2) - return; // an espeak-data directory exists - } -#endif - -#if 0 - snprintf(path_home,sizeof(path_home),"%s/espeak-data",getenv("HOME")); - if(access(path_home,R_OK) != 0) - { - strcpy(path_home,PATH_ESPEAK_DATA); - } -#endif -#endif -#endif -} - - -static int initialise(void) -{//======================== - int param; - int result; - - // It seems that the wctype functions don't work until the locale has been set - // to something other than the default "C". Then, not only Latin1 but also the - // other characters give the correct results with iswalpha() etc. -#ifdef PLATFORM_RISCOS - setlocale(LC_CTYPE,"ISO8859-1"); -#else -#if 0 - if(setlocale(LC_CTYPE,"en_US.UTF-8") == NULL) - { - if(setlocale(LC_CTYPE,"UTF-8") == NULL) - setlocale(LC_CTYPE,""); - } -#endif -#endif - - - WavegenInit(22050,0); // 22050 - if((result = LoadPhData()) != 1) - { - if(result == -1) - { - fprintf(stderr,"Failed to load espeak-data\n"); - exit(1); - } - else - fprintf(stderr,"Wrong version of espeak-data 0x%x (expects 0x%x) at %s\n",result,version_phdata,path_home); - } - LoadConfig(); - SetVoiceStack(NULL); - SynthesizeInit(); - - for(param=0; param<N_SPEECH_PARAM; param++) - param_stack[0].parameter[param] = param_defaults[param]; - - return(0); -} - - -static void StopSpeak(int unused) -{//============================== -// signal(SIGINT,SIG_IGN); - // DEBUG -// printf("\n*** Interrupting speech output (use Ctrl-D to actually quit).\n"); - fflush(stdout); - SpeakNextClause(NULL,NULL,5); -// signal(SIGINT,StopSpeak); -} // end of StopSpeak() - -#ifdef NEED_GETOPT - struct option { - char *name; - int has_arg; - int *flag; - int val; - }; - int optind; - static int optional_argument; - static const char *arg_opts = "abfgklpsvw"; // which options have arguments - static char *opt_string=""; -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 -#endif - -int main (int argc, char **argv) -//============================== -{ - 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'}, - {"stdin", no_argument, 0, 0x100}, - {"compile-debug", optional_argument, 0, 0x101}, - {"compile", optional_argument, 0, 0x102}, - {"punct", optional_argument, 0, 0x103}, - {"voices", optional_argument, 0, 0x104}, - {"stdout", no_argument, 0, 0x105}, - {"split", optional_argument, 0, 0x106}, - {"path", required_argument, 0, 0x107}, - {"phonout", required_argument, 0, 0x108}, - {0, 0, 0, 0} - }; - - static const char *err_load = "Failed to read "; - - FILE *f_text=NULL; - const char *p_text=NULL; - char *data_path = NULL; // use default path for espeak-data - - int option_index = 0; - int c; - int value; - int speed=170; - int ix; - char *optarg2; - int amp = 100; // default - int wordgap = 0; - int speaking = 0; - int flag_stdin = 0; - int flag_compile = 0; - int pitch_adjustment = 50; - espeak_VOICE voice_select; - char filename[200]; - char voicename[40]; - char dictname[40]; - - voicename[0] = 0; - mbrola_name[0] = 0; - dictname[0] = 0; - wavefile[0] = 0; - filename[0] = 0; - option_linelength = 0; - option_phonemes = 0; - option_waveout = 0; - option_wordgap = 0; - option_endpause = 1; - option_phoneme_input = 1; - option_multibyte = espeakCHARS_AUTO; // auto - f_trans = stdout; - -#ifdef NEED_GETOPT - optind = 1; - opt_string = ""; - while(optind < argc) - { - int len; - char *p; - - if((c = *opt_string) == 0) - { - opt_string = argv[optind]; - if(opt_string[0] != '-') - break; - - optind++; - opt_string++; - c = *opt_string; - } - opt_string++; - p = optarg2 = opt_string; - - if(c == '-') - { - opt_string=""; - for(ix=0; ;ix++) - { - if(long_options[ix].name == 0) - break; - len = strlen(long_options[ix].name); - if(memcmp(long_options[ix].name,p,len)==0) - { - c = long_options[ix].val; - optarg2 = NULL; - - if((long_options[ix].has_arg != 0) && (p[len]=='=')) - { - optarg2 = &p[len+1]; - } - break; - } - } - } - else - if(strchr(arg_opts,c) != NULL) - { - opt_string=""; - if(optarg2[0]==0) - { - // the option's value is in the next argument - optarg2 = argv[optind++]; - } - } -#else - while(1) - { - c = getopt_long (argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value - long_options, &option_index); - - /* Detect the end of the options. */ - if (c == -1) - break; - optarg2 = optarg; -#endif - - switch (c) - { - case 'b': - // input character encoding, 8bit, 16bit, UTF8 - option_multibyte = espeakCHARS_8BIT; - if((sscanf(optarg2,"%d",&value) == 1) && (value <= 4)) - option_multibyte= value; - break; - - case 'h': - printf("\nspeak text-to-speech: %s\n%s",version_string,help_text); - exit(0); - break; - - case 'k': - option_capitals = atoi(optarg2); - break; - - case 'x': - option_phonemes = 1; - break; - - case 'X': - option_phonemes = 2; - break; - - case 'm': - option_ssml = 1; - break; - - case 'p': - pitch_adjustment = atoi(optarg2); - if(pitch_adjustment > 99) pitch_adjustment = 99; - break; - - case 'q': - quiet = 1; - break; - - case 'f': - strncpy0(filename,optarg2,sizeof(filename)); - break; - - case 'l': - value = 0; - value = atoi(optarg2); - option_linelength = value; - break; - - case 'a': - amp = atoi(optarg2); - break; - - case 's': - speed = atoi(optarg2); - break; - - case 'g': - wordgap = atoi(optarg2); - break; - - case 'v': - strncpy0(voicename,optarg2,sizeof(voicename)); - break; - - case 'w': - option_waveout = 1; - strncpy0(wavefile,optarg2,sizeof(wavefile)); - break; - - case 'z': - option_endpause = 0; - break; - - case 0x100: // --stdin - flag_stdin = 1; - break; - - case 0x105: // --stdout - option_waveout = 1; - strcpy(wavefile,"stdout"); - break; - - case 0x101: // --compile-debug - case 0x102: // --compile - if(optarg2 != NULL) - strncpy0(voicename,optarg2,sizeof(voicename)); - flag_compile = c; - break; - - case 0x103: // --punct - option_punctuation = 1; - if(optarg2 != NULL) - { - ix = 0; - while((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++; - option_punctlist[N_PUNCTLIST-1] = 0; - option_punctuation = 2; - } - break; - - case 0x104: // --voices - init_path(argv[0],data_path); - DisplayVoices(stdout,optarg2); - exit(0); - - case 0x106: // -- split - if(optarg2 == NULL) - samples_split = 30; // default 30 minutes - else - samples_split = atoi(optarg2); - break; - - case 0x107: // --path - data_path = optarg2; - break; - - case 0x108: // --phonout - if((f_trans = fopen(optarg2,"w")) == NULL) - { - fprintf(stderr,"Can't write to: %s\n",optarg2); - f_trans = stderr; - } - break; - - default: - exit(0); - } - } - - init_path(argv[0],data_path); - initialise(); - - - if(flag_compile) - { - LoadVoice(voicename,5); - -#ifdef PLATFORM_DOS - char path_dsource[sizeof(path_home)+20]; - strcpy(path_dsource,path_home); - path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end - strcat(path_dsource,"dictsource\\"); - CompileDictionary(path_dsource,dictionary_name,NULL,NULL, flag_compile & 0x1); -#else -#ifdef PLATFORM_WINDOWS - char path_dsource[sizeof(path_home)+20]; - strcpy(path_dsource,path_home); - path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end - strcat(path_dsource,"dictsource\\"); - CompileDictionary(path_dsource,dictionary_name,NULL,NULL, flag_compile & 0x1); -#else - CompileDictionary(NULL,dictionary_name,NULL,NULL, flag_compile & 0x1); -#endif -#endif - exit(0); - } - - - if(voicename[0] == 0) - strcpy(voicename,"default"); - - if(SetVoiceByName(voicename) != EE_OK) - { - memset(&voice_select,0,sizeof(voice_select)); - voice_select.languages = voicename; - if(SetVoiceByProperties(&voice_select) != EE_OK) - { - fprintf(stderr,"%svoice '%s'\n",err_load,voicename); - exit(2); - } - } - - SetParameter(espeakRATE,speed,0); - SetParameter(espeakVOLUME,amp,0); - SetParameter(espeakCAPITALS,option_capitals,0); - SetParameter(espeakPUNCTUATION,option_punctuation,0); - SetParameter(espeakWORDGAP,wordgap,0); - - if(pitch_adjustment != 50) - { - SetParameter(espeakPITCH,pitch_adjustment,0); - } - DoVoiceChange(voice); - - if(filename[0]==0) - { - if((optind < argc) && (flag_stdin == 0)) - { - // there's a non-option parameter, and no -f or --stdin - // use it as text - p_text = argv[optind]; - } - else - { - f_text = stdin; - if(flag_stdin == 0) - option_linelength = -1; // single input lines on stdin - } - } - else - { - f_text = fopen(filename,"r"); - } - - if((f_text == NULL) && (p_text == NULL)) - { - fprintf(stderr,"%sfile '%s'\n",err_load,filename); - exit(1); - } - - if(option_waveout || quiet) - { - if(quiet) - { - // no sound output - OpenWaveFile(NULL,samplerate); - option_waveout = 1; - } - else - { - // write sound output to a WAV file - samples_split = (samplerate * samples_split) * 60; - - if(samples_split) - { - // don't open the wav file until we start generating speech - char *extn; - extn = strrchr(wavefile,'.'); - if((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) - { - strcpy(filetype,extn); - *extn = 0; - } - } - else - if(OpenWaveFile(wavefile,samplerate) != 0) - { - fprintf(stderr,"Can't write to output file '%s'\n'",wavefile); - exit(3); - } - } - - InitText(0); - SpeakNextClause(f_text,p_text,0); - - ix = 1; - for(;;) - { - if(WavegenFile() != 0) - { - if(ix == 0) - break; // finished, wavegen command queue is empty - } - - if(Generate(phoneme_list,&n_phoneme_list,1)==0) - { - ix = SpeakNextClause(NULL,NULL,1); - } - } - - CloseWaveFile(); - } - else - { - // Silence on ^C or SIGINT -// signal(SIGINT,StopSpeak); - - // output sound using portaudio - WavegenInitSound(); - - InitText(0); - SpeakNextClause(f_text,p_text,0); - - if(option_quiet) - { - while(SpeakNextClause(NULL,NULL,1) != 0); - return(0); - } - -#ifdef USE_PORTAUDIO - speaking = 1; - while(speaking) - { - // NOTE: if nanosleep() isn't recognised on your system, try replacing - // this by sleep(1); -#ifdef PLATFORM_WINDOWS - Sleep(300); // 0.3s -#else -#ifdef USE_NANOSLEEP - struct timespec period; - struct timespec remaining; - period.tv_sec = 0; - period.tv_nsec = 300000000; // 0.3 sec - nanosleep(&period,&remaining); -#else - sleep(1); -#endif -#endif - if(SynthOnTimer() != 0) - speaking = 0; - } -#else - fprintf(stderr,"-w option must be used because the program was built without a sound interface\n"); -#endif // USE_PORTAUDIO - } - - if((f_trans != stdout) && (f_trans != stderr)) - fclose(f_trans); // needed for WinCe - return(0); -} diff --git a/navit/support/espeak/speak_init.c b/navit/support/espeak/speak_init.c deleted file mode 100644 index 06a34235f..000000000 --- a/navit/support/espeak/speak_init.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "../../plugin.h" - -void -plugin_init(void) -{ -} diff --git a/navit/support/espeak/speak_lib.c b/navit/support/espeak/speak_lib.c deleted file mode 100644 index 85c1b39a3..000000000 --- a/navit/support/espeak/speak_lib.c +++ /dev/null @@ -1,1156 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include "stdio.h" -#include "ctype.h" -#include "string.h" -#include "stdlib.h" -#include "wchar.h" -#include "locale.h" -#include <assert.h> -#include <time.h> - -#include "speech.h" - -#include <sys/stat.h> -#ifdef PLATFORM_WINDOWS -#include <windows.h> -#else -#include <unistd.h> -#endif - -#include "speak_lib.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" -#include "debug.h" - -#include "fifo.h" -#include "event.h" -#include "wave.h" - -unsigned char *outbuf=NULL; -extern espeak_VOICE voice_selected; - -espeak_EVENT *event_list=NULL; -int event_list_ix=0; -int n_event_list; -long count_samples; -void* my_audio=NULL; - -static unsigned int my_unique_identifier=0; -static void* my_user_data=NULL; -static espeak_AUDIO_OUTPUT my_mode=AUDIO_OUTPUT_SYNCHRONOUS; -static int synchronous_mode = 1; -t_espeak_callback* synth_callback = NULL; -int (* uri_callback)(int, const char *, const char *) = NULL; -int (* phoneme_callback)(const char *) = NULL; - -char path_home[N_PATH_HOME]; // this is the espeak-data directory - - -#ifdef USE_ASYNC - -static int dispatch_audio(short* outbuf, int length, espeak_EVENT* event) -{//====================================================================== - ENTER("dispatch_audio"); - - int a_wave_can_be_played = fifo_is_command_enabled(); - -#ifdef DEBUG_ENABLED - SHOW("*** dispatch_audio > uid=%d, [write=%p (%d bytes)], sample=%d, a_wave_can_be_played = %d\n", - (event) ? event->unique_identifier : 0, wave_test_get_write_buffer(), 2*length, - (event) ? event->sample : 0, - a_wave_can_be_played); -#endif - - switch(my_mode) - { - case AUDIO_OUTPUT_PLAYBACK: - { - if (outbuf && length && a_wave_can_be_played) - { - wave_write (my_audio, (char*)outbuf, 2*length); - } - - while(a_wave_can_be_played) { - // TBD: some event are filtered here but some insight might be given - // TBD: in synthesise.cpp for avoiding to create WORDs with size=0. - // TBD: For example sentence "or ALT)." returns three words - // "or", "ALT" and "". - // TBD: the last one has its size=0. - if (event && (event->type == espeakEVENT_WORD) && (event->length==0)) - { - break; - } - espeak_ERROR a_error = event_declare(event); - if (a_error != EE_BUFFER_FULL) - { - break; - } - SHOW_TIME("dispatch_audio > EE_BUFFER_FULL\n"); - usleep(10000); - a_wave_can_be_played = fifo_is_command_enabled(); - } - } - break; - - case AUDIO_OUTPUT_RETRIEVAL: - if (synth_callback) - { - synth_callback(outbuf, length, event); - } - break; - - case AUDIO_OUTPUT_SYNCHRONOUS: - case AUDIO_OUTPUT_SYNCH_PLAYBACK: - break; - } - - if (!a_wave_can_be_played) - { - SHOW_TIME("dispatch_audio > synth must be stopped!\n"); - } - - SHOW_TIME("LEAVE dispatch_audio\n"); - - return (a_wave_can_be_played==0); // 1 = stop synthesis -} - - - -static int create_events(short* outbuf, int length, espeak_EVENT* event, uint32_t the_write_pos) -{//===================================================================== - int finished; - int i=0; - - // The audio data are written to the output device. - // The list of events in event_list (index: event_list_ix) is read: - // Each event is declared to the "event" object which stores them internally. - // The event object is responsible of calling the external callback - // as soon as the relevant audio sample is played. - - do - { // for each event - espeak_EVENT* event; - if (event_list_ix == 0) - { - event = NULL; - } - else - { - event = event_list + i; -#ifdef DEBUG_ENABLED - SHOW("Synthesize: event->sample(%d) + %d = %d\n", event->sample, the_write_pos, event->sample + the_write_pos); -#endif - event->sample += the_write_pos; - } -#ifdef DEBUG_ENABLED - SHOW("*** Synthesize: i=%d (event_list_ix=%d), length=%d\n",i,event_list_ix,length); -#endif - finished = dispatch_audio((short *)outbuf, length, event); - length = 0; // the wave data are played once. - i++; - } while((i < event_list_ix) && !finished); - return finished; -} - - -int sync_espeak_terminated_msg( uint unique_identifier, void* user_data) -{//===================================================================== - ENTER("sync_espeak_terminated_msg"); - - int finished=0; - - memset(event_list, 0, 2*sizeof(espeak_EVENT)); - - event_list[0].type = espeakEVENT_MSG_TERMINATED; - event_list[0].unique_identifier = unique_identifier; - event_list[0].user_data = user_data; - event_list[1].type = espeakEVENT_LIST_TERMINATED; - event_list[1].unique_identifier = unique_identifier; - event_list[1].user_data = user_data; - - if (my_mode==AUDIO_OUTPUT_PLAYBACK) - { - while(1) - { - espeak_ERROR a_error = event_declare(event_list); - if (a_error != EE_BUFFER_FULL) - { - break; - } - SHOW_TIME("sync_espeak_terminated_msg > EE_BUFFER_FULL\n"); - usleep(10000); - } - } - else - { - if (synth_callback) - { - finished=synth_callback(NULL,0,event_list); - } - } - return finished; -} - -#endif - - -static void select_output(espeak_AUDIO_OUTPUT output_type) -{//======================================================= - my_mode = output_type; - my_audio = NULL; - synchronous_mode = 1; - option_waveout = 1; // inhibit portaudio callback from wavegen.cpp - - switch(my_mode) - { - case AUDIO_OUTPUT_PLAYBACK: - synchronous_mode = 0; -#ifdef USE_ASYNC - wave_init(); - wave_set_callback_is_output_enabled( fifo_is_command_enabled); - my_audio = wave_open("alsa"); - event_init(); -#endif - break; - - case AUDIO_OUTPUT_RETRIEVAL: - synchronous_mode = 0; - break; - - case AUDIO_OUTPUT_SYNCHRONOUS: - break; - - case AUDIO_OUTPUT_SYNCH_PLAYBACK: - option_waveout = 0; - WavegenInitSound(); - break; - } -} // end of select_output - - - - -int GetFileLength(const char *filename) -{//==================================== - struct stat statbuf; - - if(stat(filename,&statbuf) != 0) - return(0); - - if((statbuf.st_mode & S_IFMT) == S_IFDIR) - // if(S_ISDIR(statbuf.st_mode)) - return(-2); // a directory - - return(statbuf.st_size); -} // end of GetFileLength - - -char *Alloc(int size) -{//================== - char *p; - 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 - return(p); -} - -void Free(void *ptr) -{//================= - if(ptr != NULL) - free(ptr); -} - - - -static void init_path(const char *path) -{//==================================== -#ifdef PLATFORM_WINDOWS - HKEY RegKey; - unsigned long size; - unsigned long var_type; - char *env; - unsigned char buf[sizeof(path_home)-13]; - - if(path != NULL) - { - sprintf(path_home,"%s/espeak-data",path); - return; - } - - if((env = getenv("ESPEAK_DATA_PATH")) != NULL) - { - sprintf(path_home,"%s/espeak-data",env); - if(GetFileLength(path_home) == -2) - return; // an espeak-data directory exists - } - - buf[0] = 0; - RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Speech\\Voices\\Tokens\\eSpeak", 0, KEY_READ, &RegKey); - size = sizeof(buf); - var_type = REG_SZ; - RegQueryValueExA(RegKey, "path", 0, &var_type, buf, &size); - - sprintf(path_home,"%s\\espeak-data",buf); - -#else - char *env; - - if(path != NULL) - { - snprintf(path_home,sizeof(path_home),"%s/espeak-data",path); - return; - } - - // check for environment variable - if((env = getenv("ESPEAK_DATA_PATH")) != NULL) - { - snprintf(path_home,sizeof(path_home),"%s/espeak-data",env); - if(GetFileLength(path_home) == -2) - return; // an espeak-data directory exists - } - - snprintf(path_home,sizeof(path_home),"%s/espeak-data",getenv("HOME")); - if(access(path_home,R_OK) != 0) - { - strcpy(path_home,PATH_ESPEAK_DATA); - } -#endif -} - -static int initialise(void) -{//======================== - int param; - int result; - - LoadConfig(); - WavegenInit(22050,0); // 22050 - if((result = LoadPhData()) != 1) - { - if(result == -1) - { - fprintf(stderr,"Failed to load espeak-data\n"); - exit(1); - } - else - fprintf(stderr,"Wrong version of espeak-data 0x%x (expects 0x%x) at %s\n",result,version_phdata,path_home); - } - - memset(&voice_selected,0,sizeof(voice_selected)); - SetVoiceStack(NULL); - SynthesizeInit(); - InitNamedata(); - - for(param=0; param<N_SPEECH_PARAM; param++) - param_stack[0].parameter[param] = param_defaults[param]; - - return(0); -} - - -static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, int flags) -{//======================================================================================== - // Fill the buffer with output sound - int length; - int finished = 0; - int count_buffers = 0; -#ifdef USE_ASYNC - uint32_t a_write_pos=0; -#endif - -#ifdef DEBUG_ENABLED - ENTER("Synthesize"); - if (text) - { - SHOW("Synthesize > uid=%d, flags=%d, >>>text=%s<<<\n", unique_identifier, flags, text); - } -#endif - - if((outbuf==NULL) || (event_list==NULL)) - return(EE_INTERNAL_ERROR); // espeak_Initialize() has not been called - - option_multibyte = flags & 7; - option_ssml = flags & espeakSSML; - option_phoneme_input = flags & espeakPHONEMES; - option_endpause = flags & espeakENDPAUSE; - - count_samples = 0; - -#ifdef USE_ASYNC - if(my_mode == AUDIO_OUTPUT_PLAYBACK) - { - a_write_pos = wave_get_write_position(my_audio); - } -#endif - - if(translator == NULL) - { - SetVoiceByName("default"); - } - - SpeakNextClause(NULL,text,0); - - if(my_mode == AUDIO_OUTPUT_SYNCH_PLAYBACK) - { - for(;;) - { -#ifdef PLATFORM_WINDOWS - Sleep(300); // 0.3s -#else -#ifdef USE_NANOSLEEP - struct timespec period; - struct timespec remaining; - period.tv_sec = 0; - period.tv_nsec = 300000000; // 0.3 sec - nanosleep(&period,&remaining); -#else - sleep(1); -#endif -#endif - if(SynthOnTimer() != 0) - break; - } - return(EE_OK); - } - - for(;;) - { -#ifdef DEBUG_ENABLED - SHOW("Synthesize > %s\n","for (next)"); -#endif - out_ptr = outbuf; - out_end = &outbuf[outbuf_size]; - event_list_ix = 0; - WavegenFill(0); - - length = (out_ptr - outbuf)/2; - count_samples += length; - event_list[event_list_ix].type = espeakEVENT_LIST_TERMINATED; // indicates end of event list - event_list[event_list_ix].unique_identifier = my_unique_identifier; - event_list[event_list_ix].user_data = my_user_data; - - count_buffers++; - if (my_mode==AUDIO_OUTPUT_PLAYBACK) - { -#ifdef USE_ASYNC - finished = create_events((short *)outbuf, length, event_list, a_write_pos); - length = 0; // the wave data are played once. -#endif - } - else - { - finished = synth_callback((short *)outbuf, length, event_list); - } - if(finished) - { - SpeakNextClause(NULL,0,2); // stop - break; - } - - if(Generate(phoneme_list,&n_phoneme_list,1)==0) - { - if(WcmdqUsed() == 0) - { - // don't process the next clause until the previous clause has finished generating speech. - // This ensures that <audio> tag (which causes end-of-clause) is at a sound buffer boundary - - event_list[0].type = espeakEVENT_LIST_TERMINATED; - event_list[0].unique_identifier = my_unique_identifier; - event_list[0].user_data = my_user_data; - - if(SpeakNextClause(NULL,NULL,1)==0) - { -#ifdef USE_ASYNC - if (my_mode==AUDIO_OUTPUT_PLAYBACK) - { - dispatch_audio(NULL, 0, NULL); // TBD: test case - } - else - { - synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data - } -#else - synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data -#endif - break; - } - } - } - } - return(EE_OK); -} // end of Synthesize - -#ifdef DEBUG_ENABLED -static const char* label[] = { - "END_OF_EVENT_LIST", - "WORD", - "SENTENCE", - "MARK", - "PLAY", - "END"}; -#endif - - -void MarkerEvent(int type, unsigned int char_position, int value, unsigned char *out_ptr) -{//====================================================================================== - // type: 1=word, 2=sentence, 3=named mark, 4=play audio, 5=end - ENTER("MarkerEvent"); - espeak_EVENT *ep; - double time; - - if((event_list == NULL) || (event_list_ix >= (n_event_list-2))) - return; - - ep = &event_list[event_list_ix++]; - ep->type = (espeak_EVENT_TYPE)type; - ep->unique_identifier = my_unique_identifier; - ep->user_data = my_user_data; - ep->text_position = char_position & 0xffffff; - ep->length = char_position >> 24; - - time = ((double)(count_samples + mbrola_delay + (out_ptr - out_start)/2)*1000.0)/samplerate; - ep->audio_position = (int)(time); - ep->sample = (count_samples + mbrola_delay + (out_ptr - out_start)/2); - -#ifdef DEBUG_ENABLED - SHOW("MarkerEvent > count_samples=%d, out_ptr=%x, out_start=0x%x\n",count_samples, out_ptr, out_start); - SHOW("*** MarkerEvent > type=%s, uid=%d, text_pos=%d, length=%d, audio_position=%d, sample=%d\n", - label[ep->type], ep->unique_identifier, ep->text_position, ep->length, - ep->audio_position, ep->sample); -#endif - - if((type == espeakEVENT_MARK) || (type == espeakEVENT_PLAY)) - ep->id.name = &namedata[value]; - else - ep->id.number = value; -} // end of MarkerEvent - - - - -espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size, - unsigned int position, espeak_POSITION_TYPE position_type, - unsigned int end_position, unsigned int flags, void* user_data) -{//=========================================================================== - -#ifdef DEBUG_ENABLED - ENTER("sync_espeak_Synth"); - SHOW("sync_espeak_Synth > position=%d, position_type=%d, end_position=%d, flags=%d, user_data=0x%x, text=%s\n", position, position_type, end_position, flags, user_data, text); -#endif - - espeak_ERROR aStatus; - - InitText(flags); - my_unique_identifier = unique_identifier; - my_user_data = user_data; - - switch(position_type) - { - case POS_CHARACTER: - skip_characters = position; - break; - - case POS_WORD: - skip_words = position; - break; - - case POS_SENTENCE: - skip_sentences = position; - break; - - } - if(skip_characters || skip_words || skip_sentences) - skipping_text = 1; - - end_character_position = end_position; - - aStatus = Synthesize(unique_identifier, text, flags); - #ifdef USE_ASYNC - wave_flush(my_audio); - #endif - - SHOW_TIME("LEAVE sync_espeak_Synth"); - return aStatus; -} // end of sync_espeak_Synth - - - - -espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size, - const char *index_mark, unsigned int end_position, - unsigned int flags, void* user_data) -{//========================================================================= - espeak_ERROR aStatus; - - InitText(flags); - - my_unique_identifier = unique_identifier; - my_user_data = user_data; - - if(index_mark != NULL) - { - strncpy0(skip_marker, index_mark, sizeof(skip_marker)); - skipping_text = 1; - } - - end_character_position = end_position; - - - aStatus = Synthesize(unique_identifier, text, flags | espeakSSML); - SHOW_TIME("LEAVE sync_espeak_Synth_Mark"); - - return (aStatus); -} // end of sync_espeak_Synth_Mark - - - -void sync_espeak_Key(const char *key) -{//================================== - // symbolic name, symbolicname_character - is there a system resource of symbolic names per language? - int letter; - int ix; - - ix = utf8_in(&letter,key); - if(key[ix] == 0) - { - // a single character - sync_espeak_Char(letter); - return; - } - - my_unique_identifier = 0; - my_user_data = NULL; - Synthesize(0, key,0); // speak key as a text string -} - - -void sync_espeak_Char(wchar_t character) -{//===================================== - // is there a system resource of character names per language? - char buf[80]; - my_unique_identifier = 0; - my_user_data = NULL; - - sprintf(buf,"<say-as interpret-as=\"tts:char\">&#%d;</say-as>",character); - Synthesize(0, buf,espeakSSML); -} - - - -void sync_espeak_SetPunctuationList(const wchar_t *punctlist) -{//========================================================== - // Set the list of punctuation which are spoken for "some". - my_unique_identifier = 0; - my_user_data = NULL; - - wcsncpy(option_punctlist, punctlist, N_PUNCTLIST); - option_punctlist[N_PUNCTLIST-1] = 0; -} // end of sync_espeak_SetPunctuationList - - - - -#pragma GCC visibility push(default) - - -ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback* SynthCallback) -{//====================================================================== - ENTER("espeak_SetSynthCallback"); - synth_callback = SynthCallback; -#ifdef USE_ASYNC - event_set_callback(synth_callback); -#endif -} - -ESPEAK_API void espeak_SetUriCallback(int (* UriCallback)(int, const char*, const char *)) -{//======================================================================================= - ENTER("espeak_SetUriCallback"); - uri_callback = UriCallback; -} - - -ESPEAK_API void espeak_SetPhonemeCallback(int (* PhonemeCallback)(const char*)) -{//=========================================================================== - phoneme_callback = PhonemeCallback; -} - -ESPEAK_API int espeak_Initialize(espeak_AUDIO_OUTPUT output_type, int buf_length, const char *path, int options) -{//============================================================================================================= -ENTER("espeak_Initialize"); - int param; - - // It seems that the wctype functions don't work until the locale has been set - // to something other than the default "C". Then, not only Latin1 but also the - // other characters give the correct results with iswalpha() etc. -#ifdef PLATFORM_RISCOS - setlocale(LC_CTYPE,"ISO8859-1"); -#else - if(setlocale(LC_CTYPE,"en_US.UTF-8") == NULL) - { - if(setlocale(LC_CTYPE,"UTF-8") == NULL) - setlocale(LC_CTYPE,""); - } -#endif - - init_path(path); - initialise(); - select_output(output_type); - - // buflength is in mS, allocate 2 bytes per sample - if(buf_length == 0) - buf_length = 200; - outbuf_size = (buf_length * samplerate)/500; - outbuf = (unsigned char*)realloc(outbuf,outbuf_size); - if((out_start = outbuf) == NULL) - return(EE_INTERNAL_ERROR); - - // allocate space for event list. Allow 200 events per second. - // Add a constant to allow for very small buf_length - n_event_list = (buf_length*200)/1000 + 20; - if((event_list = (espeak_EVENT *)realloc(event_list,sizeof(espeak_EVENT) * n_event_list)) == NULL) - return(EE_INTERNAL_ERROR); - - option_phonemes = 0; - option_phoneme_events = (options & 1); - - SetVoiceByName("default"); - - for(param=0; param<N_SPEECH_PARAM; param++) - param_stack[0].parameter[param] = param_defaults[param]; - - SetParameter(espeakRATE,170,0); - SetParameter(espeakVOLUME,100,0); - SetParameter(espeakCAPITALS,option_capitals,0); - SetParameter(espeakPUNCTUATION,option_punctuation,0); - SetParameter(espeakWORDGAP,0,0); - DoVoiceChange(voice); - -#ifdef USE_ASYNC - fifo_init(); -#endif - - return(samplerate); -} - - - -ESPEAK_API espeak_ERROR espeak_Synth(const void *text, size_t size, - unsigned int position, - espeak_POSITION_TYPE position_type, - unsigned int end_position, unsigned int flags, - unsigned int* unique_identifier, void* user_data) -{//===================================================================================== -#ifdef DEBUG_ENABLED - 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); -#endif - - espeak_ERROR a_error=EE_INTERNAL_ERROR; - static unsigned int temp_identifier; - - if (unique_identifier == NULL) - { - unique_identifier = &temp_identifier; - } - *unique_identifier = 0; - - if(synchronous_mode) - { - return(sync_espeak_Synth(0,text,size,position,position_type,end_position,flags,user_data)); - } - -#ifdef USE_ASYNC - // Create the text command - t_espeak_command* c1 = create_espeak_text(text, size, position, position_type, end_position, flags, user_data); - - // Retrieve the unique identifier - *unique_identifier = c1->u.my_text.unique_identifier; - - // Create the "terminated msg" command (same uid) - t_espeak_command* c2 = create_espeak_terminated_msg(*unique_identifier, user_data); - - // Try to add these 2 commands (single transaction) - if (c1 && c2) - { - a_error = fifo_add_commands(c1, c2); - if (a_error != EE_OK) - { - delete_espeak_command(c1); - delete_espeak_command(c2); - c1=c2=NULL; - } - } - else - { - delete_espeak_command(c1); - delete_espeak_command(c2); - } - -#endif - return a_error; -} // end of espeak_Synth - - - -ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text, size_t size, - const char *index_mark, - unsigned int end_position, - unsigned int flags, - unsigned int* unique_identifier, - void* user_data) -{//========================================================================= -#ifdef DEBUG_ENABLED - 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); -#endif - - espeak_ERROR a_error=EE_OK; - static unsigned int temp_identifier; - - if (unique_identifier == NULL) - { - unique_identifier = &temp_identifier; - } - *unique_identifier = 0; - - if(synchronous_mode) - { - return(sync_espeak_Synth_Mark(0,text,size,index_mark,end_position,flags,user_data)); - } - -#ifdef USE_ASYNC - // Create the mark command - t_espeak_command* c1 = create_espeak_mark(text, size, index_mark, end_position, - flags, user_data); - - // Retrieve the unique identifier - *unique_identifier = c1->u.my_mark.unique_identifier; - - // Create the "terminated msg" command (same uid) - t_espeak_command* c2 = create_espeak_terminated_msg(*unique_identifier, user_data); - - // Try to add these 2 commands (single transaction) - if (c1 && c2) - { - a_error = fifo_add_commands(c1, c2); - if (a_error != EE_OK) - { - delete_espeak_command(c1); - delete_espeak_command(c2); - c1=c2=NULL; - } - } - else - { - delete_espeak_command(c1); - delete_espeak_command(c2); - } - -#endif - return a_error; -} // end of espeak_Synth_Mark - - - -ESPEAK_API espeak_ERROR espeak_Key(const char *key) -{//================================================ - ENTER("espeak_Key"); - // symbolic name, symbolicname_character - is there a system resource of symbolicnames per language - - espeak_ERROR a_error = EE_OK; - - if(synchronous_mode) - { - sync_espeak_Key(key); - return(EE_OK); - } - -#ifdef USE_ASYNC - t_espeak_command* c = create_espeak_key( key, NULL); - a_error = fifo_add_command(c); - if (a_error != EE_OK) - { - delete_espeak_command(c); - } - -#endif - return a_error; -} - - -ESPEAK_API espeak_ERROR espeak_Char(wchar_t character) -{//=========================================== - ENTER("espeak_Char"); - // is there a system resource of character names per language? - -#ifdef USE_ASYNC - espeak_ERROR a_error; - - if(synchronous_mode) - { - sync_espeak_Char(character); - return(EE_OK); - } - - t_espeak_command* c = create_espeak_char( character, NULL); - a_error = fifo_add_command(c); - if (a_error != EE_OK) - { - delete_espeak_command(c); - } - return a_error; -#else - sync_espeak_Char(character); - return(EE_OK); -#endif -} - - -ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name) -{//============================================================ - ENTER("espeak_SetVoiceByName"); - -//#ifdef USE_ASYNC -// I don't think there's a need to queue change voice requests -#ifdef deleted - espeak_ERROR a_error; - - if(synchronous_mode) - { - return(SetVoiceByName(name)); - } - - t_espeak_command* c = create_espeak_voice_name(name); - a_error = fifo_add_command(c); - if (a_error != EE_OK) - { - delete_espeak_command(c); - } - return a_error; -#else - return(SetVoiceByName(name)); -#endif -} // end of espeak_SetVoiceByName - - - -ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_selector) -{//============================================================================== - ENTER("espeak_SetVoiceByProperties"); - -//#ifdef USE_ASYNC -#ifdef deleted - espeak_ERROR a_error; - - if(synchronous_mode) - { - return(SetVoiceByProperties(voice_selector)); - } - - t_espeak_command* c = create_espeak_voice_spec( voice_selector); - a_error = fifo_add_command(c); - if (a_error != EE_OK) - { - delete_espeak_command(c); - } - return a_error; -#else - return(SetVoiceByProperties(voice_selector)); -#endif -} // end of espeak_SetVoiceByProperties - - -ESPEAK_API int espeak_GetParameter(espeak_PARAMETER parameter, int current) -{//======================================================================== - ENTER("espeak_GetParameter"); - // current: 0=default value, 1=current value - if(current) - { - return(param_stack[0].parameter[parameter]); - } - else - { - return(param_defaults[parameter]); - } -} // end of espeak_GetParameter - - -ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative) -{//============================================================================================= - ENTER("espeak_SetParameter"); - -#ifdef USE_ASYNC - espeak_ERROR a_error; - - if(synchronous_mode) - { - SetParameter(parameter,value,relative); - return(EE_OK); - } - - t_espeak_command* c = create_espeak_parameter(parameter, value, relative); - - a_error = fifo_add_command(c); - if (a_error != EE_OK) - { - delete_espeak_command(c); - } - return a_error; -#else - SetParameter(parameter,value,relative); - return(EE_OK); -#endif -} - - -ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist) -{//================================================================ - ENTER("espeak_SetPunctuationList"); - // Set the list of punctuation which are spoken for "some". - -#ifdef USE_ASYNC - espeak_ERROR a_error; - - if(synchronous_mode) - { - sync_espeak_SetPunctuationList(punctlist); - return(EE_OK); - } - - t_espeak_command* c = create_espeak_punctuation_list( punctlist); - a_error = fifo_add_command(c); - if (a_error != EE_OK) - { - delete_espeak_command(c); - } - return a_error; -#else - sync_espeak_SetPunctuationList(punctlist); - return(EE_OK); -#endif -} // end of espeak_SetPunctuationList - - -ESPEAK_API void espeak_SetPhonemeTrace(int value, FILE *stream) -{//============================================================ - ENTER("espeak_SetPhonemes"); - /* Controls the output of phoneme symbols for the text - value=0 No phoneme output (default) - value=1 Output the translated phoneme symbols for the text - value=2 as (1), but also output a trace of how the translation was done (matching rules and list entries) - */ - option_phonemes = value; - f_trans = stream; - if(stream == NULL) - f_trans = stderr; - -} // end of espeak_SetPhonemes - - -ESPEAK_API void espeak_CompileDictionary(const char *path, FILE *log, int flags) -{//============================================================================= - ENTER("espeak_CompileDictionary"); - CompileDictionary(path, dictionary_name, log, NULL, flags); -} // end of espeak_CompileDirectory - - -ESPEAK_API espeak_ERROR espeak_Cancel(void) -{//=============================== -#ifdef USE_ASYNC - ENTER("espeak_Cancel"); - fifo_stop(); - event_clear_all(); - - if(my_mode == AUDIO_OUTPUT_PLAYBACK) - { - wave_close(my_audio); - } - SHOW_TIME("espeak_Cancel > LEAVE"); -#endif - embedded_value[EMBED_T] = 0; // reset echo for pronunciation announcements - return EE_OK; -} // end of espeak_Cancel - - -ESPEAK_API int espeak_IsPlaying(void) -{//================================== -// ENTER("espeak_IsPlaying"); -#ifdef USE_ASYNC - if((my_mode == AUDIO_OUTPUT_PLAYBACK) && wave_is_busy(my_audio)) - return(1); - - return(fifo_is_busy()); -#else - return(0); -#endif -} // end of espeak_IsPlaying - - -ESPEAK_API espeak_ERROR espeak_Synchronize(void) -{//============================================= -#ifdef USE_ASYNC - SHOW_TIME("espeak_Synchronize > ENTER"); - while (espeak_IsPlaying()) - { - usleep(20000); - } -#endif - SHOW_TIME("espeak_Synchronize > LEAVE"); - return EE_OK; -} // end of espeak_Synchronize - - -extern void FreePhData(void); - -ESPEAK_API espeak_ERROR espeak_Terminate(void) -{//=========================================== - ENTER("espeak_Terminate"); -#ifdef USE_ASYNC - fifo_stop(); - fifo_terminate(); - event_terminate(); - - if(my_mode == AUDIO_OUTPUT_PLAYBACK) - { - wave_close(my_audio); - wave_terminate(); - } - -#endif - Free(event_list); - event_list = NULL; - Free(outbuf); - outbuf = NULL; - FreePhData(); - - return EE_OK; -} // end of espeak_Terminate - -ESPEAK_API const char *espeak_Info(void) -{//======================================= - return(version_string); -} - -#pragma GCC visibility pop - - diff --git a/navit/support/espeak/speak_lib.h b/navit/support/espeak/speak_lib.h deleted file mode 100644 index 25c24c173..000000000 --- a/navit/support/espeak/speak_lib.h +++ /dev/null @@ -1,601 +0,0 @@ -#ifndef SPEAK_LIB_H -#define SPEAK_LIB_H -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - - -/*************************************************************/ -/* This is the header file for the library version of espeak */ -/* */ -/*************************************************************/ - -#include <stdio.h> -#include <wchar.h> -#define ESPEAK_API_REVISION 5 -/* -Revision 2 - Added parameter "options" to eSpeakInitialize() - -Revision 3 - Added espeakWORDGAP to espeak_PARAMETER - -Revision 4 - Added flags parameter to espeak_CompileDictionary() - -Revision 5 - Added espeakCHARS_16BIT -*/ - /********************/ - /* Initialization */ - /********************/ - - -typedef enum { - espeakEVENT_LIST_TERMINATED = 0, // Retrieval mode: terminates the event list. - espeakEVENT_WORD = 1, // Start of word - espeakEVENT_SENTENCE, // Start of sentence - espeakEVENT_MARK, // Mark - espeakEVENT_PLAY, // Audio element - espeakEVENT_END, // End of sentence or clause - espeakEVENT_MSG_TERMINATED, // End of message - espeakEVENT_PHONEME // Phoneme, if enabled in espeak_Initialize() -} espeak_EVENT_TYPE; - - - -typedef struct { - espeak_EVENT_TYPE type; - unsigned int unique_identifier; // message identifier (or 0 for key or character) - int text_position; // the number of characters from the start of the text - int length; // word length, in characters (for espeakEVENT_WORD) - int audio_position; // the time in mS within the generated speech output data - int sample; // sample id (internal use) - void* user_data; // pointer supplied by the calling program - union { - int number; // used for WORD and SENTENCE events. For PHONEME events this is the phoneme mnemonic. - const char *name; // used for MARK and PLAY events. UTF8 string - } id; -} espeak_EVENT; -/* - When a message is supplied to espeak_synth, the request is buffered and espeak_synth returns. When the message is really processed, the callback function will be repetedly called. - - - In RETRIEVAL mode, the callback function supplies to the calling program the audio data and an event list terminated by 0 (LIST_TERMINATED). - - In PLAYBACK mode, the callback function is called as soon as an event happens. - - For example suppose that the following message is supplied to espeak_Synth: - "hello, hello." - - - * Once processed in RETRIEVAL mode, it could lead to 3 calls of the callback function : - - ** Block 1: - <audio data> + - List of events: SENTENCE + WORD + LIST_TERMINATED - - ** Block 2: - <audio data> + - List of events: WORD + END + LIST_TERMINATED - - ** Block 3: - no audio data - List of events: MSG_TERMINATED + LIST_TERMINATED - - - * Once processed in PLAYBACK mode, it could lead to 5 calls of the callback function: - - ** SENTENCE - ** WORD (call when the sounds are actually played) - ** WORD - ** END (call when the end of sentence is actually played.) - ** MSG_TERMINATED - - - The MSG_TERMINATED event is the last event. It can inform the calling program to clear the user data related to the message. - So if the synthesis must be stopped, the callback function is called for each pending message with the MSG_TERMINATED event. - - A MARK event indicates a <mark> element in the text. - A PLAY event indicates an <audio> element in the text, for which the calling program should play the named sound file. -*/ - - - -typedef enum { - POS_CHARACTER = 1, - POS_WORD, - POS_SENTENCE -} espeak_POSITION_TYPE; - - -typedef enum { - /* PLAYBACK mode: plays the audio data, supplies events to the calling program*/ - AUDIO_OUTPUT_PLAYBACK, - - /* RETRIEVAL mode: supplies audio data and events to the calling program */ - AUDIO_OUTPUT_RETRIEVAL, - - /* SYNCHRONOUS mode: as RETRIEVAL but doesn't return until synthesis is completed */ - AUDIO_OUTPUT_SYNCHRONOUS, - - /* Synchronous playback */ - AUDIO_OUTPUT_SYNCH_PLAYBACK - -} espeak_AUDIO_OUTPUT; - - -typedef enum { - EE_OK=0, - EE_INTERNAL_ERROR=-1, - EE_BUFFER_FULL=1, - EE_NOT_FOUND=2 -} espeak_ERROR; - - -#ifdef __cplusplus -extern "C" -#endif -int espeak_Initialize(espeak_AUDIO_OUTPUT output, int buflength, const char *path, int options); -/* Must be called before any synthesis functions are called. - output: the audio data can either be played by eSpeak or passed back by the SynthCallback function. - - buflength: The length in mS of sound buffers passed to the SynthCallback function. - - path: The directory which contains the espeak-data directory, or NULL for the default location. - - options: bit 0: 1=allow espeakEVENT_PHONEME events. - - - Returns: sample rate in Hz, or -1 (EE_INTERNAL_ERROR). -*/ - -typedef int (t_espeak_callback)(short*, int, espeak_EVENT*); - -#ifdef __cplusplus -extern "C" -#endif -void espeak_SetSynthCallback(t_espeak_callback* SynthCallback); -/* Must be called before any synthesis functions are called. - This specifies a function in the calling program which is called when a buffer of - speech sound data has been produced. - - - The callback function is of the form: - -int SynthCallback(short *wav, int numsamples, espeak_EVENT *events); - - wav: is the speech sound data which has been produced. - NULL indicates that the synthesis has been completed. - - numsamples: is the number of entries in wav. This number may vary, may be less than - the value implied by the buflength parameter given in espeak_Initialize, and may - sometimes be zero (which does NOT indicate end of synthesis). - - events: an array of espeak_EVENT items which indicate word and sentence events, and - also the occurance if <mark> and <audio> elements within the text. The list of - events is terminated by an event of type = 0. - - - Callback returns: 0=continue synthesis, 1=abort synthesis. -*/ - -#ifdef __cplusplus -extern "C" -#endif -void espeak_SetUriCallback(int (*UriCallback)(int, const char*, const char*)); -/* This function may be called before synthesis functions are used, in order to deal with - <audio> tags. It specifies a callback function which is called when an <audio> element is - encountered and allows the calling program to indicate whether the sound file which - is specified in the <audio> element is available and is to be played. - - The callback function is of the form: - -int UriCallback(int type, const char *uri, const char *base); - - type: type of callback event. Currently only 1= <audio> element - - uri: the "src" attribute from the <audio> element - - base: the "xml:base" attribute (if any) from the <speak> element - - Return: 1=don't play the sound, but speak the text alternative. - 0=place a PLAY event in the event list at the point where the <audio> element - occurs. The calling program can then play the sound at that point. -*/ - - - /********************/ - /* Synthesis */ - /********************/ - - -#define espeakCHARS_AUTO 0 -#define espeakCHARS_UTF8 1 -#define espeakCHARS_8BIT 2 -#define espeakCHARS_WCHAR 3 -#define espeakCHARS_16BIT 4 - -#define espeakSSML 0x10 -#define espeakPHONEMES 0x100 -#define espeakENDPAUSE 0x1000 -#define espeakKEEP_NAMEDATA 0x2000 - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_Synth(const void *text, - size_t size, - unsigned int position, - espeak_POSITION_TYPE position_type, - unsigned int end_position, - unsigned int flags, - unsigned int* unique_identifier, - void* user_data); -/* Synthesize speech for the specified text. The speech sound data is passed to the calling - program in buffers by means of the callback function specified by espeak_SetSynthCallback(). The command is asynchronous: it is internally buffered and returns as soon as possible. If espeak_Initialize was previously called with AUDIO_OUTPUT_PLAYBACK as argument, the sound data are played by eSpeak. - - text: The text to be spoken, terminated by a zero character. It may be either 8-bit characters, - wide characters (wchar_t), or UTF8 encoding. Which of these is determined by the "flags" - parameter. - - size: Equal to (or greatrer than) the size of the text data, in bytes. This is used in order - to allocate internal storage space for the text. This value is not used for - AUDIO_OUTPUT_SYNCHRONOUS mode. - - position: The position in the text where speaking starts. Zero indicates speak from the - start of the text. - - position_type: Determines whether "position" is a number of characters, words, or sentences. - Values: - - end_position: If set, this gives a character position at which speaking will stop. A value - of zero indicates no end position. - - flags: These may be OR'd together: - Type of character codes, one of: - espeakCHARS_UTF8 UTF8 encoding - espeakCHARS_8BIT The 8 bit ISO-8859 character set for the particular language. - espeakCHARS_AUTO 8 bit or UTF8 (this is the default) - espeakCHARS_WCHAR Wide characters (wchar_t) - - espeakSSML Elements within < > are treated as SSML elements, or if not recognised are ignored. - - espeakPHONEMES Text within [[ ]] is treated as phonemes codes (in espeak's Hirshenbaum encoding). - - espeakENDPAUSE If set then a sentence pause is added at the end of the text. If not set then - this pause is suppressed. - - unique_identifier: message identifier; helpful for identifying later - data supplied to the callback. - - user_data: pointer which will be passed to the callback function. - - Return: EE_OK: operation achieved - EE_BUFFER_FULL: the command can not be buffered; - you may try after a while to call the function again. - EE_INTERNAL_ERROR. -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_Synth_Mark(const void *text, - size_t size, - const char *index_mark, - unsigned int end_position, - unsigned int flags, - unsigned int* unique_identifier, - void* user_data); -/* Synthesize speech for the specified text. Similar to espeak_Synth() but the start position is - specified by the name of a <mark> element in the text. - - index_mark: The "name" attribute of a <mark> element within the text which specified the - point at which synthesis starts. UTF8 string. - - For the other parameters, see espeak_Synth() - - Return: EE_OK: operation achieved - EE_BUFFER_FULL: the command can not be buffered; - you may try after a while to call the function again. - EE_INTERNAL_ERROR. -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_Key(const char *key_name); -/* Speak the name of a keyboard key. - If key_name is a single character, it speaks the name of the character. - Otherwise, it speaks key_name as a text string. - - Return: EE_OK: operation achieved - EE_BUFFER_FULL: the command can not be buffered; - you may try after a while to call the function again. - EE_INTERNAL_ERROR. -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_Char(wchar_t character); -/* Speak the name of the given character - - Return: EE_OK: operation achieved - EE_BUFFER_FULL: the command can not be buffered; - you may try after a while to call the function again. - EE_INTERNAL_ERROR. -*/ - - - - - /***********************/ - /* Speech Parameters */ - /***********************/ - -typedef enum { - espeakSILENCE=0, /* internal use */ - espeakRATE=1, - espeakVOLUME=2, - espeakPITCH=3, - espeakRANGE=4, - espeakPUNCTUATION=5, - espeakCAPITALS=6, - espeakWORDGAP=7, - espeakOPTIONS=8, // reserved for misc. options. not yet used - espeakINTONATION=9, - - espeakRESERVED1=10, - espeakRESERVED2=11, - espeakEMPHASIS, /* internal use */ - espeakLINELENGTH, /* internal use */ - espeakVOICETYPE, // internal, 1=mbrola - N_SPEECH_PARAM /* last enum */ -} espeak_PARAMETER; - -typedef enum { - espeakPUNCT_NONE=0, - espeakPUNCT_ALL=1, - espeakPUNCT_SOME=2 -} espeak_PUNCT_TYPE; - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative); -/* Sets the value of the specified parameter. - relative=0 Sets the absolute value of the parameter. - relative=1 Sets a relative value of the parameter. - - parameter: - espeakRATE: speaking speed in word per minute. - - espeakVOLUME: volume in range 0-100 0=silence - - espeakPITCH: base pitch, range 0-100. 50=normal - - espeakRANGE: pitch range, range 0-100. 0-monotone, 50=normal - - espeakPUNCTUATION: which punctuation characters to announce: - value in espeak_PUNCT_TYPE (none, all, some), - see espeak_GetParameter() to specify which characters are announced. - - espeakCAPITALS: announce capital letters by: - 0=none, - 1=sound icon, - 2=spelling, - 3 or higher, by raising pitch. This values gives the amount in Hz by which the pitch - of a word raised to indicate it has a capital letter. - - espeakWORDGAP: pause between words, units of 10mS (at the default speed) - - Return: EE_OK: operation achieved - EE_BUFFER_FULL: the command can not be buffered; - you may try after a while to call the function again. - EE_INTERNAL_ERROR. -*/ - -#ifdef __cplusplus -extern "C" -#endif -int espeak_GetParameter(espeak_PARAMETER parameter, int current); -/* current=0 Returns the default value of the specified parameter. - current=1 Returns the current value of the specified parameter, as set by SetParameter() -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist); -/* Specified a list of punctuation characters whose names are to be spoken when the - value of the Punctuation parameter is set to "some". - - punctlist: A list of character codes, terminated by a zero character. - - Return: EE_OK: operation achieved - EE_BUFFER_FULL: the command can not be buffered; - you may try after a while to call the function again. - EE_INTERNAL_ERROR. -*/ - -#ifdef __cplusplus -extern "C" -#endif -void espeak_SetPhonemeTrace(int value, FILE *stream); -/* Controls the output of phoneme symbols for the text - value=0 No phoneme output (default) - value=1 Output the translated phoneme symbols for the text - value=2 as (1), but also output a trace of how the translation was done (matching rules and list entries) - - stream output stream for the phoneme symbols (and trace). If stream=NULL then it uses stdout. -*/ - -#ifdef __cplusplus -extern "C" -#endif -void espeak_CompileDictionary(const char *path, FILE *log, int flags); -/* Compile pronunciation dictionary for a language which corresponds to the currently - selected voice. The required voice should be selected before calling this function. - - path: The directory which contains the language's '_rules' and '_list' files. - 'path' should end with a path separator character ('/'). - log: Stream for error reports and statistics information. If log=NULL then stderr will be used. - - flags: Bit 0: include source line information for debug purposes (This is displayed with the - -X command line option). -*/ - /***********************/ - /* Voice Selection */ - /***********************/ - - -// voice table -typedef struct { - const char *name; // a given name for this voice. UTF8 string. - const char *languages; // list of pairs of (byte) priority + (string) language (and dialect qualifier) - const char *identifier; // the filename for this voice within espeak-data/voices - unsigned char gender; // 0=none 1=male, 2=female, - unsigned char age; // 0=not specified, or age in years - unsigned char variant; // only used when passed as a parameter to espeak_SetVoiceByProperties - unsigned char xx1; // for internal use - int score; // for internal use - void *spare; // for internal use -} espeak_VOICE; - -/* Note: The espeak_VOICE structure is used for two purposes: - 1. To return the details of the available voices. - 2. As a parameter to espeak_SetVoiceByProperties() in order to specify selection criteria. - - In (1), the "languages" field consists of a list of (UTF8) language names for which this voice - may be used, each language name in the list is terminated by a zero byte and is also preceded by - a single byte which gives a "priority" number. The list of languages is terminated by an - additional zero byte. - - A language name consists of a language code, optionally followed by one or more qualifier (dialect) - names separated by hyphens (eg. "en-uk"). A voice might, for example, have languages "en-uk" and - "en". Even without "en" listed, voice would still be selected for the "en" language (because - "en-uk" is related) but at a lower priority. - - The priority byte indicates how the voice is preferred for the language. A low number indicates a - more preferred voice, a higher number indicates a less preferred voice. - - In (2), the "languages" field consists simply of a single (UTF8) language name, with no preceding - priority byte. -*/ - -#ifdef __cplusplus -extern "C" -#endif -const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec); -/* Reads the voice files from espeak-data/voices and creates an array of espeak_VOICE pointers. - The list is terminated by a NULL pointer - - If voice_spec is NULL then all voices are listed. - If voice spec is give, then only the voices which are compatible with the voice_spec - are listed, and they are listed in preference order. -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_SetVoiceByName(const char *name); -/* Searches for a voice with a matching "name" field. Language is not considered. - "name" is a UTF8 string. - - Return: EE_OK: operation achieved - EE_BUFFER_FULL: the command can not be buffered; - you may try after a while to call the function again. - EE_INTERNAL_ERROR. -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_spec); -/* An espeak_VOICE structure is used to pass criteria to select a voice. Any of the following - fields may be set: - - name NULL, or a voice name - - languages NULL, or a single language string (with optional dialect), eg. "en-uk", or "en" - - gender 0=not specified, 1=male, 2=female - - age 0=not specified, or an age in years - - variant After a list of candidates is produced, scored and sorted, "variant" is used to index - that list and choose a voice. - variant=0 takes the top voice (i.e. best match). variant=1 takes the next voice, etc -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_VOICE *espeak_GetCurrentVoice(void); -/* Returns the espeak_VOICE data for the currently selected voice. - This is not affected by temporary voice changes caused by SSML elements such as <voice> and <s> -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_Cancel(void); -/* Stop immediately synthesis and audio output of the current text. When this - function returns, the audio output is fully stopped and the synthesizer is ready to - synthesize a new message. - - Return: EE_OK: operation achieved - EE_INTERNAL_ERROR. -*/ - - -#ifdef __cplusplus -extern "C" -#endif -int espeak_IsPlaying(void); -/* Returns 1 if audio is played, 0 otherwise. -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_Synchronize(void); -/* This function returns when all data have been spoken. - Return: EE_OK: operation achieved - EE_INTERNAL_ERROR. -*/ - -#ifdef __cplusplus -extern "C" -#endif -espeak_ERROR espeak_Terminate(void); -/* last function to be called. - Return: EE_OK: operation achieved - EE_INTERNAL_ERROR. -*/ - - -#ifdef __cplusplus -extern "C" -#endif -const char *espeak_Info(void); -/* Returns the version number string. - The parameter is for future use, and should be set to NULL -*/ -#endif diff --git a/navit/support/espeak/speech.h b/navit/support/espeak/speech.h deleted file mode 100755 index 9673b0c8b..000000000 --- a/navit/support/espeak/speech.h +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - - -#include <sys/types.h> - -// conditional compilation options -#define INCLUDE_KLATT - -#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN -#define ARCH_BIG -#endif - -/* #define PLATFORM_POSIX */ -#define PATHSEP '/' -// USE_PORTAUDIO or USE_PULSEAUDIO are now defined in the makefile -//#define USE_PORTAUDIO -//#define USE_PULSEAUDIO -#define USE_NANOSLEEP -//#define ESPEAK_API extern "C" - -#ifdef LIBRARY -#define USE_ASYNC -//#define USE_MBROLA_LIB -#endif - -#ifdef _ESPEAKEDIT -#define USE_PORTAUDIO -#define USE_ASYNC -#define LOG_FRAMES // write keyframe info to log-espeakedit -#endif - -// will look for espeak_data directory here, and also in user's home directory -#ifndef PATH_ESPEAK_DATA - #define PATH_ESPEAK_DATA "/usr/share/espeak-data" -#endif - -typedef unsigned short USHORT; -typedef unsigned char UCHAR; -typedef double DOUBLEX; - - - - -typedef struct { - const char *mnem; - int value; -} MNEM_TAB; -int LookupMnem(MNEM_TAB *table, char *string); - - -#ifdef PLATFORM_WINDOWS -#define N_PATH_HOME 220 -#define ESPEAK_API -#else -#define N_PATH_HOME 150 -#ifdef __cplusplus -#define ESPEAK_API extern "C" -#else -#define ESPEAK_API -#endif -#endif - -extern char path_home[N_PATH_HOME]; // this is the espeak-data directory - -extern void strncpy0(char *to,const char *from, int size); -int GetFileLength(const char *filename); -char *Alloc(int size); -void Free(void *ptr); - diff --git a/navit/support/espeak/synth_mbrola.c b/navit/support/espeak/synth_mbrola.c deleted file mode 100755 index 1055f549f..000000000 --- a/navit/support/espeak/synth_mbrola.c +++ /dev/null @@ -1,760 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <ctype.h> -#include <wctype.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "translate.h" -#include "voice.h" - -extern int Read4Bytes(FILE *f); -extern void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pitch_range); - -#ifdef USE_MBROLA_LIB - -extern unsigned char *outbuf; - -#ifndef PLATFORM_WINDOWS - -#include "mbrolib.h" -void * mb_handle; - -#else -#include <windows.h> -typedef void (WINAPI *PROCVV)(void); -typedef void (WINAPI *PROCVI)(int); -typedef void (WINAPI *PROCVF)(float); -typedef int (WINAPI *PROCIV)(); -typedef int (WINAPI *PROCIC) (char *); -typedef int (WINAPI *PROCISI)(short *,int); -typedef char* (WINAPI *PROCVCI)(char *,int); - -PROCIC init_MBR; -PROCIC write_MBR; -PROCIV flush_MBR; -PROCISI read_MBR; -PROCVV close_MBR; -PROCVV reset_MBR; -PROCIV lastError_MBR; -PROCVCI lastErrorStr_MBR; -PROCVI setNoError_MBR; -PROCVI setFreq_MBR; -PROCVF setVolumeRatio_MBR; - - - -HINSTANCE hinstDllMBR = NULL; - - -BOOL load_MBR() -{ - if(hinstDllMBR != NULL) - return TRUE; // already loaded - - if (!(hinstDllMBR=LoadLibraryA("mbrola.dll"))) - return FALSE; - init_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"init_MBR"); - write_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"write_MBR"); - flush_MBR =(PROCIV) GetProcAddress(hinstDllMBR,"flush_MBR"); - read_MBR =(PROCISI) GetProcAddress(hinstDllMBR,"read_MBR"); - close_MBR =(PROCVV) GetProcAddress(hinstDllMBR,"close_MBR"); - reset_MBR =(PROCVV) GetProcAddress(hinstDllMBR,"reset_MBR"); - lastError_MBR =(PROCIV) GetProcAddress(hinstDllMBR,"lastError_MBR"); - lastErrorStr_MBR =(PROCVCI) GetProcAddress(hinstDllMBR,"lastErrorStr_MBR"); - setNoError_MBR =(PROCVI) GetProcAddress(hinstDllMBR,"setNoError_MBR"); - setVolumeRatio_MBR =(PROCVF) GetProcAddress(hinstDllMBR,"setVolumeRatio_MBR"); - return TRUE; -} - - -void unload_MBR() -{ - if (hinstDllMBR) - { - FreeLibrary (hinstDllMBR); - hinstDllMBR=NULL; - } -} - -#endif // windows -#endif // USE_MBROLA_LIB - - -static MBROLA_TAB *mbrola_tab = NULL; -static int mbrola_control = 0; - - - - -espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int srate) -{//=================================================================================== -// Load a phoneme name translation table from espeak-data/mbrola - - int size; - int ix; - int *pw; - FILE *f_in; - char path[sizeof(path_home)+15]; - - mbrola_name[0] = 0; - mbrola_delay = 0; - - if(mbrola_voice == NULL) - { - samplerate = samplerate_native; - SetParameter(espeakVOICETYPE,0,0); - return(EE_OK); - } - - sprintf(path,"%s/mbrola/%s",path_home,mbrola_voice); -#ifdef USE_MBROLA_LIB -#ifdef PLATFORM_WINDOWS - if(load_MBR() == FALSE) // load mbrola.dll - return(EE_INTERNAL_ERROR); - - if(init_MBR(path) != 0) // initialise the required mbrola voice - return(EE_NOT_FOUND); - - setNoError_MBR(1); // don't stop on phoneme errors -#else - mb_handle = mbrolib_init(srate); - mbrolib_parameter m_parameters; - - if(mb_handle == NULL) - return(EE_INTERNAL_ERROR); - - MBROLIB_ERROR a_status = mbrolib_set_voice(mb_handle, mbrola_voice); - if(a_status != MBROLIB_OK) - return(EE_NOT_FOUND); -#endif // not windows -#endif // USE_MBROLA_LIB - - // read eSpeak's mbrola phoneme translation data, eg. en1_phtrans - sprintf(path,"%s/mbrola_ph/%s",path_home,phtrans); - size = GetFileLength(path); - if((f_in = fopen(path,"r")) == NULL) - return(EE_NOT_FOUND); - - if((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab,size)) == NULL) - { - fclose(f_in); - return(EE_INTERNAL_ERROR); - } - - mbrola_control = Read4Bytes(f_in); - pw = (int *)mbrola_tab; - for(ix=4; ix<size; ix+=4) - { - *pw++ = Read4Bytes(f_in); - } - fread(mbrola_tab,size,1,f_in); - fclose(f_in); - - -#ifdef USE_MBROLA_LIB -#ifdef PLATFORM_WINDOWS - setVolumeRatio_MBR((float)(mbrola_control & 0xff) /16.0f); -#else - mbrolib_get_parameter(mb_handle,&m_parameters); - m_parameters.ignore_error = 1; - m_parameters.volume_ratio = (float)(mbrola_control & 0xff) /16.0; - mbrolib_set_parameter(mb_handle,&m_parameters); -#endif // not windows -#endif // USE_MBROLA_LIB - - option_quiet = 1; - samplerate = srate; - if(srate == 22050) - SetParameter(espeakVOICETYPE,0,0); - else - SetParameter(espeakVOICETYPE,1,0); - strcpy(mbrola_name,mbrola_voice); - mbrola_delay = 3800; // improve synchronization of events - 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) -{//========================================================================================================================================== -// Look up a phoneme in the mbrola phoneme name translation table -// It may give none, 1, or 2 mbrola phonemes - int mnem = ph->mnemonic; - MBROLA_TAB *pr; - PHONEME_TAB *other_ph; - int found = 0; - - // control - // bit 0 skip the next phoneme - // bit 1 match this and Previous phoneme - // bit 2 only at the start of a word - // bit 3 don't match two phonemes across a word boundary - - pr = mbrola_tab; - while(pr->name != 0) - { - if(mnem == pr->name) - { - if(pr->next_phoneme == 0) - found = 1; - else - if((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN)) - { - found = 1; - } - else - { - if(pr->control & 2) - other_ph = ph_prev; - else - if((pr->control & 8) && ((plist+1)->newword)) - other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary - else - other_ph = ph_next; - - if((pr->next_phoneme == other_ph->mnemonic) || - ((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) || - ((pr->next_phoneme == '_') && (other_ph->type == phPAUSE))) - { - found = 1; - } - } - - if((pr->control & 4) && (plist->newword == 0)) // only at start of word - found = 0; - - if(found) - { - *name2 = pr->mbr_name2; - *split = pr->percent; - *control = pr->control; - return(pr->mbr_name); - } - } - - pr++; - } - *name2=0; - *split=0; - *control=0; - return(mnem); -} - - -static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) -{//=========================================================================== -// final=1: only give the final pitch value. - int x; - int ix; - int pitch_base; - int pitch_range; - int p1,p2,p_end; - unsigned char *pitch_env; - int max = -1; - int min = 999; - int y_max=0; - int y_min=0; - int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s) - int y2; - int y[4]; - int env_split; - char buf[50]; - static char output[50]; - - output[0] = 0; - pitch_env = envelope_data[env]; - - - SetPitch2(voice, pitch1, pitch2, &pitch_base, &pitch_range); - - - env_split = (split * 128)/100; - if(env_split < 0) - env_split = 0-env_split; - - // find max and min in the pitch envelope - for(x=0; x<128; x++) - { - if(pitch_env[x] > max) - { - max = pitch_env[x]; - y_max = x; - } - if(pitch_env[x] < min) - { - min = pitch_env[x]; - y_min = x; - } - } - // set an additional pitch point half way through the phoneme. - // but look for a maximum or a minimum and use that instead - y[2] = 64; - if((y_max > 0) && (y_max < 127)) - { - y[2] = y_max; - } - if((y_min > 0) && (y_min < 127)) - { - y[2] = y_min; - } - y[1] = y[2] / 2; - y[3] = y[2] + (127 - y[2])/2; - - // set initial pitch - p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12 - p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base; - - - if(split >= 0) - { - sprintf(buf," 0 %d",p1/4096); - strcat(output,buf); - } - - // don't use intermediate pitch points for linear rise and fall - if(env > 1) - { - for(ix=1; ix<4; ix++) - { - p2 = ((pitch_env[y[ix]]*pitch_range)>>8) + pitch_base; - - if(split > 0) - { - y2 = (y[ix] * env100)/env_split; - } - else - if(split < 0) - { - y2 = ((y[ix]-env_split) * env100)/env_split; - } - else - { - y2 = (y[ix] * env100)/128; - } - if((y2 > 0) && (y2 <= env100)) - { - sprintf(buf," %d %d",y2,p2/4096); - strcat(output,buf); - } - } - } - - p_end = p_end/4096; - if(split <= 0) - { - sprintf(buf," %d %d",env100,p_end); - strcat(output,buf); - } - if(env100 < 100) - { - sprintf(buf," %d %d",100,p_end); - strcat(output,buf); - } - strcat(output,"\n"); - - if(final) - sprintf(output,"\t100 %d\n",p_end); - return(output); -} // end of WritePitch - - -#ifdef USE_MBROLA_LIB - -static void MbrolaMarker(int type, int char_posn, int length, int value) -{//===================================================================== - - MarkerEvent(type,(char_posn & 0xffffff) | (length << 24),value,outbuf); - -} - - -static void MbrolaEmbedded(int &embix, int sourceix) -{//================================================= - // 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 value; - int command; - int sign=0; - - do { - word = embedded_list[embix++]; - value = word >> 8; - command = word & 0x1f; - - if((word & 0x60) == 0x60) - sign = -1; - else - if((word & 0x60) == 0x40) - sign = 1; - - if(command < N_EMBEDDED_VALUES) - { - if(sign == 0) - embedded_value[command] = value; - else - embedded_value[command] += (value * sign); - } - - switch(command & 0x1f) - { - case EMBED_M: // named marker - MbrolaMarker(espeakEVENT_MARK, (sourceix & 0x7ff) + clause_start_char, 0, value); - break; - } - } while ((word & 0x80) == 0); -} - - -#ifdef PLATFORM_WINDOWS -static int MbrolaSynth(char *p_mbrola) -{//=================================== -// p_mbrola is a string of mbrola pho lines - Windows - int len; - int finished; - int result=0; - - if(synth_callback == NULL) - return(1); - - if(p_mbrola == NULL) - flush_MBR(); - else - result = write_MBR(p_mbrola); - - - finished = 0; - while(!finished && ((len = read_MBR((short *)outbuf, outbuf_size/2)) > 0)) - { - out_ptr = outbuf + len*2; - - if(event_list) - { - event_list[event_list_ix].type = espeakEVENT_LIST_TERMINATED; // indicates end of event list - event_list[event_list_ix].user_data = 0; - } - count_samples += len; - finished = synth_callback((short *)outbuf, len, event_list); - event_list_ix=0; - } - - if(finished) - { - // cancelled by user, discard any unused mbrola speech - flush_MBR(); - while((len = read_MBR((short *)outbuf, outbuf_size/2)) > 0); - } - return(finished); -} // end of SynthMbrola -#else - -static int MbrolaSynth(char *p_mbrola) -{//=================================== -// p_mbrola is a string of mbrola pho lines - Linux - -// This is wrong -// It must be called from WavegenFill() - - int len; - int finished; - int result=0; - - if(synth_callback == NULL) - return(1); - - if(p_mbrola == NULL) - mbrolib_flush(mb_handle); - else - result = mbrolib_write(mb_handle,p_mbrola,strlen(p_mbrola)); - - - finished = 0; - while(!finished && (mbrolib_read(mb_handle, (short *)out_ptr, (out_end - out_ptr)/2, &len) == MBROLIB_OK)) - { - if(len == 0) - break; - - out_ptr += (len*2); - - if(event_list) - { - event_list[event_list_ix].type = espeakEVENT_LIST_TERMINATED; // indicates end of event list - event_list[event_list_ix].user_data = 0; - } - count_samples += len; - finished = synth_callback((short *)outbuf, len, event_list); - event_list_ix=0; - } - - if(finished) - { - // cancelled by user, discard any unused mbrola speech - mbrolib_flush(mb_handle); - while(mbrolib_read(mb_handle, (short *)outbuf, outbuf_size/2, &len) == MBROLIB_OK) - { - if(len == 0) - break; - } - } - return(finished); -} // end of SynthMbrola -#endif // not windows -#endif // USE_MBROLA_LIB - - - -void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola) -{//====================================================================== -// Generate a mbrola pho file - unsigned int name; - int phix; - int len; - int len1; - PHONEME_TAB *ph; - PHONEME_TAB *ph_next; - PHONEME_TAB *ph_prev; - PHONEME_LIST *p; - PHONEME_LIST *next; - PHONEME_LIST *prev; - int pause = 0; - int released; - int name2; - int control; - int done; - int len_percent; - const char *final_pitch; - char buf[80]; - char mbr_buf[120]; - -#ifdef USE_MBROLA_LIB - int embedded_ix=0; - int word_count=0; - - event_list_ix = 0; - out_ptr = outbuf; -#ifdef PLATFORM_WINDOWS - setNoError_MBR(1); // don't stop on phoneme errors -#endif -#else -// fprintf(f_mbrola,";; v=%.2f\n",(float)(mbrola_control & 0xff)/16.0); // ;; v= has no effect on mbrola -#endif - - for(phix=1; phix < n_phonemes; phix++) - { - mbr_buf[0] = 0; - - p = &plist[phix]; - next = &plist[phix+1]; - prev = &plist[phix-1]; - ph = p->ph; - ph_prev = plist[phix-1].ph; - ph_next = plist[phix+1].ph; - -#ifdef USE_MBROLA_LIB - if(p->synthflags & SFLAG_EMBEDDED) - { - MbrolaEmbedded(embedded_ix, p->sourceix); - } - if(p->newword & 4) - MbrolaMarker(espeakEVENT_SENTENCE, (p->sourceix & 0x7ff) + clause_start_char, 0, count_sentences); - - if(p->newword & 1) - MbrolaMarker(espeakEVENT_WORD, (p->sourceix & 0x7ff) + clause_start_char, p->sourceix >> 11, clause_start_word + word_count++); -#endif - - name = GetMbrName(p,ph,ph_prev,ph_next,&name2,&len_percent,&control); - if(control & 1) - phix++; - - if(name == 0) - continue; // ignore this phoneme - - if((ph->type == phPAUSE) && (name == ph->mnemonic)) - { - // a pause phoneme, which has not been changed by the translation - name = '_'; - len = (p->length * speed.speed_factor1)/256; -// if(len == 0) continue; - if(len == 0) - len = 1; - } - else - len = (80 * speed.speed_factor2)/256; - -#ifdef USE_MBROLA_LIB - MbrolaMarker(espeakEVENT_PHONEME, (p->sourceix & 0x7ff) + clause_start_char, 0, ph->mnemonic); -#endif - - sprintf(buf,"%s\t",WordToString(name)); - strcat(mbr_buf,buf); - - if(name2 == '_') - { - // add a pause after this phoneme - pause = PauseLength(len_percent,0); - name2 = 0; - } - - done = 0; - final_pitch = ""; - - switch(ph->type) - { - case phVOWEL: - len = ph->std_length; - if(p->synthflags & SFLAG_LENGTHEN) - len += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol - - if(ph_next->type == phPAUSE) - len += 50; // lengthen vowels before a pause - len = (len * p->length)/256; - - if(name2 == 0) - { - sprintf(buf,"%d\t%s", len, WritePitch(p->env,p->pitch1,p->pitch2,0,0)); - strcat(mbr_buf,buf); - } - else - { - len1 = (len * len_percent)/100; - sprintf(buf,"%d\t%s", len1, WritePitch(p->env,p->pitch1,p->pitch2,len_percent,0)); - strcat(mbr_buf,buf); - - sprintf(buf,"%s\t%d\t%s", WordToString(name2), len-len1, WritePitch(p->env,p->pitch1,p->pitch2,-len_percent,0)); - strcat(mbr_buf,buf); - } - done = 1; - break; - - case phSTOP: - released = 0; - if(next->type==phVOWEL) released = 1; - if(next->type==phLIQUID && !next->newword) released = 1; - - if(released) - len = DoSample(p->ph,next->ph,2,0,-1); - else - len = DoSample(p->ph,phoneme_tab[phonPAUSE],2,0,-1); - len = (len * 1000)/samplerate; // convert to mS - len += PauseLength(p->prepause,1); - break; - - case phVSTOP: - len = (80 * speed.speed_factor2)/256; - break; - - case phFRICATIVE: - len = 0; - if(p->synthflags & SFLAG_LENGTHEN) - len = DoSample(ph,ph_next,2,p->length,-1); // play it twice for [s:] etc. - len += DoSample(ph,ph_next,2,p->length,-1); - - len = (len * 1000)/samplerate; // convert to mS - break; - - case phNASAL: - if(next->type != phVOWEL) - { - len = DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,-1); - len = (len * 1000)/samplerate; - if(next->type == phPAUSE) - len += 50; - final_pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,1); - } - break; - - case phLIQUID: - if(next->type == phPAUSE) - { - len += 50; - final_pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,1); - } - break; - } - - if(!done) - { - if(name2 != 0) - { - len1 = (len * len_percent)/100; - sprintf(buf,"%d\n%s\t",len1,WordToString(name2)); - strcat(mbr_buf,buf); - len -= len1; - } - sprintf(buf,"%d%s\n",len,final_pitch); - strcat(mbr_buf,buf); - } - - if(pause) - { - sprintf(buf,"_ \t%d\n",PauseLength(pause,0)); - strcat(mbr_buf,buf); - pause = 0; - } - - if(f_mbrola) - { - fwrite(mbr_buf,1,strlen(mbr_buf),f_mbrola); // write .pho to a file - } - else - { -#ifdef USE_MBROLA_LIB - if(MbrolaSynth(mbr_buf) != 0) - return; -#endif - } - } - -#ifdef USE_MBROLA_LIB - MbrolaSynth(NULL); -#endif -} // end of MbrolaTranslate - - -#ifdef TEST_MBROLA - -static PHONEME_LIST mbrola_phlist; -static int mbrola_n_ph; -static int mbrola_phix; - - -int MbrolaFill(int fill_zeros) -{//=========================== -} - -int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) -{//================================================================== - if(resume == 0) - { - mbrola_phlist = phoneme_list; - mbrola_n_ph = n_ph; - mbrola_phix = 0; - } - - resume(0); // finished phoneme list -} -#endif diff --git a/navit/support/espeak/synthdata.c b/navit/support/espeak/synthdata.c deleted file mode 100755 index 4f8234beb..000000000 --- a/navit/support/espeak/synthdata.c +++ /dev/null @@ -1,682 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - - -#include "StdAfx.h" - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <wctype.h> -#include <string.h> - - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" -#include "wave.h" - -const char *version_string = "1.41.01 25.Aug.09"; -const int version_phdata = 0x014100; - -int option_device_number = -1; - -// copy the current phoneme table into here -int n_phoneme_tab; -int current_phoneme_table; -PHONEME_TAB *phoneme_tab[N_PHONEME_TAB]; -unsigned char phoneme_tab_flags[N_PHONEME_TAB]; // bit 0: not inherited - -static unsigned int *phoneme_index=NULL; -char *spects_data=NULL; -unsigned char *wavefile_data=NULL; -static unsigned char *phoneme_tab_data = NULL; - -int n_phoneme_tables; -PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; -int phoneme_tab_number = 0; - -int wavefile_ix; // a wavefile to play along with the synthesis -int wavefile_amp; -int wavefile_ix2; -int wavefile_amp2; - -int seq_len_adjust; -int vowel_transition[4]; -int vowel_transition0; -int vowel_transition1; - -int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which); - - - -static char *ReadPhFile(void *ptr, const char *fname) -{//================================================== - FILE *f_in; - char *p; - unsigned int length; - char buf[sizeof(path_home)+40]; - - sprintf(buf,"%s%c%s",path_home,PATHSEP,fname); - length = GetFileLength(buf); - - if((f_in = fopen(buf,"rb")) == NULL) - { - fprintf(stderr,"Can't read data file: '%s'\n",buf); - return(NULL); - } - - if(ptr != NULL) - Free(ptr); - - if((p = Alloc(length)) == NULL) - { - fclose(f_in); - return(NULL); - } - if(fread(p,1,length,f_in) != length) - { - fclose(f_in); - return(NULL); - } - - fclose(f_in); - return(p); -} // end of ReadPhFile - - -int LoadPhData() -{//============= - int ix; - int n_phonemes; - int version; - int result = 1; - unsigned char *p; - - if((phoneme_tab_data = (unsigned char *)ReadPhFile((void *)(phoneme_tab_data),"phontab")) == NULL) - return(-1); - if((phoneme_index = (unsigned int *)ReadPhFile((void *)(phoneme_index),"phonindex")) == NULL) - return(-1); - if((spects_data = ReadPhFile((void *)(spects_data),"phondata")) == NULL) - return(-1); - wavefile_data = (unsigned char *)spects_data; - - // read the version number from the first 4 bytes of phondata - version = 0; - for(ix=0; ix<4; ix++) - { - version += (wavefile_data[ix] << (ix*8)); - } - - if(version != version_phdata) - { - result = version; - } - - // set up phoneme tables - p = phoneme_tab_data; - n_phoneme_tables = p[0]; - p+=4; - - for(ix=0; ix<n_phoneme_tables; ix++) - { - n_phonemes = p[0]; - phoneme_tab_list[ix].n_phonemes = p[0]; - phoneme_tab_list[ix].includes = p[1]; - p += 4; - memcpy(phoneme_tab_list[ix].name,p,N_PHONEME_TAB_NAME); - p += N_PHONEME_TAB_NAME; - phoneme_tab_list[ix].phoneme_tab_ptr = (PHONEME_TAB *)p; - p += (n_phonemes * sizeof(PHONEME_TAB)); - } - - if(phoneme_tab_number >= n_phoneme_tables) - phoneme_tab_number = 0; - - return(result); -} // end of LoadPhData - - -void FreePhData(void) -{//================== - Free(phoneme_tab_data); - Free(phoneme_index); - Free(spects_data); - phoneme_tab_data=NULL; - phoneme_index=NULL; - spects_data=NULL; -} - - -int PhonemeCode(unsigned int mnem) -{//=============================== - int ix; - - for(ix=0; ix<n_phoneme_tab; ix++) - { - if(phoneme_tab[ix] == NULL) - continue; - if(phoneme_tab[ix]->mnemonic == mnem) - return(phoneme_tab[ix]->code); - } - return(0); -} - - -int LookupPhonemeString(const char *string) -{//======================================== - int ix; - unsigned char c; - unsigned int mnem; - - // Pack up to 4 characters into a word - mnem = 0; - for(ix=0; ix<4; ix++) - { - if(string[ix]==0) break; - c = string[ix]; - mnem |= (c << (ix*8)); - } - - return(PhonemeCode(mnem)); -} - - - -static unsigned int LookupSound2(int index, unsigned int other_phcode, int control) -{//================================================================================ -// control=1 get formant transition data only - - unsigned int code; - unsigned int value, value2; - - while((value = phoneme_index[index++]) != 0) - { - if((code = (value & 0xff)) == other_phcode) - { - while(((value2 = phoneme_index[index]) != 0) && ((value2 & 0xff) < 8)) - { - switch(value2 & 0xff) - { - case 0: - // next entry is a wavefile to be played along with the synthesis - if(control==0) - { - wavefile_ix = value2 >> 8; - } - break; - case 1: - if(control==0) - { - seq_len_adjust = value2 >> 8; - } - break; - case 2: - if(control==0) - { - seq_len_adjust = value2 >> 8; - seq_len_adjust = -seq_len_adjust; - } - break; - case 3: - if(control==0) - { - wavefile_amp = value2 >> 8; - } - break; - case 4: - // formant transition data, 2 words - vowel_transition[0] = value2 >> 8; - vowel_transition[1] = phoneme_index[index++ + 1]; - break; - case 5: - // formant transition data, 2 words - vowel_transition[2] = value2 >> 8; - vowel_transition[3] = phoneme_index[index++ + 1]; - break; - } - index++; - } - return(value >> 8); - } - else - if((code == 4) || (code == 5)) - { - // formant transition data, ignore next word of data - index++; - } - } - return(3); // not found -} // end of LookupSound2 - - -unsigned int LookupSound(PHONEME_TAB *this_ph, PHONEME_TAB *other_ph, int which, int *match_level, int control) -{//============================================================================================================ - // follows, 1 other_ph preceeds this_ph, 2 other_ph follows this_ph - // control: 1= get formant transition data only - int spect_list; - int spect_list2; - int s_list; - unsigned char virtual_ph; - int result; - int level=0; - unsigned int other_code; - unsigned int other_virtual; - - if(control==0) - { - wavefile_ix = 0; - wavefile_amp = 32; - seq_len_adjust = 0; - } - memset(vowel_transition,0,sizeof(vowel_transition)); - - other_code = other_ph->code; - if(phoneme_tab[other_code]->type == phPAUSE) - other_code = phonPAUSE_SHORT; // use this version of Pause for matching - - if(which==1) - { - spect_list = this_ph->after; - virtual_ph = this_ph->start_type; - spect_list2 = phoneme_tab[virtual_ph]->after; - other_virtual = other_ph->end_type; - } - else - { - spect_list = this_ph->before; - virtual_ph = this_ph->end_type; - spect_list2 = phoneme_tab[virtual_ph]->before; - other_virtual = other_ph->start_type; - } - - result = 3; - // look for ph1-ph2 combination - if((s_list = spect_list) != 0) - { - if((result = LookupSound2(s_list,other_code,control)) != 3) - { - level = 2; - } - else - if(other_virtual != 0) - { - if((result = LookupSound2(spect_list,other_virtual,control)) != 3) - { - level = 1; - } - } - } - // not found, look in a virtual phoneme if one is given for this phoneme - if((result==3) && (virtual_ph != 0) && ((s_list = spect_list2) != 0)) - { - if((result = LookupSound2(s_list,other_code,control)) != 3) - { - level = 1; - } - else - if(other_virtual != 0) - { - if((result = LookupSound2(spect_list2,other_virtual,control)) != 3) - { - level = 1; - } - } - } - - if(match_level != NULL) - *match_level = level; - - if(result==0) - return(0); // NULL was given in the phoneme source - - // note: values = 1 indicates use the default for this phoneme, even though we found a match - // which set a secondary reference - if(result >= 4) - { - // values 1-3 can be used for special codes - // 1 = DFT from the phoneme source file - return(result); - } - - // no match found for other_ph, return the default - return(LookupSound2(this_ph->spect,phonPAUSE,control)); - -} // end of LookupSound - - - -frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph, - int which, int *match_level, int *n_frames, PHONEME_LIST *plist) -{//========================================================================================================= - int ix; - int nf; - int nf1; - int seq_break; - frameref_t *frames; - int length1; - int length_std; - int length_factor; - SPECT_SEQ *seq, *seq2; - SPECT_SEQK *seqk, *seqk2; - PHONEME_TAB *next2_ph; - frame_t *frame; - static frameref_t frames_buf[N_SEQ_FRAMES]; - - PHONEME_TAB *other_ph; - if(which == 1) - other_ph = prev_ph; - else - other_ph = next_ph; - - if((ix = LookupSound(this_ph,other_ph,which,match_level,0)) < 4) - return(NULL); - seq = (SPECT_SEQ *)(&spects_data[ix]); - seqk = (SPECT_SEQK *)seq; - nf = seq->n_frames; - - - if(nf >= N_SEQ_FRAMES) - nf = N_SEQ_FRAMES - 1; - - seq_break = 0; - length1 = 0; - - for(ix=0; ix<nf; ix++) - { - if(seq->frame[0].frflags & FRFLAG_KLATT) - frame = &seqk->frame[ix]; - else - frame = (frame_t *)&seq->frame[ix]; - frames_buf[ix].frame = frame; - frames_buf[ix].frflags = frame->frflags; - frames_buf[ix].length = frame->length; - if(frame->frflags & FRFLAG_VOWEL_CENTRE) - seq_break = ix; - } - - frames = &frames_buf[0]; - if(seq_break > 0) - { - if(which==1) - { - nf = seq_break + 1; - } - else - { - frames = &frames_buf[seq_break]; // body of vowel, skip past initial frames - nf -= seq_break; - } - } - - // do we need to modify a frame for blending with a consonant? - if(this_ph->type == phVOWEL) - { - if((which==2) && ((frames[nf-1].frflags & FRFLAG_BREAK) == 0)) - { - // lookup formant transition for the following phoneme - - if((*match_level == 0) || (next_ph->type == phNASAL)) - { - LookupSound(next_ph,this_ph,1,NULL,1); - seq_len_adjust += FormantTransition2(frames,&nf,vowel_transition[2],vowel_transition[3],next_ph,which); - } - else - if(next_ph->phflags == phVOWEL2) - { - // not really a consonant, rather a coloured vowel - if(LookupSound(next_ph,this_ph,1,NULL,1) == 0) - { - next2_ph = plist[2].ph; - LookupSound(next2_ph,next_ph,1,NULL,1); - seq_len_adjust += FormantTransition2(frames,&nf,vowel_transition[2],vowel_transition[3],next2_ph,which); - } - } - } - else - { - if(*match_level == 0) - seq_len_adjust = FormantTransition2(frames,&nf,vowel_transition0,vowel_transition1,prev_ph,which); - } - } - - nf1 = nf - 1; - for(ix=0; ix<nf1; ix++) - length1 += frames[ix].length; - - - if((wavefile_ix != 0) && ((wavefile_ix & 0x800000)==0)) - { - // a secondary reference has been returned, which is not a wavefile - // add these spectra to the main sequence - seq2 = (SPECT_SEQ *)(&spects_data[wavefile_ix]); - seqk2 = (SPECT_SEQK *)seq2; - - // first frame of the addition just sets the length of the last frame of the main seq - nf--; - for(ix=0; ix<seq2->n_frames; ix++) - { - if(seq2->frame[0].frflags & FRFLAG_KLATT) - frame = &seqk2->frame[ix]; - else - frame = (frame_t *)&seq2->frame[ix]; - - frames[nf].length = frame->length; - if(ix > 0) - { - frames[nf].frame = frame; - frames[nf].frflags = frame->frflags; - } - nf++; - } - wavefile_ix = 0; - } - - if((this_ph->type == phVOWEL) && (length1 > 0)) - { - if(which==2) - { - // adjust the length of the main part to match the standard length specified for the vowel - // less the front part of the vowel and any added suffix - - length_std = this_ph->std_length + seq_len_adjust - 45; - if(length_std < 10) - length_std = 10; - if(plist->synthflags & SFLAG_LENGTHEN) - length_std += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol - -// can adjust vowel length for stressed syllables here - - - length_factor = (length_std * 256)/ length1; - - for(ix=0; ix<nf1; ix++) - { - frames[ix].length = (frames[ix].length * length_factor)/256; - } - } - else - { - // front of a vowel - if(*match_level == 0) - { - // allow very short vowels to have shorter front parts - if(this_ph->std_length < 130) - frames[0].length = (frames[0].length * this_ph->std_length)/130; - } - - if(seq_len_adjust != 0) - { - length_std = 0; - for(ix=0; ix<nf1; ix++) - { - length_std += frames[ix].length; - } - length_factor = ((length_std + seq_len_adjust) * 256)/length_std; - for(ix=0; ix<nf1; ix++) - { - frames[ix].length = (frames[ix].length * length_factor)/256; - } - } - } - } - - *n_frames = nf; - return(frames); -} // end of LookupSpect - - -unsigned char *LookupEnvelope(int ix) -{//================================ - if(ix==0) - return(NULL); - return((unsigned char *)&spects_data[phoneme_index[ix]]); -} - - -static void SetUpPhonemeTable(int number, int recursing) -{//===================================================== - int ix; - int includes; - int ph_code; - PHONEME_TAB *phtab; - - if(recursing==0) - { - memset(phoneme_tab_flags,0,sizeof(phoneme_tab_flags)); - } - - if((includes = phoneme_tab_list[number].includes) > 0) - { - // recursively include base phoneme tables - SetUpPhonemeTable(includes-1,1); - } - - // now add the phonemes from this table - phtab = phoneme_tab_list[number].phoneme_tab_ptr; - for(ix=0; ix<phoneme_tab_list[number].n_phonemes; ix++) - { - ph_code = phtab[ix].code; - phoneme_tab[ph_code] = &phtab[ix]; - if(ph_code > n_phoneme_tab) - n_phoneme_tab = ph_code; - - if(recursing == 0) - phoneme_tab_flags[ph_code] |= 1; // not inherited - } -} // end of SetUpPhonemeTable - - -void SelectPhonemeTable(int number) -{//================================ - n_phoneme_tab = 0; - SetUpPhonemeTable(number,0); // recursively for included phoneme tables - n_phoneme_tab++; - current_phoneme_table = number; -} // end of SelectPhonemeTable - - -int LookupPhonemeTable(const char *name) -{//===================================== - int ix; - - for(ix=0; ix<n_phoneme_tables; ix++) - { - if(strcmp(name,phoneme_tab_list[ix].name)==0) - { - phoneme_tab_number = ix; - break; - } - } - if(ix == n_phoneme_tables) - return(-1); - - return(ix); -} - - -int SelectPhonemeTableName(const char *name) -{//========================================= -// Look up a phoneme set by name, and select it if it exists -// Returns the phoneme table number - int ix; - - if((ix = LookupPhonemeTable(name)) == -1) - return(-1); - - SelectPhonemeTable(ix); - return(ix); -} // end of DelectPhonemeTableName - - - - -void LoadConfig(void) -{//================== -// Load configuration file, if one exists - char buf[sizeof(path_home)+10]; - FILE *f; - int ix; - char c1; - char *p; - char string[200]; - - for(ix=0; ix<N_SOUNDICON_SLOTS; ix++) - { - soundicon_tab[ix].filename = NULL; - soundicon_tab[ix].data = NULL; - } - - sprintf(buf,"%s%c%s",path_home,PATHSEP,"config"); - if((f = fopen(buf,"r"))==NULL) - { - return; - } - - while(fgets(buf,sizeof(buf),f)!=NULL) - { - if(memcmp(buf,"tone",4)==0) - { - ReadTonePoints(&buf[5],tone_points); - } - else - if(memcmp(buf,"pa_device",9)==0) - { - sscanf(&buf[7],"%d",&option_device_number); - } - else - if(memcmp(buf,"soundicon",9)==0) - { - ix = sscanf(&buf[10],"_%c %s",&c1,string); - if(ix==2) - { - soundicon_tab[n_soundicon_tab].name = c1; - p = Alloc(strlen(string)+1); - strcpy(p,string); - soundicon_tab[n_soundicon_tab].filename = p; - soundicon_tab[n_soundicon_tab++].length = 0; - } - } - } - fclose(f); -} // end of LoadConfig - diff --git a/navit/support/espeak/synthesize.c b/navit/support/espeak/synthesize.c deleted file mode 100755 index 3a48b1d72..000000000 --- a/navit/support/espeak/synthesize.c +++ /dev/null @@ -1,1658 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <ctype.h> -#include <wctype.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" - - -extern FILE *f_log; -static void SmoothSpect(void); - - -// list of phonemes in a clause -int n_phoneme_list=0; -PHONEME_LIST phoneme_list[N_PHONEME_LIST]; - -int mbrola_delay; -char mbrola_name[20]; - -SPEED_FACTORS speed; - -static int last_pitch_cmd; -static int last_amp_cmd; -static frame_t *last_frame; -static int last_wcmdq; -static int pitch_length; -static int amp_length; -static int modn_flags; - -static int syllable_start; -static int syllable_end; -static int syllable_centre; - -static voice_t *new_voice=NULL; - -int n_soundicon_tab=N_SOUNDICON_SLOTS; -SOUND_ICON soundicon_tab[N_SOUNDICON_TAB]; - -#define RMS_GLOTTAL1 35 // vowel before glottal stop -#define RMS_START 28 // 28 - -#define VOWEL_FRONT_LENGTH 50 - -#define long(x) ((long)(x)) - -// a dummy phoneme_list entry which looks like a pause -static PHONEME_LIST next_pause; - - -const char *WordToString(unsigned int word) -{//======================================== -// Convert a phoneme mnemonic word into a string - int ix; - static char buf[5]; - - for(ix=0; ix<3; ix++) - buf[ix] = word >> (ix*8); - buf[4] = 0; - return(buf); -} - - - -void SynthesizeInit() -{//================== - last_pitch_cmd = 0; - last_amp_cmd = 0; - last_frame = NULL; - syllable_centre = -1; - - // initialise next_pause, a dummy phoneme_list entry -// next_pause.ph = phoneme_tab[phonPAUSE]; // this must be done after voice selection - next_pause.type = phPAUSE; - next_pause.newword = 0; -} - - - -static void EndAmplitude(void) -{//=========================== - if(amp_length > 0) - { - if(wcmdq[last_amp_cmd][1] == 0) - wcmdq[last_amp_cmd][1] = amp_length; - amp_length = 0; - } -} - - - -static void EndPitch(int voice_break) -{//================================== - // posssible end of pitch envelope, fill in the length - if((pitch_length > 0) && (last_pitch_cmd >= 0)) - { - if(wcmdq[last_pitch_cmd][1] == 0) - wcmdq[last_pitch_cmd][1] = pitch_length; - pitch_length = 0; - } - - if(voice_break) - { - last_wcmdq = -1; - last_frame = NULL; - syllable_end = wcmdq_tail; - SmoothSpect(); - syllable_centre = -1; - memset(vowel_transition,0,sizeof(vowel_transition)); - } -} // end of Synthesize::EndPitch - - - -static void DoAmplitude(int amp, unsigned char *amp_env) -{//===================================================== - long *q; - - last_amp_cmd = wcmdq_tail; - amp_length = 0; // total length of vowel with this amplitude envelope - - q = wcmdq[wcmdq_tail]; - q[0] = WCMD_AMPLITUDE; - q[1] = 0; // fill in later from amp_length - q[2] = (long)amp_env; - q[3] = amp; - WcmdqInc(); -} // end of Synthesize::DoAmplitude - - - -static void DoPitch(unsigned char *env, int pitch1, int pitch2) -{//============================================================ - long *q; - - EndPitch(0); - - if(pitch1 == 1024) - { - // pitch was not set - pitch1 = 24; - pitch2 = 33; - env = envelope_data[PITCHfall]; - } - last_pitch_cmd = wcmdq_tail; - pitch_length = 0; // total length of spect with this pitch envelope - - if(pitch2 < 0) - pitch2 = 0; - - q = wcmdq[wcmdq_tail]; - q[0] = WCMD_PITCH; - q[1] = 0; // length, fill in later from pitch_length - q[2] = (long)env; - q[3] = (pitch1 << 16) + pitch2; - WcmdqInc(); -} // end of Synthesize::DoPitch - - - -int PauseLength(int pause, int control) -{//==================================== - int len; - - if(control == 0) - len = (pause * speed.speed_factor1)/256; - else - len = (pause * speed.speed_factor2)/256; - - if(len < 5) len = 5; // mS, limit the amount to which pauses can be shortened - return(len); -} - - -static void DoPause(int length, int control) -{//========================================= -// control = 1, less shortening at fast speeds - int len; - - len = PauseLength(length, control); - - len = (len * samplerate) / 1000; // convert from mS to number of samples - - EndPitch(1); - wcmdq[wcmdq_tail][0] = WCMD_PAUSE; - wcmdq[wcmdq_tail][1] = len; - WcmdqInc(); - last_frame = NULL; -} // end of Synthesize::DoPause - - -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 length_mod, int amp) -{//================================================================ - int length; - int length1; - int format; - int min_length; - int start=0; - long *q; - unsigned char *p; - - index = index & 0x7fffff; - p = &wavefile_data[index]; - format = p[2]; - length1 = (p[1] * 256); - length1 += p[0]; // length in bytes - - if(seq_len_adjust > 0) - { - start = (seq_len_adjust * samplerate)/1000; - if(format == 0) - start *= 2; - length1 -= start; - index += start; - } - - - if(length_mod > 0) - length = (length1 * length_mod) / 256; - else - length = length1; - - - length = (length * speed.speed_factor2)/256; - min_length = speed.min_sample_len; - if(format==0) - min_length *= 2; - - if(length < min_length) - length = min_length; - - if(length > length1) - length = length1; // don't exceed wavefile length - - if(format==0) - length /= 2; // 2 byte samples - - - index += 4; - - if(amp >= 0) - { - last_wcmdq = wcmdq_tail; - q = wcmdq[wcmdq_tail]; - if(which & 0x100) - q[0] = WCMD_WAVE2; // mix this with synthesised wave - else - q[0] = WCMD_WAVE; - q[1] = length; // length in samples - q[2] = long(&wavefile_data[index]); - q[3] = format + (amp << 8); - WcmdqInc(); - } - return(length); -} // end of Synthesize::DoSample2 - - -int DoSample(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int length_mod, int amp) -{//====================== ========================================================== - int index; - int match_level; - int amp2; - int result; - - EndPitch(1); - index = LookupSound(ph1,ph2,which & 0xff,&match_level,0); - if((index & 0x800000) == 0) - return(0); // not wavefile data - - amp2 = wavefile_amp; - if(amp != 0) - amp2 = (amp * wavefile_amp)/20; - - if(amp == -1) - amp2 = amp; - - result = DoSample2(index,which,length_mod,amp2); - last_frame = NULL; - return(result); -} // end of Synthesize::DoSample - - - - -static frame_t *AllocFrame() -{//========================= - // Allocate a temporary spectrum frame for the wavegen queue. Use a pool which is big - // enough to use a round-robin without checks. - // Only needed for modifying spectra for blending to consonants - -#define N_FRAME_POOL N_WCMDQ - static int ix=0; - static frame_t frame_pool[N_FRAME_POOL]; - - ix++; - if(ix >= N_FRAME_POOL) - ix = 0; - return(&frame_pool[ix]); -} - - -static void set_frame_rms(frame_t *fr, int new_rms) -{//================================================= -// Each frame includes its RMS amplitude value, so to set a new -// RMS just adjust the formant amplitudes by the appropriate ratio - - int x; - int h; - int ix; - - static const short sqrt_tab[200] = { - 0, 64, 90,110,128,143,156,169,181,192,202,212,221,230,239,247, - 256,263,271,278,286,293,300,306,313,320,326,332,338,344,350,356, - 362,367,373,378,384,389,394,399,404,409,414,419,424,429,434,438, - 443,448,452,457,461,465,470,474,478,483,487,491,495,499,503,507, - 512,515,519,523,527,531,535,539,543,546,550,554,557,561,565,568, - 572,576,579,583,586,590,593,596,600,603,607,610,613,617,620,623, - 627,630,633,636,640,643,646,649,652,655,658,662,665,668,671,674, - 677,680,683,686,689,692,695,698,701,704,706,709,712,715,718,721, - 724,726,729,732,735,738,740,743,746,749,751,754,757,759,762,765, - 768,770,773,775,778,781,783,786,789,791,794,796,799,801,804,807, - 809,812,814,817,819,822,824,827,829,832,834,836,839,841,844,846, - 849,851,853,856,858,861,863,865,868,870,872,875,877,879,882,884, - 886,889,891,893,896,898,900,902}; - - if(voice->klattv[0]) - { - if(new_rms == -1) - { - fr->klattp[KLATT_AV] = 50; - } - return; - } - - if(fr->rms == 0) return; // check for divide by zero - x = (new_rms * 64)/fr->rms; - if(x >= 200) x = 199; - - x = sqrt_tab[x]; // sqrt(new_rms/fr->rms)*0x200; - - for(ix=0; ix < 8; ix++) - { - h = fr->fheight[ix] * x; - fr->fheight[ix] = h/0x200; - } -} /* end of set_frame_rms */ - - - -static void formants_reduce_hf(frame_t *fr, int level) -{//==================================================== -// change height of peaks 2 to 8, percentage - int ix; - int x; - - if(voice->klattv[0]) - return; - - for(ix=2; ix < 8; ix++) - { - x = fr->fheight[ix] * level; - fr->fheight[ix] = x/100; - } -} - - -static frame_t *CopyFrame(frame_t *frame1, int copy) -{//================================================= -// create a copy of the specified frame in temporary buffer - frame_t *frame2; - - if((copy==0) && (frame1->frflags & FRFLAG_COPIED)) - { - // this frame has already been copied in temporary rw memory - return(frame1); - } - - frame2 = AllocFrame(); - if(frame2 != NULL) - { - memcpy(frame2,frame1,sizeof(frame_t)); - frame2->length = 0; - frame2->frflags |= FRFLAG_COPIED; - } - return(frame2); -} - - -static frame_t *DuplicateLastFrame(frameref_t *seq, int n_frames, int length) -{//========================================================================== - frame_t *fr; - - seq[n_frames-1].length = length; - fr = CopyFrame(seq[n_frames-1].frame,1); - seq[n_frames].frame = fr; - seq[n_frames].length = 0; - return fr; -} - - -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; - -//hf_reduce = 70; // ?? using fixed amount rather than the parameter?? - - target = (target * voice->formant_factor)/256; - - x = (target - fr->ffreq[2]) / 2; - if(x > max) x = max; - if(x < min) x = min; - fr->ffreq[2] += x; - fr->ffreq[3] += f3_adj; - - if(flags & 0x20) - { - f3_adj = -f3_adj; //. reverse direction for f4,f5 change - } - fr->ffreq[4] += f3_adj; - fr->ffreq[5] += f3_adj; - - if(f1_adj==1) - { - x = (235 - fr->ffreq[1]); - if(x < -100) x = -100; - if(x > -60) x = -60; - fr->ffreq[1] += x; - } - if(f1_adj==2) - { - x = (235 - fr->ffreq[1]); - if(x < -300) x = -300; - if(x > -150) x = -150; - fr->ffreq[1] += x; - fr->ffreq[0] += x; - } - if(f1_adj==3) - { - x = (100 - fr->ffreq[1]); - if(x < -400) x = -400; - if(x > -300) x = -400; - fr->ffreq[1] += x; - fr->ffreq[0] += x; - } - formants_reduce_hf(fr,hf_reduce); -} - - -static int VowelCloseness(frame_t *fr) -{//=================================== -// return a value 0-3 depending on the vowel's f1 - int f1; - - if((f1 = fr->ffreq[1]) < 300) - return(3); - if(f1 < 400) - return(2); - if(f1 < 500) - return(1); - return(0); -} - - -int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which) -{//============================================================================================================================== - int ix; - int formant; - int next_rms; - - int len; - int rms; - int f1; - int f2; - int f2_min; - int f2_max; - int f3_adj; - int f3_amp; - int flags; - int vcolour; - -#define N_VCOLOUR 2 -// percentage change for each formant in 256ths -static short vcolouring[N_VCOLOUR][5] = { - {243,272,256,256,256}, // palatal consonant follows - {256,256,240,240,240}, // retroflex -}; - - frame_t *fr = NULL; - - if(*n_frames < 2) - return(0); - - len = (data1 & 0x3f) * 2; - rms = (data1 >> 6) & 0x3f; - flags = (data1 >> 12); - - f2 = (data2 & 0x3f) * 50; - f2_min = (((data2 >> 6) & 0x1f) - 15) * 50; - f2_max = (((data2 >> 11) & 0x1f) - 15) * 50; - f3_adj = (((data2 >> 16) & 0x1f) - 15) * 50; - f3_amp = ((data2 >> 21) & 0x1f) * 8; - f1 = ((data2 >> 26) & 0x7); - vcolour = (data2 >> 29); - -// fprintf(stderr,"FMT%d %3s %3d-%3d f1=%d f2=%4d %4d %4d f3=%4d %3d\n", -// which,WordToString(other_ph->mnemonic),len,rms,f1,f2,f2_min,f2_max,f3_adj,f3_amp); - - if(other_ph->mnemonic == '?') - flags |= 8; - - if(which == 1) - { - /* entry to vowel */ - fr = CopyFrame(seq[0].frame,0); - seq[0].frame = fr; - seq[0].length = VOWEL_FRONT_LENGTH; - if(len > 0) - seq[0].length = len; - seq[0].frflags |= FRFLAG_LEN_MOD; // reduce length modification - fr->frflags |= FRFLAG_LEN_MOD; - - next_rms = seq[1].frame->rms; - -if(voice->klattv[0]) -{ - fr->klattp[KLATT_AV] = 53; // reduce the amplituide of the start of a vowel -} - if(f2 != 0) - { - if(rms & 0x20) - { - set_frame_rms(fr,(next_rms * (rms & 0x1f))/30); - } - AdjustFormants(fr, f2, f2_min, f2_max, f1, f3_adj, f3_amp, flags); - - if((rms & 0x20) == 0) - { - set_frame_rms(fr,rms*2); - } - } - else - { - if(flags & 8) - set_frame_rms(fr,(next_rms*24)/32); - else - set_frame_rms(fr,RMS_START); - } - - if(flags & 8) - { -// set_frame_rms(fr,next_rms - 5); - modn_flags = 0x800 + (VowelCloseness(fr) << 8); - } - } - else - { - // exit from vowel - rms = rms*2; - if((f2 != 0) || (flags != 0)) - { - - if(flags & 8) - { - fr = CopyFrame(seq[*n_frames-1].frame,0); - seq[*n_frames-1].frame = fr; - rms = RMS_GLOTTAL1; - - // degree of glottal-stop effect depends on closeness of vowel (indicated by f1 freq) - modn_flags = 0x400 + (VowelCloseness(fr) << 8); - } - else - { - fr = DuplicateLastFrame(seq,(*n_frames)++,len); - if(len > 36) - seq_len_adjust += (len - 36); - - if(f2 != 0) - { - AdjustFormants(fr, f2, f2_min, f2_max, f1, f3_adj, f3_amp, flags); - } - } - - set_frame_rms(fr,rms); - - if((vcolour > 0) && (vcolour <= N_VCOLOUR)) - { - for(ix=0; ix<*n_frames; ix++) - { - fr = CopyFrame(seq[ix].frame,0); - seq[ix].frame = fr; - - for(formant=1; formant<=5; formant++) - { - int x; - x = fr->ffreq[formant] * vcolouring[vcolour-1][formant-1]; - fr->ffreq[formant] = x / 256; - } - } - } - } - } - - if(fr != NULL) - { - if(flags & 4) - fr->frflags |= FRFLAG_FORMANT_RATE; - if(flags & 2) - fr->frflags |= FRFLAG_BREAK; // don't merge with next frame - } - - if(flags & 0x40) - DoPause(12,0); // add a short pause after the consonant - - if(flags & 16) - return(len); - return(0); -} // end of FormantTransition2 - - - -static void SmoothSpect(void) -{//========================== - // Limit the rate of frequence change of formants, to reduce chirping - - long *q; - frame_t *frame; - frame_t *frame2; - frame_t *frame1; - frame_t *frame_centre; - int ix; - int len; - int pk; - int modified; - int allowed; - int diff; - - if(syllable_start == syllable_end) - return; - - if((syllable_centre < 0) || (syllable_centre == syllable_start)) - { - syllable_start = syllable_end; - return; - } - - q = wcmdq[syllable_centre]; - frame_centre = (frame_t *)q[2]; - - // backwards - ix = syllable_centre -1; - frame = frame2 = frame_centre; - for(;;) - { - if(ix < 0) ix = N_WCMDQ-1; - q = wcmdq[ix]; - - if(q[0] == WCMD_PAUSE || q[0] == WCMD_WAVE) - break; - - if(q[0] <= WCMD_SPECT2) - { - len = q[1] & 0xffff; - - frame1 = (frame_t *)q[3]; - if(frame1 == frame) - { - q[3] = (long)frame2; - frame1 = frame2; - } - else - break; // doesn't follow on from previous frame - - frame = frame2 = (frame_t *)q[2]; - modified = 0; - - if(frame->frflags & FRFLAG_BREAK) - break; - - if(frame->frflags & FRFLAG_FORMANT_RATE) - len = (len * 12)/10; // allow slightly greater rate of change for this frame (was 12/10) - - for(pk=0; pk<6; pk++) - { - int f1, f2; - - if((frame->frflags & FRFLAG_BREAK_LF) && (pk < 3)) - continue; - - f1 = frame1->ffreq[pk]; - f2 = frame->ffreq[pk]; - - // backwards - if((diff = f2 - f1) > 0) - { - allowed = f1*2 + f2; - } - else - { - allowed = f1 + f2*2; - } - - // the allowed change is specified as percentage (%*10) of the frequency - // take "frequency" as 1/3 from the lower freq - allowed = (allowed * formant_rate[pk])/3000; - allowed = (allowed * len)/256; - - if(diff > allowed) - { - if(modified == 0) - { - frame2 = CopyFrame(frame,0); - modified = 1; - } - frame2->ffreq[pk] = frame1->ffreq[pk] + allowed; - q[2] = (long)frame2; - } - else - if(diff < -allowed) - { - if(modified == 0) - { - frame2 = CopyFrame(frame,0); - modified = 1; - } - frame2->ffreq[pk] = frame1->ffreq[pk] - allowed; - q[2] = (long)frame2; - } - } - } - - if(ix == syllable_start) - break; - ix--; - } - - // forwards - ix = syllable_centre; - - frame = NULL; - for(;;) - { - q = wcmdq[ix]; - - if(q[0] == WCMD_PAUSE || q[0] == WCMD_WAVE) - break; - - if(q[0] <= WCMD_SPECT2) - { - - len = q[1] & 0xffff; - - frame1 = (frame_t *)q[2]; - if(frame != NULL) - { - if(frame1 == frame) - { - q[2] = (long)frame2; - frame1 = frame2; - } - else - break; // doesn't follow on from previous frame - } - - frame = frame2 = (frame_t *)q[3]; - modified = 0; - - if(frame1->frflags & FRFLAG_BREAK) - break; - - if(frame1->frflags & FRFLAG_FORMANT_RATE) - len = (len *6)/5; // allow slightly greater rate of change for this frame - - for(pk=0; pk<6; pk++) - { - int f1, f2; - f1 = frame1->ffreq[pk]; - f2 = frame->ffreq[pk]; - - // forwards - if((diff = f2 - f1) > 0) - { - allowed = f1*2 + f2; - } - else - { - allowed = f1 + f2*2; - } - allowed = (allowed * formant_rate[pk])/3000; - allowed = (allowed * len)/256; - - if(diff > allowed) - { - if(modified == 0) - { - frame2 = CopyFrame(frame,0); - modified = 1; - } - frame2->ffreq[pk] = frame1->ffreq[pk] + allowed; - q[3] = (long)frame2; - } - else - if(diff < -allowed) - { - if(modified == 0) - { - frame2 = CopyFrame(frame,0); - modified = 1; - } - frame2->ffreq[pk] = frame1->ffreq[pk] - allowed; - q[3] = (long)frame2; - } - } - } - - ix++; - if(ix >= N_WCMDQ) ix = 0; - if(ix == syllable_end) - break; - } - - syllable_start = syllable_end; -} // end of SmoothSpect - - -static void StartSyllable(void) -{//============================ - // start of syllable, if not already started - if(syllable_end == syllable_start) - syllable_end = wcmdq_tail; -} - - -int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph, - int which, PHONEME_LIST *plist, int modulation) -{//=================================================================================== - // which 1 start of phoneme, 2 body and end - // length_mod: 256 = 100% - // modulation: -1 = don't write to wcmdq - - int n_frames; - frameref_t *frames; - int frameix; - frame_t *frame1; - frame_t *frame2; - frame_t *fr; - int ix; - long *q; - int len; - int match_level; - int frame_length; - int frame1_length; - int frame2_length; - int length_factor; - int length_mod; - int total_len = 0; - static int wave_flag = 0; - int wcmd_spect = WCMD_SPECT; - - length_mod = plist->length; - if(length_mod==0) length_mod=256; - -if(which==1) -{ - // limit the shortening of sonorants before shortened (eg. unstressed vowels) - if((this_ph->type==phLIQUID) || (prev_ph->type==phLIQUID) || (prev_ph->type==phNASAL)) - { - if(length_mod < (len = translator->langopts.param[LOPT_SONORANT_MIN])) - { - length_mod = len; - } - } -} - - modn_flags = 0; - frames = LookupSpect(this_ph,prev_ph,next_ph,which,&match_level,&n_frames, plist); - if(frames == NULL) - return(0); // not found - - frame1 = frames[0].frame; - frame1_length = frames[0].length; - if(voice->klattv[0]) - wcmd_spect = WCMD_KLATT; - - if(wavefile_ix == 0) - { - if(wave_flag) - { - // cancel any wavefile that was playing previously - wcmd_spect = WCMD_SPECT2; - if(voice->klattv[0]) - wcmd_spect = WCMD_KLATT2; - wave_flag = 0; - } - else - { - wcmd_spect = WCMD_SPECT; - if(voice->klattv[0]) - wcmd_spect = WCMD_KLATT; - } - } - - if(last_frame != NULL) - { - if(((last_frame->length < 2) || (last_frame->frflags & FRFLAG_VOWEL_CENTRE)) - && !(last_frame->frflags & FRFLAG_BREAK)) - { - // last frame of previous sequence was zero-length, replace with first of this sequence - wcmdq[last_wcmdq][3] = (long)frame1; - - if(last_frame->frflags & FRFLAG_BREAK_LF) - { - // but flag indicates keep HF peaks in last segment - fr = CopyFrame(frame1,1); - for(ix=3; ix < 8; ix++) - { - if(ix < 7) - fr->ffreq[ix] = last_frame->ffreq[ix]; - fr->fheight[ix] = last_frame->fheight[ix]; - } - wcmdq[last_wcmdq][3] = (long)fr; - } - } - } - - if((this_ph->type == phVOWEL) && (which == 2)) - { - SmoothSpect(); // process previous syllable - - // remember the point in the output queue of the centre of the vowel - syllable_centre = wcmdq_tail; - } - - frame_length = frame1_length; - for(frameix=1; frameix<n_frames; frameix++) - { - frame2 = frames[frameix].frame; - frame2_length = frames[frameix].length; - - if((wavefile_ix != 0) && ((frame1->frflags & FRFLAG_DEFER_WAV)==0)) - { - // there is a wave file to play along with this synthesis - seq_len_adjust = 0; - DoSample2(wavefile_ix,which+0x100,0,wavefile_amp); - wave_flag = 1; - wavefile_ix = 0; - } - - length_factor = length_mod; - if(frame1->frflags & FRFLAG_LEN_MOD) // reduce effect of length mod - { - length_factor = (length_mod*(256-speed.speed_factor3) + 256*speed.speed_factor3)/256; - } - len = (frame_length * samplerate)/1000; - len = (len * length_factor)/256; - - if(modulation >= 0) - { - if(frame1->frflags & FRFLAG_MODULATE) - { - modulation = 6; - } - if((frameix == n_frames-1) && (modn_flags & 0xf00)) - modulation |= modn_flags; // before or after a glottal stop - } - - pitch_length += len; - amp_length += len; - - if(frame_length < 2) - { - last_frame = NULL; - frame_length = frame2_length; - frame1 = frame2; - } - else - { - last_wcmdq = wcmdq_tail; - - if(modulation >= 0) - { - q = wcmdq[wcmdq_tail]; - q[0] = wcmd_spect; - q[1] = len + (modulation << 16); - q[2] = long(frame1); - q[3] = long(frame2); - - WcmdqInc(); - } - last_frame = frame1 = frame2; - frame_length = frame2_length; - total_len += len; - } - } - return(total_len); -} // end of Synthesize::DoSpect - - -static 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 -// Type 1=word, 2=sentence, 3=named marker, 4=play audio, 5=end - wcmdq[wcmdq_tail][0] = WCMD_MARKER; - wcmdq[wcmdq_tail][1] = type; - wcmdq[wcmdq_tail][2] = (char_posn & 0xffffff) | (length << 24); - wcmdq[wcmdq_tail][3] = value; - WcmdqInc(); - -} // end of Synthesize::DoMarker - - -void DoVoiceChange(voice_t *v) -{//=========================== -// allocate memory for a copy of the voice data, and free it in wavegenfill() - voice_t *v2; - - v2 = (voice_t *)malloc(sizeof(voice_t)); - memcpy(v2,v,sizeof(voice_t)); - wcmdq[wcmdq_tail][0] = WCMD_VOICE; - wcmdq[wcmdq_tail][1] = (long)(v2); - WcmdqInc(); -} - - -static void DoEmbedded(int *embix, int sourceix) -{//============================================= - // 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 value; - int command; - - do { - word = embedded_list[(*embix)++]; - value = word >> 8; - command = word & 0x7f; - - switch(command & 0x1f) - { - case EMBED_S: // speed - SetEmbedded((command & 0x60) + EMBED_S2,value); // adjusts embedded_value[EMBED_S2] - SetSpeed(2); - break; - - case EMBED_I: // play dynamically loaded wav data (sound icon) - if((int)value < n_soundicon_tab) - { - if(soundicon_tab[value].length != 0) - { - DoPause(10,0); // ensure a break in the speech - wcmdq[wcmdq_tail][0] = WCMD_WAVE; - wcmdq[wcmdq_tail][1] = soundicon_tab[value].length; - wcmdq[wcmdq_tail][2] = (long)soundicon_tab[value].data + 44; // skip WAV header - wcmdq[wcmdq_tail][3] = 0x1500; // 16 bit data, amp=21 - WcmdqInc(); - } - } - break; - - case EMBED_M: // named marker - DoMarker(espeakEVENT_MARK, (sourceix & 0x7ff) + clause_start_char, 0, value); - break; - - case EMBED_U: // play sound - DoMarker(espeakEVENT_PLAY, count_characters+1, 0, value); // always occurs at end of clause - break; - - default: - DoPause(10,0); // ensure a break in the speech - wcmdq[wcmdq_tail][0] = WCMD_EMBEDDED; - wcmdq[wcmdq_tail][1] = command; - wcmdq[wcmdq_tail][2] = value; - WcmdqInc(); - break; - } - } while ((word & 0x80) == 0); -} - - - -int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) -{//============================================================ - static int ix; - static int embedded_ix; - static int word_count; - PHONEME_LIST *prev; - PHONEME_LIST *next; - PHONEME_LIST *next2; - PHONEME_LIST *p; - int released; - int stress; - int modulation; - int pre_voiced; - int free_min; - unsigned char *pitch_env=NULL; - unsigned char *amp_env; - PHONEME_TAB *ph; - PHONEME_TAB *prev_ph; - static int sourceix=0; - -#ifdef TEST_MBROLA - if(mbrola_name[0] != 0) - return(MbrolaGenerate(phoneme_list,n_ph,resume)); -#endif - - if(option_quiet) - return(0); - - if(resume == 0) - { - ix = 1; - embedded_ix=0; - word_count = 0; - pitch_length = 0; - amp_length = 0; - last_frame = NULL; - last_wcmdq = -1; - syllable_start = wcmdq_tail; - syllable_end = wcmdq_tail; - syllable_centre = -1; - last_pitch_cmd = -1; - memset(vowel_transition,0,sizeof(vowel_transition)); - } - - while(ix < (*n_ph)) - { - p = &phoneme_list[ix]; - - if(p->type == phPAUSE) - free_min = 5; - else - if(p->type != phVOWEL) - free_min = 10; // we need less Q space for non-vowels, and we need to generate phonemes after a vowel so that the pitch_length is filled in - else - free_min = MIN_WCMDQ; // 22 - - if(WcmdqFree() <= free_min) - return(1); // wait - - prev = &phoneme_list[ix-1]; - next = &phoneme_list[ix+1]; - next2 = &phoneme_list[ix+2]; - - if(p->synthflags & SFLAG_EMBEDDED) - { - DoEmbedded(&embedded_ix, p->sourceix); - } - - if(p->newword) - { - if(translator->langopts.param[LOPT_WORD_MERGE] == 0) - last_frame = NULL; - - sourceix = (p->sourceix & 0x7ff) + clause_start_char; - - if(p->newword & 4) - DoMarker(espeakEVENT_SENTENCE, sourceix, 0, count_sentences); // start of sentence - -// if(p->newword & 2) -// DoMarker(espeakEVENT_END, count_characters, 0, count_sentences); // end of clause - - if(p->newword & 1) - DoMarker(espeakEVENT_WORD, sourceix, p->sourceix >> 11, clause_start_word + word_count++); - } - - EndAmplitude(); - - if(p->prepause > 0) - DoPause(p->prepause,1); - - if(option_phoneme_events && (p->type != phVOWEL)) - { - // Note, for vowels, do the phoneme event after the vowel-start - DoMarker(espeakEVENT_PHONEME, sourceix, 0, p->ph->mnemonic); - } - - switch(p->type) - { - case phPAUSE: - DoPause(p->length,0); - break; - - case phSTOP: - released = 0; - if(next->type==phVOWEL) released = 1; - if(next->type==phLIQUID && !next->newword) released = 1; - - if(released) - DoSample(p->ph,next->ph,2,0,0); - else - DoSample(p->ph,phoneme_tab[phonPAUSE],2,0,0); - break; - - case phFRICATIVE: - if(p->synthflags & SFLAG_LENGTHEN) - DoSample(p->ph,next->ph,2,p->length,0); // play it twice for [s:] etc. - DoSample(p->ph,next->ph,2,p->length,0); - break; - - case phVSTOP: - pre_voiced = 0; - if(next->type==phVOWEL) - { - DoAmplitude(p->amp,NULL); - DoPitch(envelope_data[p->env],p->pitch1,p->pitch2); - pre_voiced = 1; - } - else - if((next->type==phLIQUID) && !next->newword) - { - DoAmplitude(next->amp,NULL); - DoPitch(envelope_data[next->env],next->pitch1,next->pitch2); - pre_voiced = 1; - } - else - { - if(last_pitch_cmd < 0) - { - DoAmplitude(next->amp,NULL); - DoPitch(envelope_data[p->env],p->pitch1,p->pitch2); - } - } - - if((prev->type==phVOWEL) || (prev->ph->phflags & phVOWEL2)) - { - // a period of voicing before the release - DoSpect(p->ph,phoneme_tab[phonSCHWA],next->ph,1,p,0); - if(p->synthflags & SFLAG_LENGTHEN) - { - DoPause(20,0); - DoSpect(p->ph,phoneme_tab[phonSCHWA],next->ph,1,p,0); - } - } - else - { - if(p->synthflags & SFLAG_LENGTHEN) - { - DoPause(50,0); - } - } - - if(pre_voiced) - { - // followed by a vowel, or liquid + vowel - StartSyllable(); - DoSpect(p->ph,prev->ph,next->ph,2,p,0); - } - else - { -// if((prev->type != phVOWEL) && ((prev->ph->phflags & phVOICED)==0) && ((next->ph->phflags & phVOICED)==0)) -// DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE_SHORT],2,p,0); -// else - DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0); -// DoSpect(p->ph,prev->ph,next->ph,2,p,0); - } - break; - - case phVFRICATIVE: - if(next->type==phVOWEL) - { - DoAmplitude(p->amp,NULL); - DoPitch(envelope_data[p->env],p->pitch1,p->pitch2); - } - else - if(next->type==phLIQUID) - { - DoAmplitude(next->amp,NULL); - DoPitch(envelope_data[next->env],next->pitch1,next->pitch2); - } - else - { - if(last_pitch_cmd < 0) - { - DoAmplitude(p->amp,NULL); - DoPitch(envelope_data[p->env],p->pitch1,p->pitch2); - } - } - - if((next->type==phVOWEL) || ((next->type==phLIQUID)) && (next->newword==0)) // ?? test 14.Aug.2007 - { - StartSyllable(); - if(p->synthflags & SFLAG_LENGTHEN) - DoSpect(p->ph,prev->ph,next->ph,2,p,0); - DoSpect(p->ph,prev->ph,next->ph,2,p,0); - } - else - { - if(p->synthflags & SFLAG_LENGTHEN) - DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0); - DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0); - } - break; - - case phNASAL: - if(!(p->synthflags & SFLAG_SEQCONTINUE)) - { - DoAmplitude(p->amp,NULL); - DoPitch(envelope_data[p->env],p->pitch1,p->pitch2); - } - - if(prev->type==phNASAL) - { - last_frame = NULL; - } - - if(next->type==phVOWEL) - { - StartSyllable(); - DoSpect(p->ph,prev->ph,next->ph,1,p,0); - } - else - if(prev->type==phVOWEL && (p->synthflags & SFLAG_SEQCONTINUE)) - { - DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0); - } - else - { - last_frame = NULL; // only for nasal ? - if(next->type == phLIQUID) - DoSpect(p->ph,prev->ph,phoneme_tab[phonSONORANT],2,p,0); - else - DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0); - last_frame = NULL; - } - - break; - - case phLIQUID: - modulation = 0; - if(p->ph->phflags & phTRILL) - modulation = 5; - - prev_ph = prev->ph; -// if(p->newword) -// prev_ph = phoneme_tab[phonPAUSE]; // pronounce fully at the start of a word - - if(!(p->synthflags & SFLAG_SEQCONTINUE)) - { - DoAmplitude(p->amp,NULL); - DoPitch(envelope_data[p->env],p->pitch1,p->pitch2); - } - - if(prev->type==phNASAL) - { - last_frame = NULL; - } - - if(next->type==phVOWEL) - { - StartSyllable(); - DoSpect(p->ph,prev_ph,next->ph,1,p,modulation); // (,)r - } - else - if(prev->type==phVOWEL && (p->synthflags & SFLAG_SEQCONTINUE)) - { - DoSpect(p->ph,prev_ph,next->ph,1,p,modulation); - } - else - { - DoSpect(p->ph,prev_ph,next->ph,1,p,modulation); - } - - break; - - case phVOWEL: - ph = p->ph; - stress = p->stresslevel & 0xf; - - // vowel transition from the preceding phoneme - vowel_transition0 = vowel_transition[0]; - vowel_transition1 = vowel_transition[1]; - - pitch_env = envelope_data[p->env]; - amp_env = NULL; - if(p->tone_ph != 0) - { - pitch_env = LookupEnvelope(phoneme_tab[p->tone_ph]->spect); - amp_env = LookupEnvelope(phoneme_tab[p->tone_ph]->after); - } - - StartSyllable(); - - modulation = 2; - if(stress <= 1) - modulation = 1; // 16ths - else - if(stress >= 7) - modulation = 3; - - if(prev->type == phVSTOP || prev->type == phVFRICATIVE) - { - DoAmplitude(p->amp,amp_env); - DoPitch(pitch_env,p->pitch1,p->pitch2); // don't use prevocalic rising tone - DoSpect(ph,prev->ph,next->ph,1,p,modulation); - } - else - if(prev->type==phLIQUID || prev->type==phNASAL) - { - DoAmplitude(p->amp,amp_env); - DoSpect(ph,prev->ph,next->ph,1,p,modulation); // continue with pre-vocalic rising tone - DoPitch(pitch_env,p->pitch1,p->pitch2); - } - else - { - if(!(p->synthflags & SFLAG_SEQCONTINUE)) - { - DoAmplitude(p->amp,amp_env); - DoPitch(pitch_env,p->pitch1,p->pitch2); - } - - DoSpect(ph,prev->ph,next->ph,1,p,modulation); - } - - if(option_phoneme_events) - { - DoMarker(espeakEVENT_PHONEME, sourceix, 0, p->ph->mnemonic); - } - - DoSpect(p->ph,prev->ph,next->ph,2,p,modulation); - - memset(vowel_transition,0,sizeof(vowel_transition)); - break; - } - ix++; - } - EndPitch(1); - if(*n_ph > 0) - { - DoMarker(espeakEVENT_END, count_characters, 0, count_sentences); // end of clause - *n_ph = 0; - } - - return(0); // finished the phoneme list -} // end of Generate - - - - -static int timer_on = 0; -static int paused = 0; - -int SynthOnTimer() -{//=============== - if(!timer_on) - { - return(WavegenCloseSound()); - } - - do { - if(WcmdqUsed() > 0) - WavegenOpenSound(); - - if(Generate(phoneme_list,&n_phoneme_list,1)==0) - { - SpeakNextClause(NULL,NULL,1); - } - } while(skipping_text); - - return(0); -} - - -int SynthStatus() -{//============== - return(timer_on | paused); -} - - - -int SpeakNextClause(FILE *f_in, const void *text_in, int control) -{//============================================================== -// Speak text from file (f_in) or memory (text_in) -// control 0: start -// either f_in or text_in is set, the other must be NULL - -// The other calls have f_in and text_in = NULL -// control 1: speak next text -// 2: stop -// 3: pause (toggle) -// 4: is file being read (0=no, 1=yes) -// 5: interrupt and flush current text. - - int clause_tone; - char *voice_change; - static FILE *f_text=NULL; - static const void *p_text=NULL; - - if(control == 4) - { - if((f_text == NULL) && (p_text == NULL)) - return(0); - else - return(1); - } - - if(control == 2) - { - // stop speaking - timer_on = 0; - p_text = NULL; - if(f_text != NULL) - { - fclose(f_text); - f_text=NULL; - } - n_phoneme_list = 0; - WcmdqStop(); - - embedded_value[EMBED_T] = 0; - return(0); - } - - if(control == 3) - { - // toggle pause - if(paused == 0) - { - timer_on = 0; - paused = 2; - } - else - { - WavegenOpenSound(); - timer_on = 1; - paused = 0; - Generate(phoneme_list,&n_phoneme_list,0); // re-start from beginning of clause - } - return(0); - } - - if(control == 5) - { - // stop speaking, but continue looking for text - n_phoneme_list = 0; - WcmdqStop(); - return(0); - } - - if((f_in != NULL) || (text_in != NULL)) - { - f_text = f_in; - p_text = text_in; - timer_on = 1; - paused = 0; - } - - if((f_text==NULL) && (p_text==NULL)) - { - skipping_text = 0; - timer_on = 0; - return(0); - } - - if((f_text != NULL) && feof(f_text)) - { - timer_on = 0; - fclose(f_text); - f_text=NULL; - return(0); - } - - if(current_phoneme_table != voice->phoneme_tab_ix) - { - SelectPhonemeTable(voice->phoneme_tab_ix); - } - - // read the next clause from the input text file, translate it, and generate - // entries in the wavegen command queue - p_text = TranslateClause(translator, f_text, p_text, &clause_tone, &voice_change); - - CalcPitches(translator, clause_tone); - CalcLengths(translator); - - GetTranslatedPhonemeString(translator->phon_out,sizeof(translator->phon_out)); - if(option_phonemes > 0) - { - fprintf(f_trans,"%s\n",translator->phon_out); - - if(!iswalpha(0x010d)) - { - // check that c-caron is recognized as an alphabetic character - fprintf(stderr,"Warning: Accented letters are not recognized, eg: U+010D\nSet LC_CTYPE to a UTF-8 locale\n"); - } - } - if(phoneme_callback != NULL) - { - phoneme_callback(translator->phon_out); - } - - - if(skipping_text) - { - n_phoneme_list = 0; - return(1); - } - - if(mbrola_name[0] != 0) - { -#ifdef USE_MBROLA_LIB - MbrolaTranslate(phoneme_list,n_phoneme_list,NULL); -#else - { - FILE *f_mbrola; - if((f_mbrola = f_trans) == stderr) - f_mbrola = stdout; - MbrolaTranslate(phoneme_list,n_phoneme_list,f_mbrola); - } -#endif - } - - Generate(phoneme_list,&n_phoneme_list,0); - WavegenOpenSound(); - - if(voice_change != NULL) - { - // voice change at the end of the clause (i.e. clause was terminated by a voice change) - new_voice = LoadVoiceVariant(voice_change,0); // add a Voice instruction to wavegen at the end of the clause - } - - if(new_voice) - { - // finished the current clause, now change the voice if there was an embedded - // change voice command at the end of it (i.e. clause was broken at the change voice command) - DoVoiceChange(voice); - new_voice = NULL; - } - - return(1); -} // end of SpeakNextClause - diff --git a/navit/support/espeak/synthesize.h b/navit/support/espeak/synthesize.h deleted file mode 100755 index 193b93297..000000000 --- a/navit/support/espeak/synthesize.h +++ /dev/null @@ -1,377 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - - -#define N_PHONEME_LIST 1000 // enough for source[N_TR_SOURCE] full of text, else it will truncate - -#define MAX_HARMONIC 400 // 400 * 50Hz = 20 kHz, more than enough -#define N_SEQ_FRAMES 25 // max frames in a spectrum sequence (real max is ablut 8) -#define STEPSIZE 64 // 2.9mS at 22 kHz sample rate - -#define PITCHfall 0 -#define PITCHrise 1 - -// flags set for frames within a spectrum sequence -#define FRFLAG_KLATT 0x01 // this frame includes extra data for Klatt synthesizer -#define FRFLAG_VOWEL_CENTRE 0x02 // centre point of vowel -#define FRFLAG_LEN_MOD 0x04 // reduce effect of length adjustment -#define FRFLAG_BREAK_LF 0x08 // but keep f3 upwards -#define FRFLAG_BREAK 0x10 // don't merge with next frame -#define FRFLAG_BREAK_2 0x18 // FRFLAG_BREAK_LF or FRFLAG_BREAK -#define FRFLAG_FORMANT_RATE 0x20 // Flag5 allow increased rate of change of formant freq -#define FRFLAG_MODULATE 0x40 // Flag6 modulate amplitude of some cycles to give trill -#define FRFLAG_DEFER_WAV 0x80 // Flag7 defer mixing WAV until the next frame -#define FRFLAG_COPIED 0x8000 // This frame has been copied into temporary rw memory - -#define SFLAG_SEQCONTINUE 0x01 // a liquid or nasal after a vowel, but not followed by a vowel -#define SFLAG_EMBEDDED 0x02 // there are embedded commands before this phoneme -#define SFLAG_SYLLABLE 0x04 // vowel or syllabic consonant -#define SFLAG_LENGTHEN 0x08 // lengthen symbol : included after this phoneme -#define SFLAG_DICTIONARY 0x10 // the pronunciation of this word was listed in the xx_list dictionary -#define SFLAG_SWITCHED_LANG 0x20 // this word uses phonemes from a different language -#define SFLAG_PROMOTE_STRESS 0x40 // this unstressed word can be promoted to stressed - -// embedded command numbers -#define EMBED_P 1 // pitch -#define EMBED_S 2 // speed (used in setlengths) -#define EMBED_A 3 // amplitude/volume -#define EMBED_R 4 // pitch range/expression -#define EMBED_H 5 // echo/reverberation -#define EMBED_T 6 // different tone for announcing punctuation -#define EMBED_I 7 // sound icon -#define EMBED_S2 8 // speed (used in synthesize) -#define EMBED_Y 9 // say-as commands -#define EMBED_M 10 // mark name -#define EMBED_U 11 // audio uri -#define EMBED_B 12 // break -#define EMBED_F 13 // emphasis - -#define N_EMBEDDED_VALUES 14 -extern int embedded_value[N_EMBEDDED_VALUES]; -extern int embedded_default[N_EMBEDDED_VALUES]; - - -#define N_PEAKS 9 -#define N_MARKERS 8 - -#define N_KLATTP 10 // this affects the phoneme data file format -#define N_KLATTP2 14 // used in vowel files, with extra parameters for future extensions - -#define KLATT_AV 0 -#define KLATT_FNZ 1 // nasal zero freq -#define KLATT_Tilt 2 -#define KLATT_Aspr 3 -#define KLATT_Skew 4 - -#define KLATT_Kopen 5 -#define KLATT_AVp 6 -#define KLATT_Fric 7 -#define KLATT_FricBP 8 -#define KLATT_Turb 9 - - - -typedef struct { // 44 bytes - short frflags; - short ffreq[7]; - unsigned char length; - unsigned char rms; - unsigned char fheight[8]; - unsigned char fwidth[6]; // width/4 f0-5 - unsigned char fright[3]; // width/4 f0-2 - unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 - unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew - unsigned char klattp2[5]; // continuation of klattp[], Avp, Fric, FricBP, Turb - unsigned char klatt_ap[7]; // Klatt parallel amplitude - unsigned char klatt_bp[7]; // Klatt parallel bandwidth /2 -} frame_t; // with extra Klatt parameters for parallel resonators - -typedef struct { // 44 bytes - short frflags; - short ffreq[7]; - unsigned char length; - unsigned char rms; - unsigned char fheight[8]; - unsigned char fwidth[6]; // width/4 f0-5 - unsigned char fright[3]; // width/4 f0-2 - unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3 - unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew -} frame_t2; // TESTING - - -#ifdef deleted -typedef struct { - short frflags; - unsigned char length; - unsigned char rms; - short ffreq[9]; - unsigned char fheight[9]; - unsigned char fwidth[6]; // width/4 - unsigned char fright[6]; // width/4 - unsigned char fwidth6, fright6; - unsigned char klattp[N_KLATTP]; -} frame_t; - -typedef struct { // 43 bytes - short frflags; - unsigned char length; - unsigned char rms; - short ffreq[9]; - unsigned char fheight[9]; - unsigned char fwidth[6]; // width/4 - unsigned char fright[6]; // width/4 -} frame_t2; // the original, without Klatt additions, used for file "phondata" -#endif - - - -// formant data used by wavegen -typedef struct { - int freq; // Hz<<16 - int height; // height<<15 - int left; // Hz<<16 - int right; // Hz<<16 - DOUBLEX freq1; // floating point versions of the above - DOUBLEX height1; - DOUBLEX left1; - DOUBLEX right1; - DOUBLEX freq_inc; // increment by this every 64 samples - DOUBLEX height_inc; - DOUBLEX left_inc; - DOUBLEX right_inc; -} wavegen_peaks_t; - -typedef struct { -unsigned char *pitch_env; -int pitch; // pitch Hz*256 -int pitch_ix; // index into pitch envelope (*256) -int pitch_inc; // increment to pitch_ix -int pitch_base; // Hz*256 low, before modified by envelope -int pitch_range; // Hz*256 range of envelope - -unsigned char *mix_wavefile; // wave file to be added to synthesis -int n_mix_wavefile; // length in bytes -int mix_wave_scale; // 0=2 byte samples -int mix_wave_amp; -int mix_wavefile_ix; - -int amplitude; -int amplitude_v; -int prev_was_synth; // previous sound was synthesized (not a played wave or pause) -} WGEN_DATA; - - -typedef struct { - double a; - double b; - double c; - double x1; - double x2; -} RESONATOR; - - -typedef struct { - short length_total; // not used - unsigned char n_frames; - unsigned char flags; - frame_t2 frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence -} SPECT_SEQ; // sequence of espeak formant frames - -typedef struct { - short length_total; // not used - unsigned char n_frames; - unsigned char flags; - frame_t frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence -} SPECT_SEQK; // sequence of klatt formants frames - - -typedef struct { - short length; - short frflags; - frame_t *frame; -} frameref_t; - - -typedef struct { - PHONEME_TAB *ph; - unsigned char env; // pitch envelope number - unsigned char stresslevel; - unsigned char type; - unsigned char prepause; - unsigned char amp; - unsigned char tone_ph; // tone phoneme to use with this vowel - unsigned char newword; // bit 0=start of word, bit 1=end of clause, bit 2=start of sentence - unsigned char synthflags; - short length; // length_mod - short pitch1; // pitch, 0-4095 within the Voice's pitch range - short pitch2; - unsigned short sourceix; // ix into the original source text string, only set at the start of a word -} PHONEME_LIST; - - -typedef struct { - int name; - int length; - char *data; - char *filename; -} SOUND_ICON; - -typedef struct { - int name; - unsigned int next_phoneme; - int mbr_name; - int mbr_name2; - int percent; // percentage length of first component - int control; -} MBROLA_TAB; - -typedef struct { - int speed_factor1; - int speed_factor2; - int speed_factor3; - int min_sample_len; - int fast_settings[8]; -} SPEED_FACTORS; - - -// phoneme table -extern PHONEME_TAB *phoneme_tab[N_PHONEME_TAB]; - -// list of phonemes in a clause -extern int n_phoneme_list; -extern PHONEME_LIST phoneme_list[N_PHONEME_LIST]; -extern unsigned int embedded_list[]; - -extern unsigned char env_fall[128]; -extern unsigned char env_rise[128]; -extern unsigned char env_frise[128]; - -#define MAX_PITCH_VALUE 101 -extern unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1]; - -// queue of commands for wavegen -#define WCMD_KLATT 1 -#define WCMD_KLATT2 2 -#define WCMD_SPECT 3 -#define WCMD_SPECT2 4 -#define WCMD_PAUSE 5 -#define WCMD_WAVE 6 -#define WCMD_WAVE2 7 -#define WCMD_AMPLITUDE 8 -#define WCMD_PITCH 9 -#define WCMD_MARKER 10 -#define WCMD_VOICE 11 -#define WCMD_EMBEDDED 12 - - -#define N_WCMDQ 160 -#define MIN_WCMDQ 22 // need this many free entries before adding new phoneme - -extern long wcmdq[N_WCMDQ][4]; -extern int wcmdq_head; -extern int wcmdq_tail; - -// from Wavegen file -int WcmdqFree(); -void WcmdqStop(); -int WcmdqUsed(); -void WcmdqInc(); -int WavegenOpenSound(); -int WavegenCloseSound(); -int WavegenInitSound(); -void WavegenInit(int rate, int wavemult_fact); -float polint(float xa[],float ya[],int n,float x); -int WavegenFill(int fill_zeros); -void MarkerEvent(int type, unsigned int char_position, int value, unsigned char *out_ptr); - - -extern unsigned char *wavefile_data; -extern int samplerate; -extern int samplerate_native; - -extern int wavefile_ix; -extern int wavefile_amp; -extern int wavefile_ix2; -extern int wavefile_amp2; -extern int vowel_transition[4]; -extern int vowel_transition0, vowel_transition1; - -extern int mbrola_delay; -extern char mbrola_name[20]; - -// from synthdata file -unsigned int LookupSound(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int *match_level, int control); -frameref_t *LookupSpect(PHONEME_TAB *ph1, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph, int which, int *match_level, int *n_frames, PHONEME_LIST *plist); - -unsigned char *LookupEnvelope(int ix); -int LoadPhData(); - -void SynthesizeInit(void); -int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume); -void MakeWave2(PHONEME_LIST *p, int n_ph); -int SynthOnTimer(void); -int SpeakNextClause(FILE *f_text, const void *text_in, int control); -int SynthStatus(void); -void SetSpeed(int control); -void SetEmbedded(int control, int value); -void SelectPhonemeTable(int number); -int SelectPhonemeTableName(const char *name); - -void Write4Bytes(FILE *f, int value); -int Read4Bytes(FILE *f); -int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name,int flags); - - -extern unsigned char *envelope_data[18]; -extern int formant_rate[]; // max rate of change of each formant -extern SPEED_FACTORS speed; - -extern long count_samples; -extern int outbuf_size; -extern unsigned char *out_ptr; -extern unsigned char *out_start; -extern unsigned char *out_end; -extern int event_list_ix; -extern espeak_EVENT *event_list; -extern t_espeak_callback* synth_callback; -extern int option_log_frames; -extern const char *version_string; -extern const int version_phdata; - -#define N_SOUNDICON_TAB 80 // total entries in soundicon_tab -#define N_SOUNDICON_SLOTS 4 // number of slots reserved for dynamic loading of audio files -extern int n_soundicon_tab; -extern SOUND_ICON soundicon_tab[N_SOUNDICON_TAB]; - -espeak_ERROR SetVoiceByName(const char *name); -espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector); -espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int srate); -void SetParameter(int parameter, int value, int relative); -void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola); -//int MbrolaSynth(char *p_mbrola); -int DoSample(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int length_mod, int amp); -int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph, - int which, PHONEME_LIST *plist, int modulation); -int PauseLength(int pause, int control); -int LookupPhonemeTable(const char *name); - -void InitBreath(void); - -void KlattInit(); -int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2); diff --git a/navit/support/espeak/tr_languages.c b/navit/support/espeak/tr_languages.c deleted file mode 100644 index 83d1c8041..000000000 --- a/navit/support/espeak/tr_languages.c +++ /dev/null @@ -1,1335 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <ctype.h> -#include <wctype.h> -#include <stdlib.h> -#include <string.h> -#include <locale.h> - -#include <wctype.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "translate.h" - - - -#define L_qa 0x716100 -#define L_grc 0x677263 // grc Ancient Greek -#define L_jbo 0x6a626f // jbo Lojban -#define L_pap 0x706170 // pap Papiamento -#define L_zhy 0x7a6879 // zhy - -// start of unicode pages for character sets -#define OFFSET_GREEK 0x380 -#define OFFSET_CYRILLIC 0x420 -#define OFFSET_ARMENIAN 0x530 -#define OFFSET_DEVANAGARI 0x900 -#define OFFSET_BENGALI 0x980 -#define OFFSET_TAMIL 0xb80 -#define OFFSET_KANNADA 0xc80 -#define OFFSET_MALAYALAM 0xd00 -#define OFFSET_KOREAN 0x1100 - -static void Translator_Russian(Translator *tr); - -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) -} - -static void ResetLetterBits(Translator *tr, int groups) -{//==================================================== -// Clear all the specified groups - unsigned int ix; - unsigned int mask; - - mask = ~groups; - - for(ix=0; ix<sizeof(tr->letter_bits); ix++) - { - tr->letter_bits[ix] &= mask; - } -} - -static void SetLetterBits(Translator *tr, int group, const char *string) -{//===================================================================== - int bits; - unsigned char c; - - bits = (1L << group); - while((c = *string++) != 0) - tr->letter_bits[c] |= bits; -} - -static void SetLetterBitsRange(Translator *tr, int group, int first, int last) -{//=========================================================================== - int bits; - int ix; - - bits = (1L << group); - for(ix=first; ix<=last; ix++) - { - tr->letter_bits[ix] |= bits; - } -} - - -static Translator* NewTranslator(void) -{//=================================== - Translator *tr; - int ix; - static const unsigned char stress_amps2[] = {17,17, 20,20, 20,22, 22,20 }; - static const short stress_lengths2[8] = {182,140, 220,220, 220,240, 260,280}; - static const wchar_t empty_wstring[1] = {0}; - static const wchar_t punct_in_word[2] = {'\'', 0}; // allow hyphen within words - - tr = (Translator *)Alloc(sizeof(Translator)); - if(tr == NULL) - return(NULL); - - tr->charset_a0 = charsets[1]; // ISO-8859-1, this is for when the input is not utf8 - dictionary_name[0] = 0; - tr->dict_condition=0; - tr->data_dictrules = NULL; // language_1 translation rules file - tr->data_dictlist = NULL; // language_2 dictionary lookup file - - tr->transpose_offset = 0; - - // only need lower case - tr->letter_bits_offset = 0; - memset(tr->letter_bits,0,sizeof(tr->letter_bits)); - memset(tr->letter_groups,0,sizeof(tr->letter_groups)); - - // 0-5 sets of characters matched by A B C E F G in pronunciation rules - // these may be set differently for different languages - SetLetterBits(tr,0,"aeiou"); // A vowels, except y - SetLetterBits(tr,1,"bcdfgjklmnpqstvxz"); // B hard consonants, excluding h,r,w - SetLetterBits(tr,2,"bcdfghjklmnpqrstvwxz"); // C all consonants - SetLetterBits(tr,3,"hlmnr"); // H 'soft' consonants - SetLetterBits(tr,4,"cfhkpqstx"); // F voiceless consonants - SetLetterBits(tr,5,"bdgjlmnrvwyz"); // G voiced - SetLetterBits(tr,6,"eiy"); // Letter group Y, front vowels - SetLetterBits(tr,7,"aeiouy"); // vowels, including y - - - tr->char_plus_apostrophe = empty_wstring; - tr->punct_within_word = punct_in_word; - - for(ix=0; ix<8; ix++) - { - tr->stress_amps[ix] = stress_amps2[ix]; - tr->stress_amps_r[ix] = stress_amps2[ix] - 1; - tr->stress_lengths[ix] = stress_lengths2[ix]; - } - memset(&(tr->langopts),0,sizeof(tr->langopts)); - - tr->langopts.stress_rule = 2; - tr->langopts.unstressed_wd1 = 1; - tr->langopts.unstressed_wd2 = 3; - tr->langopts.param[LOPT_SONORANT_MIN] = 95; - tr->langopts.param[LOPT_MAXAMP_EOC] = 19; - tr->langopts.param[LOPT_UNPRONOUNCABLE] = 's'; // don't count this character at start of word - tr->langopts.max_initial_consonants = 3; - tr->langopts.replace_chars = NULL; - tr->langopts.ascii_language = ""; // Non-Latin alphabet languages, use this language to speak Latin words, default is English - - SetLengthMods(tr,201); -// tr->langopts.length_mods = length_mods_en; -// tr->langopts.length_mods0 = length_mods_en0; - - tr->langopts.long_stop = 100; - - tr->langopts.max_roman = 49; - tr->langopts.thousands_sep = ','; - tr->langopts.decimal_sep = '.'; - - memcpy(tr->punct_to_tone, punctuation_to_tone, sizeof(tr->punct_to_tone)); - - return(tr); -} - - -static const unsigned int replace_cyrillic_latin[] = - {0x430,'a', - 0x431,'b', - 0x446,'c', - 0x45b,0x107, - 0x447,0x10d, - 0x45f,'d'+(0x17e<<16), - 0x455,'d'+('z'<<16), - 0x434,'d', - 0x452,0x111, - 0x435,'e', - 0x444,'f', - 0x433,'g', - 0x445,'h', - 0x438,'i', - 0x458,'j', - 0x43a,'k', - 0x459,'l'+('j'<<16), - 0x43b,'l', - 0x43c,'m', - 0x45a,'n'+('j'<<16), - 0x43d,'n', - 0x43e,'o', - 0x43f,'p', - 0x440,'r', - 0x441,'s', - 0x448,0x161, - 0x442,'t', - 0x443,'u', - 0x432,'v', - 0x437,'z', - 0x436,0x17e, - 0x453,0x111, - 0x45c,0x107, -0}; // ѓ ѕ ќ - - -void SetIndicLetters(Translator *tr) -{//================================= - // Set letter types for Indic scripts, Devanagari, Tamill, etc - static const char dev_consonants2[] = {0x02,0x03,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f}; - - memset(tr->letter_bits,0,sizeof(tr->letter_bits)); - SetLetterBitsRange(tr,LETTERGP_A,0x04,0x14); // vowel letters only - SetLetterBitsRange(tr,LETTERGP_B,0x3e,0x4d); // vowel signs, and virama - - SetLetterBitsRange(tr,LETTERGP_C,0x15,0x39); // the main consonant range - SetLetterBits(tr,LETTERGP_C,dev_consonants2); // + additional consonants - - SetLetterBitsRange(tr,LETTERGP_Y,0x04,0x14); // vowel letters - SetLetterBitsRange(tr,LETTERGP_Y,0x3e,0x4c); // + vowel signs - - tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words -} - -void SetupTranslator(Translator *tr, const short *lengths, const unsigned char *amps) -{//================================================================================== - if(lengths != NULL) - memcpy(tr->stress_lengths,lengths,sizeof(tr->stress_lengths)); - if(amps != NULL) - memcpy(tr->stress_amps,amps,sizeof(tr->stress_amps)); -} - - -Translator *SelectTranslator(const char *name) -{//=========================================== - int name2 = 0; - Translator *tr; - - static const unsigned char stress_amps_sk[8] = {17,17, 20,20, 20,22, 22,21 }; - static const short stress_lengths_sk[8] = {190,190, 210,210, 0,0, 210,210}; - - // convert name string into a word of up to 4 characters, for the switch() - while(*name != 0) - name2 = (name2 << 8) + *name++; - - tr = NewTranslator(); - - switch(name2) - { - case L('a','f'): - { - static const short stress_lengths_af[8] = {170,140, 220,220, 0, 0, 250,270}; - SetupTranslator(tr,stress_lengths_af,NULL); - - tr->langopts.stress_rule = 0; - tr->langopts.vowel_pause = 0x30; - tr->langopts.param[LOPT_DIERESES] = 1; - tr->langopts.param[LOPT_PREFIXES] = 1; - SetLetterVowel(tr,'y'); // add 'y' to vowels - - tr->langopts.numbers = 0x8d1 + NUM_ROMAN; - tr->langopts.accents = 1; - } - break; - - case L('b','n'): // Bengali - { - static const short stress_lengths_bn[8] = {180, 180, 210, 210, 0, 0, 230, 240}; - static const unsigned char stress_amps_bn[8] = {18,18, 18,18, 20,20, 22,22 }; - - SetupTranslator(tr,stress_lengths_bn,stress_amps_bn); - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - - tr->langopts.stress_rule = 0; - tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable - tr->letter_bits_offset = OFFSET_BENGALI; - SetIndicLetters(tr); // call this after setting OFFSET_BENGALI - SetLetterBitsRange(tr,LETTERGP_F,0x3e,0x4c); // vowel signs, but not virama - - tr->langopts.numbers = 0x1; - tr->langopts.numbers2 = NUM2_100000; - } - break; - - case L('c','y'): // Welsh - { - static const short stress_lengths_cy[8] = {170,220, 180,180, 0, 0, 250,270}; - static const unsigned char stress_amps_cy[8] = {17,15, 18,18, 0,0, 22,20 }; // 'diminished' is used to mark a quieter, final unstressed syllable - - SetupTranslator(tr,stress_lengths_cy,stress_amps_cy); - - tr->charset_a0 = charsets[14]; // ISO-8859-14 -// tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - tr->langopts.stress_rule = 2; -// tr->langopts.intonation_group = 4; - - // 'diminished' is an unstressed final syllable - tr->langopts.stress_flags = 0x6 | 0x10; - tr->langopts.unstressed_wd1 = 0; - tr->langopts.unstressed_wd2 = 2; - tr->langopts.param[LOPT_SONORANT_MIN] = 120; // limit the shortening of sonorants before short vowels - - tr->langopts.numbers = 0x401; - - SetLetterVowel(tr,'w'); // add letter to vowels and remove from consonants - SetLetterVowel(tr,'y'); - } - break; - - case L('d','a'): // Danish - { - static const short stress_lengths_da[8] = {160,140, 200,200, 0,0, 220,210}; - SetupTranslator(tr,stress_lengths_da,NULL); - - tr->langopts.stress_rule = 0; - SetLetterVowel(tr,'y'); - tr->langopts.numbers = 0x10c59; - } - break; - - - case L('d','e'): - { - static const short stress_lengths_de[8] = {150,130, 200,200, 0, 0, 260,275}; - tr->langopts.stress_rule = 0; - tr->langopts.word_gap = 0x8; // don't use linking phonemes - tr->langopts.vowel_pause = 0x30; - tr->langopts.param[LOPT_PREFIXES] = 1; - memcpy(tr->stress_lengths,stress_lengths_de,sizeof(tr->stress_lengths)); - - tr->langopts.numbers = 0x11419 + NUM_ROMAN; - SetLetterVowel(tr,'y'); - } - break; - - case L('e','n'): - { - static const short stress_lengths_en[8] = {182,140, 220,220, 0,0, 248,275}; - SetupTranslator(tr,stress_lengths_en,NULL); - - tr->langopts.stress_rule = 0; - tr->langopts.numbers = 0x841 + NUM_ROMAN; - tr->langopts.param[LOPT_COMBINE_WORDS] = 2; // allow "mc" to cmbine with the following word - } - break; - - case L('e','l'): // Greek - case L_grc: // Ancient Greek - { - static const short stress_lengths_el[8] = {155, 180, 210, 210, 0, 0, 270, 300}; - static const unsigned char stress_amps_el[8] = {15,12, 20,20, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable - - // character codes offset by 0x380 - static const char el_vowels[] = {0x10,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x35,0x37,0x39,0x3f,0x45,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0}; - static const char el_fvowels[] = {0x2d,0x2e,0x2f,0x35,0x37,0x39,0x45,0x4d,0}; // ε η ι υ έ ή ί ύ - static const char el_voiceless[]= {0x38,0x3a,0x3e,0x40,0x42,0x43,0x44,0x46,0x47,0}; // θ κ ξ π ς σ τ φ χ - static const char el_consonants[]={0x32,0x33,0x34,0x36,0x38,0x3a,0x3b,0x3c,0x3d,0x3e,0x40,0x41,0x42,0x43,0x44,0x46,0x47,0x48,0}; - static const wchar_t el_char_apostrophe[] = {0x3c3,0}; // σ - - SetupTranslator(tr,stress_lengths_el,stress_amps_el); - - tr->charset_a0 = charsets[7]; // ISO-8859-7 - tr->char_plus_apostrophe = el_char_apostrophe; - - tr->letter_bits_offset = OFFSET_GREEK; - memset(tr->letter_bits,0,sizeof(tr->letter_bits)); - SetLetterBits(tr,LETTERGP_A,el_vowels); - SetLetterBits(tr,LETTERGP_B,el_voiceless); - SetLetterBits(tr,LETTERGP_C,el_consonants); - SetLetterBits(tr,LETTERGP_Y,el_fvowels); // front vowels: ε η ι υ - - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x6; // mark unstressed final syllables as diminished - tr->langopts.unstressed_wd1 = 0; - tr->langopts.unstressed_wd2 = 2; - tr->langopts.param[LOPT_SONORANT_MIN] = 130; // limit the shortening of sonorants before short vowels - - tr->langopts.numbers = 0x109; - tr->langopts.numbers2 = 0x2; // variant form of numbers before thousands - - if(name2 == L_grc) - { - // ancient greek - tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; - } - } - break; - - case L('e','o'): - { - static const short stress_lengths_eo[8] = {145, 145, 230, 170, 0, 0, 360, 370}; - static const unsigned char stress_amps_eo[] = {16,14, 20,20, 20,22, 22,21 }; - static const wchar_t eo_char_apostrophe[2] = {'l',0}; - - SetupTranslator(tr,stress_lengths_eo,stress_amps_eo); - - tr->charset_a0 = charsets[3]; // ISO-8859-3 - tr->char_plus_apostrophe = eo_char_apostrophe; - - tr->langopts.word_gap = 1; - tr->langopts.vowel_pause = 2; - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x6 | 0x10; - tr->langopts.unstressed_wd1 = 3; - tr->langopts.unstressed_wd2 = 2; - - tr->langopts.numbers = 0x1409 + NUM_ROMAN; - } - break; - - case L('e','s'): // Spanish - case L('c','a'): // Catalan - case L_pap: // Papiamento - { - static const short stress_lengths_es[8] = {180, 210, 190, 190, 0, 0, 230, 260}; -// static const short stress_lengths_es[8] = {170, 200, 180, 180, 0, 0, 220, 250}; - static const unsigned char stress_amps_es[8] = {16,12, 18,18, 20,20, 20,20 }; // 'diminished' is used to mark a quieter, final unstressed syllable - static const wchar_t ca_punct_within_word[] = {'\'',0xb7,0}; // ca: allow middle-dot within word - - SetupTranslator(tr,stress_lengths_es,stress_amps_es); - - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - tr->langopts.stress_rule = 2; - - // stress last syllable if it doesn't end in vowel or "s" or "n" - // 'diminished' is an unstressed final syllable - tr->langopts.stress_flags = 0x200 | 0x6 | 0x10; - tr->langopts.unstressed_wd1 = 0; - tr->langopts.unstressed_wd2 = 2; - tr->langopts.param[LOPT_SONORANT_MIN] = 120; // limit the shortening of sonorants before short vowels - - tr->langopts.numbers = 0x529 + NUM_ROMAN + NUM_ROMAN_AFTER; - - if(name2 == L('c','a')) - { - tr->punct_within_word = ca_punct_within_word; - tr->langopts.stress_flags = 0x200 | 0x6 | 0x30; // stress last syllable unless word ends with a vowel - } - else - if(name2 == L_pap) - { - tr->langopts.stress_flags = 0x100 | 0x6 | 0x30; // stress last syllable unless word ends with a vowel - } - } - break; - - - case L('e','u'): // basque - { - static const short stress_lengths_eu[8] = {200, 200, 200, 200, 0, 0, 210, 230}; // very weak stress - static const unsigned char stress_amps_eu[8] = {16,16, 18,18, 18,18, 18,18 }; - SetupTranslator(tr,stress_lengths_eu,stress_amps_eu); - tr->langopts.stress_rule = 1; // ?? second syllable ?? - tr->langopts.numbers = 0x569 + NUM_VIGESIMAL; - } - break; - - - case L('f','i'): // Finnish - { - static const unsigned char stress_amps_fi[8] = {18,16, 22,22, 20,22, 22,22 }; - static const short stress_lengths_fi[8] = {150,180, 200,200, 0,0, 210,250}; - - SetupTranslator(tr,stress_lengths_fi,stress_amps_fi); - - tr->langopts.stress_rule = 0; - tr->langopts.stress_flags = 0x56; // move secondary stress from light to a following heavy syllable - tr->langopts.param[LOPT_IT_DOUBLING] = 1; - tr->langopts.long_stop = 130; - - tr->langopts.numbers = 0x1009; - SetLetterVowel(tr,'y'); -// tr->langopts.max_initial_consonants = 2; // BUT foreign words may have 3 - tr->langopts.spelling_stress = 1; - tr->langopts.intonation_group = 3; // less intonation, don't raise pitch at comma - } - break; - - - case L('f','r'): // french - { - static const short stress_lengths_fr[8] = {190, 170, 190, 200, 0, 0, 235, 240}; - static const unsigned char stress_amps_fr[8] = {18,16, 20,20, 20,22, 22,21 }; - - SetupTranslator(tr,stress_lengths_fr,stress_amps_fr); - tr->langopts.stress_rule = 3; // stress on final syllable - tr->langopts.stress_flags = 0x0024; // don't use secondary stress - tr->langopts.param[LOPT_IT_LENGTHEN] = 1; // remove lengthen indicator from unstressed syllables - - tr->langopts.numbers = 0x1509 + 0x8000 + (NUM_NOPAUSE | NUM_ROMAN | NUM_VIGESIMAL); - SetLetterVowel(tr,'y'); - } - break; - -#ifdef deleted - case L('g','a'): // Irish Gaelic - { - tr->langopts.stress_rule = 1; - } - break; -#endif - - case L('h','i'): // Hindi - case L('n','e'): // Nepali - { - static const short stress_lengths_hi[8] = {190, 190, 210, 210, 0, 0, 230, 250}; - static const unsigned char stress_amps_hi[8] = {17,14, 20,19, 20,22, 22,21 }; - - SetupTranslator(tr,stress_lengths_hi,stress_amps_hi); - tr->charset_a0 = charsets[19]; // ISCII - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - - tr->langopts.stress_rule = 6; // stress on last heaviest syllable, excluding final syllable - tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable - tr->langopts.numbers = 0x011; - tr->langopts.numbers2 = NUM2_100000; - tr->letter_bits_offset = OFFSET_DEVANAGARI; - SetIndicLetters(tr); - } - break; - - - case L('h','r'): // Croatian - case L('b','s'): // Bosnian - case L('s','r'): // Serbian - { - static const unsigned char stress_amps_hr[8] = {17,17, 20,20, 20,22, 22,21 }; - static const short stress_lengths_hr[8] = {180,160, 200,200, 0,0, 220,230}; - static const short stress_lengths_sr[8] = {160,150, 200,200, 0,0, 250,260}; - - if(name2 == L('s','r')) - SetupTranslator(tr,stress_lengths_sr,stress_amps_hr); - else - SetupTranslator(tr,stress_lengths_hr,stress_amps_hr); - tr->charset_a0 = charsets[2]; // ISO-8859-2 - - tr->langopts.stress_rule = 0; - tr->langopts.stress_flags = 0x10; - tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x3; - tr->langopts.max_initial_consonants = 5; - tr->langopts.spelling_stress = 1; - tr->langopts.accents = 1; - - tr->langopts.numbers = 0x140d + 0x4000 + NUM_ROMAN_UC; - tr->langopts.numbers2 = 0x4a; // variant numbers before thousands,milliards - tr->langopts.replace_chars = replace_cyrillic_latin; - - SetLetterVowel(tr,'y'); - SetLetterVowel(tr,'r'); - } - break; - - - case L('h','u'): // Hungarian - { - static const unsigned char stress_amps_hu[8] = {17,17, 19,19, 20,22, 22,21 }; - static const short stress_lengths_hu[8] = {185,195, 195,190, 0,0, 210,220}; - - SetupTranslator(tr,stress_lengths_hu,stress_amps_hu); - tr->charset_a0 = charsets[2]; // ISO-8859-2 - - tr->langopts.vowel_pause = 0x20; - tr->langopts.stress_rule = 0; - tr->langopts.stress_flags = 0x8036; - tr->langopts.unstressed_wd1 = 2; -// tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x4; // don't propagate over word boundaries - tr->langopts.param[LOPT_IT_DOUBLING] = 1; - tr->langopts.param[LOPT_COMBINE_WORDS] = 99; // combine some prepositions with the following word - - tr->langopts.numbers = 0x1009 + 0xa000 + NUM_ROMAN + 0x10000; - SetLetterVowel(tr,'y'); - tr->langopts.spelling_stress = 1; -SetLengthMods(tr,3); // all equal - } - break; - - case L('h','y'): // Armenian - { - static const short stress_lengths_hy[8] = {250, 200, 250, 250, 0, 0, 250, 250}; - static const char hy_vowels[] = {0x31, 0x35, 0x37, 0x38, 0x3b, 0x48, 0x55, 0}; - static const char hy_consonants[] = {0x32,0x33,0x34,0x36,0x39,0x3a,0x3c,0x3d,0x3e,0x3f, - 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x56,0}; - - SetupTranslator(tr,stress_lengths_hy,NULL); - tr->langopts.stress_rule = 3; // default stress on final syllable - - tr->letter_bits_offset = OFFSET_ARMENIAN; - memset(tr->letter_bits,0,sizeof(tr->letter_bits)); - SetLetterBits(tr,LETTERGP_A,hy_vowels); - SetLetterBits(tr,LETTERGP_C,hy_consonants); - tr->langopts.max_initial_consonants = 6; - tr->langopts.numbers = 0x409; -// tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words - } - break; - - case L('i','d'): // Indonesian - { - static const short stress_lengths_id[8] = {160, 200, 180, 180, 0, 0, 220, 240}; - static const unsigned char stress_amps_id[8] = {16,18, 18,18, 20,22, 22,21 }; - - SetupTranslator(tr,stress_lengths_id,stress_amps_id); - tr->langopts.stress_rule = 2; - tr->langopts.numbers = 0x1009 + NUM_ROMAN; - tr->langopts.stress_flags = 0x6 | 0x10; - tr->langopts.accents = 2; // "capital" after letter name - } - break; - - case L('i','s'): // Icelandic - { - static const short stress_lengths_is[8] = {180,160, 200,200, 0,0, 240,250}; - static const wchar_t is_lettergroup_B[] = {'c','f','h','k','p','t','x',0xfe,0}; // voiceless conants, including 'þ' ?? 's' - - SetupTranslator(tr,stress_lengths_is,NULL); - tr->langopts.stress_rule = 0; - tr->langopts.stress_flags = 0x10; - tr->langopts.param[LOPT_IT_LENGTHEN] = 0x11; // remove lengthen indicator from unstressed vowels - tr->langopts.param[LOPT_REDUCE] = 2; - - ResetLetterBits(tr,0x18); - SetLetterBits(tr,4,"kpst"); // Letter group F - SetLetterBits(tr,3,"jvr"); // Letter group H - tr->letter_groups[1] = is_lettergroup_B; - SetLetterVowel(tr,'y'); - tr->langopts.numbers = 0x8e9; - tr->langopts.numbers2 = 0x2; - } - break; - - case L('i','t'): // Italian - { - static const short stress_lengths_it[8] = {150, 140, 170, 170, 0, 0, 300, 330}; - static const unsigned char stress_amps_it[8] = {15,14, 19,19, 20,22, 22,20 }; - - SetupTranslator(tr,stress_lengths_it,stress_amps_it); - - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x10 | 0x20000; - tr->langopts.vowel_pause = 1; - tr->langopts.unstressed_wd1 = 2; - tr->langopts.unstressed_wd2 = 2; - tr->langopts.param[LOPT_IT_LENGTHEN] = 2; // remove lengthen indicator from unstressed or non-penultimate syllables - tr->langopts.param[LOPT_IT_DOUBLING] = 2; // double the first consonant if the previous word ends in a stressed vowel - tr->langopts.param[LOPT_SONORANT_MIN] = 130; // limit the shortening of sonorants before short vowels - tr->langopts.param[LOPT_REDUCE] = 1; // reduce vowels even if phonemes are specified in it_list - tr->langopts.param[LOPT_ALT] = 2; // call ApplySpecialAttributes2() if a word has $alt or $alt2 - tr->langopts.numbers = 0x2709 + NUM_ROMAN; - tr->langopts.accents = 2; // Say "Capital" after the letter. - SetLetterVowel(tr,'y'); - } - break; - - case L_jbo: // Lojban - { - static const short stress_lengths_jbo[8] = {145,145, 170,160, 0,0, 330,350}; - static const wchar_t jbo_punct_within_word[] = {'.',',','\'',0x2c8,0}; // allow period and comma within a word, also stress marker (from LOPT_CAPS_IN_WORD) - - SetupTranslator(tr,stress_lengths_jbo,NULL); - tr->langopts.stress_rule = 2; - tr->langopts.vowel_pause = 0x20c; // pause before a word which starts with a vowel, or after a word which ends in a consonant -// tr->langopts.word_gap = 1; - tr->punct_within_word = jbo_punct_within_word; - tr->langopts.param[LOPT_CAPS_IN_WORD] = 2; // capitals indicate stressed syllables - SetLetterVowel(tr,'y'); - } - break; - - case L('k','o'): // Korean, TEST - { - static const char ko_ivowels[] = {0x63,0x64,0x67,0x68,0x6d,0x72,0x74,0x75,0}; // y and i vowels - static const unsigned char ko_voiced[] = {0x02,0x05,0x06,0xab,0xaf,0xb7,0xbc,0}; // voiced consonants, l,m,n,N - - tr->letter_bits_offset = OFFSET_KOREAN; - memset(tr->letter_bits,0,sizeof(tr->letter_bits)); - SetLetterBitsRange(tr,LETTERGP_A,0x61,0x75); - SetLetterBits(tr,LETTERGP_Y,ko_ivowels); - SetLetterBits(tr,LETTERGP_G,(const char *)ko_voiced); - - tr->langopts.stress_rule = 8; // ?? 1st syllable if it is heavy, else 2nd syllable - tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words - tr->langopts.numbers = 0x0401; - } - break; - - case L('k','u'): // Kurdish - { - static const unsigned char stress_amps_ku[8] = {18,18, 20,20, 20,22, 22,21 }; - static const short stress_lengths_ku[8] = {180,180, 190,180, 0,0, 230,240}; - - SetupTranslator(tr,stress_lengths_ku,stress_amps_ku); - tr->charset_a0 = charsets[9]; // ISO-8859-9 - Latin5 - - tr->langopts.stress_rule = 7; // stress on the last syllable, before any explicitly unstressed syllable - - tr->langopts.numbers = 0x100461; - tr->langopts.max_initial_consonants = 2; - } - break; - - case L('l','a'): //Latin - { - tr->charset_a0 = charsets[4]; // ISO-8859-4, includes a,e,i,o,u-macron - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x20; - tr->langopts.unstressed_wd1 = 0; - tr->langopts.unstressed_wd2 = 2; - tr->langopts.param[LOPT_DIERESES] = 1; - tr->langopts.numbers = 0x1 + NUM_ROMAN; - tr->langopts.max_roman = 5000; - } - break; - - case L('l','v'): // latvian - { - static const unsigned char stress_amps_lv[8] = {17,13, 20,20, 20,22, 22,21 }; - static const short stress_lengths_lv[8] = {180,130, 210,210, 0,0, 210,210}; - - SetupTranslator(tr,stress_lengths_lv,stress_amps_lv); - - tr->langopts.stress_rule = 0; - tr->langopts.spelling_stress = 1; - tr->charset_a0 = charsets[4]; // ISO-8859-4 - tr->langopts.numbers = 0x409 + 0x8000 + 0x10000; - tr->langopts.stress_flags = 0x16 + 0x40000; - } - break; - - case L('m','k'): // Macedonian - { - static wchar_t vowels_cyrillic[] = {0x440, // also include 'р' [R] - 0x430,0x435,0x438,0x439,0x43e,0x443,0x44b,0x44d,0x44e,0x44f,0x450,0x451,0x456,0x457,0x45d,0x45e,0}; - static const unsigned char stress_amps_mk[8] = {17,17, 20,20, 20,22, 22,21 }; - static const short stress_lengths_mk[8] = {180,160, 200,200, 0,0, 220,230}; - - SetupTranslator(tr,stress_lengths_mk,stress_amps_mk); - tr->charset_a0 = charsets[5]; // ISO-8859-5 - tr->letter_groups[0] = vowels_cyrillic; - - tr->langopts.stress_rule = 4; // antipenultimate - tr->langopts.numbers = 0x0429 + 0x4000; - tr->langopts.numbers2 = 0x8a; // variant numbers before thousands,milliards - } - break; - - - case L('n','l'): // Dutch - { - static const short stress_lengths_nl[8] = {160,135, 210,210, 0, 0, 260,280}; - - tr->langopts.stress_rule = 0; - tr->langopts.vowel_pause = 1; - tr->langopts.param[LOPT_DIERESES] = 1; - tr->langopts.param[LOPT_PREFIXES] = 1; - SetLetterVowel(tr,'y'); - - tr->langopts.numbers = 0x11c19; - memcpy(tr->stress_lengths,stress_lengths_nl,sizeof(tr->stress_lengths)); - } - break; - - case L('n','o'): // Norwegian - { - static const short stress_lengths_no[8] = {160,140, 200,200, 0,0, 220,210}; - - SetupTranslator(tr,stress_lengths_no,NULL); - tr->langopts.stress_rule = 0; - SetLetterVowel(tr,'y'); - tr->langopts.numbers = 0x11849; - } - break; - - case L('o','m'): - { - static const unsigned char stress_amps_om[] = {18,15, 20,20, 20,22, 22,22 }; - static const short stress_lengths_om[8] = {200,200, 200,200, 0,0, 200,200}; - - SetupTranslator(tr,stress_lengths_om,stress_amps_om); - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x16 + 0x80000; - } - break; - - case L('p','l'): // Polish - { - static const short stress_lengths_pl[8] = {160, 190, 175, 175, 0, 0, 200, 210}; - static const unsigned char stress_amps_pl[8] = {17,13, 19,19, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable - - SetupTranslator(tr,stress_lengths_pl,stress_amps_pl); - - tr->charset_a0 = charsets[2]; // ISO-8859-2 - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x6; // mark unstressed final syllables as diminished - tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x8; - tr->langopts.max_initial_consonants = 7; // for example: wchrzczony :) - tr->langopts.numbers=0x1009 + 0x4000; - tr->langopts.numbers2=0x40; - tr->langopts.param[LOPT_COMBINE_WORDS] = 4 + 0x100; // combine 'nie' (marked with $alt2) with some 1-syllable (and 2-syllable) words (marked with $alt) - SetLetterVowel(tr,'y'); - } - break; - - case L('p','t'): // Portuguese - { - static const short stress_lengths_pt[8] = {180, 125, 210, 210, 0, 0, 270, 295}; - static const unsigned char stress_amps_pt[8] = {16,13, 19,19, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable - - SetupTranslator(tr,stress_lengths_pt,stress_amps_pt); - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - - tr->langopts.stress_rule = 3; // stress on final syllable - tr->langopts.stress_flags = 0x6 | 0x10 | 0x20000; - tr->langopts.numbers = 0x069 + 0x4000 + NUM_ROMAN; - SetLetterVowel(tr,'y'); - ResetLetterBits(tr,0x2); - SetLetterBits(tr,1,"bcdfgjkmnpqstvxz"); // B hard consonants, excluding h,l,r,w,y - } - break; - - case L('r','o'): // Romanian - { - static const short stress_lengths_ro[8] = {170, 170, 180, 180, 0, 0, 240, 260}; - static const unsigned char stress_amps_ro[8] = {15,13, 18,18, 20,22, 22,21 }; - - SetupTranslator(tr,stress_lengths_ro,stress_amps_ro); - - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x100 + 0x6; - - tr->charset_a0 = charsets[2]; // ISO-8859-2 - tr->langopts.numbers = 0x1029+0x6000 + NUM_ROMAN; - tr->langopts.numbers2 = 0x1e; // variant numbers before all thousandplex - } - break; - - case L('r','u'): // Russian - Translator_Russian(tr); - break; - - case L('r','w'): // Kiryarwanda - { - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x16; - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - - tr->langopts.numbers = 0x61 + 0x100000 + 0x4000; - tr->langopts.numbers2 = 0x200; // say "thousands" before its number - } - break; - - case L('s','k'): // Slovak - case L('c','s'): // Czech - { - static const char *sk_voiced = "bdgjlmnrvwzaeiouy"; - - SetupTranslator(tr,stress_lengths_sk,stress_amps_sk); - tr->charset_a0 = charsets[2]; // ISO-8859-2 - - tr->langopts.stress_rule = 0; - tr->langopts.stress_flags = 0x16; - tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x3; - tr->langopts.max_initial_consonants = 5; - tr->langopts.spelling_stress = 1; - tr->langopts.param[LOPT_COMBINE_WORDS] = 4; // combine some prepositions with the following word - - tr->langopts.numbers = 0x0401 + 0x4000 + NUM_ROMAN; - tr->langopts.numbers2 = 0x100; - tr->langopts.thousands_sep = 0; //no thousands separator - tr->langopts.decimal_sep = ','; - - if(name2 == L('c','s')) - { - tr->langopts.numbers2 = 0x108; // variant numbers before milliards - } - - SetLetterVowel(tr,'y'); - SetLetterVowel(tr,'r'); - ResetLetterBits(tr,0x20); - SetLetterBits(tr,5,sk_voiced); - } - break; - - case L('s','q'): // Albanian - { - static const short stress_lengths_sq[8] = {150, 150, 180, 180, 0, 0, 300, 300}; - static const unsigned char stress_amps_sq[8] = {16,12, 16,16, 20,20, 21,19 }; - - SetupTranslator(tr,stress_lengths_sq,stress_amps_sq); - - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x16 + 0x100; - SetLetterVowel(tr,'y'); - tr->langopts.numbers = 0x69 + 0x8000; - tr->langopts.accents = 2; // "capital" after letter name - } - break; - - - case L('s','v'): // Swedish - { - static const unsigned char stress_amps_sv[] = {16,16, 20,20, 20,22, 22,21 }; - static const short stress_lengths_sv[8] = {160,135, 220,220, 0,0, 250,280}; - SetupTranslator(tr,stress_lengths_sv,stress_amps_sv); - - tr->langopts.stress_rule = 0; - SetLetterVowel(tr,'y'); - tr->langopts.numbers = 0x1909; - tr->langopts.accents = 1; - } - break; - - case L('s','w'): // Swahili - { - static const short stress_lengths_sw[8] = {160, 170, 200, 200, 0, 0, 320, 340}; - static const unsigned char stress_amps_sw[] = {16,12, 19,19, 20,22, 22,21 }; - - SetupTranslator(tr,stress_lengths_sw,stress_amps_sw); - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - - tr->langopts.vowel_pause = 1; - tr->langopts.stress_rule = 2; - tr->langopts.stress_flags = 0x6 | 0x10; - - tr->langopts.numbers = 0x4e1; - tr->langopts.numbers2 = NUM2_100000a; - } - break; - - case L('t','a'): // Tamil - case L('m','l'): // Malayalam - case L('k','n'): // Kannada - case L('m','r'): // Marathi - { - static const short stress_lengths_ta[8] = {200, 200, 210, 210, 0, 0, 230, 230}; - static const unsigned char stress_amps_ta[8] = {18,18, 18,18, 20,20, 22,22 }; - - SetupTranslator(tr,stress_lengths_ta,stress_amps_ta); - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - - tr->langopts.stress_rule = 0; - tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable - tr->letter_bits_offset = OFFSET_TAMIL; - - if(name2 == L('m','r')) - { - tr->letter_bits_offset = OFFSET_DEVANAGARI; - } - else - if(name2 == L('m','l')) - { - tr->letter_bits_offset = OFFSET_MALAYALAM; - } - else - if(name2 == L('k','n')) - { - tr->letter_bits_offset = OFFSET_KANNADA; - tr->langopts.numbers = 0x1; - tr->langopts.numbers2 = NUM2_100000; - } - tr->langopts.param[LOPT_WORD_MERGE] = 1; // don't break vowels betwen words - SetIndicLetters(tr); // call this after setting OFFSET_ - } - break; - -#ifdef deleted - case L('t','h'): // Thai - { - static const short stress_lengths_th[8] = {230,150, 230,230, 230,0, 230,250}; - static const unsigned char stress_amps_th[] = {22,16, 22,22, 22,22, 22,22 }; - - SetupTranslator(tr,stress_lengths_th,stress_amps_th); - - tr->langopts.stress_rule = 0; // stress on final syllable of a "word" - tr->langopts.stress_flags = 2; // don't automatically set diminished stress (may be set in the intonation module) - tr->langopts.tone_language = 1; // Tone language, use CalcPitches_Tone() rather than CalcPitches() - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable -// tr->langopts.tone_numbers = 1; // a number after letters indicates a tone number (eg. pinyin or jyutping) - tr->langopts.word_gap = 0x21; // length of a final vowel is less dependent on the next consonant, don't merge consonant with next word - } - break; -#endif - - case L('t','r'): // Turkish - { - static const unsigned char stress_amps_tr[8] = {18,18, 20,20, 20,22, 22,21 }; - static const short stress_lengths_tr[8] = {190,190, 190,190, 0,0, 250,270}; - - SetupTranslator(tr,stress_lengths_tr,stress_amps_tr); - tr->charset_a0 = charsets[9]; // ISO-8859-9 - Latin5 - - tr->langopts.stress_rule = 7; // stress on the last syllable, before any explicitly unstressed syllable - tr->langopts.stress_flags = 0x20; //no automatic secondary stress - - tr->langopts.numbers = 0x1509 + 0x4000; - tr->langopts.max_initial_consonants = 2; - } - break; - - case L('v','i'): // Vietnamese - { - static const short stress_lengths_vi[8] = {150, 150, 180, 180, 210, 230, 230, 240}; - static const unsigned char stress_amps_vi[] = {16,16, 16,16, 22,22, 22,22 }; - static wchar_t vowels_vi[] = { - 0x61, 0xe0, 0xe1, 0x1ea3, 0xe3, 0x1ea1, // a - 0x103, 0x1eb1, 0x1eaf, 0x1eb3, 0x1eb5, 0x1eb7, // ă - 0xe2, 0x1ea7, 0x1ea5, 0x1ea9, 0x1eab, 0x1ead, // â - 0x65, 0xe8, 0xe9, 0x1ebb, 0x1ebd, 0x1eb9, // e - 0xea, 0x1ec1, 0x1ebf, 0x1ec3, 0x1ec5, 0x1ec7, // i - 0x69, 0xec, 0xed, 0x1ec9, 0x129, 0x1ecb, // i - 0x6f, 0xf2, 0xf3, 0x1ecf, 0xf5, 0x1ecd, // o - 0xf4, 0x1ed3, 0x1ed1, 0x1ed5, 0x1ed7, 0x1ed9, // ô - 0x1a1, 0x1edd, 0x1edb, 0x1edf, 0x1ee1, 0x1ee3, // ơ - 0x75, 0xf9, 0xfa, 0x1ee7, 0x169, 0x1ee5, // u - 0x1b0, 0x1eeb, 0x1ee9, 0x1eed, 0x1eef, 0x1ef1, // ư - 0x79, 0x1ef3, 0xfd, 0x1ef7, 0x1ef9, 0x1e, 0 }; // y - - SetupTranslator(tr,stress_lengths_vi,stress_amps_vi); - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - - tr->langopts.stress_rule = 0; - tr->langopts.word_gap = 0x21; // length of a final vowel is less dependent on the next consonant, don't merge consonant with next word -// tr->langopts.vowel_pause = 4; - tr->letter_groups[0] = vowels_vi; - tr->langopts.tone_language = 1; // Tone language, use CalcPitches_Tone() rather than CalcPitches() - tr->langopts.unstressed_wd1 = 2; - tr->langopts.numbers = 0x0049 + 0x8000; - - } - break; - - case L('z','h'): - case L_zhy: - { - static const short stress_lengths_zh[8] = {230,150, 230,230, 230,0, 240,250}; // 1=tone5. end-of-sentence, 6=tone 1&4, 7=tone 2&3 - static const unsigned char stress_amps_zh[] = {22,16, 22,22, 22,22, 22,22 }; - - SetupTranslator(tr,stress_lengths_zh,stress_amps_zh); - - tr->langopts.stress_rule = 3; // stress on final syllable of a "word" - tr->langopts.stress_flags = 2; // don't automatically set diminished stress (may be set in the intonation module) - tr->langopts.vowel_pause = 0; - tr->langopts.tone_language = 1; // Tone language, use CalcPitches_Tone() rather than CalcPitches() - tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable - tr->langopts.tone_numbers = 1; // a number after letters indicates a tone number (eg. pinyin or jyutping) - tr->langopts.ideographs = 1; - tr->langopts.word_gap = 0x21; // length of a final vowel is less dependent on the next consonant, don't merge consonant with next word - if(name2 == L('z','h')) - { - tr->langopts.textmode = 1; - tr->langopts.listx = 1; // compile zh_listx after zh_list - } - } - break; - - default: - tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words - break; - } - - tr->translator_name = name2; - - if(tr->langopts.numbers & 0x8) - { - // use . and ; for thousands and decimal separators - tr->langopts.thousands_sep = '.'; - tr->langopts.decimal_sep = ','; - } - if(tr->langopts.numbers & 0x4) - { - tr->langopts.thousands_sep = 0; // don't allow thousands separator, except space - } - return(tr); -} // end of SelectTranslator - - - -//********************************************************************************************************** - - - -static void Translator_Russian(Translator *tr) -{//=========================================== - 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}; - - - // character codes offset by 0x420 - static const char ru_vowels[] = {0x10,0x15,0x31,0x18,0x1e,0x23,0x2b,0x2d,0x2e,0x2f,0}; - static const 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,0}; - 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_nothard[] = {0x11,0x12,0x13,0x14,0x17,0x19,0x1a,0x1b,0x1c,0x1d,0x1f,0x20,0x21,0x22,0x24,0x25,0x27,0x29,0x2c,0}; - static const char ru_voiced[] = {0x11,0x12,0x13,0x14,0x16,0x17,0}; // letter group G (voiced obstruents) - static const char ru_ivowels[] = {0x2c,0x15,0x31,0x18,0x2e,0x2f,0}; // letter group Y (iotated vowels & soft-sign) - - SetupTranslator(tr,stress_lengths_ru,stress_amps_ru); - - tr->charset_a0 = charsets[18]; // KOI8-R - tr->transpose_offset = 0x42f; // convert cyrillic from unicode into range 0x01 to 0x22 - tr->transpose_min = 0x430; - tr->transpose_max = 0x451; - - tr->letter_bits_offset = OFFSET_CYRILLIC; - memset(tr->letter_bits,0,sizeof(tr->letter_bits)); - SetLetterBits(tr,0,ru_vowels); - SetLetterBits(tr,1,ru_soft); - SetLetterBits(tr,2,ru_consonants); - SetLetterBits(tr,3,ru_hard); - SetLetterBits(tr,4,ru_nothard); - SetLetterBits(tr,5,ru_voiced); - SetLetterBits(tr,6,ru_ivowels); - SetLetterBits(tr,7,ru_vowels); - - tr->langopts.param[LOPT_UNPRONOUNCABLE] = 0x432; // [v] don't count this character at start of word - tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 1; - tr->langopts.param[LOPT_REDUCE] = 2; - tr->langopts.stress_rule = 5; - tr->langopts.stress_flags = 0x0020; // waas 0x1010 - - tr->langopts.numbers = 0x0409; - tr->langopts.numbers2 = 0xc2; // variant numbers before thousands - tr->langopts.phoneme_change = 1; - tr->langopts.testing = 2; - -} // end of Translator_Russian - - - -/* -typedef struct { - int flags; - unsigned char stress; // stress level of this vowel - unsigned char stress_highest; // the highest stress level of a vowel in this word - unsigned char n_vowels; // number of vowels in the word - unsigned char vowel_this; // syllable number of this vowel (counting from 1) - unsigned char vowel_stressed; // syllable number of the highest stressed vowel -} CHANGEPH; -*/ - - -#define RUSSIAN2 -#ifdef RUSSIAN2 - -int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) -{//============================================================================================================= -// Called for each phoneme in the phoneme list, to allow a language to make changes -// ph The current phoneme - - int variant; - int vowelix; - int stressed; - int soft; - PHONEME_TAB *prev, *next; - - if(ch->flags & 8) - return(0); // full phoneme translation has already been given - // Russian vowel softening and reduction rules - - if(ph->type == phVOWEL) - { - int prestressed = ch->vowel_stressed==ch->vowel_this+1; // the next vowel after this has the main stress - - #define N_VOWELS_RU 11 - static unsigned int vowels_ru[N_VOWELS_RU] = {'a','V','O','I',PH('I','#'),PH('E','#'),PH('E','2'), -PH('V','#'),PH('I','3'),PH('I','2'),PH('E','3')}; - - - static unsigned int vowel_replace[N_VOWELS_RU][6] = { - // stressed, soft, soft-stressed, j+stressed, j+soft, j+soft-stressed - /*0*/ {'A', 'I', PH('j','a'), 'a', 'a', 'a'}, // a Uses 3,4,5 columns. - /*1*/ {'A', 'V', PH('j','a'), 'a', 'V', 'a'}, // V Uses 3,4,5 columns. - /*2*/ {'o', '8', '8', 'o', '8', '8'}, // O - /*3*/ {'i', 'I', 'i', 'a', 'I', 'a'}, // I Uses 3,4,5 columns. - /*4*/ {'i', PH('I','#'), 'i', 'i', PH('I','#'), 'i'}, // I# - /*5*/ {'E', PH('E','#'), 'E', 'e', PH('E','#'), 'e'}, // E# - /*6*/ {'E', PH('E','2'), 'E', 'e', PH('E','2'), 'e'}, // E2 Uses 3,4,5 columns. - /*7*/ {PH('j','a'), 'V', PH('j','a'), 'A', 'V', 'A'}, // V# - /*8*/ {PH('j','a'), 'I', PH('j','a'), 'e', 'I', 'e'}, // I3 Uses 3,4,5 columns. - /*9*/ {'e', 'I', 'e', 'e', 'I', 'e'}, // I2 - /*10*/ {'e', PH('E', '2'), 'e', 'e', PH('E','2'), 'e'} // E3 - }; - - prev = phoneme_tab[phlist[index-1].phcode]; - next = phoneme_tab[phlist[index+1].phcode]; - - // lookup the vowel name to get an index into the vowel_replace[] table - for(vowelix=0; vowelix<N_VOWELS_RU; vowelix++) - { - if(vowels_ru[vowelix] == ph->mnemonic) - break; - } - if(vowelix == N_VOWELS_RU) - return(0); - - if(prestressed) - { - if((vowelix==6)&&(prev->mnemonic=='j')) - vowelix=8; - if(vowelix==1) - vowelix=0; - if(vowelix==4) - vowelix=3; - if(vowelix==6) - vowelix=5; - if(vowelix==7) - vowelix=8; - if(vowelix==10) - vowelix=9; - } - // do we need a variant of this vowel, depending on the stress and adjacent phonemes ? - variant = -1; - stressed = ch->flags & 2; - soft=prev->phflags & phPALATAL; - - if (soft && stressed) - variant = 2; else - if (stressed) - variant = 0; else - if (soft) - variant = 1; - if(variant >= 0) - { - if(prev->mnemonic == 'j') - variant += 3; - - phlist[index].phcode = PhonemeCode(vowel_replace[vowelix][variant]); - } - else - { - phlist[index].phcode = PhonemeCode(vowels_ru[vowelix]); - } - } - - return(0); -} -#else - - -int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) -{//============================================================================================================= -// Called for each phoneme in the phoneme list, to allow a language to make changes -// flags: bit 0=1 last phoneme in a word -// bit 1=1 this is the highest stressed vowel in the current word -// bit 2=1 after the highest stressed vowel in the current word -// bit 3=1 the phonemes were specified explicitly, or found from an entry in the xx_list dictionary -// ph The current phoneme - - int variant; - int vowelix; - PHONEME_TAB *prev, *next; - - if(ch->flags & 8) - return(0); // full phoneme translation has already been given - - // Russian vowel softening and reduction rules - if(ph->type == phVOWEL) - { - #define N_VOWELS_RU 7 - static unsigned char vowels_ru[N_VOWELS_RU] = {'a','A','o','E','i','u','y'}; - - // each line gives: soft, reduced, soft-reduced, post-tonic - static unsigned short vowel_replace[N_VOWELS_RU][4] = { - {'&', 'V', 'I', 'V'}, // a - {'&', 'V', 'I', 'V'}, // A - {'8', 'V', 'I', 'V'}, // o - {'e', 'I', 'I', 'I'}, // E - {'i', 'I', 'I', 'I'}, // i - {'u'+('"'<<8), 'U', 'U', 'U'}, // u - {'y', 'Y', 'Y', 'Y'}}; // y - - prev = phoneme_tab[phlist[index-1].phcode]; - next = phoneme_tab[phlist[index+1].phcode]; - -if(prev->mnemonic == 'j') - return(0); - - // lookup the vowel name to get an index into the vowel_replace[] table - for(vowelix=0; vowelix<N_VOWELS_RU; vowelix++) - { - if(vowels_ru[vowelix] == ph->mnemonic) - break; - } - if(vowelix == N_VOWELS_RU) - return(0); - - // do we need a variant of this vowel, depending on the stress and adjacent phonemes ? - variant = -1; - if(ch->flags & 2) - { - // a stressed vowel - if((prev->phflags & phPALATAL) && ((next->phflags & phPALATAL) || phoneme_tab[phlist[index+2].phcode]->mnemonic == ';')) - { - // between two palatal consonants, use the soft variant - variant = 0; - } - } - else - { - // an unstressed vowel - if(prev->phflags & phPALATAL) - { - variant = 2; // unstressed soft - } - else - if((ph->mnemonic == 'o') && ((prev->phflags & phPLACE) == phPLACE_pla)) - { - variant = 2; // unstressed soft ([o] vowel following: ш ж - } - else - if(ch->flags & 4) - { - variant = 3; // post tonic - } - else - { - variant = 1; // unstressed - } - } - if(variant >= 0) - { - phlist[index].phcode = PhonemeCode(vowel_replace[vowelix][variant]); - } - } - - return(0); -} -#endif - diff --git a/navit/support/espeak/translate.c b/navit/support/espeak/translate.c deleted file mode 100755 index 4891644cd..000000000 --- a/navit/support/espeak/translate.c +++ /dev/null @@ -1,2800 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include <stdio.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#include <wctype.h> -#include <wchar.h> - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" - -#define WORD_STRESS_CHAR '*' - - -Translator *translator = NULL; // the main translator -Translator *translator2 = NULL; // secondary translator for certain words -static char translator2_language[20] = {0}; - -FILE *f_trans = NULL; // phoneme output text -int option_tone2 = 0; -int option_tone_flags = 0; // bit 8=emphasize allcaps, bit 9=emphasize penultimate stress -int option_phonemes = 0; -int option_phoneme_events = 0; -int option_quiet = 0; -int option_endpause = 0; // suppress pause after end of text -int option_capitals = 0; -int option_punctuation = 0; -int option_sayas = 0; -static int option_sayas2 = 0; // used in translate_clause() -static int option_emphasis = 0; // 0=normal, 1=normal, 2=weak, 3=moderate, 4=strong -int option_ssml = 0; -int option_phoneme_input = 0; // allow [[phonemes]] in input -int option_phoneme_variants = 0; // 0= don't display phoneme variant mnemonics -int option_wordgap = 0; - -static int count_sayas_digits; -int skip_sentences; -int skip_words; -int skip_characters; -char skip_marker[N_MARKER_LENGTH]; -int skipping_text; // waiting until word count, sentence count, or named marker is reached -int end_character_position; -int count_sentences; -int count_words; -int clause_start_char; -int clause_start_word; -int new_sentence; -static int word_emphasis = 0; // set if emphasis level 3 or 4 -static int embedded_flag = 0; // there are embedded commands to be applied to the next phoneme, used in TranslateWord2() - -static int prev_clause_pause=0; -static int max_clause_pause = 0; -int pre_pause; - - -// these were previously in translator class -char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes -int n_ph_list2; -PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes - - - -wchar_t option_punctlist[N_PUNCTLIST]={0}; -char ctrl_embedded = '\001'; // to allow an alternative CTRL for embedded commands -int option_multibyte=espeakCHARS_AUTO; // 0=auto, 1=utf8, 2=8bit, 3=wchar, 4=16bit - -// these are overridden by defaults set in the "speak" file -int option_linelength = 0; - -#define N_EMBEDDED_LIST 250 -static int embedded_ix; -static int embedded_read; -unsigned int embedded_list[N_EMBEDDED_LIST]; - -// the source text of a single clause (UTF8 bytes) -#define N_TR_SOURCE 700 -static char source[N_TR_SOURCE+40]; // extra space for embedded command & voice change info at end - -int n_replace_phonemes; -REPLACE_PHONEMES replace_phonemes[N_REPLACE_PHONEMES]; - - -// brackets, also 0x2014 to 0x021f which don't need to be in this list -static const unsigned short brackets[] = { -'(',')','[',']','{','}','<','>','"','\'','`', -0xab,0xbb, // double angle brackets -0x300a,0x300b, // double angle brackets (ideograph) -0}; - -// other characters which break a word, but don't produce a pause -static const unsigned short breaks[] = {'_', 0}; - -// treat these characters as spaces, in addition to iswspace() -static const wchar_t chars_space[] = {0x2500,0}; // box drawing horiz - - -// Translate character codes 0xA0 to 0xFF into their unicode values -// ISO_8859_1 is set as default -static const unsigned short ISO_8859_1[0x60] = { - 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, // a0 - 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, // a8 - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, // b0 - 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, // b8 - 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0 - 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, // c8 - 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0 - 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, // d8 - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0 - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, // e8 - 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0 - 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff, // f8 -}; - -static const unsigned short ISO_8859_2[0x60] = { - 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, // a0 - 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, // a8 - 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, // b0 - 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, // b8 - 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, // c0 - 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, // c8 - 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, // d0 - 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, // d8 - 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, // e0 - 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, // e8 - 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, // f0 - 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, // f8 -}; - -static const unsigned short ISO_8859_3[0x60] = { - 0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0x0000, 0x0124, 0x00a7, // a0 - 0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0x0000, 0x017b, // a8 - 0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7, // b0 - 0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0x0000, 0x017c, // b8 - 0x00c0, 0x00c1, 0x00c2, 0x0000, 0x00c4, 0x010a, 0x0108, 0x00c7, // c0 - 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, // c8 - 0x0000, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7, // d0 - 0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df, // d8 - 0x00e0, 0x00e1, 0x00e2, 0x0000, 0x00e4, 0x010b, 0x0109, 0x00e7, // e0 - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, // e8 - 0x0000, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7, // f0 - 0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9, // f8 -}; - -static const unsigned short ISO_8859_4[0x60] = { - 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, // a0 - 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, // a8 - 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, // b0 - 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, // b8 - 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, // c0 - 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, // c8 - 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0 - 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, // d8 - 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, // e0 - 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, // e8 - 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0 - 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, // f8 -}; - -static const unsigned short ISO_8859_5[0x60] = { - 0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, // a0 Cyrillic - 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f, // a8 - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, // b0 - 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, // b8 - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, // c0 - 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, // c8 - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, // d0 - 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, // d8 - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, // e0 - 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, // e8 - 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, // f0 - 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f, // f8 -}; - -static const unsigned short ISO_8859_7[0x60] = { - 0x00a0, 0x2018, 0x2019, 0x00a3, 0x20ac, 0x20af, 0x00a6, 0x00a7, // a0 Greek - 0x00a8, 0x00a9, 0x037a, 0x00ab, 0x00ac, 0x00ad, 0x0000, 0x2015, // a8 - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7, // b0 - 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, // b8 - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, // c0 - 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, // c8 - 0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, // d0 - 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, // d8 - 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, // e0 - 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, // e8 - 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, // f0 - 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000, // f8 -}; - -static const unsigned short ISO_8859_9[0x60] = { - 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, // a0 - 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, // a8 - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, // b0 - 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, // b8 - 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0 - 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, // c8 - 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0 - 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, // d8 - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0 - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, // e8 - 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0 - 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, // f8 -}; - -static const unsigned short ISO_8859_14[0x60] = { - 0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7, // a0 Welsh - 0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178, // a8 - 0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56, // b0 - 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, // b8 - 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0 - 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, // c8 - 0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a, // d0 - 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df, // d8 - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0 - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, // e8 - 0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b, // f0 - 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff, // f8 -}; - -static const unsigned short KOI8_R[0x60] = { - 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, // a0 Russian - 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, // a8 - 0x255f, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, // b0 - 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x00a9, // b8 - 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, // c0 - 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, // c8 - 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, // d0 - 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, // d8 - 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, // e0 - 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, // e8 - 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, // f0 - 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a, // f8 -}; - -static const unsigned short ISCII[0x60] = { - 0x0020, 0x0901, 0x0902, 0x0903, 0x0905, 0x0906, 0x0907, 0x0908, // a0 - 0x0909, 0x090a, 0x090b, 0x090e, 0x090f, 0x0910, 0x090d, 0x0912, // a8 - 0x0913, 0x0914, 0x0911, 0x0915, 0x0916, 0x0917, 0x0918, 0x0919, // b0 - 0x091a, 0x091b, 0x091c, 0x091d, 0x091e, 0x091f, 0x0920, 0x0921, // b8 - 0x0922, 0x0923, 0x0924, 0x0925, 0x0926, 0x0927, 0x0928, 0x0929, // c0 - 0x092a, 0x092b, 0x092c, 0x092d, 0x092e, 0x092f, 0x095f, 0x0930, // c8 - 0x0931, 0x0932, 0x0933, 0x0934, 0x0935, 0x0936, 0x0937, 0x0938, // d0 - 0x0939, 0x0020, 0x093e, 0x093f, 0x0940, 0x0941, 0x0942, 0x0943, // d8 - 0x0946, 0x0947, 0x0948, 0x0945, 0x094a, 0x094b, 0x094c, 0x0949, // e0 - 0x094d, 0x093c, 0x0964, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, // e8 - 0x0020, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, // f0 - 0x0037, 0x0038, 0x0039, 0x20, 0x20, 0x20, 0x20, 0x20, // f8 -}; - -const unsigned short *charsets[N_CHARSETS] = { - ISO_8859_1, - ISO_8859_1, - ISO_8859_2, - ISO_8859_3, - ISO_8859_4, - ISO_8859_5, - ISO_8859_1, - ISO_8859_7, - ISO_8859_1, - ISO_8859_9, - ISO_8859_1, - ISO_8859_1, - ISO_8859_1, - ISO_8859_1, - ISO_8859_14, - ISO_8859_1, - ISO_8859_1, - ISO_8859_1, - KOI8_R, // 18 - ISCII }; - -// Tables of the relative lengths of vowels, depending on the -// type of the two phonemes that follow -// indexes are the "length_mod" value for the following phonemes - -// use this table if vowel is not the last in the word -static unsigned char length_mods_en[100] = { -/* a , t s n d z r N <- next */ - 100,120,100,105,100,110,110,100, 95, 100, /* a <- next2 */ - 105,120,105,110,125,130,135,115,125, 100, /* , */ - 105,120, 75,100, 75,105,120, 85, 75, 100, /* t */ - 105,120, 85,105, 95,115,120,100, 95, 100, /* s */ - 110,120, 95,105,100,115,120,100,100, 100, /* n */ - 105,120,100,105, 95,115,120,110, 95, 100, /* d */ - 105,120,100,105,105,122,125,110,105, 100, /* z */ - 105,120,100,105,105,122,125,110,105, 100, /* r */ - 105,120, 95,105,100,115,120,110,100, 100, /* N */ - 100,120,100,100,100,100,100,100,100, 100 }; // SPARE - -// as above, but for the last syllable in a word -static unsigned char length_mods_en0[100] = { -/* a , t s n d z r N <- next */ - 100,150,100,105,110,115,110,110,110, 100, /* a <- next2 */ - 105,150,105,110,125,135,140,115,135, 100, /* , */ - 105,150, 90,105, 90,122,135,100, 90, 100, /* t */ - 105,150,100,105,100,122,135,100,100, 100, /* s */ - 105,150,100,105,105,115,135,110,105, 100, /* n */ - 105,150,100,105,105,122,130,120,125, 100, /* d */ - 105,150,100,105,110,122,125,115,110, 100, /* z */ - 105,150,100,105,105,122,135,120,105, 100, /* r */ - 105,150,100,105,105,115,135,110,105, 100, /* N */ - 100,100,100,100,100,100,100,100,100, 100 }; // SPARE - - -static unsigned char length_mods_equal[100] = { -/* a , t s n d z r N <- next */ - 110,110,110,110,110,110,110,110,110, 110, /* a <- next2 */ - 110,110,110,110,110,110,110,110,110, 110, /* , */ - 110,110,110,110,110,110,110,110,110, 110, /* t */ - 110,110,110,110,110,110,110,110,110, 110, /* s */ - 110,110,110,110,110,110,110,110,110, 110, /* n */ - 110,110,110,110,110,110,110,110,110, 110, /* d */ - 110,110,110,110,110,110,110,110,110, 110, /* z */ - 110,110,110,110,110,110,110,110,110, 110, /* r */ - 110,110,110,110,110,110,110,110,110, 110, /* N */ - 110,110,110,110,110,110,110,110,110, 110 }; // SPARE - - -static unsigned char *length_mod_tabs[6] = { - length_mods_en, - length_mods_en, // 1 - length_mods_en0, // 2 - length_mods_equal, // 3 - length_mods_equal, // 4 - length_mods_equal // 5 - }; - - -void SetLengthMods(Translator *tr, int value) -{//========================================== - int value2; - - tr->langopts.length_mods0 = tr->langopts.length_mods = length_mod_tabs[value % 100]; - if((value2 = value / 100) != 0) - { - tr->langopts.length_mods0 = length_mod_tabs[value2]; - } -} - - -int IsAlpha(unsigned int c) -{//======================== -// Replacement for iswalph() which also checks for some in-word symbols - - if(iswalpha(c)) - return(1); - - if((c >= 0x901) && (c <= 0xdf7)) - { - // Indic scripts: Devanagari, Tamil, etc - if((c & 0x7f) < 0x64) - return(1); - return(0); - } - - if((c >= 0x300) && (c <= 0x36f)) - return(1); // combining accents - - if((c >= 0x1100) && (c <= 0x11ff)) - return(1); //Korean jamo - - if((c > 0x3040) && (c <= 0xa700)) - return(1); // Chinese/Japanese. Should never get here, but Mac OS 10.4's iswalpha seems to be broken, so just make sure - - return(0); -} - -static int IsDigit09(unsigned int c) -{//========================= - if((c >= '0') && (c <= '9')) - return(1); - return(0); -} - -int IsDigit(unsigned int c) -{//======================== - if(iswdigit(c)) - return(1); - - if((c >= 0x966) && (c <= 0x96f)) - return(1); - - return(0); -} - -int IsSpace(unsigned int c) -{//======================== - if(c == 0) - return(0); - if(wcschr(chars_space,c)) - return(1); - return(iswspace(c)); -} - - -void DeleteTranslator(Translator *tr) -{//================================== - if(tr->data_dictlist != NULL) - Free(tr->data_dictlist); - Free(tr); -} - - -int lookupwchar(const unsigned short *list,int c) -{//============================================== -// Is the character c in the list ? - int ix; - - for(ix=0; list[ix] != 0; ix++) - { - if(list[ix] == c) - return(ix+1); - } - return(0); -} - -int IsBracket(int c) -{//================= - if((c >= 0x2014) && (c <= 0x201f)) - return(1); - return(lookupwchar(brackets,c)); -} - - -int utf8_out(unsigned int c, char *buf) -{//==================================== -// write a unicode character into a buffer as utf8 -// returns the number of bytes written - int n_bytes; - int j; - int shift; - static char unsigned code[4] = {0,0xc0,0xe0,0xf0}; - - if(c < 0x80) - { - buf[0] = c; - return(1); - } - if(c >= 0x110000) - { - buf[0] = ' '; // out of range character code - return(1); - } - if(c < 0x0800) - n_bytes = 1; - else - if(c < 0x10000) - n_bytes = 2; - else - n_bytes = 3; - - shift = 6*n_bytes; - buf[0] = code[n_bytes] | (c >> shift); - for(j=0; j<n_bytes; j++) - { - shift -= 6; - buf[j+1] = 0x80 + ((c >> shift) & 0x3f); - } - return(n_bytes+1); -} // end of utf8_out - - -int utf8_nbytes(const char *buf) -{//============================= -// Returns the number of bytes for the first UTF-8 character in buf - unsigned char c = (unsigned char)buf[0]; - if(c < 0x80) - return(1); - if(c < 0xe0) - return(2); - if(c < 0xf0) - return(3); - return(4); -} - - -int utf8_in2(int *c, const char *buf, int backwards) -{//================================================= -// Read a unicode characater from a UTF8 string -// Returns the number of UTF8 bytes used. -// backwards: set if we are moving backwards through the UTF8 string - int c1; - int n_bytes; - int ix; - static const unsigned char mask[4] = {0xff,0x1f,0x0f,0x07}; - - // find the start of the next/previous character - while((*buf & 0xc0) == 0x80) - { - // skip over non-initial bytes of a multi-byte utf8 character - if(backwards) - buf--; - else - buf++; - } - - n_bytes = 0; - - if((c1 = *buf++) & 0x80) - { - if((c1 & 0xe0) == 0xc0) - n_bytes = 1; - else - if((c1 & 0xf0) == 0xe0) - n_bytes = 2; - else - if((c1 & 0xf8) == 0xf0) - n_bytes = 3; - - c1 &= mask[n_bytes]; - for(ix=0; ix<n_bytes; ix++) - { - c1 = (c1 << 6) + (*buf++ & 0x3f); - } - } - *c = c1; - return(n_bytes+1); -} - - -int utf8_in(int *c, const char *buf) -{//================================= -// Read a unicode characater from a UTF8 string -// Returns the number of UTF8 bytes used. - return(utf8_in2(c,buf,0)); -} - - -char *strchr_w(const char *s, int c) -{//================================= -// return NULL for any non-ascii character - if(c >= 0x80) - return(NULL); - return(strchr((char *)s,c)); // (char *) is needed for Borland compiler -} - - - - -int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab) -{//=========================================================================== -// word1 is terminated by space (0x20) character - - int length; - int word_length; - int ix; - int posn; - int pfix; - int n_chars; - unsigned int dictionary_flags[2]; - unsigned int dictionary_flags2[2]; - int end_type=0; - int prefix_type=0; - char *wordx; - char phonemes[N_WORD_PHONEMES]; - char *ph_limit; - char *phonemes_ptr; - char prefix_phonemes[N_WORD_PHONEMES]; - char end_phonemes[N_WORD_PHONEMES]; - char word_copy[N_WORD_BYTES]; - char prefix_chars[N_WORD_BYTES]; - int found=0; - int end_flags; - char c_temp; // save a character byte while we temporarily replace it with space - int first_char; - int last_char = 0; - int unpron_length; - int add_plural_suffix = 0; - int prefix_flags = 0; - int confirm_prefix; - int spell_word; - int stress_bits; - int emphasize_allcaps = 0; - int wflags = wtab->flags; - int wmark = wtab->wmark; - - // translate these to get pronunciations of plural 's' suffix (different forms depending on - // the preceding letter - static char word_zz[4] = {0,'z','z',0}; - static char word_iz[4] = {0,'i','z',0}; - static char word_ss[4] = {0,'s','s',0}; - - dictionary_flags[0] = 0; - dictionary_flags[1] = 0; - dictionary_flags2[0] = 0; - dictionary_flags2[1] = 0; - dictionary_skipwords = 0; - - prefix_phonemes[0] = 0; - end_phonemes[0] = 0; - ph_limit = &phonemes[N_WORD_PHONEMES]; - - // count the length of the word - wordx = word1; - utf8_in(&first_char,wordx); - word_length = 0; - while((*wordx != 0) && (*wordx != ' ')) - { - wordx += utf8_in(&last_char,wordx); - word_length++; - } - - // try an initial lookup in the dictionary list, we may find a pronunciation specified, or - // we may just find some flags - spell_word = 0; - if(option_sayas == SAYAS_KEY) - { - if(word_length == 1) - spell_word = 4; - } - - if(option_sayas & 0x10) - { - // SAYAS_CHAR, SAYAS_GYLPH, or SAYAS_SINGLE_CHAR - spell_word = option_sayas & 0xf; // 2,3,4 - } - else - { - found = LookupDictList(tr, &word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word - if(dictionary_flags[0] & FLAG_TEXTMODE) - { - first_char = word1[0]; - stress_bits = dictionary_flags[0] & 0x7f; - found = LookupDictList(tr, &word1, phonemes, dictionary_flags2, 0, wtab); // the text replacement - if(dictionary_flags2[0]!=0) - { - dictionary_flags[0] = dictionary_flags2[0]; - dictionary_flags[1] = dictionary_flags2[1]; - if(stress_bits != 0) - { - // keep any stress information from the original word - dictionary_flags[0] = (dictionary_flags[0] & ~0x7f) | stress_bits; - } - } - } - else - if((found==0) && (dictionary_flags[0] & FLAG_SKIPWORDS)) - { - // grouped words, but no translation. Join the words with hyphens. - wordx = word1; - ix = 0; - while(ix < dictionary_skipwords) - { - if(*wordx == ' ') - { - *wordx = '-'; - ix++; - } - wordx++; - } - } - - // if textmode, LookupDictList() replaces word1 by the new text and returns found=0 - - if(phonemes[0] == phonSWITCH) - { - // change to another language in order to translate this word - strcpy(word_phonemes,phonemes); - return(0); - } - -if((wmark > 0) && (wmark < 8)) -{ - // the stressed syllable has been specified in the text (TESTING) - dictionary_flags[0] = (dictionary_flags[0] & ~0xf) | wmark; -} - - if(!found && (dictionary_flags[0] & FLAG_ABBREV)) - { - // the word has $abbrev flag, but no pronunciation specified. Speak as individual letters - spell_word = 1; - } - - if(!found && iswdigit(first_char)) - { - Lookup(tr,"_0lang",word_phonemes); - if(word_phonemes[0] == phonSWITCH) - return(0); - - found = TranslateNumber(tr,word1,phonemes,dictionary_flags,wflags); - } - - if(!found & ((wflags & FLAG_UPPERS) != FLAG_FIRST_UPPER)) - { - // either all upper or all lower case - - if((tr->langopts.numbers & NUM_ROMAN) || ((tr->langopts.numbers & NUM_ROMAN_UC) && (wflags & FLAG_ALL_UPPER))) - { - if((found = TranslateRoman(tr, word1, phonemes)) != 0) - dictionary_flags[0] |= FLAG_ABBREV; // prevent emphasis if capitals - } - } - - if((wflags & FLAG_ALL_UPPER) && (word_length > 1)&& iswalpha(first_char)) - { - if((option_tone_flags & OPTION_EMPHASIZE_ALLCAPS) && !(dictionary_flags[0] & FLAG_ABBREV)) - { - // emphasize words which are in capitals - emphasize_allcaps = FLAG_EMPHASIZED; - } - else - if(!found && !(dictionary_flags[0] & FLAG_SKIPWORDS) && (word_length<4) && (tr->clause_lower_count > 3) - && (tr->clause_upper_count <= tr->clause_lower_count)) - { - // An upper case word in a lower case clause. This could be an abbreviation. - spell_word = 1; - } - } - } - - if(spell_word > 0) - { - // Speak as individual letters - wordx = word1; - posn = 0; - phonemes[0] = 0; - end_type = 0; - - while(*wordx != ' ') - { - wordx += TranslateLetter(tr,wordx, phonemes,spell_word, word_length); - posn++; - if(phonemes[0] == phonSWITCH) - { - // change to another language in order to translate this word - strcpy(word_phonemes,phonemes); - if(word_length > 1) - return(FLAG_SPELLWORD); // a mixture of languages, retranslate as individual letters, separated by spaces - return(0); - } - } - SetSpellingStress(tr,phonemes,spell_word,posn); - } - else - if(found == 0) - { - // word's pronunciation is not given in the dictionary list, although - // dictionary_flags may have ben set there - - posn = 0; - length = 999; - wordx = word1; - - while(((length < 3) && (length > 0))|| (word_length > 1 && Unpronouncable(tr,wordx))) - { - char *p; - // This word looks "unpronouncable", so speak letters individually until we - // find a remainder that we can pronounce. - emphasize_allcaps = 0; - wordx += TranslateLetter(tr,wordx,phonemes,0, word_length); - posn++; - if(phonemes[0] == phonSWITCH) - { - // change to another language in order to translate this word - strcpy(word_phonemes,phonemes); - if(strcmp(&phonemes[1],"en")==0) - return(FLAG_SPELLWORD); // _^_en must have been set in TranslateLetter(), not *_rules - return(0); - } - - p = &wordx[word_length-3]; // this looks wrong. Doesn't consider multi-byte chars. - if(memcmp(p,"'s ",3) == 0) - { - // remove a 's suffix and pronounce this separately (not as an individual letter) - add_plural_suffix = 1; - p[0] = ' '; - p[1] = ' '; - last_char = p[-1]; - } - - length=0; - while(wordx[length] != ' ') length++; - if(length > 0) - wordx[-1] = ' '; // prevent this affecting the pronunciation of the pronuncable part - } - SetSpellingStress(tr,phonemes,0,posn); - - // anything left ? - if(*wordx != ' ') - { - // Translate the stem - unpron_length = strlen(phonemes); - end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags, dictionary_flags); - - if(phonemes[0] == phonSWITCH) - { - // change to another language in order to translate this word - strcpy(word_phonemes,phonemes); - return(0); - } - - if((phonemes[0] == 0) && (end_phonemes[0] == 0)) - { - int wc; - // characters not recognised, speak them individually - - utf8_in(&wc, wordx); - if((word_length == 1) && IsAlpha(wc)) - { - posn = 0; - while((*wordx != ' ') && (*wordx != 0)) - { - wordx += TranslateLetter(tr,wordx, phonemes, 4, word_length); - posn++; - if(phonemes[0] == phonSWITCH) - { - // change to another language in order to translate this word - strcpy(word_phonemes,phonemes); - return(0); - } - } - SetSpellingStress(tr,phonemes,spell_word,posn); - } - } - - c_temp = wordx[-1]; - - found = 0; - confirm_prefix = 1; - while(end_type & SUFX_P) - { - // Found a standard prefix, remove it and retranslate - - if(confirm_prefix && !(end_type & SUFX_B)) - { - int end2; - char phonemes2[N_WORD_PHONEMES]; - char end_phonemes2[N_WORD_PHONEMES]; - - // remove any standard suffix and confirm that the prefix is still recognised - phonemes2[0] = 0; - end2 = TranslateRules(tr, wordx, phonemes2, N_WORD_PHONEMES, end_phonemes2, wflags|FLAG_NO_PREFIX|FLAG_NO_TRACE, dictionary_flags); - if(end2) - { - RemoveEnding(tr, wordx, end2, word_copy); - end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags|FLAG_NO_TRACE, dictionary_flags); - memcpy(wordx,word_copy,strlen(word_copy)); - if((end_type & SUFX_P) == 0) - { - // after removing the suffix, the prefix is no longer recognised. - // Keep the suffix, but don't use the prefix - end_type = end2; - strcpy(phonemes,phonemes2); - strcpy(end_phonemes,end_phonemes2); - if(option_phonemes == 2) - { - DecodePhonemes(end_phonemes,end_phonemes2); - fprintf(f_trans," suffix [%s]\n\n",end_phonemes2); - } - } - confirm_prefix = 0; - continue; - } - } - - prefix_type = end_type; - - if(prefix_type & SUFX_V) - { - tr->expect_verb = 1; // use the verb form of the word - } - - wordx[-1] = c_temp; - - if((prefix_type & SUFX_B) == 0) - { - for(ix=(prefix_type & 0xf); ix>0; ix--) // num. of characters to remove - { - wordx++; - while((*wordx & 0xc0) == 0x80) wordx++; // for multibyte characters - } - } - else - { - pfix = 1; - prefix_chars[0] = 0; - n_chars = prefix_type & 0x3f; - - for(ix=0; ix < n_chars; ix++) // num. of bytes to remove - { - prefix_chars[pfix++] = *wordx++; - - if((prefix_type & SUFX_B) && (ix == (n_chars-1))) - { - prefix_chars[pfix-1] = 0; // discard the last character of the prefix, this is the separator character - } - } - prefix_chars[pfix] = 0; - } - c_temp = wordx[-1]; - wordx[-1] = ' '; - confirm_prefix = 1; - - if(prefix_type & SUFX_B) - { -// SUFX_B is used for Turkish, tr_rules contains "(Pb£ - // retranslate the prefix part - char *wordpf; - char prefix_phonemes2[12]; - - strncpy0(prefix_phonemes2,end_phonemes,sizeof(prefix_phonemes2)); - wordpf = &prefix_chars[1]; - found = LookupDictList(tr, &wordpf, phonemes, dictionary_flags, SUFX_P, wtab); // without prefix - if(found == 0) - { - end_type = TranslateRules(tr, wordpf, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags); - sprintf(prefix_phonemes,"%s%s%s",phonemes,end_phonemes,prefix_phonemes2); - } - prefix_flags = 1; - } - else - { - strcat(prefix_phonemes,end_phonemes); - } - end_phonemes[0] = 0; - - end_type = 0; - found = LookupDictList(tr, &wordx, phonemes, dictionary_flags2, SUFX_P, wtab); // without prefix - if(dictionary_flags[0]==0) - { - dictionary_flags[0] = dictionary_flags2[0]; - dictionary_flags[1] = dictionary_flags2[1]; - } - else - prefix_flags = 1; - if(found == 0) - { - end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags); - - if(phonemes[0] == phonSWITCH) - { - // change to another language in order to translate this word - wordx[-1] = c_temp; - strcpy(word_phonemes,phonemes); - return(0); - } - } - } - - if((end_type != 0) && !(end_type & SUFX_P)) - { -char phonemes2[N_WORD_PHONEMES]; -strcpy(phonemes2,phonemes); - - // The word has a standard ending, re-translate without this ending - end_flags = RemoveEnding(tr, wordx, end_type, word_copy); - - phonemes_ptr = &phonemes[unpron_length]; - phonemes_ptr[0] = 0; - - if(prefix_phonemes[0] != 0) - { - // lookup the stem without the prefix removed - wordx[-1] = c_temp; - found = LookupDictList(tr, &word1, phonemes_ptr, dictionary_flags2, end_flags, wtab); // include prefix, but not suffix - wordx[-1] = ' '; - if(dictionary_flags[0]==0) - { - dictionary_flags[0] = dictionary_flags2[0]; - dictionary_flags[1] = dictionary_flags2[1]; - } - if(found) - prefix_phonemes[0] = 0; // matched whole word, don't need prefix now - - if((found==0) && (dictionary_flags2[0] != 0)) - prefix_flags = 1; - } - if(found == 0) - { - found = LookupDictList(tr, &wordx, phonemes_ptr, dictionary_flags2, end_flags, wtab); // without prefix and suffix - if(phonemes_ptr[0] == phonSWITCH) - { - // change to another language in order to translate this word - memcpy(wordx,word_copy,strlen(word_copy)); - strcpy(word_phonemes,phonemes_ptr); - return(0); - } - if(dictionary_flags[0]==0) - { - dictionary_flags[0] = dictionary_flags2[0]; - dictionary_flags[1] = dictionary_flags2[1]; - } - } - if(found == 0) - { - if(end_type & SUFX_Q) - { - // don't retranslate, use the original lookup result - strcpy(phonemes,phonemes2); - - // language specific changes - ApplySpecialAttribute(tr,phonemes,dictionary_flags[0]); - } - else - { - if(end_flags & FLAG_SUFX) - TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, NULL,wflags | FLAG_SUFFIX_REMOVED, dictionary_flags); - else - TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, NULL,wflags,dictionary_flags); - - if(phonemes[0] == phonSWITCH) - { - // change to another language in order to translate this word - strcpy(word_phonemes,phonemes); - memcpy(wordx,word_copy,strlen(word_copy)); - wordx[-1] = c_temp; - return(0); - } - } - } - - if((end_type & SUFX_T) == 0) - { - // the default is to add the suffix and then determine the word's stress pattern - AppendPhonemes(tr,phonemes, N_WORD_PHONEMES, end_phonemes); - end_phonemes[0] = 0; - } - } - wordx[-1] = c_temp; - } - } - - if((add_plural_suffix) || (wflags & FLAG_HAS_PLURAL)) - { - // s or 's suffix, append [s], [z] or [Iz] depending on previous letter - if(last_char == 'f') - TranslateRules(tr, &word_ss[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); - else - if((last_char==0) || (strchr_w("hsx",last_char)==NULL)) - TranslateRules(tr, &word_zz[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); - else - TranslateRules(tr, &word_iz[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); - } - - wflags |= emphasize_allcaps; - - - /* determine stress pattern for this word */ - /******************************************/ - /* NOTE: this also adds a single PAUSE if the previous word ended - in a primary stress, and this one starts with one */ - if(prefix_flags || (strchr(prefix_phonemes,phonSTRESS_P)!=NULL)) - { - if((tr->langopts.param[LOPT_PREFIXES]) || (prefix_type & SUFX_T)) - { - char *p; - // German, keep a secondary stress on the stem - SetWordStress(tr, phonemes, &dictionary_flags[0], 3, 0); - - // reduce all but the first primary stress - ix=0; - for(p=prefix_phonemes; *p != 0; p++) - { - if(*p == phonSTRESS_P) - { - if(ix==0) - ix=1; - else - *p = phonSTRESS_3; - } - } - strcpy(word_phonemes,prefix_phonemes); - strcat(word_phonemes,phonemes); - SetWordStress(tr, word_phonemes, &dictionary_flags[0], -1, 0); - } - else - { - // stress position affects the whole word, including prefix - strcpy(word_phonemes,prefix_phonemes); - strcat(word_phonemes,phonemes); - SetWordStress(tr, word_phonemes, &dictionary_flags[0], -1, tr->prev_last_stress); - } - } - else - { - if(prefix_phonemes[0] == 0) - SetWordStress(tr, phonemes, &dictionary_flags[0], -1, tr->prev_last_stress); - else - SetWordStress(tr, phonemes, &dictionary_flags[0], -1, 0); - strcpy(word_phonemes,prefix_phonemes); - strcat(word_phonemes,phonemes); - } - - if(end_phonemes[0] != 0) - { - // a suffix had the SUFX_T option set, add the suffix after the stress pattern has been determined - strcat(word_phonemes,end_phonemes); - } - - if(wflags & FLAG_LAST_WORD) - { - // don't use $brk pause before the last word of a sentence - // (but allow it for emphasis, see below - dictionary_flags[0] &= ~FLAG_PAUSE1; - } - - if(wflags & FLAG_EMPHASIZED2) - { - // A word is indicated in the source text as stressed - // Give it stress level 6 (for the intonation module) - ChangeWordStress(tr,word_phonemes,6); - - if(wflags & FLAG_EMPHASIZED) - dictionary_flags[0] |= FLAG_PAUSE1; // precede by short pause - } - else - if(wtab[dictionary_skipwords].flags & FLAG_LAST_WORD) - { - // the word has attribute to stress or unstress when at end of clause - if(dictionary_flags[0] & (FLAG_STRESS_END | FLAG_STRESS_END2)) - ChangeWordStress(tr,word_phonemes,4); - else - if(dictionary_flags[0] & FLAG_UNSTRESS_END) - ChangeWordStress(tr,word_phonemes,3); - } - - // dictionary flags for this word give a clue about which alternative pronunciations of - // following words to use. - if(end_type & SUFX_F) - { - // expect a verb form, with or without -s suffix - tr->expect_verb = 2; - tr->expect_verb_s = 2; - } - - if(dictionary_flags[1] & FLAG_PASTF) - { - /* expect perfect tense in next two words */ - tr->expect_past = 3; - tr->expect_verb = 0; - tr->expect_noun = 0; - } - else - if(dictionary_flags[1] & FLAG_VERBF) - { - /* expect a verb in the next word */ - tr->expect_verb = 2; - tr->expect_verb_s = 0; /* verb won't have -s suffix */ - tr->expect_noun = 0; - } - else - if(dictionary_flags[1] & FLAG_VERBSF) - { - // expect a verb, must have a -s suffix - tr->expect_verb = 0; - tr->expect_verb_s = 2; - tr->expect_past = 0; - tr->expect_noun = 0; - } - else - if(dictionary_flags[1] & FLAG_NOUNF) - { - /* not expecting a verb next */ - tr->expect_noun = 2; - tr->expect_verb = 0; - tr->expect_verb_s = 0; - tr->expect_past = 0; - } - - if((wordx[0] != 0) && (!(dictionary_flags[1] & FLAG_VERB_EXT))) - { - if(tr->expect_verb > 0) - tr->expect_verb--; - - if(tr->expect_verb_s > 0) - tr->expect_verb_s--; - - if(tr->expect_noun >0) - tr->expect_noun--; - - if(tr->expect_past > 0) - tr->expect_past--; - } - - if((word_length == 1) && iswalpha(first_char) && (first_char != 'i')) - { -// English Specific !!!! - // any single letter before a dot is an abbreviation, except 'I' - dictionary_flags[0] |= FLAG_DOT; - } - - if((tr->langopts.param[LOPT_ALT] & 2) && ((dictionary_flags[0] & (FLAG_ALT_TRANS | FLAG_ALT2_TRANS)) != 0)) - { - ApplySpecialAttribute2(tr,word_phonemes,dictionary_flags[0]); - } - - return(dictionary_flags[0]); -} // end of TranslateWord - - - -static void SetPlist2(PHONEME_LIST2 *p, unsigned char phcode) -{//========================================================== - p->phcode = phcode; - p->stress = 0; - p->tone_number = 0; - p->synthflags = embedded_flag; - p->sourceix = 0; - embedded_flag = 0; -} - -static int CountSyllables(unsigned char *phonemes) -{//=============================================== - int count = 0; - int phon; - while((phon = *phonemes++) != 0) - { - if(phoneme_tab[phon]->type == phVOWEL) - count++; - } - return(count); -} - - -int SetTranslator2(const char *new_language) -{//========================================= -// Set translator2 to a second language - int new_phoneme_tab; - - if((new_phoneme_tab = SelectPhonemeTableName(new_language)) >= 0) - { - if((translator2 != NULL) && (strcmp(new_language,translator2_language) != 0)) - { - // we already have an alternative translator, but not for the required language, delete it - DeleteTranslator(translator2); - translator2 = NULL; - } - - if(translator2 == NULL) - { - translator2 = SelectTranslator(new_language); - strcpy(translator2_language,new_language); - - if(LoadDictionary(translator2, new_language, 0) != 0) - { - SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table - new_phoneme_tab = -1; - translator2_language[0] = 0; - } - } - } - return(new_phoneme_tab); -} // end of SetTranslator2 - - - -static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pause, int next_pause) -{//================================================================================================= - int flags=0; - int stress; - int next_stress; - int next_tone=0; - unsigned char *p; - int srcix; - int embedded_cmd; - int value; - int found_dict_flag; - unsigned char ph_code; - PHONEME_LIST2 *plist2; - PHONEME_TAB *ph; - int max_stress; - int max_stress_ix=0; - int prev_vowel = -1; - int pitch_raised = 0; - int switch_phonemes = -1; - int first_phoneme = 1; - int source_ix; - int len; - int ix; - int sylimit; // max. number of syllables in a word to be combined with a preceding preposition - const char *new_language; - unsigned char bad_phoneme[4]; - int word_flags; - int word_copy_len; - char word_copy[N_WORD_BYTES+1]; - - len = wtab->length; - if(len > 31) len = 31; - source_ix = (wtab->sourceix & 0x7ff) | (len << 11); // bits 0-10 sourceix, bits 11-15 word length - - word_flags = wtab[0].flags; - if(word_flags & FLAG_EMBEDDED) - { - embedded_flag = SFLAG_EMBEDDED; - - do - { - embedded_cmd = embedded_list[embedded_read++]; - value = embedded_cmd >> 8; - - switch(embedded_cmd & 0x1f) - { - case EMBED_Y: - option_sayas = value; - break; - - case EMBED_F: - option_emphasis = value; - break; - - case EMBED_B: - // break command - if(value == 0) - pre_pause = 0; // break=none - else - pre_pause += value; - break; - } - } while((embedded_cmd & 0x80) == 0); - } - - if(word[0] == 0) - { - // nothing to translate - word_phonemes[0] = 0; - return(0); - } - - // after a $pause word attribute, ignore a $pause attribute on the next two words - if(tr->prepause_timeout > 0) - tr->prepause_timeout--; - - if((option_sayas & 0xf0) == 0x10) - { - if(!(word_flags & FLAG_FIRST_WORD)) - { - // SAYAS_CHARS, SAYAS_GLYPHS, or SAYAS_SINGLECHARS. Pause between each word. - pre_pause += 4; - } - } - - if(word_flags & FLAG_FIRST_UPPER) - { - if((option_capitals > 2) && (embedded_ix < N_EMBEDDED_LIST-6)) - { - // indicate capital letter by raising pitch - if(embedded_flag) - embedded_list[embedded_ix-1] &= ~0x80; // already embedded command before this word, remove terminator - if((pitch_raised = option_capitals) == 3) - pitch_raised = 20; // default pitch raise for capitals - embedded_list[embedded_ix++] = EMBED_P+0x40+0x80 + (pitch_raised << 8); // raise pitch - embedded_flag = SFLAG_EMBEDDED; - } - } - - p = (unsigned char *)word_phonemes; - if(word_flags & FLAG_PHONEMES) - { - // The input is in phoneme mnemonics, not language text - int c1; - char lang_name[12]; - - if(memcmp(word,"_^_",3)==0) - { - // switch languages - word+=3; - for(ix=0;;) - { - c1 = *word++; - if((c1==' ') || (c1==0)) - break; - lang_name[ix++] = tolower(c1); - } - lang_name[ix] = 0; - - if((ix = LookupPhonemeTable(lang_name)) > 0) - { - SelectPhonemeTable(ix); - word_phonemes[0] = phonSWITCH; - word_phonemes[1] = ix; - word_phonemes[2] = 0; - } - } - else - { - EncodePhonemes(word,word_phonemes,bad_phoneme); - } - flags = FLAG_FOUND; - } - else - { - int c2; - ix = 0; - while(((c2 = word_copy[ix] = word[ix]) != ' ') && (c2 != 0) && (ix < N_WORD_BYTES)) ix++; - word_copy_len = ix; - - flags = TranslateWord(translator, word, next_pause, wtab); - - if(flags & FLAG_SPELLWORD) - { - // re-translate the word as individual letters, separated by spaces - memcpy(word, word_copy, word_copy_len); - return(flags); - } - - if((flags & FLAG_ALT2_TRANS) && ((sylimit = tr->langopts.param[LOPT_COMBINE_WORDS]) > 0)) - { - char *p2; - int ok = 1; - int flags2; - int c_word2; - char ph_buf[N_WORD_PHONEMES]; - - // LANG=cs,sk - // combine a preposition with the following word - p2 = word; - while(*p2 != ' ') p2++; - - utf8_in(&c_word2, p2+1); // first character of the next word; - if(!iswalpha(c_word2)) - { - ok =0; - } - - if(ok != 0) - { - if(sylimit & 0x100) - { - // only if the second word has $alt attribute - strcpy(ph_buf,word_phonemes); - flags2 = TranslateWord(translator, p2+1, 0, wtab+1); - if((flags2 & FLAG_ALT_TRANS) == 0) - { - ok = 0; - strcpy(word_phonemes,ph_buf); - } - } - - if((sylimit & 0x200) && ((wtab+1)->flags & FLAG_LAST_WORD)) - { - // not if the next word is end-of-sentence - ok = 0; - } - } - - if(ok) - { - *p2 = '-'; // replace next space by hyphen - flags = TranslateWord(translator, word, next_pause, wtab); // translate the combined word - if(CountSyllables(p) > (sylimit & 0xf)) - { - // revert to separate words - *p2 = ' '; - flags = TranslateWord(translator, word, next_pause, wtab); - } - else - { - flags |= FLAG_SKIPWORDS; - dictionary_skipwords = 1; - } - } - } - - if(p[0] == phonSWITCH) - { - // this word uses a different language - memcpy(word, word_copy, word_copy_len); - - new_language = (char *)(&p[1]); - if(new_language[0]==0) - new_language = "en"; - - switch_phonemes = SetTranslator2(new_language); - - if(switch_phonemes >= 0) - { - // re-translate the word using the new translator - flags = TranslateWord(translator2, word, next_pause, wtab); -// strcpy((char *)p,translator2->word_phonemes); - if(p[0] == phonSWITCH) - { - // the second translator doesn't want to process this word - switch_phonemes = -1; - } - } - if(switch_phonemes < 0) - { - // language code is not recognised or 2nd translator won't translate it - p[0] = phonSCHWA; // just say something - p[1] = phonSCHWA; - p[2] = 0; - } - } - - if(!(word_flags & FLAG_HYPHEN)) - { - if(flags & FLAG_PAUSE1) - { - if(pre_pause < 1) - pre_pause = 1; - } - if((flags & FLAG_PREPAUSE) && ((word_flags && FLAG_LAST_WORD) == 0) && (tr->prepause_timeout == 0)) - { - // the word is marked in the dictionary list with $pause - if(pre_pause < 4) pre_pause = 4; - tr->prepause_timeout = 3; - } - } - - if((option_emphasis >= 3) && (pre_pause < 1)) - pre_pause = 1; - } - - plist2 = &ph_list2[n_ph_list2]; - stress = 0; - next_stress = 0; - srcix = 0; - max_stress = -1; - - found_dict_flag = 0; - if(flags & FLAG_FOUND) - found_dict_flag = SFLAG_DICTIONARY; - - while((pre_pause > 0) && (n_ph_list2 < N_PHONEME_LIST-4)) - { - // add pause phonemes here. Either because of punctuation (brackets or quotes) in the - // text, or because the word is marked in the dictionary lookup as a conjunction - if(pre_pause > 1) - { - SetPlist2(&ph_list2[n_ph_list2++],phonPAUSE); - pre_pause -= 2; - } - else - { - SetPlist2(&ph_list2[n_ph_list2++],phonPAUSE_NOLINK); - pre_pause--; - } - tr->end_stressed_vowel = 0; // forget about the previous word - tr->prev_dict_flags = 0; - } - - if((option_capitals==1) && (word_flags & FLAG_FIRST_UPPER)) - { - SetPlist2(&ph_list2[n_ph_list2++],phonPAUSE_SHORT); - SetPlist2(&ph_list2[n_ph_list2++],phonCAPITAL); - if((word_flags & FLAG_ALL_UPPER) && IsAlpha(word[1])) - { - // word > 1 letter and all capitals - SetPlist2(&ph_list2[n_ph_list2++],phonPAUSE_SHORT); - SetPlist2(&ph_list2[n_ph_list2++],phonCAPITAL); - } - } - - if(switch_phonemes >= 0) - { - // this word uses a different phoneme table - SetPlist2(&ph_list2[n_ph_list2],phonSWITCH); - ph_list2[n_ph_list2++].tone_number = switch_phonemes; // temporary phoneme table number - } - - // remove initial pause from a word if it follows a hyphen - if((word_flags & FLAG_HYPHEN) && (phoneme_tab[*p]->type == phPAUSE)) - p++; - - while(((ph_code = *p++) != 0) && (n_ph_list2 < N_PHONEME_LIST-4)) - { - if(ph_code == 255) - continue; // unknown phoneme - - // Add the phonemes to the first stage phoneme list (ph_list2) - ph = phoneme_tab[ph_code]; - - if(ph_code == phonSWITCH) - { - ph_list2[n_ph_list2].phcode = ph_code; - ph_list2[n_ph_list2].sourceix = 0; - ph_list2[n_ph_list2].synthflags = embedded_flag; - ph_list2[n_ph_list2++].tone_number = *p++; - } - else - if(ph->type == phSTRESS) - { - // don't add stress phonemes codes to the list, but give their stress - // value to the next vowel phoneme - // std_length is used to hold stress number or (if >10) a tone number for a tone language - if(ph->spect == 0) - next_stress = ph->std_length; - else - { - // for tone languages, the tone number for a syllable follows the vowel - if(prev_vowel >= 0) - { - ph_list2[prev_vowel].tone_number = ph_code; - } - else - { - next_tone = ph_code; // no previous vowel, apply to the next vowel - } - } - } - else - if(ph_code == phonSYLLABIC) - { - // mark the previous phoneme as a syllabic consonant - prev_vowel = n_ph_list2-1; - ph_list2[prev_vowel].synthflags |= SFLAG_SYLLABLE; - ph_list2[prev_vowel].stress = next_stress; - } - else - if(ph_code == phonLENGTHEN) - { - ph_list2[n_ph_list2-1].synthflags |= SFLAG_LENGTHEN; - } - else - if(ph_code == phonEND_WORD) - { - // a || symbol in a phoneme string was used to indicate a word boundary - // Don't add this phoneme to the list, but make sure the next phoneme has - // a newword indication - srcix = source_ix+1; - } - else - if(ph_code == phonX1) - { - // a language specific action - if(tr->langopts.param[LOPT_IT_DOUBLING]) - { - flags |= FLAG_DOUBLING; - } - } - else - { - ph_list2[n_ph_list2].phcode = ph_code; - ph_list2[n_ph_list2].tone_number = 0; - ph_list2[n_ph_list2].synthflags = embedded_flag | found_dict_flag; - embedded_flag = 0; - ph_list2[n_ph_list2].sourceix = srcix; - srcix = 0; - - if(ph->type == phVOWEL) - { - stress = next_stress; - next_stress = 0; - - if((prev_vowel >= 0) && (n_ph_list2-1) != prev_vowel) - ph_list2[n_ph_list2-1].stress = stress; // set stress for previous consonant - - ph_list2[n_ph_list2].synthflags |= SFLAG_SYLLABLE; - prev_vowel = n_ph_list2; - - if(stress > max_stress) - { - max_stress = stress; - max_stress_ix = n_ph_list2; - } - if(next_tone != 0) - { - ph_list2[n_ph_list2].tone_number = next_tone; - next_tone=0; - } - } - else - { - if(first_phoneme && tr->langopts.param[LOPT_IT_DOUBLING]) - { - if(((tr->prev_dict_flags & FLAG_DOUBLING) && (tr->langopts.param[LOPT_IT_DOUBLING] & 1)) || - (tr->end_stressed_vowel && (tr->langopts.param[LOPT_IT_DOUBLING] & 2))) - { - // italian, double the initial consonant if the previous word ends with a - // stressed vowel, or is marked with a flag - ph_list2[n_ph_list2].synthflags |= SFLAG_LENGTHEN; - } - } - } - - ph_list2[n_ph_list2].stress = stress; - n_ph_list2++; - first_phoneme = 0; - } - } - // don't set new-word if there is a hyphen before it - if((word_flags & FLAG_HYPHEN) == 0) - { - plist2->sourceix = source_ix; - } - - tr->end_stressed_vowel = 0; - if((stress >= 4) && (phoneme_tab[ph_list2[n_ph_list2-1].phcode]->type == phVOWEL)) - { - tr->end_stressed_vowel = 1; // word ends with a stressed vowel - } - - if(switch_phonemes >= 0) - { - // this word uses a different phoneme table, now switch back - SelectPhonemeTable(voice->phoneme_tab_ix); - SetPlist2(&ph_list2[n_ph_list2],phonSWITCH); - ph_list2[n_ph_list2++].tone_number = voice->phoneme_tab_ix; // original phoneme table number - } - - - if(pitch_raised > 0) - { - embedded_list[embedded_ix++] = EMBED_P+0x60+0x80 + (pitch_raised << 8); // lower pitch - SetPlist2(&ph_list2[n_ph_list2],phonPAUSE_SHORT); - ph_list2[n_ph_list2++].synthflags = SFLAG_EMBEDDED; - } - - if(flags & FLAG_STRESS_END2) - { - // this's word's stress could be increased later - ph_list2[max_stress_ix].synthflags |= SFLAG_PROMOTE_STRESS; - } - - tr->prev_dict_flags = flags; - return(flags); -} // end of TranslateWord2 - - - -static int EmbeddedCommand(unsigned int *source_index) -{//=================================================== - // An embedded command to change the pitch, volume, etc. - // returns number of commands added to embedded_list - - // pitch,speed,amplitude,expression,reverb,tone,voice,sayas - const char *commands = "PSARHTIVYMUBF"; - int value = -1; - int sign = 0; - unsigned char c; - char *p; - int cmd; - - c = source[*source_index]; - if(c == '+') - { - sign = 0x40; - (*source_index)++; - } - else - if(c == '-') - { - sign = 0x60; - (*source_index)++; - } - - if(isdigit(source[*source_index])) - { - value = atoi(&source[*source_index]); - while(isdigit(source[*source_index])) - source_index++; - } - - c = source[(*source_index)++]; - if(embedded_ix >= (N_EMBEDDED_LIST - 2)) - return(0); // list is full - - if((p = strchr_w(commands,c)) == NULL) - return(0); - cmd = (p - commands)+1; - if(value == -1) - { - value = embedded_default[cmd]; - sign = 0; - } - - if(cmd == EMBED_Y) - { - option_sayas2 = value; - count_sayas_digits = 0; - } - if(cmd == EMBED_F) - { - if(value >= 3) - word_emphasis = FLAG_EMPHASIZED; - else - word_emphasis = 0; - } - - embedded_list[embedded_ix++] = cmd + sign + (value << 8); - return(1); -} // end of EmbeddedCommand - - - -static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *insert) -{//========================================================================================= - int ix; - unsigned int word; - unsigned int new_c, c2, c_lower; - int upper_case = 0; - static int ignore_next = 0; - const unsigned int *replace_chars; - - if(ignore_next) - { - ignore_next = 0; - return(8); - } - if(c == 0) return(0); - - if((replace_chars = tr->langopts.replace_chars) == NULL) - return(c); - - // there is a list of character codes to be substituted with alternative codes - - if(iswupper(c_lower = c)) - { - c_lower = towlower(c); - upper_case = 1; - } - - new_c = 0; - for(ix=0; (word = replace_chars[ix]) != 0; ix+=2) - { - if(c_lower == (word & 0xffff)) - { - if((word >> 16) == 0) - { - new_c = replace_chars[ix+1]; - break; - } - if((word >> 16) == (unsigned int)towlower(next_in)) - { - new_c = replace_chars[ix+1]; - ignore_next = 1; - break; - } - } - } - - if(new_c == 0) - return(c); // no substitution - - if(new_c & 0xffe00000) - { - // there is a second character to be inserted - // don't convert the case of the second character unless the next letter is also upper case - c2 = new_c >> 16; - if(upper_case && iswupper(next_in)) - c2 = towupper(c2); - *insert = c2; - new_c &= 0xffff; - } - - if(upper_case) - new_c = towupper(new_c); - return(new_c); - -} - - -static int TranslateChar(Translator *tr, char *ptr, int prev_in, unsigned int c, unsigned int next_in, int *insert) -{//================================================================================================================ - // To allow language specific examination and replacement of characters - - int code; - int initial; - int medial; - int final; - int next2; - - static const unsigned char hangul_compatibility[0x34] = { - 0, 0x00,0x01,0xaa,0x02,0xac,0xad,0x03, - 0x04,0x05,0xb0,0xb1,0xb2,0xb3,0xb4,0xb4, - 0xb6,0x06,0x07,0x08,0xb9,0x09,0x0a,0xbc, - 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x61, - 0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69, - 0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71, - 0x72,0x73,0x74,0x75 }; - - switch(tr->translator_name) - { - case L('a','f'): - // look for 'n and replace by a special character (unicode: schwa) - - utf8_in(&next2, &ptr[1]); - - if(!iswalpha(prev_in)) - { - if((c == '\'') && (next_in == 'n') && IsSpace(next2)) - { - // n preceded by either apostrophe or U2019 "right single quotation mark" - ptr[0] = ' '; // delete the n - return(0x0259); // replace ' by unicode schwa character - } - } - break; - - case L('k','o'): - if(((code = c - 0xac00) >= 0) && (c <= 0xd7af)) - { - // break a syllable hangul into 2 or 3 individual jamo - initial = (code/28)/21; - medial = (code/28) % 21; - final = code % 28; - - if(initial == 11) - { - // null initial - c = medial + 0x1161; - if(final > 0) - *insert = final + 0x11a7; - } - else - { - // extact the initial and insert the remainder with a null initial - c = initial + 0x1100; - *insert = (11*28*21) + (medial*28) + final + 0xac00; - } - return(c); - } - else - if(((code = c - 0x3130) >= 0) && (code < 0x34)) - { - // Hangul compatibility jamo - return(hangul_compatibility[code] + 0x1100); - } - break; - } - return(SubstituteChar(tr,c,next_in,insert)); -} - - -void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone_out, char **voice_change) -{//========================================================================================================== - int ix; - int c; - int cc; - unsigned int source_index=0; - unsigned int prev_source_index=0; - int prev_in; - int prev_out=' '; - int prev_out2; - int prev_in2=0; - int next_in; - int char_inserted=0; - int clause_pause; - int pre_pause_add=0; - int word_mark = 0; - int all_upper_case=FLAG_ALL_UPPER; - int finished; - int single_quoted; - int phoneme_mode = 0; - int dict_flags = 0; // returned from dictionary lookup - int word_flags; // set here - int next_word_flags; - int embedded_count = 0; - int letter_count = 0; - int space_inserted = 0; - int syllable_marked = 0; - int decimal_sep_count = 0; - char *word; - char *p; - int j, k; - int n_digits; - int charix_top=0; - - short charix[N_TR_SOURCE+4]; - WORD_TAB words[N_CLAUSE_WORDS]; - int word_count=0; // index into words - - char sbuf[N_TR_SOURCE]; - - int terminator; - int tone; - int tone2; - - p_textinput = (unsigned char *)vp_input; - p_wchar_input = (wchar_t *)vp_input; - - embedded_ix = 0; - embedded_read = 0; - option_phoneme_input &= ~2; // clear bit 1 (temporary indication) - pre_pause = 0; - - if((clause_start_char = count_characters) < 0) - clause_start_char = 0; - clause_start_word = count_words + 1; - - for(ix=0; ix<N_TR_SOURCE; ix++) - charix[ix] = 0; - terminator = ReadClause(tr, f_text, source, charix, &charix_top, N_TR_SOURCE, &tone2); - - charix[charix_top+1] = 0; - charix[charix_top+2] = 0x7fff; - charix[charix_top+3] = 0; - - clause_pause = (terminator & 0xfff) * 10; // mS - tone = (terminator >> 12) & 0xf; - if(tone2 != 0) - { - // override the tone type - tone = tone2; - } - - for(p=source; *p != 0; p++) - { - if(!isspace2(*p)) - { - break; - } - } - if(*p == 0) - { - // No characters except spaces. This is not a sentence. - // Don't add this pause, just make up the previous pause to this value; - clause_pause -= max_clause_pause; - if(clause_pause < 0) - clause_pause = 0; - - terminator &= ~CLAUSE_BIT_SENTENCE; // clear sentence bit - max_clause_pause += clause_pause; - } - else - { - max_clause_pause = clause_pause; - } - - if(new_sentence) - { - count_sentences++; - if(skip_sentences > 0) - { - skip_sentences--; - if(skip_sentences == 0) - skipping_text = 0; - } - } - - memset(&ph_list2[0],0,sizeof(ph_list2[0])); - ph_list2[0].phcode = phonPAUSE_SHORT; - - n_ph_list2 = 1; - tr->prev_last_stress = 0; - tr->prepause_timeout = 0; - tr->expect_verb=0; - tr->expect_noun=0; - tr->expect_past=0; - tr->expect_verb_s=0; - tr->phonemes_repeat_count = 0; - tr->end_stressed_vowel=0; - tr->prev_dict_flags = 0; - - word_count = 0; - single_quoted = 0; - word_flags = 0; - next_word_flags = 0; - - sbuf[0] = 0; - sbuf[1] = ' '; - sbuf[2] = ' '; - ix = 3; - prev_in = ' '; - - words[0].start = ix; - words[0].flags = 0; - finished = 0; - - for(j=0; charix[j]==0; j++); - words[0].sourceix = charix[j]; - k = 0; - while(charix[j] != 0) - { - // count the number of characters (excluding multibyte continuation bytes) - if(charix[j++] != -1) - k++; - } - words[0].length = k; - - while(!finished && (ix < (int)sizeof(sbuf))&& (n_ph_list2 < N_PHONEME_LIST-4)) - { - prev_out2 = prev_out; - utf8_in2(&prev_out,&sbuf[ix-1],1); // prev_out = sbuf[ix-1]; - - if(tr->langopts.tone_numbers && IsDigit09(prev_out) && IsAlpha(prev_out2)) - { - // tone numbers can be part of a word, consider them as alphabetic - prev_out = 'a'; - } - - if(prev_in2 != 0) - { - prev_in = prev_in2; - prev_in2 = 0; - } - else - if(source_index > 0) - { - utf8_in2(&prev_in,&source[source_index-1],1); // prev_in = source[source_index-1]; - } - - prev_source_index = source_index; - - if(char_inserted) - { - c = char_inserted; - char_inserted = 0; - } - else - { - source_index += utf8_in(&cc,&source[source_index]); // cc = source[source_index++]; - c = cc; - } - utf8_in(&next_in,&source[source_index]); - - if((c == CTRL_EMBEDDED) || (c == ctrl_embedded)) - { - // start of embedded command in the text - int srcix = source_index-1; - - if(prev_in != ' ') - { - c = ' '; - prev_in2 = c; - source_index--; - } - else - { - embedded_count += EmbeddedCommand(&source_index); - prev_in2 = prev_in; - // replace the embedded command by spaces - memset(&source[srcix],' ',source_index-srcix); - source_index = srcix; - continue; - } - } - - if(option_sayas2 == SAYAS_KEY) - { - if(((c == '_') || (c == '-')) && IsAlpha(prev_in)) - { - c = ' '; - } - c = towlower2(c); - } - - if(phoneme_mode) - { - all_upper_case = FLAG_PHONEMES; - - if((c == ']') && (next_in == ']')) - { - phoneme_mode = 0; - source_index++; - c = ' '; - } - } - else - if((option_sayas2 & 0xf0) == SAYAS_DIGITS) - { - if(iswdigit(c)) - { - count_sayas_digits++; - if(count_sayas_digits > (option_sayas2 & 0xf)) - { - // break after the specified number of digits - c = ' '; - space_inserted = 1; - count_sayas_digits = 0; - } - } - else - { - count_sayas_digits = 0; - if(iswdigit(prev_out)) - { - c = ' '; - space_inserted = 1; - } - } - } - else - if((option_sayas2 & 0x30) == 0) - { - // speak as words - -#ifdef deleted -if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_out)) -{ - // TESTING, explicit indication of stressed syllable by /2 after the word - word_mark = next_in-'0'; - source_index++; - c = ' '; -} -#endif - if((c == 0x92) || (c == 0xb4) || (c == 0x2019) || (c == 0x2032)) - c = '\''; // 'microsoft' quote or sexed closing single quote, or prime - possibly used as apostrophe - - if((c == '?') && IsAlpha(prev_out) && IsAlpha(next_in)) - { - // ? between two letters may be a smart-quote replaced by ? - c = '\''; - } - - if(c == CHAR_EMPHASIS) - { - // this character is a marker that the previous word is the focus of the clause - c = ' '; - word_flags |= FLAG_FOCUS; - } - - c = TranslateChar(tr, &source[source_index], prev_in,c, next_in, &char_inserted); // optional language specific function - if(c == 8) - continue; // ignore this character - - if(char_inserted) - next_in = char_inserted; - - // allow certain punctuation within a word (usually only apostrophe) - if(!IsAlpha(c) && !IsSpace(c) && (wcschr(tr->punct_within_word,c) == 0)) - { - if(IsAlpha(prev_out)) - { - if(tr->langopts.tone_numbers && IsDigit09(c) && !IsDigit09(next_in)) - { - // allow a tone number as part of the word - } - else - { - c = ' '; // ensure we have an end-of-word terminator - space_inserted = 1; - } - } - } - - if(iswdigit(prev_out)) - { - if(!iswdigit(c) && (c != '.') && (c != ',')) - { - c = ' '; // terminate digit string with a space - space_inserted = 1; - } - } - else - { - if(prev_in != ',') - { - decimal_sep_count = 0; - } - } - - if((c == '[') && (next_in == '[') && option_phoneme_input) - { - phoneme_mode = FLAG_PHONEMES; - source_index++; - continue; - } - - if(c == 0) - { - finished = 1; - c = ' '; - } - else - if(IsAlpha(c)) - { - if(!IsAlpha(prev_out) || (tr->langopts.ideographs && ((c > 0x3040) || (prev_out > 0x3040)))) - { - if(wcschr(tr->punct_within_word,prev_out) == 0) - letter_count = 0; // don't reset count for an apostrophy within a word - - if((prev_out != ' ') && (wcschr(tr->punct_within_word,prev_out) == 0)) - { - // start of word, insert space if not one there already - c = ' '; - space_inserted = 1; - } - else - { - if(iswupper(c)) - word_flags |= FLAG_FIRST_UPPER; - - if((prev_out == ' ') && iswdigit(sbuf[ix-2]) && !iswdigit(prev_in)) - { - // word, following a number, but with a space between - // Add an extra space, to distinguish "2 a" from "2a" - sbuf[ix++] = ' '; - words[word_count].start++; - } - } - } - - letter_count++; - - if(iswupper(c)) - { - c = towlower2(c); - - if((j = tr->langopts.param[LOPT_CAPS_IN_WORD]) > 0) - { - if((j == 2) && (syllable_marked == 0)) - { - char_inserted = c; - c = 0x2c8; // stress marker - syllable_marked = 1; - } - } - else - { - if(iswlower(prev_in)) - { - c = ' '; // lower case followed by upper case, treat as new word - space_inserted = 1; - prev_in2 = c; - } - else - if((c != ' ') && iswupper(prev_in) && iswlower(next_in) && - (memcmp(&source[source_index],"s ",2) != 0)) // ENGLISH specific plural - { - c = ' '; // change from upper to lower case, start new word at the last uppercase - space_inserted = 1; - prev_in2 = c; - next_word_flags |= FLAG_NOSPACE; - } - } - } - else - { - if((all_upper_case) && (letter_count > 2)) - { - if((c == 's') && (next_in==' ')) - { - c = ' '; - all_upper_case |= FLAG_HAS_PLURAL; - - if(sbuf[ix-1] == '\'') - sbuf[ix-1] = ' '; - } - else - all_upper_case = 0; // current word contains lower case letters, not "'s" - } - else - all_upper_case = 0; - } - } - else - if(c=='-') - { - if(IsAlpha(prev_in) && IsAlpha(next_in)) - { - // '-' between two letters is a hyphen, treat as a space - word_flags |= FLAG_HYPHEN; - words[word_count-1].flags |= FLAG_HYPHEN_AFTER; - c = ' '; - } - else - if((prev_in==' ') && (next_in==' ')) - { - // ' - ' dash between two spaces, treat as pause - c = ' '; - pre_pause_add = 4; - } - else - if(next_in=='-') - { - // double hyphen, treat as pause - source_index++; - c = ' '; - pre_pause_add = 4; - } - else - if((prev_out == ' ') && IsAlpha(sbuf[ix-2]) && !IsAlpha(prev_in)) - { - // insert extra space between a word + space + hyphen, to distinguish 'a -2' from 'a-2' - sbuf[ix++] = ' '; - words[word_count].start++; - } - } - else - if(c == '\'') - { - if(iswalnum(prev_in) && IsAlpha(next_in)) - { - // between two letters, consider apostrophe as part of the word - single_quoted = 0; - } - else - if((wcschr(tr->char_plus_apostrophe,prev_in) != 0) && (prev_out2 == ' ')) - { - // consider single character plus apostrophe as a word - single_quoted = 0; - if(next_in == ' ') - { - source_index++; // skip following space - } - } - else - { - if((prev_out == 's') && (single_quoted==0)) - { - // looks like apostrophe after an 's' - c = ' '; - } - else - { - if(IsSpace(prev_out)) - single_quoted = 1; - else - single_quoted = 0; - - pre_pause_add = 4; // single quote - c = ' '; - } - } - } - else -#ifdef deleted -// Brackets are now recognised in TranslateRules() - if(IsBracket(c)) - { - pre_pause_add = 4; - c = ' '; - } - else -#endif - if(lookupwchar(breaks,c) != 0) - { - c = ' '; // various characters to treat as space - } - else - if(iswdigit(c)) - { - if(tr->langopts.tone_numbers && IsAlpha(prev_out) && !IsDigit(next_in)) - { - } - else - if((prev_out != ' ') && !iswdigit(prev_out)) - { - if((prev_out != tr->langopts.decimal_sep) || ((decimal_sep_count > 0) && (tr->langopts.decimal_sep == ','))) - { - c = ' '; - space_inserted = 1; - } - else - { - decimal_sep_count = 1; - } - } - else - if((prev_out == ' ') && IsAlpha(sbuf[ix-2]) && !IsAlpha(prev_in)) - { - // insert extra space between a word and a number, to distinguish 'a 2' from 'a2' - sbuf[ix++] = ' '; - words[word_count].start++; - } - } - } - - if(IsSpace(c)) - { - if(prev_out == ' ') - { - continue; // multiple spaces - } - - if(space_inserted) - { - words[word_count].length = source_index - words[word_count].sourceix; - } - - // end of 'word' - sbuf[ix++] = ' '; - - if((ix > words[word_count].start) && (word_count < N_CLAUSE_WORDS-1)) - { - if(embedded_count > 0) - { - // there are embedded commands before this word - embedded_list[embedded_ix-1] |= 0x80; // terminate list of commands for this word - words[word_count].flags |= FLAG_EMBEDDED; - embedded_count = 0; - } - words[word_count].pre_pause = pre_pause; - words[word_count].flags |= (all_upper_case | word_flags | word_emphasis); - words[word_count].wmark = word_mark; - - if(pre_pause > 0) - { - // insert an extra space before the word, to prevent influence from previous word across the pause - for(j=ix; j>words[word_count].start; j--) - { - sbuf[j] = sbuf[j-1]; - } - sbuf[j] = ' '; - words[word_count].start++; - ix++; - } - - word_count++; - words[word_count].start = ix; - words[word_count].flags = 0; - - for(j=source_index; charix[j] <= 0; j++); // skip blanks - words[word_count].sourceix = charix[j]; - k = 0; - while(charix[j] != 0) - { - // count the number of characters (excluding multibyte continuation bytes) - if(charix[j++] != -1) - k++; - } - words[word_count].length = k; - - word_flags = next_word_flags; - next_word_flags = 0; - pre_pause = 0; - word_mark = 0; - all_upper_case = FLAG_ALL_UPPER; - syllable_marked = 0; - } - - if(space_inserted) - { - source_index = prev_source_index; // rewind to the previous character - char_inserted = 0; - space_inserted = 0; - } - } - else - { - ix += utf8_out(c,&sbuf[ix]); // sbuf[ix++] = c; - } - if(pre_pause_add > pre_pause) - pre_pause = pre_pause_add; - pre_pause_add = 0; - } - - if((word_count==0) && (embedded_count > 0)) - { - // add a null 'word' to carry the embedded command flag - embedded_list[embedded_ix-1] |= 0x80; - words[word_count].flags |= FLAG_EMBEDDED; - word_count = 1; - } - - tr->clause_end = &sbuf[ix-1]; - sbuf[ix] = 0; - words[0].pre_pause = 0; // don't add extra pause at beginning of clause - words[word_count].pre_pause = 8; - if(word_count > 0) - words[word_count-1].flags |= FLAG_LAST_WORD; - words[0].flags |= FLAG_FIRST_WORD; - - for(ix=0; ix<word_count; ix++) - { - int nx; - int c_temp; - char *pn; - char *pw; - static unsigned int break_numbers1 = 0x49249248; - static unsigned int break_numbers2 = 0x24924aa8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi - static unsigned int break_numbers3 = 0x49249268; // for languages which have numbers for 100,000 and 1,000,000 - unsigned int break_numbers; - char number_buf[80]; - - // start speaking at a specified word position in the text? - count_words++; - if(skip_words > 0) - { - skip_words--; - if(skip_words == 0) - skipping_text = 0; - } - if(skipping_text) - continue; - - - // digits should have been converted to Latin alphabet ('0' to '9') - word = pw = &sbuf[words[ix].start]; - - if(iswdigit(word[0]) && (tr->langopts.numbers2 & NUM2_100000)) - { - // Languages with 100000 numbers. Remove thousands separators so that we can insert them again later - pn = number_buf; - while(pn < &number_buf[sizeof(number_buf)-3]) - { - if(iswdigit(*pw)) - { - *pn++ = *pw++; - } - else - if((*pw == tr->langopts.thousands_sep) && (pw[1] == ' ') && iswdigit(pw[2])) - { - pw += 2; - ix++; // skip "word" - } - else - { - nx = pw - word; - memset(word,' ',nx); - nx = pn - number_buf; - memcpy(word,number_buf,nx); - break; - } - } - pw = word; - } - - for(n_digits=0; iswdigit(word[n_digits]); n_digits++); // count consecutive digits - - if((n_digits > 4) && (word[0] != '0')) - { - // word is entirely digits, insert commas and break into 3 digit "words" - number_buf[0] = ' '; - pn = &number_buf[1]; - nx = n_digits; - - if((tr->langopts.numbers2 & NUM2_100000a) == NUM2_100000a) - break_numbers = break_numbers3; - else - if(tr->langopts.numbers2 & NUM2_100000) - break_numbers = break_numbers2; - else - break_numbers = break_numbers1; - - while(pn < &number_buf[sizeof(number_buf)-3]) - { - if(!isdigit(c = *pw++) && (c != tr->langopts.decimal_sep)) - break; - - *pn++ = c; - if((--nx > 0) && (break_numbers & (1 << nx))) - { - if(tr->langopts.thousands_sep != ' ') - { - *pn++ = tr->langopts.thousands_sep; - } - *pn++ = ' '; - if(break_numbers & (1 << (nx-1))) - { - // the next group only has 1 digits (i.e. NUM2_10000), make it three - *pn++ = '0'; - *pn++ = '0'; - } - if(break_numbers & (1 << (nx-2))) - { - // the next group only has 2 digits (i.e. NUM2_10000), make it three - *pn++ = '0'; - } - } - } - word = pw; - - // include the next few characters, in case there are an ordinal indicator - pn[0] = ' '; - memcpy(pn+1, pw, 8); - pn[8] = 0; - - for(pw = &number_buf[1]; pw < pn;) - { - dict_flags = TranslateWord2(tr, pw, &words[ix], words[ix].pre_pause,0 ); - while(*pw++ != ' '); - words[ix].pre_pause = 0; - words[ix].flags = 0; - } - } - else - { - pre_pause = 0; - dict_flags = TranslateWord2(tr, word, &words[ix], words[ix].pre_pause, words[ix+1].pre_pause); - - if(pre_pause > words[ix+1].pre_pause) - { - words[ix+1].pre_pause = pre_pause; - pre_pause = 0; - } - - if(dict_flags & FLAG_SPELLWORD) - { - // redo the word, speaking single letters - for(pw = word; *pw != ' ';) - { - memset(number_buf,' ',9); - nx = utf8_in(&c_temp, pw); - memcpy(&number_buf[2],pw,nx); - TranslateWord2(tr, &number_buf[2], &words[ix], 0, 0 ); - pw += nx; - } - } - - if((dict_flags & FLAG_DOT) && (ix == word_count-1) && (terminator == CLAUSE_PERIOD)) - { - // probably an abbreviation such as Mr. or B. rather than end of sentence - clause_pause = 10; - tone = 4; - } - } - - if(dict_flags & FLAG_SKIPWORDS) - { - ix += dictionary_skipwords; // dictionary indicates skip next word(s) - } - } - - for(ix=0; ix<2; ix++) - { - // terminate the clause with 2 PAUSE phonemes - PHONEME_LIST2 *p2; - p2 = &ph_list2[n_ph_list2 + ix]; - p2->phcode = phonPAUSE; - p2->stress = 0; - p2->sourceix = source_index; - p2->synthflags = 0; - } - n_ph_list2 += 2; - - if(count_words == 0) - { - clause_pause = 0; - } - if(Eof() && ((word_count == 0) || (option_endpause==0))) - { - clause_pause = 10; - } - - MakePhonemeList(tr, clause_pause, new_sentence); - - if(embedded_count) // ???? is this needed - { - phoneme_list[n_phoneme_list-2].synthflags = SFLAG_EMBEDDED; - embedded_list[embedded_ix-1] |= 0x80; - } - - - prev_clause_pause = clause_pause; - - *tone_out = tone; - - new_sentence = 0; - if(terminator & CLAUSE_BIT_SENTENCE) - { - new_sentence = 1; // next clause is a new sentence - } - - - if(voice_change != NULL) - { - // return new voice name if an embedded voice change command terminated the clause - if(terminator & CLAUSE_BIT_VOICE) - *voice_change = &source[source_index]; - else - *voice_change = NULL; - } - - if(Eof() || (vp_input==NULL)) - return(NULL); - - if(option_multibyte == espeakCHARS_WCHAR) - return((void *)p_wchar_input); - else - return((void *)p_textinput); -} // end of TranslateClause - - - - - -void InitText(int control) -{//======================= - count_sentences = 0; - count_words = 0; - end_character_position = 0; - skip_sentences = 0; - skip_marker[0] = 0; - skip_words = 0; - skip_characters = 0; - skipping_text = 0; - new_sentence = 1; - - prev_clause_pause = 0; - - option_sayas = 0; - option_sayas2 = 0; - option_emphasis = 0; - word_emphasis = 0; - embedded_flag = 0; - - InitText2(); - - if((control & espeakKEEP_NAMEDATA) == 0) - { - InitNamedata(); - } -} - diff --git a/navit/support/espeak/translate.h b/navit/support/espeak/translate.h deleted file mode 100755 index 0556bf280..000000000 --- a/navit/support/espeak/translate.h +++ /dev/null @@ -1,584 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - - -#define L(c1,c2) (c1<<8)+c2 // combine two characters into an integer for translator name - -#define CTRL_EMBEDDED 0x01 // control character at the start of an embedded command -#define REPLACED_E 'E' // 'e' replaced by silent e - -#define N_WORD_PHONEMES 160 // max phonemes in a word -#define N_WORD_BYTES 160 // max bytes for the UTF8 characters in a word -#define N_CLAUSE_WORDS 300 // max words in a clause -#define N_RULE_GROUP2 120 // max num of two-letter rule chains -#define N_HASH_DICT 1024 -#define N_CHARSETS 20 -#define N_LETTER_GROUPS 26 - - -/* dictionary flags, word 1 */ -// bits 0-3 stressed syllable, bit 6=unstressed -#define FLAG_SKIPWORDS 0x80 -#define FLAG_PREPAUSE 0x100 - -#define FLAG_ONLY 0x200 -#define FLAG_ONLY_S 0x400 -#define BITNUM_FLAG_ONLY 9 // bit 9 is set -#define BITNUM_FLAG_ONLY_S 10 // bit 10 is set - -#define FLAG_STRESS_END 0x800 /* full stress if at end of clause */ -#define FLAG_STRESS_END2 0x1000 /* full stress if at end of clause, or only followed by unstressed */ -#define FLAG_UNSTRESS_END 0x2000 /* reduce stress at end of clause */ -#define FLAG_ATEND 0x4000 /* use this pronunciation if at end of clause */ -#define FLAG_SPELLWORD 0x8000 // re-translate the word as individual letters, separated by spaces - -#define FLAG_DOT 0x10000 /* ignore '.' after word (abbreviation) */ -#define FLAG_ABBREV 0x20000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters -#define FLAG_STEM 0x40000 // must have a suffix - -#define FLAG_DOUBLING 0x80000 // doubles the following consonant -#define FLAG_ALT_TRANS 0x100000 // language specific -#define FLAG_ALT2_TRANS 0x200000 // language specific - -#define FLAG_MAX3 0x08000000 // limit to 3 repeats -#define FLAG_PAUSE1 0x10000000 // shorter prepause -#define FLAG_TEXTMODE 0x20000000 // word translates to replacement text, not phonemes -#define BITNUM_FLAG_TEXTMODE 29 - -#define FLAG_FOUND_ATTRIBUTES 0x40000000 // word was found in the dictionary list (has attributes) -#define FLAG_FOUND 0x80000000 // pronunciation was found in the dictionary list - -// dictionary flags, word 2 -#define FLAG_VERBF 0x1 /* verb follows */ -#define FLAG_VERBSF 0x2 /* verb follows, may have -s suffix */ -#define FLAG_NOUNF 0x4 /* noun follows */ -#define FLAG_PASTF 0x8 /* past tense follows */ -#define FLAG_VERB 0x10 /* pronunciation for verb */ -#define FLAG_NOUN 0x20 /* pronunciation for noun */ -#define FLAG_PAST 0x40 /* pronunciation for past tense */ -#define FLAG_VERB_EXT 0x100 /* extend the 'verb follows' */ -#define FLAG_CAPITAL 0x200 /* pronunciation if initial letter is upper case */ -#define FLAG_ALLCAPS 0x400 // only if the word is all capitals -#define BITNUM_FLAG_ALLCAPS 0x2a -#define FLAG_ACCENT 0x800 // character name is base-character name + accent name -#define FLAG_HYPHENATED 0x1000 // multiple-words, but needs hyphen between parts 1 and 2 -#define BITNUM_FLAG_HYPHENATED 0x2c - - -// wordflags, flags in source word -#define FLAG_ALL_UPPER 0x1 /* no lower case letters in the word */ -#define FLAG_FIRST_UPPER 0x2 /* first letter is upper case */ -#define FLAG_UPPERS 0x3 // FLAG_ALL_UPPER | FLAG_FIRST_UPPER -#define FLAG_HAS_PLURAL 0x4 /* upper-case word with s or 's lower-case ending */ -#define FLAG_PHONEMES 0x8 /* word is phonemes */ -#define FLAG_LAST_WORD 0x10 /* last word in clause */ -#define FLAG_EMBEDDED 0x40 /* word is preceded by embedded commands */ -#define FLAG_HYPHEN 0x80 -#define FLAG_NOSPACE 0x100 // word is not seperated from previous word by a space -#define FLAG_FIRST_WORD 0x200 // first word in clause -#define FLAG_FOCUS 0x400 // the focus word of a clause -#define FLAG_EMPHASIZED 0x800 -#define FLAG_EMPHASIZED2 0xc00 // FLAG_FOCUS | FLAG_EMPHASIZED -#define FLAG_DONT_SWITCH_TRANSLATOR 0x1000 -#define FLAG_SUFFIX_REMOVED 0x2000 -#define FLAG_HYPHEN_AFTER 0x4000 - -#define FLAG_NO_TRACE 0x10000 // passed to TranslateRules() to suppress dictionary lookup printout -#define FLAG_NO_PREFIX 0x20000 - -// prefix/suffix flags (bits 8 to 14, bits 16 to 22) don't use 0x8000, 0x800000 -#define SUFX_E 0x0100 // e may have been added -#define SUFX_I 0x0200 // y may have been changed to i -#define SUFX_P 0x0400 // prefix -#define SUFX_V 0x0800 // suffix means use the verb form pronunciation -#define SUFX_D 0x1000 // previous letter may have been doubles -#define SUFX_F 0x2000 // verb follows -#define SUFX_Q 0x4000 // don't retranslate -#define SUFX_T 0x10000 // don't affect the stress position in the stem -#define SUFX_B 0x20000 // break, this character breaks the word into stem and suffix (used with SUFX_P) - -#define FLAG_ALLOW_TEXTMODE 0x02 // allow dictionary to translate to text rather than phonemes -#define FLAG_SUFX 0x04 -#define FLAG_SUFX_S 0x08 -#define FLAG_SUFX_E_ADDED 0x10 - - -// codes in dictionary rules -#define RULE_PRE 1 -#define RULE_POST 2 -#define RULE_PHONEMES 3 -#define RULE_PH_COMMON 4 // At start of rule. Its phoneme string is used by subsequent rules -#define RULE_CONDITION 5 // followed by condition number (byte) -#define RULE_GROUP_START 6 -#define RULE_GROUP_END 7 -#define RULE_LINENUM 8 // next 2 bytes give a line number, for debugging purposes - -#define RULE_SPACE 32 // ascii space -#define RULE_SYLLABLE 9 -#define RULE_STRESSED 10 -#define RULE_DOUBLE 11 -#define RULE_INC_SCORE 12 -#define RULE_DEL_FWD 13 -#define RULE_ENDING 14 -#define RULE_DIGIT 15 // D digit -#define RULE_NONALPHA 16 // Z non-alpha -#define RULE_LETTERGP 17 // A B C H F G Y letter group number -#define RULE_LETTERGP2 18 // L + letter group number -#define RULE_CAPITAL 19 // word starts with a capital letter -#define RULE_REPLACEMENTS 20 // section for character replacements -#define RULE_NO_SUFFIX 24 // N -#define RULE_NOTVOWEL 25 // K -#define RULE_IFVERB 26 // V -#define RULE_ALT1 28 // T word has $alt attribute -#define RULE_NOVOWELS 29 // X no vowels up to word boundary -#define RULE_SPELLING 31 // W while spelling letter-by-letter -#define RULE_LAST_RULE 31 - -#define LETTERGP_A 0 -#define LETTERGP_B 1 -#define LETTERGP_C 2 -#define LETTERGP_H 3 -#define LETTERGP_F 4 -#define LETTERGP_G 5 -#define LETTERGP_Y 6 -#define LETTERGP_VOWEL2 7 - - -// Punctuation types returned by ReadClause() -// bits 0-7 pause x 10mS, bits 12-14 intonation type, -// bit 19=sentence, bit 18=clause, bits 17=voice change -// bit 16 used to distinguish otherwise identical types -// bit 20= punctuation character can be inside a word (Armenian) -#define CLAUSE_BIT_SENTENCE 0x80000 -#define CLAUSE_BIT_VOICE 0x20000 -#define PUNCT_IN_WORD 0x100000 - -#define CLAUSE_NONE 0 + 0x04000 -#define CLAUSE_PARAGRAPH 70 + 0x80000 -#define CLAUSE_EOF 35 + 0x90000 -#define CLAUSE_VOICE 0 + 0x24000 -#define CLAUSE_PERIOD 35 + 0x80000 -#define CLAUSE_COMMA 20 + 0x41000 -#define CLAUSE_SHORTCOMMA 4 + 0x41000 -#define CLAUSE_SHORTFALL 4 + 0x40000 -#define CLAUSE_QUESTION 35 + 0x82000 -#define CLAUSE_EXCLAMATION 40 + 0x83000 -#define CLAUSE_COLON 30 + 0x40000 -#ifdef PLATFORM_RISCOS -#define CLAUSE_SEMICOLON 30 + 0x40000 -#else -#define CLAUSE_SEMICOLON 30 + 0x41000 -#endif - -#define SAYAS_CHARS 0x12 -#define SAYAS_GLYPHS 0x13 -#define SAYAS_SINGLE_CHARS 0x14 -#define SAYAS_KEY 0x24 -#define SAYAS_DIGITS 0x40 // + number of digits -#define SAYAS_DIGITS1 0xc1 - -#define CHAR_EMPHASIS 0x0530 // this is an unused character code - -// Rule: -// [4] [match] [1 pre] [2 post] [3 phonemes] 0 -// match 1 pre 2 post 0 - use common phoneme string -// match 1 pre 2 post 3 0 - empty phoneme string - -typedef const char * constcharptr; - -typedef struct { - int points; - const char *phonemes; - int end_type; - char *del_fwd; -} MatchRecord; - - -// used to mark words with the source[] buffer -typedef struct{ - unsigned short start; - unsigned short sourceix; - unsigned short flags; - unsigned char pre_pause; - unsigned char wmark; - unsigned char length; -} WORD_TAB; - -// a clause translated into phoneme codes (first stage) -typedef struct { - unsigned char phcode; - unsigned char stress; - unsigned char tone_number; - unsigned char synthflags; - unsigned short sourceix; -} PHONEME_LIST2; - - -typedef struct { - int type; - int parameter[N_SPEECH_PARAM]; -} PARAM_STACK; - -extern PARAM_STACK param_stack[]; -extern const int param_defaults[N_SPEECH_PARAM]; - - - -#define N_LOPTS 16 -#define LOPT_DIERESES 1 - // 1=remove [:] from unstressed syllables, 2= remove from unstressed or non-penultimate syllables - // bit 4=0, if stress < 4, bit 4=1, if not the highest stress in the word -#define LOPT_IT_LENGTHEN 2 - - // 1=german -#define LOPT_PREFIXES 3 - - // non-zero, change voiced/unoiced to match last consonant in a cluster - // bit 1=LANG=ru, don't propagate over [v] - // bit 2=don't propagate acress word boundaries - // bit 3=LANG=pl, propagate over liquids and nasals -#define LOPT_REGRESSIVE_VOICING 4 - - // 0=default, 1=no check, other allow this character as an extra initial letter (default is 's') -#define LOPT_UNPRONOUNCABLE 5 - - // select length_mods tables, (length_mod_tab) + (length_mod_tab0 * 100) -#define LOPT_LENGTH_MODS 6 - - // increase this to prevent sonorants being shortened before shortened (eg. unstressed) vowels -#define LOPT_SONORANT_MIN 7 - - // don't break vowels at word boundary -#define LOPT_WORD_MERGE 8 - - // max. amplitude for vowel at the end of a clause -#define LOPT_MAXAMP_EOC 9 - - // bit 0=reduce even if phonemes are specified in the **_list file - // bit 1=don't reduce the strongest vowel in a word which is marked 'unstressed' -#define LOPT_REDUCE 10 - - // LANG=cs,sk combine some prepositions with the following word, if the combination has N or fewer syllables - // bits 0-3 N syllables - // bit 4=only if the second word has $alt attribute - // bit 5=not if the second word is end-of-sentence -#define LOPT_COMBINE_WORDS 11 - - // change [t] when followed by unstressed vowel -#define LOPT_REDUCE_T 12 - - // 1 = allow capitals inside a word - // 2 = stressed syllable is indicated by capitals -#define LOPT_CAPS_IN_WORD 13 - - // bit 0=Italian "syntactic doubling" of consoants in the word after a word marked with $double attribute - // bit 1=also after a word which ends with a stressed vowel -#define LOPT_IT_DOUBLING 14 - - // Call ApplySpecialAttributes() if $alt or $alt2 is set for a word -#define LOPT_ALT 15 - - -typedef struct { -// bits0-2 separate words with (1=pause_vshort, 2=pause_short, 3=pause, 4=pause_long 5=[?] phonemme) -// bit 3=don't use linking phoneme -// bit4=longer pause before STOP, VSTOP,FRIC -// bit5=length of a final vowel doesn't depend on the next phoneme - int word_gap; - int vowel_pause; - int stress_rule; // 1=first syllable, 2=penultimate, 3=last - -// bit0=don't stress monosyllables, except at end of clause -// bit1=don't set diminished stress, -// bit2=mark unstressed final syllables as diminished -// bit4=don't allow secondary stress on last syllable -// bit5-don't use automatic secondary stress -// bit6=light syllable followed by heavy, move secondary stress to the heavy syllable. LANG=Finnish -// bit8=stress last syllable if it doesn't end in a vowel -// bit9=stress last syllable if it doesn't end in vowel or "s" or "n" LANG=Spanish -// bit12= In a 2-syllable word, if one has primary stress then give the other secondary stress -// bit13= If there is only one syllable before the primary stress, give it a secondary stress -// bit15= Give stress to the first unstressed syllable -// bit16= Don't diminish consecutive syllables within a word. -// bit17= "priority" stress reduces other primary stress to "unstressed" not "secondary" -// bit18= don't lengthen short vowels more than long vowels at end-of-clause -// bit19=stress on final syllable if it has a long vowel, but previous syllable has a short vowel - - int stress_flags; - int unstressed_wd1; // stress for $u word of 1 syllable - int unstressed_wd2; // stress for $u word of >1 syllable - int param[N_LOPTS]; - unsigned char *length_mods; - unsigned char *length_mods0; - -#define NUM_ROMAN 0x20000 -#define NUM_ROMAN_UC 0x40000 -#define NUM_NOPAUSE 0x80000 -#define NUM_ROMAN_AFTER 0x200000 -#define NUM_VIGESIMAL 0x400000 - - // bits0-1=which numbers routine to use. - // bit2= thousands separator must be space - // bit3= , decimal separator, not . - // bit4=use three-and-twenty rather than twenty-three - // bit5='and' between tens and units - // bit6=add "and" after hundred or thousand - // bit7=don't have "and" both after hundreds and also between tens and units - // bit8=only one primary stress in tens+units - // bit9=only one vowel betwen tens and units - // bit10=omit "one" before "hundred" - // bit11=say 19** as nineteen hundred - // bit12=allow space as thousands separator (in addition to langopts.thousands_sep) - // bits13-15 post-decimal-digits 0=single digits, 1=(LANG=it) 2=(LANG=pl) 3=(LANG=ro) - // bit16=dot after number indicates ordinal - // bit17=recognize roman numbers - // bit18=Roman numbers only if upper case - // bit19=don't add pause after a number - // bit20='and' before hundreds - // bit21= say "roman" after the number, not before - // bit22= vigesimal number, if tens are not found - int numbers; - -#define NUM2_100000 0x800 // numbers for 100,000 and 10,000,000 -#define NUM2_100000a 0xc00 // numbers for 100,000 and 1,000,000 - // bits 1-4 use variant form of numbers before thousands,millions,etc. - // bit6=(LANG=pl) two forms of plural, M or MA - // bit7=(LANG-ru) use MB for 1 thousand, million, etc - // bit8=(LANG=cs,sk) two forms of plural, M or MA - // bit9=(LANG=rw) say "thousand" and "million" before its number, not after - // bit10=(LANG=sw) special word for 100,000 and 1,000,000 - // bit11=(LANG=hi) special word for 100,000 and 10,000,000 - int numbers2; - - int max_roman; - int thousands_sep; - int decimal_sep; - - // bit 0, accent name before the letter name, bit 1 "capital" after letter name - int accents; - - int tone_language; // 1=tone language - int intonation_group; - int long_stop; // extra mS pause for a lengthened stop - int phoneme_change; // TEST, change phonemes, after translation - char max_initial_consonants; - char spelling_stress; // 0=default, 1=stress first letter - char tone_numbers; - char ideographs; // treat as separate words - char textmode; // the meaning of FLAG_TEXTMODE is reversed (to save data when *_list file is compiled) - int testing; // testing options: bit 1= specify stressed syllable in the form: "outdoor/2" - int listx; // compile *_listx after *list - const unsigned int *replace_chars; // characters to be substitutes - const char *ascii_language; // switch to this language for Latin characters -} LANGUAGE_OPTIONS; - - -// a parameter of ChangePhonemes() -typedef struct { - int flags; - unsigned char stress; // stress level of this vowel - unsigned char stress_highest; // the highest stress level of a vowel in this word - unsigned char n_vowels; // number of vowels in the word - unsigned char vowel_this; // syllable number of this vowel (counting from 1) - unsigned char vowel_stressed; // syllable number of the highest stressed vowel -} CHANGEPH; - - - -#define NUM_SEP_DOT 0x0008 // . , for thousands and decimal separator -#define NUM_SEP_SPACE 0x1000 // allow space as thousands separator (in addition to langopts.thousands_sep) -#define NUM_DEC_IT 0x2000 // (LANG=it) speak post-decimal-point digits as a combined number not as single digits - -typedef struct Translator -{//============= - - LANGUAGE_OPTIONS langopts; - int translator_name; - int transpose_offset; - int transpose_max; - int transpose_min; - - char phon_out[300]; - char phonemes_repeat[20]; - int phonemes_repeat_count; - - unsigned char stress_amps[8]; - unsigned char stress_amps_r[8]; - short stress_lengths[8]; - int dict_condition; // conditional apply some pronunciation rules and dict.lookups - const unsigned short *charset_a0; // unicodes for characters 0xa0 to oxff - const wchar_t *char_plus_apostrophe; // single chars + apostrophe treated as words - const wchar_t *punct_within_word; // allow these punctuation characters within words - -// holds properties of characters: vowel, consonant, etc for pronunciation rules - unsigned char letter_bits[256]; - int letter_bits_offset; - const wchar_t *letter_groups[8]; - - /* index1=option, index2 by 0=. 1=, 2=?, 3=! 4=none */ -#define INTONATION_TYPES 8 -#define PUNCT_INTONATIONS 6 - unsigned char punct_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS]; - - char *data_dictrules; // language_1 translation rules file - char *data_dictlist; // language_2 dictionary lookup file - char *dict_hashtab[N_HASH_DICT]; // hash table to index dictionary lookup file - char *letterGroups[N_LETTER_GROUPS]; - - // groups1 and groups2 are indexes into data_dictrules, set up by InitGroups() - // the two-letter rules for each letter must be consecutive in the language_rules source - - char *groups1[256]; // translation rule lists, index by single letter - char *groups2[N_RULE_GROUP2]; // translation rule lists, indexed by two-letter pairs - unsigned int groups2_name[N_RULE_GROUP2]; // the two letter pairs for groups2[] - int n_groups2; // number of groups2[] entries used - - unsigned char groups2_count[256]; // number of 2 letter groups for this initial letter - unsigned char groups2_start[256]; // index into groups2 - - - int expect_verb; - int expect_past; // expect past tense - int expect_verb_s; - int expect_noun; - int prev_last_stress; - char *clause_end; - - int word_vowel_count; // number of vowels so far - int word_stressed_count; // number of vowels so far which could be stressed - - int clause_upper_count; // number of upper case letters in the clause - int clause_lower_count; // number of lower case letters in the clause - - int prepause_timeout; - int end_stressed_vowel; // word ends with stressed vowel - int prev_dict_flags; // dictionary flags from previous word -} Translator; // end of class Translator - - -extern int option_tone2; -#define OPTION_EMPHASIZE_ALLCAPS 0x100 -#define OPTION_EMPHASIZE_PENULTIMATE 0x200 -extern int option_tone_flags; -extern int option_waveout; -extern int option_quiet; -extern int option_phonemes; -extern int option_phoneme_events; -extern int option_linelength; // treat lines shorter than this as end-of-clause -extern int option_multibyte; -extern int option_capitals; -extern int option_punctuation; -extern int option_endpause; -extern int option_ssml; -extern int option_phoneme_input; // allow [[phonemes]] in input text -extern int option_phoneme_variants; -extern int option_sayas; -extern int option_wordgap; - -extern int count_characters; -extern int count_words; -extern int count_sentences; -extern int skip_characters; -extern int skip_words; -extern int skip_sentences; -extern int skipping_text; -extern int end_character_position; -extern int clause_start_char; -extern int clause_start_word; -extern char *namedata; -extern int pre_pause; - - - -#define N_MARKER_LENGTH 50 // max.length of a mark name -extern char skip_marker[N_MARKER_LENGTH]; - -#define N_PUNCTLIST 60 -extern wchar_t option_punctlist[N_PUNCTLIST]; // which punctuation characters to announce -extern unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS]; - -extern struct Translator *translator; -extern struct Translator *translator2; -extern const unsigned short *charsets[N_CHARSETS]; -extern char dictionary_name[40]; -extern char ctrl_embedded; // to allow an alternative CTRL for embedded commands -extern unsigned char *p_textinput; -extern wchar_t *p_wchar_input; -extern int dictionary_skipwords; - -extern int (* uri_callback)(int, const char *, const char *); -extern int (* phoneme_callback)(const char *); -extern void SetLengthMods(struct Translator *tr, int value); - -void LoadConfig(void); -int TransposeAlphabet(char *text, int offset, int min, int max); -int utf8_in(int *c, const char *buf); -int utf8_in2(int *c, const char *buf, int backwards); -int utf8_out(unsigned int c, char *buf); -int utf8_nbytes(const char *buf); -int lookupwchar(const unsigned short *list,int c); -int Eof(void); -char *strchr_w(const char *s, int c); -int IsBracket(int c); -void InitNamedata(void); -void InitText(int flags); -void InitText2(void); -int IsDigit(unsigned int c); -int IsAlpha(unsigned int c); -int isspace2(unsigned int c); -int towlower2(unsigned int c); -void GetTranslatedPhonemeString(char *phon_out, int n_phon_out); - -struct Translator *SelectTranslator(const char *name); -int SetTranslator2(const char *name); -void DeleteTranslator(struct Translator *tr); -int Lookup(struct Translator *tr, const char *word, char *ph_out); - -int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, int wflags); -int TranslateRoman(Translator *tr, char *word, char *ph_out); - -void ChangeWordStress(Translator *tr, char *word, int new_stress); -void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars); -int TranslateLetter(Translator *tr, char *letter, char *phonemes, int control, int word_length); -void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf); -void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf); - -int LoadDictionary(Translator *tr, const char *name, int no_error); -int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab); - -void MakePhonemeList(Translator *tr, int post_pause, int new_sentence); -int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch); -void ApplySpecialAttribute(Translator *tr, char *phonemes, int dict_flags); -void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags); -void AppendPhonemes(Translator *tr, char *string, int size, const char *ph); - -void CalcLengths(Translator *tr); -void CalcPitches(Translator *tr, int clause_tone); - -int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy); -int Unpronouncable(Translator *tr, char *word); -void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int prev_stress); -int TranslateRules(Translator *tr, char *p, char *phonemes, int size, char *end_phonemes, int end_flags, unsigned int *dict_flags); -int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab); -void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone, char **voice_change); -int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix_top, int n_buf, int *tone_type); - -void SetVoiceStack(espeak_VOICE *v); - -extern FILE *f_trans; // for logging diff --git a/navit/support/espeak/voice.h b/navit/support/espeak/voice.h deleted file mode 100644 index ab69fa128..000000000 --- a/navit/support/espeak/voice.h +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - - - -typedef struct { - char v_name[40]; - - int phoneme_tab_ix; // phoneme table number - int pitch_base; // Hz<<12 - int pitch_range; // standard = 0x1000 - - int speedf1; - int speedf2; - int speedf3; - - int flutter; - int roughness; - int echo_delay; - int echo_amp; - int n_harmonic_peaks; // highest formant which is formed from adding harmonics - int peak_shape; // alternative shape for formant peaks (0=standard 1=squarer) - int voicing; // 100% = 64, level of formant-synthesized sound - int formant_factor; // adjust nominal formant frequencies by this because of the voice's pitch (256ths) - int consonant_amp; // amplitude of unvoiced consonants - int consonant_ampv; // amplitude of the noise component of voiced consonants - int klattv[8]; - - // parameters used by Wavegen - short freq[N_PEAKS]; // 100% = 256 - short height[N_PEAKS]; // 100% = 256 - short width[N_PEAKS]; // 100% = 256 - short freqadd[N_PEAKS]; // Hz - - // copies without temporary adjustments from embedded commands - short freq2[N_PEAKS]; // 100% = 256 - short height2[N_PEAKS]; // 100% = 256 - short width2[N_PEAKS]; // 100% = 256 - - int breath[N_PEAKS]; // amount of breath for each formant. breath[0] indicates whether any are set. - int breathw[N_PEAKS]; // width of each breath formant - - // This table provides the opportunity for tone control. - // Adjustment of harmonic amplitudes, steps of 8Hz - // value of 128 means no change - #define N_TONE_ADJUST 1000 - unsigned char tone_adjust[N_TONE_ADJUST]; // 8Hz steps * 1000 = 8kHz - -} voice_t; - -// percentages shown to user, ix=N_PEAKS means ALL peaks -extern USHORT voice_pcnt[N_PEAKS+1][3]; - - -extern voice_t *voice; -extern int tone_points[12]; - -const char *SelectVoice(espeak_VOICE *voice_select, int *found); -espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name); -voice_t *LoadVoice(const char *voice_name, int control); -voice_t *LoadVoiceVariant(const char *voice_name, int variant); -void DoVoiceChange(voice_t *v); -void WavegenSetVoice(voice_t *v); -void ReadTonePoints(char *string, int *tone_pts); - diff --git a/navit/support/espeak/voices.c b/navit/support/espeak/voices.c deleted file mode 100755 index a7bd3f5a0..000000000 --- a/navit/support/espeak/voices.c +++ /dev/null @@ -1,1746 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -#include "stdio.h" -#include "ctype.h" -#include "wctype.h" -#include "string.h" -#include "stdlib.h" -#include "speech.h" - -#ifdef PLATFORM_WINDOWS -#include "windows.h" -#else -#ifdef PLATFORM_RISCOS -#include "kernel.h" -#else -#include "dirent.h" -#endif -#endif - -#include "speak_lib.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" -#include "translate.h" - -#define int(x) ((int)(x)) -#define double(x) ((double)(x)) -#define __cdecl - -MNEM_TAB genders [] = { - {"unknown", 0}, - {"male", 1}, - {"female", 2}, - {NULL, 0 }}; - -int tone_points[12] = {600,170, 1200,135, 2000,110, 3000,110, -1,0}; -//int tone_points[12] = {250,200, 400,170, 600,170, 1200,135, 2000,110, -1,0}; - -// limit the rate of change for each formant number -//static int formant_rate_22050[9] = {50, 104, 165, 230, 220, 220, 220, 220, 220}; // values for 22kHz sample rate -//static int formant_rate_22050[9] = {240, 180, 180, 180, 180, 180, 180, 180, 180}; // values for 22kHz sample rate -static int formant_rate_22050[9] = {240, 170, 170, 170, 170, 170, 170, 170, 170}; // values for 22kHz sample rate -int formant_rate[9]; // values adjusted for actual sample rate - - - -#define DEFAULT_LANGUAGE_PRIORITY 5 -#define N_VOICES_LIST 150 -static int n_voices_list = 0; -static espeak_VOICE *voices_list[N_VOICES_LIST]; -static int len_path_voices; - -espeak_VOICE voice_selected; - - -enum { - V_NAME = 1, - V_LANGUAGE, - V_GENDER, - V_TRANSLATOR, - V_PHONEMES, - V_DICTIONARY, - -// these affect voice quality, are independent of language - V_FORMANT, - V_PITCH, - V_ECHO, - V_FLUTTER, - V_ROUGHNESS, - V_CLARITY, - V_TONE, - V_VOICING, - V_BREATH, - V_BREATHW, - -// these override defaults set by the translator - V_WORDGAP, - V_INTONATION, - V_STRESSLENGTH, - V_STRESSAMP, - V_STRESSADD, - V_DICTRULES, - V_STRESSRULE, - V_CHARSET, - V_NUMBERS, - V_OPTION, - - V_MBROLA, - V_KLATT, - V_FAST, - -// these need a phoneme table to have been specified - V_REPLACE, - V_CONSONANTS -}; - - - -typedef struct { - const char *mnem; - int data; -} keywtab_t; - -static keywtab_t keyword_tab[] = { - {"name", V_NAME}, - {"language", V_LANGUAGE}, - {"gender", V_GENDER}, - - {"formant", V_FORMANT}, - {"pitch", V_PITCH}, - {"phonemes", V_PHONEMES}, - {"translator", V_TRANSLATOR}, - {"dictionary", V_DICTIONARY}, - {"stressLength", V_STRESSLENGTH}, - {"stressAmp", V_STRESSAMP}, - {"stressAdd", V_STRESSADD}, - {"intonation", V_INTONATION}, - {"dictrules", V_DICTRULES}, - {"stressrule", V_STRESSRULE}, - {"charset", V_CHARSET}, - {"replace", V_REPLACE}, - {"words", V_WORDGAP}, - {"echo", V_ECHO}, - {"flutter", V_FLUTTER}, - {"roughness", V_ROUGHNESS}, - {"clarity", V_CLARITY}, - {"tone", V_TONE}, - {"voicing", V_VOICING}, - {"breath", V_BREATH}, - {"breathw", V_BREATHW}, - {"numbers", V_NUMBERS}, - {"option", V_OPTION}, - {"mbrola", V_MBROLA}, - {"consonants", V_CONSONANTS}, - {"klatt", V_KLATT}, - {"fast_test", V_FAST}, - - // these just set a value in langopts.param[] - {"l_dieresis", 0x100+LOPT_DIERESES}, -// {"l_lengthen", 0x100+LOPT_IT_LENGTHEN}, - {"l_prefix", 0x100+LOPT_PREFIXES}, - {"l_regressive_v", 0x100+LOPT_REGRESSIVE_VOICING}, - {"l_unpronouncable", 0x100+LOPT_UNPRONOUNCABLE}, - {"l_sonorant_min", 0x100+LOPT_SONORANT_MIN}, - {"l_length_mods", 0x100+LOPT_LENGTH_MODS}, - {NULL, 0} }; - -#define N_VOICE_VARIANTS 12 -const char variants_either[N_VOICE_VARIANTS] = {1,2,12,3,13,4,14,5,11,0}; -const char variants_male[N_VOICE_VARIANTS] = {1,2,3,4,5,0}; -const char variants_female[N_VOICE_VARIANTS] = {11,12,13,14,0}; -const char *variant_lists[3] = {variants_either, variants_male, variants_female}; - -static voice_t voicedata; -voice_t *voice = &voicedata; - - -static char *fgets_strip(char *buf, int size, FILE *f_in) -{//====================================================== -// strip trailing spaces, and truncate lines at // comment - int len; - char *p; - - if(fgets(buf,size,f_in) == NULL) - return(NULL); - - len = strlen(buf); - while((--len > 0) && isspace(buf[len])) - buf[len] = 0; - - if((p = strstr(buf,"//")) != NULL) - *p = 0; - - return(buf); -} - - -static void SetToneAdjust(voice_t *voice, int *tone_pts) -{//===================================================== - int ix; - int pt; - int y; - int freq1=0; - int freq2; - int height1 = tone_pts[1]; - int height2; - double rate; - - for(pt=0; pt<12; pt+=2) - { - if(tone_pts[pt] == -1) - { - tone_pts[pt] = N_TONE_ADJUST*8; - if(pt > 0) - tone_pts[pt+1] = tone_pts[pt-1]; - } - freq2 = tone_pts[pt] / 8; // 8Hz steps - height2 = tone_pts[pt+1]; - if((freq2 - freq1) > 0) - { - rate = double(height2-height1)/(freq2-freq1); - - for(ix=freq1; ix<freq2; ix++) - { - y = height1 + int(rate * (ix-freq1)); - if(y > 255) - y = 255; - voice->tone_adjust[ix] = y; - } - } - freq1 = freq2; - height1 = height2; - } -} - - -void ReadTonePoints(char *string, int *tone_pts) -{//============================================= -// tone_pts[] is int[12] - int ix; - - for(ix=0; ix<12; ix++) - tone_pts[ix] = -1; - - sscanf(string,"%d %d %d %d %d %d %d %d %d %d", - &tone_pts[0],&tone_pts[1],&tone_pts[2],&tone_pts[3], - &tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7], - &tone_pts[8],&tone_pts[9]); -} - - - - -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 -// file's language, gender, name lines - - char linebuf[120]; - char vname[80]; - char vgender[80]; - char vlanguage[80]; - char languages[300]; // allow space for several alternate language names and priorities - - - unsigned int len; - int langix = 0; - int n_languages = 0; - char *p; - espeak_VOICE *voice_data; - int priority; - int age; - int n_variants = 3; // default, number of variants of this voice before using another voice - int gender; - -#ifdef PLATFORM_WINDOWS - char fname_buf[sizeof(path_home)+15]; - if(memcmp(leafname,"mb-",3) == 0) - { - // check whether the mbrola speech data is present for this voice - memcpy(vname,&leafname[3],3); - vname[3] = 0; - sprintf(fname_buf,"%s/mbrola/%s",path_home,vname); - - if(GetFileLength(fname_buf) <= 0) - return(0); - } -#endif - - vname[0] = 0; - vgender[0] = 0; - age = 0; - - while(fgets_strip(linebuf,sizeof(linebuf),f_in) != NULL) - { - if(memcmp(linebuf,"name",4)==0) - { - p = &linebuf[4]; - while(isspace(*p)) p++; - strncpy0(vname,p,sizeof(vname)); - } - else - if(memcmp(linebuf,"language",8)==0) - { - priority = DEFAULT_LANGUAGE_PRIORITY; - vlanguage[0] = 0; - - sscanf(&linebuf[8],"%s %d",vlanguage,&priority); - len = strlen(vlanguage) + 2; - // check for space in languages[] - if(len < (sizeof(languages)-langix-1)) - { - languages[langix] = priority; - - strcpy(&languages[langix+1],vlanguage); - langix += len; - n_languages++; - } - } - else - if(memcmp(linebuf,"gender",6)==0) - { - sscanf(&linebuf[6],"%s %d",vgender,&age); - } - else - if(memcmp(linebuf,"variants",8)==0) - { - sscanf(&linebuf[8],"%d",&n_variants); - } - } - languages[langix++] = 0; - - gender = LookupMnem(genders,vgender); - - if(n_languages == 0) - { - return(NULL); // no language lines in the voice file - } - - p = (char *)calloc(sizeof(espeak_VOICE) + langix + strlen(fname) + strlen(vname) + 3, 1); - voice_data = (espeak_VOICE *)p; - p = &p[sizeof(espeak_VOICE)]; - - memcpy(p,languages,langix); - voice_data->languages = p; - - strcpy(&p[langix],fname); - voice_data->identifier = &p[langix]; - voice_data->name = &p[langix]; - - if(vname[0] != 0) - { - langix += strlen(fname)+1; - strcpy(&p[langix],vname); - voice_data->name = &p[langix]; - } - - voice_data->age = age; - voice_data->gender = gender; - voice_data->variant = 0; - voice_data->xx1 = n_variants; - return(voice_data); -} // end of ReadVoiceFile - - - - -void VoiceReset(int tone_only) -{//=========================== -// Set voice to the default values - - int pk; - static unsigned char default_heights[N_PEAKS] = {128,128,120,120,110,110,128,128,128}; - static unsigned char default_widths[N_PEAKS] = {128,128,128,160,171,171,128,128,128}; - - static int breath_widths[N_PEAKS] = {0,200,200,400,400,400,600,600,600}; - - // default is: pitch 82,118 -// voice->pitch_base = 0x49000; // default, 73 << 12; -// voice->pitch_range = 0x0f30; // default = 0x1000 - voice->pitch_base = 0x47000; - voice->pitch_range = 3996; - - voice->formant_factor = 256; - - voice->echo_delay = 0; - voice->echo_amp = 0; - voice->flutter = 64; - voice->n_harmonic_peaks = 5; - voice->peak_shape = 0; - voice->voicing = 64; - voice->consonant_amp = 100; - voice->consonant_ampv = 100; - memset(voice->klattv,0,sizeof(voice->klattv)); - memset(speed.fast_settings,0,sizeof(speed.fast_settings)); - -#ifdef PLATFORM_RISCOS - voice->roughness = 1; -#else - voice->roughness = 2; -#endif - - InitBreath(); - for(pk=0; pk<N_PEAKS; pk++) - { - voice->freq[pk] = 256; - voice->height[pk] = default_heights[pk]*2; - voice->width[pk] = default_widths[pk]*2; - voice->breath[pk] = 0; - voice->breathw[pk] = breath_widths[pk]; // default breath formant woidths - voice->freqadd[pk] = 0; - - // adjust formant smoothing depending on sample rate - formant_rate[pk] = (formant_rate_22050[pk] * 22050)/samplerate; - } - voice->height[2] = 240; // reduce F2 slightly - - // This table provides the opportunity for tone control. - // Adjustment of harmonic amplitudes, steps of 8Hz - // value of 128 means no change -// memset(voice->tone_adjust,128,sizeof(voice->tone_adjust)); -SetToneAdjust(voice,tone_points); - - // default values of speed factors - voice->speedf1 = 256; - voice->speedf2 = 238; - voice->speedf3 = 232; - - if(tone_only == 0) - { - n_replace_phonemes = 0; - option_quiet = 0; - LoadMbrolaTable(NULL,NULL,0); - } -} // end of VoiceReset - - -static void VoiceFormant(char *p) -{//============================== - // Set parameters for a formant - int ix; - int formant; - int freq = 100; - int height = 100; - int width = 100; - int freqadd = 0; - - ix = sscanf(p,"%d %d %d %d %d",&formant,&freq,&height,&width,&freqadd); - if(ix < 2) - return; - - if((formant < 0) || (formant > 8)) - return; - - if(freq >= 0) - voice->freq[formant] = int(freq * 2.56001); - if(height >= 0) - voice->height[formant] = int(height * 2.56001); - if(width >= 0) - voice->width[formant] = int(width * 2.56001); - voice->freqadd[formant] = freqadd; -} - - - - - -static void PhonemeReplacement(int type, char *p) -{//============================================== - int n; - int phon; - int flags = 0; - char phon_string1[12]; - char phon_string2[12]; - - strcpy(phon_string2,"NULL"); - n = sscanf(p,"%d %s %s",&flags,phon_string1,phon_string2); - if((n < 2) || (n_replace_phonemes >= N_REPLACE_PHONEMES)) - return; - - if((phon = LookupPhonemeString(phon_string1)) == 0) - return; // not recognised - - replace_phonemes[n_replace_phonemes].old_ph = phon; - replace_phonemes[n_replace_phonemes].new_ph = LookupPhonemeString(phon_string2); - replace_phonemes[n_replace_phonemes++].type = flags; -} // end of PhonemeReplacement - - - -static int Read8Numbers(char *data_in,int *data) -{//============================================= -// Read 8 integer numbers - return(sscanf(data_in,"%d %d %d %d %d %d %d %d", - &data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7])); -} - - -voice_t *LoadVoice(const char *vname, int control) -{//=============================================== -// control, bit 0 1= no_default -// bit 1 1 = change tone only, not language -// bit 2 1 = don't report error on LoadDictionary -// bit 4 1 = vname = full path - - FILE *f_voice = NULL; - keywtab_t *k; - char *p; - int key; - int ix; - int n; - int value; - int error = 0; - int langix = 0; - int tone_only = control & 2; - int language_set = 0; - int phonemes_set = 0; - int stress_amps_set = 0; - int stress_lengths_set = 0; - int stress_add_set = 0; - int conditional_rules = 0; - LANGUAGE_OPTIONS *langopts = NULL; - - Translator *new_translator = NULL; - - char voicename[40]; - char language_name[40]; - char translator_name[40]; - char new_dictionary[40]; - char phonemes_name[40]; - const char *language_type; - char buf[200]; - char path_voices[sizeof(path_home)+12]; - char langname[4]; - - int stress_amps[8]; - int stress_lengths[8]; - int stress_add[8]; - - int pitch1; - int pitch2; - - static char voice_identifier[40]; // file name for voice_selected - static char voice_name[40]; // voice name for voice_selected - static char voice_languages[100]; // list of languages and priorities for voice_selected - - strcpy(voicename,vname); - if(voicename[0]==0) - strcpy(voicename,"default"); - - if(control & 0x10) - { - strcpy(buf,vname); - if(GetFileLength(buf) <= 0) - return(NULL); - } - else - { - sprintf(path_voices,"%s%cvoices%c",path_home,PATHSEP,PATHSEP); - sprintf(buf,"%s%s",path_voices,voicename); - - if(GetFileLength(buf) <= 0) - { - // look for the voice in a sub-directory of the language name - langname[0] = voicename[0]; - langname[1] = voicename[1]; - langname[2] = 0; - sprintf(buf,"%s%s%c%s",path_voices,langname,PATHSEP,voicename); - - if(GetFileLength(buf) <= 0) - { - // look in "test" sub-directory - sprintf(buf,"%stest%c%s",path_voices,PATHSEP,voicename); - } - } - } - - f_voice = fopen(buf,"r"); - - language_type = "en"; // default - if(f_voice == NULL) - { - if(control & 3) - return(NULL); // can't open file - - if(SelectPhonemeTableName(voicename) >= 0) - language_type = voicename; - } - - if(!tone_only && (translator != NULL)) - { - DeleteTranslator(translator); - translator = NULL; - } - - strcpy(translator_name,language_type); - strcpy(new_dictionary,language_type); - strcpy(phonemes_name,language_type); - - - if(!tone_only) - { - voice = &voicedata; - strncpy0(voice_identifier,vname,sizeof(voice_identifier)); - voice_name[0] = 0; - voice_languages[0] = 0; - - voice_selected.identifier = voice_identifier; - voice_selected.name = voice_name; - voice_selected.languages = voice_languages; - } - else - { - // append the variant file name to the voice identifier - if((p = strchr(voice_identifier,'+')) != NULL) - *p = 0; // remove previous variant name - sprintf(buf,"+%s",&vname[3]); // omit !v/ from the variant filename - strcat(voice_identifier,buf); - langopts = &translator->langopts; - } - VoiceReset(tone_only); - - if(!tone_only) - SelectPhonemeTableName(phonemes_name); // set up phoneme_tab - - - while((f_voice != NULL) && (fgets_strip(buf,sizeof(buf),f_voice) != NULL)) - { - // isolate the attribute name - for(p=buf; (*p != 0) && !isspace(*p); p++); - *p++ = 0; - - if(buf[0] == 0) continue; - - key = 0; - for(k=keyword_tab; k->mnem != NULL; k++) - { - if(strcmp(buf,k->mnem)==0) - { - key = k->data; - break; - } - } - - switch(key) - { - case V_LANGUAGE: - { - unsigned int len; - int priority; - - if(tone_only) - break; - - priority = DEFAULT_LANGUAGE_PRIORITY; - language_name[0] = 0; - - sscanf(p,"%s %d",language_name,&priority); - if(strcmp(language_name,"variant") == 0) - break; - - len = strlen(language_name) + 2; - // check for space in languages[] - if(len < (sizeof(voice_languages)-langix-1)) - { - voice_languages[langix] = priority; - - strcpy(&voice_languages[langix+1],language_name); - langix += len; - } - - // only act on the first language line - if(language_set == 0) - { - language_type = strtok(language_name,"-"); - language_set = 1; - strcpy(translator_name,language_type); - strcpy(new_dictionary,language_type); - strcpy(phonemes_name,language_type); - SelectPhonemeTableName(phonemes_name); - - if(new_translator != NULL) - DeleteTranslator(new_translator); - - new_translator = SelectTranslator(translator_name); - langopts = &new_translator->langopts; - } - } - break; - - case V_NAME: - if(tone_only == 0) - { - while(isspace(*p)) p++; - strncpy0(voice_name,p,sizeof(voice_name)); - } - break; - - case V_GENDER: - { - int age; - char vgender[80]; - sscanf(p,"%s %d",vgender,&age); - voice_selected.gender = LookupMnem(genders,vgender); - voice_selected.age = age; - } - break; - - case V_TRANSLATOR: - if(tone_only) break; - - sscanf(p,"%s",translator_name); - - if(new_translator != NULL) - DeleteTranslator(new_translator); - - new_translator = SelectTranslator(translator_name); - langopts = &new_translator->langopts; - break; - - case V_DICTIONARY: // dictionary - sscanf(p,"%s",new_dictionary); - break; - - case V_PHONEMES: // phoneme table - sscanf(p,"%s",phonemes_name); - break; - - case V_FORMANT: - VoiceFormant(p); - break; - - case V_PITCH: - { - double factor; - // default is pitch 82 118 - n = sscanf(p,"%d %d",&pitch1,&pitch2); - voice->pitch_base = (pitch1 - 9) << 12; - voice->pitch_range = (pitch2 - pitch1) * 108; - factor = double(pitch1 - 82)/82; - voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch - } - break; - - case V_STRESSLENGTH: // stressLength - stress_lengths_set = Read8Numbers(p,stress_lengths); - break; - - case V_STRESSAMP: // stressAmp - stress_amps_set = Read8Numbers(p,stress_amps); - break; - - case V_STRESSADD: // stressAdd - stress_add_set = Read8Numbers(p,stress_add); - break; - - case V_INTONATION: // intonation - sscanf(p,"%d %d",&option_tone_flags,&option_tone2); - if((option_tone_flags & 0xff) != 0) - langopts->intonation_group = option_tone_flags & 0xff; - break; - - case V_DICTRULES: // conditional dictionary rules and list entries - while(*p != 0) - { - while(isspace(*p)) p++; - n = -1; - if(((n = atoi(p)) > 0) && (n < 32)) - { - p++; - conditional_rules |= (1 << n); - } - while(isalnum(*p)) p++; - } - break; - - case V_REPLACE: - if(phonemes_set == 0) - { - // must set up a phoneme table before we can lookup phoneme mnemonics - SelectPhonemeTableName(phonemes_name); - phonemes_set = 1; - } - PhonemeReplacement(key,p); - break; - - case V_WORDGAP: // words - sscanf(p,"%d %d",&langopts->word_gap, &langopts->vowel_pause); - break; - - case V_STRESSRULE: - sscanf(p,"%d %d %d %d",&langopts->stress_rule, - &langopts->stress_flags, - &langopts->unstressed_wd1, - &langopts->unstressed_wd2); - break; - - case V_CHARSET: - if((sscanf(p,"%d",&value)==1) && (value < N_CHARSETS)) - new_translator->charset_a0 = charsets[value]; - break; - - case V_NUMBERS: - sscanf(p,"%d %d",&langopts->numbers,&langopts->numbers2); - break; - - case V_OPTION: - if(sscanf(p,"%d %d",&ix,&value) == 2) - { - if((ix >= 0) && (ix < N_LOPTS)) - langopts->param[ix] = value; - } - break; - - case V_ECHO: - // echo. suggest: 135mS 11% - value = 0; - voice->echo_amp = 0; - sscanf(p,"%d %d",&voice->echo_delay,&voice->echo_amp); - break; - - case V_FLUTTER: // flutter - if(sscanf(p,"%d",&value)==1) - voice->flutter = value * 32; - break; - - case V_ROUGHNESS: // roughness - if(sscanf(p,"%d",&value)==1) - voice->roughness = value; - break; - - case V_CLARITY: // formantshape - if(sscanf(p,"%d",&value)==1) - { - if(value > 4) - { - voice->peak_shape = 1; // squarer formant peaks - value = 4; - } - voice->n_harmonic_peaks = 1+value; - } - break; - - case V_TONE: - { - int tone_data[12]; - ReadTonePoints(p,tone_data); - SetToneAdjust(voice,tone_data); - } - break; - - case V_VOICING: - if(sscanf(p,"%d",&value)==1) - voice->voicing = (value * 64)/100; - break; - - case V_BREATH: - voice->breath[0] = Read8Numbers(p,&voice->breath[1]); - for(ix=1; ix<8; ix++) - { - if(ix % 2) - voice->breath[ix] = -voice->breath[ix]; - } - break; - - case V_BREATHW: - voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]); - break; - - case V_CONSONANTS: - value = sscanf(p,"%d %d",&voice->consonant_amp, &voice->consonant_ampv); - break; - - case V_MBROLA: - { - int srate = 16000; - char name[40]; - char phtrans[40]; - - phtrans[0] = 0; - sscanf(p,"%s %s %d",name,phtrans,&srate); - LoadMbrolaTable(name,phtrans,srate); - } - break; - - case V_KLATT: - voice->klattv[0] = 1; // default source: IMPULSIVE - Read8Numbers(p,voice->klattv); - voice->klattv[KLATT_Kopen] -= 40; - break; - - case V_FAST: - Read8Numbers(p,speed.fast_settings); - SetSpeed(2); - break; - - default: - if((key & 0xff00) == 0x100) - { - sscanf(p,"%d",&langopts->param[key &0xff]); - } - else - { - fprintf(stderr,"Bad voice attribute: %s\n",buf); - } - break; - } - } - if(f_voice != NULL) - fclose(f_voice); - - if((new_translator == NULL) && (!tone_only)) - { - // not set by language attribute - new_translator = SelectTranslator(translator_name); - } - - for(ix=0; ix<N_PEAKS; ix++) - { - voice->freq2[ix] = voice->freq[ix]; - voice->height2[ix] = voice->height[ix]; - voice->width2[ix] = voice->width[ix]; - } - - if(tone_only) - { - new_translator = translator; - } - else - { - if((ix = SelectPhonemeTableName(phonemes_name)) < 0) - { - fprintf(stderr,"Unknown phoneme table: '%s'\n",phonemes_name); - } - voice->phoneme_tab_ix = ix; - error = LoadDictionary(new_translator, new_dictionary, control & 4); - if(dictionary_name[0]==0) - return(NULL); // no dictionary loaded - - new_translator->dict_condition = conditional_rules; - - voice_languages[langix] = 0; - } - - langopts = &new_translator->langopts; - - - if((value = langopts->param[LOPT_LENGTH_MODS]) != 0) - { - SetLengthMods(new_translator,value); - } - - voice->width[0] = (voice->width[0] * 105)/100; - - if(!tone_only) - { - translator = new_translator; - } - - // relative lengths of different stress syllables - for(ix=0; ix<stress_lengths_set; ix++) - { - translator->stress_lengths[ix] = stress_lengths[ix]; - } - for(ix=0; ix<stress_add_set; ix++) - { - translator->stress_lengths[ix] += stress_add[ix]; - } - for(ix=0; ix<stress_amps_set; ix++) - { - translator->stress_amps[ix] = stress_amps[ix]; - translator->stress_amps_r[ix] = stress_amps[ix] -1; - } - - return(voice); -} // end of LoadVoice - - -static char *ExtractVoiceVariantName(char *vname, int variant_num) -{//=============================================================== -// Remove any voice variant suffix (name or number) from a voice name -// Returns the voice variant name - - char *p; - static char variant_name[20]; - char variant_prefix[5]; - - variant_name[0] = 0; - sprintf(variant_prefix,"!v%c",PATHSEP); - - if(vname != NULL) - { - if((p = strchr(vname,'+')) != NULL) - { - // The voice name has a +variant suffix - *p++ = 0; // delete the suffix from the voice name - if(isdigit(*p)) - { - variant_num = atoi(p); // variant number - } - else - { - // voice variant name, not number - strcpy(variant_name,variant_prefix); - strncpy0(&variant_name[3],p,sizeof(variant_name)-3); - } - } - } - - if(variant_num > 0) - { - if(variant_num < 10) - sprintf(variant_name,"%sm%d",variant_prefix, variant_num); // male - else - sprintf(variant_name,"%sf%d",variant_prefix, variant_num-10); // female - } - - return(variant_name); -} // end of ExtractVoiceVariantName - - - -voice_t *LoadVoiceVariant(const char *vname, int variant_num) -{//========================================================== -// Load a voice file. -// Also apply a voice variant if specified by "variant", or by "+number" or "+name" in the "vname" - - voice_t *v; - char *variant_name; - char buf[60]; - - strncpy0(buf,vname,sizeof(buf)); - variant_name = ExtractVoiceVariantName(buf,variant_num); - - if((v = LoadVoice(buf,0)) == NULL) - return(NULL); - - if(variant_name[0] != 0) - { - v = LoadVoice(variant_name,2); - } - return(v); -} - - - -static int __cdecl VoiceNameSorter(const void *p1, const void *p2) -{//======================================================= - int ix; - espeak_VOICE *v1 = *(espeak_VOICE **)p1; - espeak_VOICE *v2 = *(espeak_VOICE **)p2; - - - if((ix = strcmp(&v1->languages[1],&v2->languages[1])) != 0) // primary language name - return(ix); - if((ix = v1->languages[0] - v2->languages[0]) != 0) // priority number - return(ix); - return(strcmp(v1->name,v2->name)); -} - - -static int __cdecl VoiceScoreSorter(const void *p1, const void *p2) -{//======================================================== - int ix; - espeak_VOICE *v1 = *(espeak_VOICE **)p1; - espeak_VOICE *v2 = *(espeak_VOICE **)p2; - - if((ix = v2->score - v1->score) != 0) - return(ix); - return(strcmp(v1->name,v2->name)); -} - - -static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int spec_n_parts, int spec_lang_len, espeak_VOICE *voice) -{//========================================================================================================================= - int ix; - const char *p; - int c1, c2; - int language_priority; - int n_parts; - int matching; - int matching_parts; - int score = 0; - int x; - int ratio; - int required_age; - int diff; - - p = voice->languages; // list of languages+dialects for which this voice is suitable - - if(strcmp(spec_language,"mbrola")==0) - { - // only list mbrola voices - if(memcmp(voice->identifier,"mb/",3) == 0) - return(100); - return(0); - } - - if(spec_n_parts == 0) - { - score = 100; - } - else - { - if((*p == 0) && (strcmp(spec_language,"variants")==0)) - { - // match on a voice with no languages if the required language is "variants" - score = 100; - } - - // compare the required language with each of the languages of this voice - while(*p != 0) - { - language_priority = *p++; - - matching = 1; - matching_parts = 0; - n_parts = 1; - - for(ix=0; ; ix++) - { - if((ix >= spec_lang_len) || ((c1 = spec_language[ix]) == '-')) - c1 = 0; - if((c2 = p[ix]) == '-') - c2 = 0; - - if(c1 != c2) - { - matching = 0; - } - - if(p[ix] == '-') - { - n_parts++; - if(matching) - matching_parts++; - } - if(p[ix] == 0) - break; - } - p += (ix+1); - matching_parts += matching; // number of parts which match - - if(matching_parts == 0) - continue; // no matching parts for this language - - x = 5; - // reduce the score if not all parts of the required language match - if((diff = (spec_n_parts - matching_parts)) > 0) - x -= diff; - - // reduce score if the language is more specific than required - if((diff = (n_parts - matching_parts)) > 0) - x -= diff; - - x = x*100 - (language_priority * 2); - - if(x > score) - score = x; - } - } - if(score == 0) - return(0); - - if(voice_spec->name != NULL) - { - if(strcmp(voice_spec->name,voice->name)==0) - { - // match on voice name - score += 500; - } - else - if(strcmp(voice_spec->name,voice->identifier)==0) - { - score += 400; - } - } - - if(((voice_spec->gender == 1) || (voice_spec->gender == 2)) && - ((voice->gender == 1) || (voice->gender == 2))) - { - if(voice_spec->gender == voice->gender) - score += 50; - else - score -= 50; - } - - if((voice_spec->age <= 12) && (voice->gender == 2) && (voice->age > 12)) - { - score += 5; // give some preference for non-child female voice if a child is requested - } - - if(voice->age != 0) - { - if(voice_spec->age == 0) - required_age = 30; - else - required_age = voice_spec->age; - - ratio = (required_age*100)/voice->age; - if(ratio < 100) - ratio = 10000/ratio; - ratio = (ratio - 100)/10; // 0=exact match, 10=out by factor of 2 - x = 5 - ratio; - if(x > 0) x = 0; - - score = score + x; - - if(voice_spec->age > 0) - score += 10; // required age specified, favour voices with a specified age (near it) - } - if(score < 1) - score = 1; - return(score); -} // end of ScoreVoice - - -static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int control) -{//====================================================================================== -// control: bit0=1 include mbrola voices - int ix; - int score; - int nv; // number of candidates - int n_parts=0; - int lang_len=0; - espeak_VOICE *vp; - char language[80]; - - // count number of parts in the specified language - if((voice_select->languages != NULL) && (voice_select->languages[0] != 0)) - { - n_parts = 1; - lang_len = strlen(voice_select->languages); - for(ix=0; (ix<=lang_len) && ((unsigned)ix < sizeof(language)); ix++) - { - if((language[ix] = tolower(voice_select->languages[ix])) == '-') - n_parts++; - } - } - // select those voices which match the specified language - nv = 0; - for(ix=0; ix<n_voices_list; ix++) - { - vp = voices_list[ix]; - - if(((control & 1) == 0) && (memcmp(vp->identifier,"mb/",3) == 0)) - continue; - - if((score = ScoreVoice(voice_select, language, n_parts, lang_len, voices_list[ix])) > 0) - { - voices[nv++] = vp; - vp->score = score; - } - } - voices[nv] = NULL; // list terminator - - if(nv==0) - return(0); - - // sort the selected voices by their score - qsort(voices,nv,sizeof(espeak_VOICE *),VoiceScoreSorter); - - return(nv); -} // end of SetVoiceScores - - - - -espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name) -{//===================================================================== - int ix; - int match_fname = -1; - int match_fname2 = -1; - int match_name = -1; - const char *id; - int last_part_len; - char last_part[41]; - - if(voices == NULL) - { - if(n_voices_list == 0) - espeak_ListVoices(NULL); // create the voices list - voices = voices_list; - } - - sprintf(last_part,"%c%s",PATHSEP,name); - last_part_len = strlen(last_part); - - for(ix=0; voices[ix] != NULL; ix++) - { - if(strcmp(name,voices[ix]->name)==0) - { - match_name = ix; // found matching voice name - break; - } - else - if(strcmp(name,id = voices[ix]->identifier)==0) - { - match_fname = ix; // matching identifier, use this if no matching name - } - else - if(strcmp(last_part,&id[strlen(id)-last_part_len])==0) - { - match_fname2 = ix; - } - } - - if(match_name < 0) - { - match_name = match_fname; // no matching name, try matching filename - if(match_name < 0) - match_name = match_fname2; // try matching just the last part of the filename - } - - if(match_name < 0) - return(NULL); - - return(voices[match_name]); -} // end of SelectVoiceByName - - - - -char const *SelectVoice(espeak_VOICE *voice_select, int *found) -{//============================================================ -// Returns a path within espeak-voices, with a possible +variant suffix -// variant is an output-only parameter - int nv; // number of candidates - int ix, ix2; - int j; - int n_variants; - int variant_number; - int gender; - int skip; - int aged=1; - char *variant_name; - const char *p, *p_start; - espeak_VOICE *vp = NULL; - espeak_VOICE *vp2; - espeak_VOICE voice_select2; - espeak_VOICE *voices[N_VOICES_LIST]; // list of candidates - espeak_VOICE *voices2[N_VOICES_LIST+N_VOICE_VARIANTS]; - static espeak_VOICE voice_variants[N_VOICE_VARIANTS]; - static char voice_id[50]; - - *found = 1; - memcpy(&voice_select2,voice_select,sizeof(voice_select2)); - - if(n_voices_list == 0) - espeak_ListVoices(NULL); // create the voices list - - if((voice_select2.languages == NULL) || (voice_select2.languages[0] == 0)) - { - // no language is specified. Get language from the named voice - static char buf[60]; - - if(voice_select2.name == NULL) - { - if((voice_select2.name = voice_select2.identifier) == NULL) - voice_select2.name = "default"; - } - - strncpy0(buf,voice_select2.name,sizeof(buf)); - variant_name = ExtractVoiceVariantName(buf,0); - - vp = SelectVoiceByName(voices_list,buf); - if(vp != NULL) - { - voice_select2.languages = &(vp->languages[1]); - - if((voice_select2.gender==0) && (voice_select2.age==0) && (voice_select2.variant==0)) - { - if(variant_name[0] != 0) - { - sprintf(voice_id,"%s+%s",vp->identifier,&variant_name[3]); // omit the !v/ from variant_name - return(voice_id); - } - - return(vp->identifier); - } - } - } - - // select and sort voices for the required language - nv = SetVoiceScores(&voice_select2,voices,0); - - if(nv == 0) - { - // no matching voice, choose the default - *found = 0; - if((voices[0] = SelectVoiceByName(voices_list,"default")) != NULL) - nv = 1; - } - - gender = 0; - if((voice_select2.gender == 2) || ((voice_select2.age > 0) && (voice_select2.age < 13))) - gender = 2; - else - if(voice_select2.gender == 1) - gender = 1; - -#define AGE_OLD 60 - if(voice_select2.age < AGE_OLD) - aged = 0; - - p = p_start = variant_lists[gender]; - if(aged == 0) - p++; // the first voice in the variants list is older - - // add variants for the top voices - n_variants = 0; - for(ix=0, ix2=0; ix<nv; ix++) - { - vp = voices[ix]; - // is the main voice the required gender? - skip=0; - if((gender != 0) && (vp->gender != gender)) - { - skip=1; - } - if((ix2==0) && aged && (vp->age < AGE_OLD)) - { - skip=1; - } - if(skip==0) - { - voices2[ix2++] = vp; - } - - for(j=0; (j < vp->xx1) && (n_variants < N_VOICE_VARIANTS);) - { - if((variant_number = *p) == 0) - { - p = p_start; - continue; - } - - vp2 = &voice_variants[n_variants++]; // allocate space for voice variant - memcpy(vp2,vp,sizeof(espeak_VOICE)); // copy from the original voice - vp2->variant = variant_number; - voices2[ix2++] = vp2; - p++; - j++; - } - } - // add any more variants to the end of the list - while((vp != NULL) && ((variant_number = *p++) != 0) && (n_variants < N_VOICE_VARIANTS)) - { - vp2 = &voice_variants[n_variants++]; // allocate space for voice variant - memcpy(vp2,vp,sizeof(espeak_VOICE)); // copy from the original voice - vp2->variant = variant_number; - voices2[ix2++] = vp2; - } - - // index the sorted list by the required variant number - vp = voices2[voice_select2.variant % ix2]; - - if(vp->variant != 0) - { - variant_name = ExtractVoiceVariantName(NULL,vp->variant); - sprintf(voice_id,"%s+%s",vp->identifier,&variant_name[3]); - return(voice_id); - } - - return(vp->identifier); -} // end of SelectVoice - - - -static void GetVoices(const char *path) -{//==================================== - FILE *f_voice; - espeak_VOICE *voice_data; - int ftype; - char fname[sizeof(path_home)+100]; - -#ifdef PLATFORM_RISCOS - int len; - int *type; - char *p; - _kernel_swi_regs regs; - _kernel_oserror *error; - char buf[80]; - char directory2[sizeof(path_home)+100]; - - regs.r[0] = 10; - regs.r[1] = (int)path; - regs.r[2] = (int)buf; - regs.r[3] = 1; - regs.r[4] = 0; - regs.r[5] = sizeof(buf); - regs.r[6] = 0; - - while(regs.r[3] > 0) - { - error = _kernel_swi(0x0c+0x20000,®s,®s); /* OS_GBPB 10, read directory entries */ - if((error != NULL) || (regs.r[3] == 0)) - { - break; - } - type = (int *)(&buf[16]); - len = strlen(&buf[20]); - sprintf(fname,"%s.%s",path,&buf[20]); - - if(*type == 2) - { - // a sub-directory - GetVoices(fname); - } - else - { - // a regular line, add it to the voices list - if((f_voice = fopen(fname,"r")) == NULL) - continue; - - // pass voice file name within the voices directory - voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, &buf[20]); - fclose(f_voice); - - if(voice_data != NULL) - { - voices_list[n_voices_list++] = voice_data; - } - } - } -#else -#ifdef PLATFORM_WINDOWS - WIN32_FIND_DATAA FindFileData; - HANDLE hFind = INVALID_HANDLE_VALUE; - -#undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string - sprintf(fname,"%s\\*",path); - hFind = FindFirstFileA(fname, &FindFileData); - if(hFind == INVALID_HANDLE_VALUE) - return; - - do { - sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName); - - ftype = GetFileLength(fname); - - if((ftype == -2) && (FindFileData.cFileName[0] != '.')) - { - // a sub-sirectory - GetVoices(fname); - } - else - if(ftype > 0) - { - // a regular line, add it to the voices list - if((f_voice = fopen(fname,"r")) == NULL) - continue; - - // pass voice file name within the voices directory - voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName); - fclose(f_voice); - - if(voice_data != NULL) - { - voices_list[n_voices_list++] = voice_data; - } - } - } while(FindNextFileA(hFind, &FindFileData) != 0); - FindClose(hFind); - -#else - DIR *dir; - struct dirent *ent; - - if((dir = opendir((char *)path)) == NULL) // note: (char *) is needed for WINCE - return; - - while((ent = readdir(dir)) != NULL) - { - if(n_voices_list >= (N_VOICES_LIST-2)) - break; // voices list is full - - sprintf(fname,"%s%c%s",path,PATHSEP,ent->d_name); - - ftype = GetFileLength(fname); - - if((ftype == -2) && (ent->d_name[0] != '.')) - { - // a sub-sirectory - GetVoices(fname); - } - else - if(ftype > 0) - { - // a regular line, add it to the voices list - if((f_voice = fopen(fname,"r")) == NULL) - continue; - - // pass voice file name within the voices directory - voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, ent->d_name); - fclose(f_voice); - - if(voice_data != NULL) - { - voices_list[n_voices_list++] = voice_data; - } - } - } - closedir(dir); -#endif -#endif -} // end of GetVoices - - - -espeak_ERROR SetVoiceByName(const char *name) -{//========================================= - espeak_VOICE *v; - espeak_VOICE voice_selector; - char *variant_name; - static char buf[60]; - - strncpy0(buf,name,sizeof(buf)); - variant_name = ExtractVoiceVariantName(buf,0); - - memset(&voice_selector,0,sizeof(voice_selector)); -// voice_selector.name = buf; - voice_selector.name = (char *)name; // include variant name in voice stack ?? - - // first check for a voice with this filename - // This may avoid the need to call espeak_ListVoices(). - - if(LoadVoice(buf,1) != NULL) - { - if(variant_name[0] != 0) - { - LoadVoice(variant_name,2); - } - - DoVoiceChange(voice); - SetVoiceStack(&voice_selector); - return(EE_OK); - } - - if(n_voices_list == 0) - espeak_ListVoices(NULL); // create the voices list - - if((v = SelectVoiceByName(voices_list,buf)) != NULL) - { - if(LoadVoice(v->identifier,0) != NULL) - { - if(variant_name[0] != 0) - { - LoadVoice(variant_name,2); - } - DoVoiceChange(voice); - SetVoiceStack(&voice_selector); - return(EE_OK); - } - } - return(EE_INTERNAL_ERROR); // voice name not found -} // end of SetVoiceByName - - - -espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector) -{//============================================================ - const char *voice_id; - int voice_found; - - voice_id = SelectVoice(voice_selector, &voice_found); - - if(voice_found == 0) - return(EE_NOT_FOUND); - - LoadVoiceVariant(voice_id,0); - DoVoiceChange(voice); - SetVoiceStack(voice_selector); - - return(EE_OK); -} // end of SetVoiceByProperties - - - - -//======================================================================= -// Library Interface Functions -//======================================================================= -#pragma GCC visibility push(default) - - -const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) -{//======================================================================== -#ifndef PLATFORM_RISCOS - int ix; - int j; - espeak_VOICE *v; - static espeak_VOICE *voices[N_VOICES_LIST]; - char path_voices[sizeof(path_home)+12]; - - // free previous voice list data - - for(ix=0; ix<n_voices_list; ix++) - { - if(voices_list[ix] != NULL) - free(voices_list[ix]); - } - n_voices_list = 0; - - sprintf(path_voices,"%s%cvoices",path_home,PATHSEP); - len_path_voices = strlen(path_voices)+1; - - GetVoices(path_voices); - voices_list[n_voices_list] = NULL; // voices list terminator - - // sort the voices list - qsort(voices_list,n_voices_list,sizeof(espeak_VOICE *),VoiceNameSorter); - - - if(voice_spec) - { - // select the voices which match the voice_spec, and sort them by preference - SetVoiceScores(voice_spec,voices,1); - } - else - { - // list all: omit variant voices and mbrola voices - j = 0; - for(ix=0; (v = voices_list[ix]) != NULL; ix++) - { - if((v->languages[0] != 0) && (strcmp(&v->languages[1],"variant") != 0) && (memcmp(v->identifier,"mb/",3) != 0)) - { - voices[j++] = v; - } - } - voices[j] = NULL; - } - return((const espeak_VOICE **)voices); -#endif - return((const espeak_VOICE **)voices_list); -} // end of espeak_ListVoices - - - -espeak_VOICE *espeak_GetCurrentVoice(void) -{//================================================== - return(&voice_selected); -} - -#pragma GCC visibility pop - - diff --git a/navit/support/espeak/wave.c b/navit/support/espeak/wave.c deleted file mode 100755 index 364dcf577..000000000 --- a/navit/support/espeak/wave.c +++ /dev/null @@ -1,1112 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007, Gilles Casse <gcasse@oralux.org> * - * based on AudioIO.cc (Audacity-1.2.4b) and wavegen.cpp * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "speech.h" - -#ifdef USE_ASYNC -// This source file is only used for asynchronious modes - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> -#include <assert.h> -#include <sys/time.h> -#include <time.h> - -#include "portaudio.h" -#ifndef PLATFORM_WINDOWS -#include <unistd.h> -#endif -#include "wave.h" -#include "debug.h" - -//<Definitions - -enum {ONE_BILLION=1000000000}; - -#ifdef USE_PORTAUDIO - -#undef USE_PORTAUDIO -// determine portaudio version by looking for a #define which is not in V18 -#ifdef paNeverDropInput -#define USE_PORTAUDIO 19 -#else -#define USE_PORTAUDIO 18 -#endif - - -static t_wave_callback* my_callback_is_output_enabled=NULL; - -#define N_WAV_BUF 10 -#define SAMPLE_RATE 22050 -#define FRAMES_PER_BUFFER 512 -#define BUFFER_LENGTH (SAMPLE_RATE*2*sizeof(uint16_t)) -#define THRESHOLD (BUFFER_LENGTH/5) -static char myBuffer[BUFFER_LENGTH]; -static char* myRead=NULL; -static char* myWrite=NULL; -static int out_channels=1; -static int my_stream_could_start=0; - -static int mInCallbackFinishedState = false; -#if (USE_PORTAUDIO == 18) -static PortAudioStream *pa_stream=NULL; -#endif -#if (USE_PORTAUDIO == 19) -static struct PaStreamParameters myOutputParameters; -static PaStream *pa_stream=NULL; -#endif - -static int userdata[4]; -static PaError pa_init_err=0; - -// time measurement -// The read and write position audio stream in the audio stream are measured in ms. -// -// * When the stream is opened, myReadPosition and myWritePosition are cleared. -// * myWritePosition is updated in wave_write. -// * myReadPosition is updated in pa_callback (+ sample delay). - -static uint32_t myReadPosition = 0; // in ms -static uint32_t myWritePosition = 0; - -//> -//<init_buffer, get_used_mem - -static void init_buffer() -{ - myWrite = myBuffer; - myRead = myBuffer; - memset(myBuffer,0,BUFFER_LENGTH); - myReadPosition = myWritePosition = 0; - SHOW("init_buffer > myRead=0x%x, myWrite=0x%x, BUFFER_LENGTH=0x%x, myReadPosition = myWritePosition = 0\n", (int)myRead, (int)myWrite, BUFFER_LENGTH); -} - -static unsigned int get_used_mem() -{ - char* aRead = myRead; - char* aWrite = myWrite; - unsigned int used = 0; - - assert ((aRead >= myBuffer) - && (aRead <= myBuffer + BUFFER_LENGTH) - && (aWrite >= myBuffer) - && (aWrite <= myBuffer + BUFFER_LENGTH)); - - if (aRead < aWrite) - { - used = aWrite - aRead; - } - else - { - used = aWrite + BUFFER_LENGTH - aRead; - } - SHOW("get_used_mem > %d\n", used); - - return used; -} - -//> -//<start stream - -static void start_stream() -{ - PaError err; - SHOW_TIME("start_stream"); - - my_stream_could_start=0; - mInCallbackFinishedState = false; - - err = Pa_StartStream(pa_stream); - SHOW("start_stream > Pa_StartStream=%d (%s)\n", err, Pa_GetErrorText(err)); - -#if USE_PORTAUDIO == 19 - if(err == paStreamIsNotStopped) - { - SHOW_TIME("start_stream > restart stream (begin)"); - // not sure why we need this, but PA v19 seems to need it - err = Pa_StopStream(pa_stream); - SHOW("start_stream > Pa_StopStream=%d (%s)\n", err, Pa_GetErrorText(err)); - err = Pa_StartStream(pa_stream); - SHOW("start_stream > Pa_StartStream=%d (%s)\n", err, Pa_GetErrorText(err)); - SHOW_TIME("start_stream > restart stream (end)"); - } -#endif -} - -//> -//<pa_callback - -/* This routine will be called by the PortAudio engine when audio is needed. -** It may called at interrupt level on some machines so don't do anything -** that could mess up the system like calling malloc() or free(). -*/ -#if USE_PORTAUDIO == 18 -static int pa_callback(void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, PaTimestamp outTime, void *userData ) -#else - static int pa_callback(const void *inputBuffer, void *outputBuffer, - long unsigned int framesPerBuffer, const PaStreamCallbackTimeInfo *outTime, - PaStreamCallbackFlags flags, void *userData ) -#endif -{ - int aResult=0; // paContinue - char* aWrite = myWrite; - size_t n = out_channels*sizeof(uint16_t)*framesPerBuffer; - - myReadPosition += framesPerBuffer; - SHOW("pa_callback > myReadPosition=%u, framesPerBuffer=%lu (n=0x%x) \n",(int)myReadPosition, framesPerBuffer, n); - - if (aWrite >= myRead) - { - if((size_t)(aWrite - myRead) >= n) - { - memcpy(outputBuffer, myRead, n); - myRead += n; - } - else - { - SHOW_TIME("pa_callback > underflow"); - aResult=1; // paComplete; - mInCallbackFinishedState = true; - size_t aUsedMem=0; - aUsedMem = (size_t)(aWrite - myRead); - if (aUsedMem) - { - memcpy(outputBuffer, myRead, aUsedMem); - } - char* p = (char*)outputBuffer + aUsedMem; - memset(p, 0, n - aUsedMem); - // myReadPosition += aUsedMem/(out_channels*sizeof(uint16_t)); - myRead = aWrite; - } - } - else // myRead > aWrite - { - if ((size_t)(myBuffer + BUFFER_LENGTH - myRead) >= n) - { - memcpy(outputBuffer, myRead, n); - myRead += n; - } - else if ((size_t)(aWrite + BUFFER_LENGTH - myRead) >= n) - { - int aTopMem = myBuffer + BUFFER_LENGTH - myRead; - if (aTopMem) - { - SHOW("pa_callback > myRead=0x%x, aTopMem=0x%x\n",(int)myRead, (int)aTopMem); - memcpy(outputBuffer, myRead, aTopMem); - } - int aRest = n - aTopMem; - if (aRest) - { - SHOW("pa_callback > myRead=0x%x, aRest=0x%x\n",(int)myRead, (int)aRest); - char* p = (char*)outputBuffer + aTopMem; - memcpy(p, myBuffer, aRest); - } - myRead = myBuffer + aRest; - } - else - { - SHOW_TIME("pa_callback > underflow"); - aResult=1; // paComplete; - - int aTopMem = myBuffer + BUFFER_LENGTH - myRead; - if (aTopMem) - { - SHOW("pa_callback > myRead=0x%x, aTopMem=0x%x\n",(int)myRead, (int)aTopMem); - memcpy(outputBuffer, myRead, aTopMem); - } - int aRest = aWrite - myBuffer; - if (aRest) - { - SHOW("pa_callback > myRead=0x%x, aRest=0x%x\n",(int)myRead, (int)aRest); - char* p = (char*)outputBuffer + aTopMem; - memcpy(p, myBuffer, aRest); - } - - size_t aUsedMem = aTopMem + aRest; - char* p = (char*)outputBuffer + aUsedMem; - memset(p, 0, n - aUsedMem); - // myReadPosition += aUsedMem/(out_channels*sizeof(uint16_t)); - myRead = aWrite; - } - } - - SHOW("pa_callback > myRead=%x\n",(int)myRead); - - - // #if USE_PORTAUDIO == 18 - // if(aBufferEmpty) - // { - // static int end_timer = 0; - // if(end_timer == 0) - // end_timer = 4; - // if(end_timer > 0) - // { - // end_timer--; - // if(end_timer == 0) - // return(1); - // } - // } - // return(0); - // #else - -#ifdef ARCH_BIG - { - // BIG-ENDIAN, swap the order of bytes in each sound sample in the portaudio buffer - int c; - unsigned char *out_ptr; - unsigned char *out_end; - out_ptr = (unsigned char *)outputBuffer; - out_end = out_ptr + framesPerBuffer*2 * out_channels; - while(out_ptr < out_end) - { - c = out_ptr[0]; - out_ptr[0] = out_ptr[1]; - out_ptr[1] = c; - out_ptr += 2; - } - } -#endif - - - return(aResult); - //#endif - -} // end of WaveCallBack - -//> - - -void wave_flush(void* theHandler) -{ - ENTER("wave_flush"); - - if (my_stream_could_start) - { -// #define buf 1024 -// static char a_buffer[buf*2]; -// memset(a_buffer,0,buf*2); -// wave_write(theHandler, a_buffer, buf*2); - start_stream(); - } -} - -//<wave_open_sound - -static int wave_open_sound() -{ - ENTER("wave_open_sound"); - - PaError err=paNoError; - PaError active; - -#if USE_PORTAUDIO == 18 - active = Pa_StreamActive(pa_stream); -#else - active = Pa_IsStreamActive(pa_stream); -#endif - - if(active == 1) - { - SHOW_TIME("wave_open_sound > already active"); - return(0); - } - if(active < 0) - { - out_channels = 1; - -#if USE_PORTAUDIO == 18 - // err = Pa_OpenDefaultStream(&pa_stream,0,1,paInt16,SAMPLE_RATE,FRAMES_PER_BUFFER,N_WAV_BUF,pa_callback,(void *)userdata); - - PaDeviceID playbackDevice = Pa_GetDefaultOutputDeviceID(); - - PaError err = Pa_OpenStream( &pa_stream, - /* capture parameters */ - paNoDevice, - 0, - paInt16, - NULL, - /* playback parameters */ - playbackDevice, - out_channels, - paInt16, - NULL, - /* general parameters */ - SAMPLE_RATE, FRAMES_PER_BUFFER, 0, - //paClipOff | paDitherOff, - paNoFlag, - pa_callback, (void *)userdata); - - SHOW("wave_open_sound > Pa_OpenDefaultStream(1): err=%d (%s)\n",err, Pa_GetErrorText(err)); - - if(err == paInvalidChannelCount) - { - SHOW_TIME("wave_open_sound > try stereo"); - // failed to open with mono, try stereo - out_channels = 2; - // myOutputParameters.channelCount = out_channels; - PaError err = Pa_OpenStream( &pa_stream, - /* capture parameters */ - paNoDevice, - 0, - paInt16, - NULL, - /* playback parameters */ - playbackDevice, - out_channels, - paInt16, - NULL, - /* general parameters */ - SAMPLE_RATE, FRAMES_PER_BUFFER, 0, - //paClipOff | paDitherOff, - paNoFlag, - pa_callback, (void *)userdata); -// err = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16, -// SAMPLE_RATE, -// FRAMES_PER_BUFFER, -// N_WAV_BUF,pa_callback,(void *)userdata); - SHOW("wave_open_sound > Pa_OpenDefaultStream(2): err=%d (%s)\n",err, Pa_GetErrorText(err)); - err=0; // avoid warning - } - mInCallbackFinishedState = false; // v18 only -#else - myOutputParameters.channelCount = out_channels; - unsigned long framesPerBuffer = paFramesPerBufferUnspecified; - err = Pa_OpenStream( - &pa_stream, - NULL, /* no input */ - &myOutputParameters, - SAMPLE_RATE, - framesPerBuffer, - paNoFlag, - // paClipOff | paDitherOff, - pa_callback, - (void *)userdata); - if ((err!=paNoError) - && (err!=paInvalidChannelCount)) //err==paUnanticipatedHostError - { - fprintf(stderr, "wave_open_sound > Pa_OpenStream : err=%d (%s)\n",err,Pa_GetErrorText(err)); - framesPerBuffer = FRAMES_PER_BUFFER; - err = Pa_OpenStream( - &pa_stream, - NULL, /* no input */ - &myOutputParameters, - SAMPLE_RATE, - framesPerBuffer, - paNoFlag, - // paClipOff | paDitherOff, - pa_callback, - (void *)userdata); - } - if(err == paInvalidChannelCount) - { - SHOW_TIME("wave_open_sound > try stereo"); - // failed to open with mono, try stereo - out_channels = 2; - myOutputParameters.channelCount = out_channels; - err = Pa_OpenStream( - &pa_stream, - NULL, /* no input */ - &myOutputParameters, - SAMPLE_RATE, - framesPerBuffer, - paNoFlag, - // paClipOff | paDitherOff, - pa_callback, - (void *)userdata); - - // err = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,(double)SAMPLE_RATE,FRAMES_PER_BUFFER,pa_callback,(void *)userdata); - } - mInCallbackFinishedState = false; -#endif - } - - SHOW("wave_open_sound > %s\n","LEAVE"); - - return (err != paNoError); -} - -//> -//<select_device - -#if (USE_PORTAUDIO == 19) -static void update_output_parameters(int selectedDevice, const PaDeviceInfo *deviceInfo) -{ - // const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i); - myOutputParameters.device = selectedDevice; - // myOutputParameters.channelCount = pdi->maxOutputChannels; - myOutputParameters.channelCount = 1; - myOutputParameters.sampleFormat = paInt16; - - // Latency greater than 100ms for avoiding glitches - // (e.g. when moving a window in a graphical desktop) - // deviceInfo = Pa_GetDeviceInfo(selectedDevice); - if (deviceInfo) - { - double aLatency = deviceInfo->defaultLowOutputLatency; - double aCoeff = round(0.100 / aLatency); -// myOutputParameters.suggestedLatency = aCoeff * aLatency; // to avoid glitches ? - myOutputParameters.suggestedLatency = aLatency; // for faster response ? - SHOW("Device=%d, myOutputParameters.suggestedLatency=%f, aCoeff=%f\n", - selectedDevice, - myOutputParameters.suggestedLatency, - aCoeff); - } - else - { - myOutputParameters.suggestedLatency = (double)0.1; // 100ms - SHOW("Device=%d, myOutputParameters.suggestedLatency=%f (default)\n", - selectedDevice, - myOutputParameters.suggestedLatency); - } - //pdi->defaultLowOutputLatency; - - myOutputParameters.hostApiSpecificStreamInfo = NULL; -} -#endif - -static void select_device(const char* the_api) -{ - ENTER("select_device"); - -#if (USE_PORTAUDIO == 19) - int numDevices = Pa_GetDeviceCount(); - if( numDevices < 0 ) - { - SHOW( "ERROR: Pa_CountDevices returned 0x%x\n", numDevices ); - assert(0); - } - - PaDeviceIndex i=0, selectedIndex=0, defaultAlsaIndex=numDevices; - const PaDeviceInfo *deviceInfo=NULL; - const PaDeviceInfo *selectedDeviceInfo=NULL; - - if(option_device_number >= 0) - { - selectedIndex = option_device_number; - selectedDeviceInfo = Pa_GetDeviceInfo(selectedIndex); - } - - if(selectedDeviceInfo == NULL) - { - for( i=0; i<numDevices; i++ ) - { - deviceInfo = Pa_GetDeviceInfo( i ); - - if (deviceInfo == NULL) - { - break; - } - const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); - - if (hostInfo && hostInfo->type == paALSA) - { - // Check (once) the default output device - if (defaultAlsaIndex == numDevices) - { - defaultAlsaIndex = hostInfo->defaultOutputDevice; - const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo( defaultAlsaIndex ); - update_output_parameters(defaultAlsaIndex, deviceInfo); - if (Pa_IsFormatSupported(NULL, &myOutputParameters, SAMPLE_RATE) == 0) - { - SHOW( "select_device > ALSA (default), name=%s (#%d)\n", deviceInfo->name, defaultAlsaIndex); - selectedIndex = defaultAlsaIndex; - selectedDeviceInfo = deviceInfo; - break; - } - } - - // if the default output device does not match, - // look for the device with the highest number of output channels - SHOW( "select_device > ALSA, i=%d (numDevices=%d)\n", i, numDevices); - - update_output_parameters(i, deviceInfo); - - if (Pa_IsFormatSupported(NULL, &myOutputParameters, SAMPLE_RATE) == 0) - { - SHOW( "select_device > ALSA, name=%s (#%d)\n", deviceInfo->name, i); - - if (!selectedDeviceInfo - || (selectedDeviceInfo->maxOutputChannels < deviceInfo->maxOutputChannels)) - { - selectedIndex = i; - selectedDeviceInfo = deviceInfo; - } - } - } - } - } - - if (selectedDeviceInfo) - { - update_output_parameters(selectedIndex, selectedDeviceInfo); - } - else - { - i = Pa_GetDefaultOutputDevice(); - deviceInfo = Pa_GetDeviceInfo( i ); - update_output_parameters(i, deviceInfo); - } - -#endif -} - -//> - - -// int wave_Close(void* theHandler) -// { -// SHOW_TIME("WaveCloseSound"); - -// // PaError active; - -// // check whether speaking has finished, and close the stream -// if(pa_stream != NULL) -// { -// Pa_CloseStream(pa_stream); -// pa_stream = NULL; -// init_buffer(); - -// // #if USE_PORTAUDIO == 18 -// // active = Pa_StreamActive(pa_stream); -// // #else -// // active = Pa_IsStreamActive(pa_stream); -// // #endif -// // if(active == 0) -// // { -// // SHOW_TIME("WaveCloseSound > ok, not active"); -// // Pa_CloseStream(pa_stream); -// // pa_stream = NULL; -// // return(1); -// // } -// } -// return(0); -// } - -//<wave_set_callback_is_output_enabled - -void wave_set_callback_is_output_enabled(t_wave_callback* cb) -{ - my_callback_is_output_enabled = cb; -} - -//> -//<wave_init - -// TBD: the arg could be "alsa", "oss",... -void wave_init() -{ - ENTER("wave_init"); - PaError err; - - pa_stream = NULL; - mInCallbackFinishedState = false; - init_buffer(); - - // PortAudio sound output library - err = Pa_Initialize(); - pa_init_err = err; - if(err != paNoError) - { - SHOW_TIME("wave_init > Failed to initialise the PortAudio sound"); - } -} - -//> -//<wave_open - -void* wave_open(const char* the_api) -{ - ENTER("wave_open"); - static int once=0; - - // TBD: the_api (e.g. "alsa") is not used at the moment - // select_device is called once - if (!once) - { - select_device("alsa"); - once=1; - } - return((void*)1); -} - -//> -//<copyBuffer - - -static size_t copyBuffer(char* dest, char* src, const size_t theSizeInBytes) -{ - size_t bytes_written = 0; - unsigned int i = 0; - uint16_t* a_dest = NULL; - uint16_t* a_src = NULL; - - if ((src != NULL) && dest != NULL) - { - // copy for one channel (mono)? - if(out_channels==1) - { - SHOW("copyBuffer > 1 channel > memcpy %x (%d bytes)\n", (int)myWrite, theSizeInBytes); - memcpy(dest, src, theSizeInBytes); - bytes_written = theSizeInBytes; - } - else // copy for 2 channels (stereo) - { - SHOW("copyBuffer > 2 channels > memcpy %x (%d bytes)\n", (int)myWrite, theSizeInBytes); - i = 0; - a_dest = (uint16_t* )dest; - a_src = (uint16_t* )src; - - for(i=0; i<theSizeInBytes/2; i++) - { - a_dest[2*i] = a_src[i]; - a_dest[2*i+1] = a_src[i]; - } - bytes_written = 2*theSizeInBytes; - } // end if(out_channels==1) - } // end if ((src != NULL) && dest != NULL) - - return bytes_written; -} - -//> -//<wave_write - -size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) -{ - ENTER("wave_write"); - size_t bytes_written = 0; - // space in ringbuffer for the sample needed: 1x mono channel but 2x for 1 stereo channel - size_t bytes_to_write = (out_channels==1) ? theSize : theSize*2; - my_stream_could_start = 0; - - if(pa_stream == NULL) - { - SHOW_TIME("wave_write > wave_open_sound\n"); - if (0 != wave_open_sound()) - { - SHOW_TIME("wave_write > wave_open_sound fails!"); - return 0; - } - my_stream_could_start=1; - } - else if (!wave_is_busy(NULL)) - { - my_stream_could_start = 1; - } - assert(BUFFER_LENGTH >= bytes_to_write); - - if (myWrite >= myBuffer + BUFFER_LENGTH) - { - myWrite = myBuffer; - } // end if (myWrite >= myBuffer + BUFFER_LENGTH) - - size_t aTotalFreeMem=0; - char* aRead = myRead; - SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite); - - while (1) - { - if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) - { - SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); - return 0; - } - - aRead = myRead; - - // write pointer is before read pointer? - if (myWrite >= aRead) - { - aTotalFreeMem = aRead + BUFFER_LENGTH - myWrite; - } - else // read pointer is before write pointer! - { - aTotalFreeMem = aRead - myWrite; - } // end if (myWrite >= aRead) - - if (aTotalFreeMem>1) - { - // -1 because myWrite must be different of aRead - // otherwise buffer would be considered as empty - aTotalFreeMem -= 1; - } // end if (aTotalFreeMem>1) - - if (aTotalFreeMem >= bytes_to_write) - { - break; - } // end if (aTotalFreeMem >= bytes_to_write) - - //SHOW_TIME("wave_write > wait"); - SHOW("wave_write > wait: aTotalFreeMem=%d\n", aTotalFreeMem); - SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite); - usleep(10000); - } // end while (1) - - aRead = myRead; - - // write pointer is ahead the read pointer? - if (myWrite >= aRead) - { - SHOW_TIME("wave_write > myWrite >= aRead"); - // determine remaining free memory to the end of the ringbuffer - size_t aFreeMem = myBuffer + BUFFER_LENGTH - myWrite; - // is enough linear space available (regardless 1 or 2 channels)? - if (aFreeMem >= bytes_to_write) - { - // copy direct - no wrap around at end of ringbuffer needed - myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize); - } - else // not enough linear space available - { - // 2 channels (stereo)? - if (out_channels == 2) - { - // copy with wrap around at the end of ringbuffer - copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem/2); - myWrite = myBuffer; - myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem/2, theSize - aFreeMem/2); - } - else // 1 channel (mono) - { - // copy with wrap around at the end of ringbuffer - copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem); - myWrite = myBuffer; - myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem, theSize - aFreeMem); - } // end if (out_channels == 2) - } // end if (aFreeMem >= bytes_to_write) - } // if (myWrite >= aRead) - else // read pointer is ahead the write pointer - { - SHOW_TIME("wave_write > myWrite <= aRead"); - myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize); - } // end if (myWrite >= aRead) - - bytes_written = bytes_to_write; - myWritePosition += theSize/sizeof(uint16_t); // add number of samples - - if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER)) - { - start_stream(); - } // end if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER)) - - SHOW_TIME("wave_write > LEAVE"); - - return bytes_written; -} - -//> -//<wave_close - -int wave_close(void* theHandler) -{ - SHOW_TIME("wave_close > ENTER"); - - static int aStopStreamCount = 0; - -#if (USE_PORTAUDIO == 19) - if( pa_stream == NULL ) - { - SHOW_TIME("wave_close > LEAVE (NULL stream)"); - return 0; - } - - if( Pa_IsStreamStopped( pa_stream ) ) - { - SHOW_TIME("wave_close > LEAVE (stopped)"); - return 0; - } -#else - if( pa_stream == NULL ) - { - SHOW_TIME("wave_close > LEAVE (NULL stream)"); - return 0; - } - - if( Pa_StreamActive( pa_stream ) == false && mInCallbackFinishedState == false ) - { - SHOW_TIME("wave_close > LEAVE (not active)"); - return 0; - } -#endif - - // Avoid race condition by making sure this function only - // gets called once at a time - aStopStreamCount++; - if (aStopStreamCount != 1) - { - SHOW_TIME("wave_close > LEAVE (stopStreamCount)"); - return 0; - } - - // Comment from Audacity-1.2.4b adapted to the eSpeak context. - // - // We got here in one of two ways: - // - // 1. The calling program calls the espeak_Cancel function and we - // therefore want to stop as quickly as possible. - // So we use AbortStream(). If this is - // the case the portaudio stream is still in the Running state - // (see PortAudio state machine docs). - // - // 2. The callback told PortAudio to stop the stream since it had - // reached the end of the selection. - // The event polling thread discovered this by noticing that - // wave_is_busy() returned false. - // wave_is_busy() (which calls Pa_GetStreamActive()) will not return - // false until all buffers have finished playing, so we can call - // AbortStream without losing any samples. If this is the case - // we are in the "callback finished state" (see PortAudio state - // machine docs). - // - // The moral of the story: We can call AbortStream safely, without - // losing samples. - // - // DMM: This doesn't seem to be true; it seems to be necessary to - // call StopStream if the callback brought us here, and AbortStream - // if the user brought us here. - // - -#if (USE_PORTAUDIO == 19) - if (pa_stream) - { - Pa_AbortStream( pa_stream ); - SHOW_TIME("wave_close > Pa_AbortStream (end)"); - - Pa_CloseStream( pa_stream ); - SHOW_TIME("wave_close > Pa_CloseStream (end)"); - pa_stream = NULL; - mInCallbackFinishedState = false; - } -#else - if (pa_stream) - { - if (mInCallbackFinishedState) - { - Pa_StopStream( pa_stream ); - SHOW_TIME("wave_close > Pa_StopStream (end)"); - } - else - { - Pa_AbortStream( pa_stream ); - SHOW_TIME("wave_close > Pa_AbortStream (end)"); - } - Pa_CloseStream( pa_stream ); - SHOW_TIME("wave_close > Pa_CloseStream (end)"); - - pa_stream = NULL; - mInCallbackFinishedState = false; - } -#endif - init_buffer(); - - aStopStreamCount = 0; // last action - SHOW_TIME("wave_close > LEAVE"); - return 0; -} - -// int wave_close(void* theHandler) -// { -// ENTER("wave_close"); - -// if(pa_stream != NULL) -// { -// PaError err = Pa_AbortStream(pa_stream); -// SHOW_TIME("wave_close > Pa_AbortStream (end)"); -// SHOW("wave_close Pa_AbortStream > err=%d\n",err); -// while(1) -// { -// PaError active; -// #if USE_PORTAUDIO == 18 -// active = Pa_StreamActive(pa_stream); -// #else -// active = Pa_IsStreamActive(pa_stream); -// #endif -// if (active != 1) -// { -// break; -// } -// SHOW("wave_close > active=%d\n",err); -// usleep(10000); /* sleep until playback has finished */ -// } -// err = Pa_CloseStream( pa_stream ); -// SHOW_TIME("wave_close > Pa_CloseStream (end)"); -// SHOW("wave_close Pa_CloseStream > err=%d\n",err); -// pa_stream = NULL; -// init_buffer(); -// } -// return 0; -// } - -//> -//<wave_is_busy - -int wave_is_busy(void* theHandler) -{ - PaError active=0; - - SHOW_TIME("wave_is_busy"); - - if (pa_stream) - { -#if USE_PORTAUDIO == 18 - active = Pa_StreamActive(pa_stream) - && (mInCallbackFinishedState == false); -#else - active = Pa_IsStreamActive(pa_stream) - && (mInCallbackFinishedState == false); -#endif - } - - SHOW("wave_is_busy: %d\n",active); - - - return (active==1); -} - -//> -//<wave_terminate - -void wave_terminate() -{ - ENTER("wave_terminate"); - - Pa_Terminate(); - -} - -//> -//<wave_get_read_position, wave_get_write_position, wave_get_remaining_time - -uint32_t wave_get_read_position(void* theHandler) -{ - SHOW("wave_get_read_position > myReadPosition=%u\n", myReadPosition); - return myReadPosition; -} - -uint32_t wave_get_write_position(void* theHandler) -{ - SHOW("wave_get_write_position > myWritePosition=%u\n", myWritePosition); - return myWritePosition; -} - -int wave_get_remaining_time(uint32_t sample, uint32_t* time) -{ - double a_time=0; - - if (!time || !pa_stream) - { - SHOW("event get_remaining_time> %s\n","audio device not available"); - return -1; - } - - if (sample > myReadPosition) - { - // TBD: take in account time suplied by portaudio V18 API - a_time = sample - myReadPosition; - a_time = 0.5 + (a_time * 1000.0) / SAMPLE_RATE; - } - else - { - a_time = 0; - } - - SHOW("wave_get_remaining_time > sample=%d, time=%d\n", sample, (uint32_t)a_time); - - *time = (uint32_t)a_time; - - return 0; -} - -//> -//<wave_test_get_write_buffer - -void *wave_test_get_write_buffer() -{ - return myWrite; -} - - -#else -// notdef USE_PORTAUDIO - - -void wave_init() {} -void* wave_open(const char* the_api) {return (void *)1;} -size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {return theSize;} -int wave_close(void* theHandler) {return 0;} -int wave_is_busy(void* theHandler) {return 0;} -void wave_terminate() {} -uint32_t wave_get_read_position(void* theHandler) {return 0;} -uint32_t wave_get_write_position(void* theHandler) {return 0;} -void wave_flush(void* theHandler) {} -typedef int (t_wave_callback)(void); -void wave_set_callback_is_output_enabled(t_wave_callback* cb) {} -extern void* wave_test_get_write_buffer() {return NULL;} - -int wave_get_remaining_time(uint32_t sample, uint32_t* time) -{ - if (!time) return(-1); - *time = (uint32_t)0; - return 0; -} - -#endif // of USE_PORTAUDIO - -//> -//<clock_gettime2, add_time_in_ms - -void clock_gettime2(struct timespec *ts) -{ - struct timeval tv; - - if (!ts) - { - return; - } - - assert (gettimeofday(&tv, NULL) != -1); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec*1000; -} - -void add_time_in_ms(struct timespec *ts, int time_in_ms) -{ - if (!ts) - { - return; - } - - uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms; - while(t_ns >= ONE_BILLION) - { - SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns); - ts->tv_sec += 1; - t_ns -= ONE_BILLION; - } - ts->tv_nsec = (long int)t_ns; -} - - -#endif // USE_ASYNC - -//> diff --git a/navit/support/espeak/wave.h b/navit/support/espeak/wave.h deleted file mode 100644 index de8bf1ef8..000000000 --- a/navit/support/espeak/wave.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef WAVE_H -#define WAVE_H - -#ifdef _MSC_VER - -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int32 uint64_t; - -#else -#ifndef PLATFORM_DOS -#include "stdint.h" -#endif -#endif - -extern int option_device_number; - -extern void wave_init(); -// TBD: the arg could be "alsa", "oss",... -extern void* wave_open(const char* the_api); - -extern size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize); -extern int wave_close(void* theHandler); -extern void wave_flush(void* theHandler); -extern int wave_is_busy(void* theHandler); -extern void wave_terminate(); -extern uint32_t wave_get_read_position(void* theHandler); -extern uint32_t wave_get_write_position(void* theHandler); - -// Supply the remaining time in ms before the sample is played -// (or 0 if the event has been already played). -// sample: sample identifier -// time: supplied value in ms -// -// return 0 if ok or -1 otherwise (stream not opened). -extern int wave_get_remaining_time(uint32_t sample, uint32_t* time); - -// set the callback which informs if the output is still enabled. -// Helpful if a new sample is waiting for free space whereas sound must be stopped. -typedef int (t_wave_callback)(void); -extern void wave_set_callback_is_output_enabled(t_wave_callback* cb); - - -// general functions -extern void clock_gettime2(struct timespec *ts); -extern void add_time_in_ms(struct timespec *ts, int time_in_ms); - -// for tests -extern void *wave_test_get_write_buffer(); - -#endif diff --git a/navit/support/espeak/wave_pulse.c b/navit/support/espeak/wave_pulse.c deleted file mode 100755 index d5fbc8c1e..000000000 --- a/navit/support/espeak/wave_pulse.c +++ /dev/null @@ -1,935 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007, Gilles Casse <gcasse@oralux.org> * - * eSpeak driver for PulseAudio * - * based on the XMMS PulseAudio Plugin * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -// TBD: -// * ARCH_BIG -// * uint64? a_timing_info.read_index -// * prebuf,... size? -// * 0.9.6: pb pulse_free using tlength=8820 (max size never returned -> tlength=10000 ok, but higher drain). -// -#include "speech.h" - -#ifdef USE_ASYNC -// This source file is only used for asynchronious modes - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> -#include <assert.h> -#include <sys/time.h> -#include <time.h> -#include <pulse/pulseaudio.h> -#include <pthread.h> - -#ifndef PLATFORM_WINDOWS -#include <unistd.h> -#endif -#include "wave.h" -#include "debug.h" - -//<Definitions - -enum {ONE_BILLION=1000000000}; - -enum { -// /* 100ms. -// If a greater value is set (several seconds), -// please update _pulse_timeout_start accordingly */ -// PULSE_TIMEOUT_IN_USEC = 100000, - - /* return value */ - PULSE_OK = 0, - PULSE_ERROR = -1, - PULSE_NO_CONNECTION = -2 -}; - -#ifdef USE_PULSEAUDIO - -static t_wave_callback* my_callback_is_output_enabled=NULL; - -#define SAMPLE_RATE 22050 -#define ESPEAK_FORMAT PA_SAMPLE_S16LE -#define ESPEAK_CHANNEL 1 - -#define MAXLENGTH 132300 -#define TLENGTH 4410 -#define PREBUF 2200 -#define MINREQ 880 -#define FRAGSIZE 0 - -static pthread_mutex_t pulse_mutex; - -static pa_context *context = NULL; -static pa_stream *stream = NULL; -static pa_threaded_mainloop *mainloop = NULL; - -static pa_cvolume volume; -static int volume_valid = 0; - -static int do_trigger = 0; -static uint64_t written = 0; -static int time_offset_msec = 0; -static int just_flushed = 0; - -static int connected = 0; - -#define CHECK_DEAD_GOTO(label, warn) do { \ -if (!mainloop || \ - !context || pa_context_get_state(context) != PA_CONTEXT_READY || \ - !stream || pa_stream_get_state(stream) != PA_STREAM_READY) { \ - if (warn) \ - SHOW("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \ - goto label; \ - } \ -} while(0); - -#define CHECK_CONNECTED(retval) \ -do { \ - if (!connected) return retval; \ -} while (0); - -#define CHECK_CONNECTED_NO_RETVAL(id) \ - do { \ - if (!connected){ SHOW("CHECK_CONNECTED_NO_RETVAL: !pulse_connected\n", ""); return; } \ - } while (0); - -//> - - -// static void display_timing_info(const pa_timing_info* the_time) -// { -// const struct timeval *tv=&(the_time->timestamp); - -// SHOW_TIME("ti>"); -// SHOW("ti> timestamp=%03d.%03dms\n",(int)(tv->tv_sec%1000), (int)(tv->tv_usec/1000)); -// SHOW("ti> synchronized_clocks=%d\n",the_time->synchronized_clocks); -// SHOW("ti> sink_usec=%ld\n",the_time->sink_usec); -// SHOW("ti> source_usec=%ld\n",the_time->source_usec); -// SHOW("ti> transport=%ld\n",the_time->transport_usec); -// SHOW("ti> playing=%d\n",the_time->playing); -// SHOW("ti> write_index_corrupt=%d\n",the_time->write_index_corrupt); -// SHOW("ti> write_index=0x%lx\n",the_time->write_index); -// SHOW("ti> read_index_corrupt=%d\n",the_time->read_index_corrupt); -// SHOW("ti> read_index=0x%lx\n",the_time->read_index); -// } - - -static void info_cb(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) { - ENTER(__FUNCTION__); - assert(c); - - if (!i) - return; - - volume = i->volume; - volume_valid = 1; -} - -static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { - pa_operation *o; - ENTER(__FUNCTION__); - - assert(c); - - if (!stream || - index != pa_stream_get_index(stream) || - (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && - t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW))) - return; - - if (!(o = pa_context_get_sink_input_info(c, index, info_cb, NULL))) { - SHOW("pa_context_get_sink_input_info() failed: %s\n", pa_strerror(pa_context_errno(c))); - return; - } - - pa_operation_unref(o); -} - -static void context_state_cb(pa_context *c, void *userdata) { - ENTER(__FUNCTION__); - assert(c); - - switch (pa_context_get_state(c)) { - case PA_CONTEXT_READY: - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - pa_threaded_mainloop_signal(mainloop, 0); - break; - - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - break; - } -} - -static void stream_state_cb(pa_stream *s, void * userdata) { - ENTER(__FUNCTION__); - assert(s); - - switch (pa_stream_get_state(s)) { - - case PA_STREAM_READY: - case PA_STREAM_FAILED: - case PA_STREAM_TERMINATED: - pa_threaded_mainloop_signal(mainloop, 0); - break; - - case PA_STREAM_UNCONNECTED: - case PA_STREAM_CREATING: - break; - } -} - -static void stream_success_cb(pa_stream *s, int success, void *userdata) { - ENTER(__FUNCTION__); - assert(s); - - if (userdata) - *(int*) userdata = success; - - pa_threaded_mainloop_signal(mainloop, 0); -} - -static void context_success_cb(pa_context *c, int success, void *userdata) { - ENTER(__FUNCTION__); - assert(c); - - if (userdata) - *(int*) userdata = success; - - pa_threaded_mainloop_signal(mainloop, 0); -} - -static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { - ENTER(__FUNCTION__); - assert(s); - - pa_threaded_mainloop_signal(mainloop, 0); -} - -static void stream_latency_update_cb(pa_stream *s, void *userdata) { - // ENTER(__FUNCTION__); - assert(s); - - pa_threaded_mainloop_signal(mainloop, 0); -} - -static int pulse_free(void) { - ENTER(__FUNCTION__); - size_t l = 0; - pa_operation *o = NULL; - - CHECK_CONNECTED(0); - - SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop_lock"); - pa_threaded_mainloop_lock(mainloop); - CHECK_DEAD_GOTO(fail, 1); - - if ((l = pa_stream_writable_size(stream)) == (size_t) -1) { - SHOW("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(context))); - l = 0; - goto fail; - } - - SHOW("pulse_free: %s (ret=%d)\n", "pa_stream_writable_size", l); - - /* If this function is called twice with no pulse_write() call in - * between this means we should trigger the playback */ - if (do_trigger) { - int success = 0; - - SHOW("pulse_free: %s (call)\n", "pa_stream_trigger"); - if (!(o = pa_stream_trigger(stream, stream_success_cb, &success))) { - SHOW("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); - goto fail; - } - - SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop"); - while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - CHECK_DEAD_GOTO(fail, 1); - pa_threaded_mainloop_wait(mainloop); - } - SHOW("pulse_free: %s (ret)\n", "pa_threaded_main_loop"); - - if (!success) - SHOW("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); - } - -fail: - SHOW("pulse_free: %s (call)\n", "pa_operation_unref"); - if (o) - pa_operation_unref(o); - - SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop_unlock"); - pa_threaded_mainloop_unlock(mainloop); - - do_trigger = !!l; - SHOW("pulse_free: %d (ret)\n", (int)l); - return (int) l; -} - -static int pulse_playing(const pa_timing_info *the_timing_info) { - ENTER(__FUNCTION__); - int r = 0; - const pa_timing_info *i; - - assert(the_timing_info); - - CHECK_CONNECTED(0); - - pa_threaded_mainloop_lock(mainloop); - - for (;;) { - CHECK_DEAD_GOTO(fail, 1); - - if ((i = pa_stream_get_timing_info(stream))) - { - break; - } - if (pa_context_errno(context) != PA_ERR_NODATA) { - SHOW("pa_stream_get_timing_info() failed: %s", pa_strerror(pa_context_errno(context))); - goto fail; - } - - pa_threaded_mainloop_wait(mainloop); - } - - r = i->playing; - memcpy((void*)the_timing_info, (void*)i, sizeof(pa_timing_info)); - - // display_timing_info(i); - -fail: - pa_threaded_mainloop_unlock(mainloop); - - return r; -} - - -// static void pulse_flush(int time) { -// ENTER(__FUNCTION__); -// pa_operation *o = NULL; -// int success = 0; - -// CHECK_CONNECTED(); - -// pa_threaded_mainloop_lock(mainloop); -// CHECK_DEAD_GOTO(fail, 1); - -// if (!(o = pa_stream_flush(stream, stream_success_cb, &success))) { -// SHOW("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context))); -// goto fail; -// } - -// while (pa_operation_get_state(o) != PA_OPERATION_DONE) { -// CHECK_DEAD_GOTO(fail, 1); -// pa_threaded_mainloop_wait(mainloop); -// } - -// if (!success) -// SHOW("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context))); - -// written = (uint64_t) (((double) time * pa_bytes_per_second(pa_stream_get_sample_spec(stream))) / 1000); -// just_flushed = 1; -// time_offset_msec = time; - -// fail: -// if (o) -// pa_operation_unref(o); - -// pa_threaded_mainloop_unlock(mainloop); -// } - - -static void pulse_write(void* ptr, int length) { - ENTER(__FUNCTION__); - - - SHOW("pulse_write > length=%d\n", length); - - CHECK_CONNECTED(); - - pa_threaded_mainloop_lock(mainloop); - CHECK_DEAD_GOTO(fail, 1); - - if (pa_stream_write(stream, ptr, length, NULL, PA_SEEK_RELATIVE, (pa_seek_mode_t)0) < 0) { - SHOW("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context))); - goto fail; - } - - do_trigger = 0; - written += length; - -fail: - - pa_threaded_mainloop_unlock(mainloop); -} - -static int drain(void) { - pa_operation *o = NULL; - int success = 0; - int ret = PULSE_ERROR; - - ENTER(__FUNCTION__); - - CHECK_CONNECTED(ret); - - pa_threaded_mainloop_lock(mainloop); - CHECK_DEAD_GOTO(fail, 0); - - SHOW_TIME("pa_stream_drain (call)"); - if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) { - SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context))); - goto fail; - } - - SHOW_TIME("pa_threaded_mainloop_wait (call)"); - while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - CHECK_DEAD_GOTO(fail, 1); - pa_threaded_mainloop_wait(mainloop); - } - SHOW_TIME("pa_threaded_mainloop_wait (ret)"); - - if (!success) { - SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context))); - } - else { - ret = PULSE_OK; - } - -fail: - SHOW_TIME("pa_operation_unref (call)"); - if (o) - pa_operation_unref(o); - - pa_threaded_mainloop_unlock(mainloop); - SHOW_TIME("drain (ret)"); - - return ret; -} - - -static void pulse_close(void) { - - ENTER(__FUNCTION__); - - drain(); - - connected = 0; - - if (mainloop) - pa_threaded_mainloop_stop(mainloop); - - connected = 0; - - if (context) { - SHOW_TIME("pa_context_disconnect (call)"); - pa_context_disconnect(context); - pa_context_unref(context); - context = NULL; - } - - if (mainloop) { - SHOW_TIME("pa_threaded_mainloop_free (call)"); - pa_threaded_mainloop_free(mainloop); - mainloop = NULL; - } - SHOW_TIME("pulse_close (ret)"); - -} - - -static int pulse_open() -{ - ENTER(__FUNCTION__); - pa_sample_spec ss; - pa_operation *o = NULL; - int success; - int ret = PULSE_ERROR; - - assert(!mainloop); - assert(!context); - assert(!stream); - assert(!connected); - - pthread_mutex_init( &pulse_mutex, (const pthread_mutexattr_t *)NULL); - - ss.format = ESPEAK_FORMAT; - ss.rate = SAMPLE_RATE; - ss.channels = ESPEAK_CHANNEL; - - if (!pa_sample_spec_valid(&ss)) - return false; - -/* if (!volume_valid) { */ - pa_cvolume_reset(&volume, ss.channels); - volume_valid = 1; -/* } else if (volume.channels != ss.channels) */ -/* pa_cvolume_set(&volume, ss.channels, pa_cvolume_avg(&volume)); */ - - SHOW_TIME("pa_threaded_mainloop_new (call)"); - if (!(mainloop = pa_threaded_mainloop_new())) { - SHOW("Failed to allocate main loop\n",""); - goto fail; - } - - pa_threaded_mainloop_lock(mainloop); - - SHOW_TIME("pa_context_new (call)"); - if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "eSpeak"))) { - SHOW("Failed to allocate context\n",""); - goto unlock_and_fail; - } - - pa_context_set_state_callback(context, context_state_cb, NULL); - pa_context_set_subscribe_callback(context, subscribe_cb, NULL); - - SHOW_TIME("pa_context_connect (call)"); - if (pa_context_connect(context, NULL, (pa_context_flags_t)0, NULL) < 0) { - SHOW("Failed to connect to server: %s", pa_strerror(pa_context_errno(context))); - ret = PULSE_NO_CONNECTION; - goto unlock_and_fail; - } - - SHOW_TIME("pa_threaded_mainloop_start (call)"); - if (pa_threaded_mainloop_start(mainloop) < 0) { - SHOW("Failed to start main loop",""); - goto unlock_and_fail; - } - - /* Wait until the context is ready */ - SHOW_TIME("pa_threaded_mainloop_wait"); - pa_threaded_mainloop_wait(mainloop); - - if (pa_context_get_state(context) != PA_CONTEXT_READY) { - SHOW("Failed to connect to server: %s", pa_strerror(pa_context_errno(context))); - ret = PULSE_NO_CONNECTION; - if (mainloop) - pa_threaded_mainloop_stop(mainloop); - goto unlock_and_fail; - } - - SHOW_TIME("pa_stream_new"); - if (!(stream = pa_stream_new(context, "unknown", &ss, NULL))) { - SHOW("Failed to create stream: %s", pa_strerror(pa_context_errno(context))); - goto unlock_and_fail; - } - - pa_stream_set_state_callback(stream, stream_state_cb, NULL); - pa_stream_set_write_callback(stream, stream_request_cb, NULL); - pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL); - - - - pa_buffer_attr a_attr; - - a_attr.maxlength = MAXLENGTH; - a_attr.tlength = TLENGTH; - a_attr.prebuf = PREBUF; - a_attr.minreq = MINREQ; - a_attr.fragsize = 0; - - SHOW_TIME("pa_connect_playback"); - if (pa_stream_connect_playback(stream, NULL, &a_attr, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE), &volume, NULL) < 0) { - SHOW("Failed to connect stream: %s", pa_strerror(pa_context_errno(context))); - goto unlock_and_fail; - } - - /* Wait until the stream is ready */ - SHOW_TIME("pa_threaded_mainloop_wait"); - pa_threaded_mainloop_wait(mainloop); - - if (pa_stream_get_state(stream) != PA_STREAM_READY) { - SHOW("Failed to connect stream: %s", pa_strerror(pa_context_errno(context))); - goto unlock_and_fail; - } - - /* Now subscribe to events */ - SHOW_TIME("pa_context_subscribe"); - if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) { - SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); - goto unlock_and_fail; - } - - success = 0; - SHOW_TIME("pa_threaded_mainloop_wait"); - while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - CHECK_DEAD_GOTO(fail, 1); - pa_threaded_mainloop_wait(mainloop); - } - - if (!success) { - SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); - goto unlock_and_fail; - } - - pa_operation_unref(o); - - /* Now request the initial stream info */ - if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_cb, NULL))) { - SHOW("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); - goto unlock_and_fail; - } - - SHOW_TIME("pa_threaded_mainloop_wait 2"); - while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - CHECK_DEAD_GOTO(fail, 1); - pa_threaded_mainloop_wait(mainloop); - } - -/* if (!volume_valid) { */ -/* SHOW("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); */ -/* goto unlock_and_fail; */ -/* } */ - - do_trigger = 0; - written = 0; - time_offset_msec = 0; - just_flushed = 0; - connected = 1; - // volume_time_event = NULL; - - pa_threaded_mainloop_unlock(mainloop); - SHOW_TIME("pulse_open (ret true)"); - - // return true; - return PULSE_OK; - - -unlock_and_fail: - - if (o) - pa_operation_unref(o); - - pa_threaded_mainloop_unlock(mainloop); - -fail: - - // pulse_close(); - - if (ret == PULSE_NO_CONNECTION) { - if (context) { - SHOW_TIME("pa_context_disconnect (call)"); - pa_context_disconnect(context); - pa_context_unref(context); - context = NULL; - } - - if (mainloop) { - SHOW_TIME("pa_threaded_mainloop_free (call)"); - pa_threaded_mainloop_free(mainloop); - mainloop = NULL; - } - } - else { - pulse_close(); - } - - SHOW_TIME("pulse_open (ret false)"); - - return ret; - -} - -void wave_flush(void* theHandler) -{ - ENTER("wave_flush"); - -// if (my_stream_could_start) -// { -// // #define buf 1024 -// // static char a_buffer[buf*2]; -// // memset(a_buffer,0,buf*2); -// // wave_write(theHandler, a_buffer, buf*2); -// start_stream(); -// } -} - - - -//<wave_set_callback_is_output_enabled - -void wave_set_callback_is_output_enabled(t_wave_callback* cb) -{ - my_callback_is_output_enabled = cb; -} - -//> -//<wave_init - -void wave_init() -{ - ENTER("wave_init"); - - stream = NULL; - - pulse_open(); -} - -//> -//<wave_open - -void* wave_open(const char* the_api) -{ - ENTER("wave_open"); - return((void*)1); -} - -//> -//<wave_write - -size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) -{ - ENTER("wave_write"); - size_t bytes_to_write = theSize; - char* aBuffer=theMono16BitsWaveBuffer; - - assert(stream); - - size_t aTotalFreeMem=0; - - pthread_mutex_lock(&pulse_mutex); - - while (1) - { - if (my_callback_is_output_enabled - && (0==my_callback_is_output_enabled())) - { - SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); - theSize=0; - goto terminate; - } - - aTotalFreeMem = pulse_free(); - if (aTotalFreeMem >= bytes_to_write) - { - SHOW("wave_write > aTotalFreeMem(%d) >= bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write); - break; - } - - // TBD: check if really helpful - if (aTotalFreeMem >= MAXLENGTH*2) - { - aTotalFreeMem = MAXLENGTH*2; - } - - SHOW("wave_write > wait: aTotalFreeMem(%d) < bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write); - - // 500: threshold for avoiding too many calls to pulse_write - if (aTotalFreeMem>500) - { - pulse_write(aBuffer, aTotalFreeMem); - bytes_to_write -= aTotalFreeMem; - aBuffer += aTotalFreeMem; - } - - usleep(10000); - } - - pulse_write(aBuffer, bytes_to_write); - - terminate: - pthread_mutex_unlock(&pulse_mutex); - SHOW("wave_write: theSize=%d", theSize); - SHOW_TIME("wave_write > LEAVE"); - return theSize; -} - -//> -//<wave_close - -int wave_close(void* theHandler) -{ - SHOW_TIME("wave_close > ENTER"); - - int a_status = pthread_mutex_lock(&pulse_mutex); - if (a_status) { - SHOW("Error: pulse_mutex lock=%d (%s)\n", a_status, __FUNCTION__); - return PULSE_ERROR; - } - - drain(); - - pthread_mutex_unlock(&pulse_mutex); - SHOW_TIME("wave_close (ret)"); - - return PULSE_OK; -} - -//> -//<wave_is_busy - -int wave_is_busy(void* theHandler) -{ - SHOW_TIME("wave_is_busy"); - - pa_timing_info a_timing_info; - int active = pulse_playing(&a_timing_info); - SHOW("wave_is_busy: %d\n",active); - return active; -} - -//> -//<wave_terminate - -void wave_terminate() -{ - ENTER("wave_terminate"); - -// Pa_Terminate(); - - int a_status; - pthread_mutex_t* a_mutex = NULL; - a_mutex = &pulse_mutex; - a_status = pthread_mutex_lock(a_mutex); - - pulse_close(); - - SHOW_TIME("unlock mutex"); - a_status = pthread_mutex_unlock(a_mutex); - pthread_mutex_destroy(a_mutex); -} - -//> -//<wave_get_read_position, wave_get_write_position, wave_get_remaining_time - -uint32_t wave_get_read_position(void* theHandler) -{ - pa_timing_info a_timing_info; - pulse_playing(&a_timing_info); - SHOW("wave_get_read_position > %lx\n", a_timing_info.read_index); - return a_timing_info.read_index; -} - -uint32_t wave_get_write_position(void* theHandler) -{ - pa_timing_info a_timing_info; - pulse_playing(&a_timing_info); - SHOW("wave_get_read_position > %lx\n", a_timing_info.write_index); - return a_timing_info.write_index; -} - -int wave_get_remaining_time(uint32_t sample, uint32_t* time) -{ - double a_time=0; - - if (!time || !stream) - { - SHOW("event get_remaining_time> %s\n","audio device not available"); - return -1; - } - - pa_timing_info a_timing_info; - pulse_playing(&a_timing_info); - - if (sample > a_timing_info.read_index) - { - // TBD: take in account time suplied by portaudio V18 API - a_time = sample - a_timing_info.read_index; - a_time = 0.5 + (a_time * 1000.0) / SAMPLE_RATE; - } - else - { - a_time = 0; - } - - SHOW("wave_get_remaining_time > sample=%d, time=%d\n", sample, (uint32_t)a_time); - - *time = (uint32_t)a_time; - - return 0; -} - -//> -//<wave_test_get_write_buffer - -void *wave_test_get_write_buffer() -{ - return NULL; -} - - -#else -// notdef USE_PULSEAUDIO - - -void wave_init() {} -void* wave_open(const char* the_api) {return (void *)1;} -size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {return theSize;} -int wave_close(void* theHandler) {return 0;} -int wave_is_busy(void* theHandler) {return 0;} -void wave_terminate() {} -uint32_t wave_get_read_position(void* theHandler) {return 0;} -uint32_t wave_get_write_position(void* theHandler) {return 0;} -void wave_flush(void* theHandler) {} -typedef int (t_wave_callback)(void); -void wave_set_callback_is_output_enabled(t_wave_callback* cb) {} -extern void* wave_test_get_write_buffer() {return NULL;} - -int wave_get_remaining_time(uint32_t sample, uint32_t* time) -{ - if (!time) return(-1); - *time = (uint32_t)0; - return 0; -} - -#endif // of USE_PORTAUDIO - -//> -//<clock_gettime2, add_time_in_ms - -void clock_gettime2(struct timespec *ts) -{ - struct timeval tv; - - if (!ts) - { - return; - } - - assert (gettimeofday(&tv, NULL) != -1); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec*1000; -} - -void add_time_in_ms(struct timespec *ts, int time_in_ms) -{ - if (!ts) - { - return; - } - - uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms; - while(t_ns >= ONE_BILLION) - { - SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns); - ts->tv_sec += 1; - t_ns -= ONE_BILLION; - } - ts->tv_nsec = (long int)t_ns; -} - - -#endif // USE_ASYNC - -//> diff --git a/navit/support/espeak/wave_sada.c b/navit/support/espeak/wave_sada.c deleted file mode 100755 index c69a4dc99..000000000 --- a/navit/support/espeak/wave_sada.c +++ /dev/null @@ -1,588 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008, Sun Microsystems, Inc. * - * eSpeak driver for Solaris Audio Device Architecture (SADA) * - * Written by Willie Walker, based on the eSpeak PulseAudio driver * - * from Gilles Casse * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "speech.h" - -#ifdef USE_ASYNC -// This source file is only used for asynchronious modes - -#include <errno.h> -#include <string.h> -#include <stropts.h> -#include <assert.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/audioio.h> - -#include "wave.h" -#include "debug.h" - -enum {ONE_BILLION=1000000000}; -#define SAMPLE_RATE 22050 -#define SAMPLE_SIZE 16 - -#ifdef USE_SADA - -static t_wave_callback* my_callback_is_output_enabled=NULL; - -static const char *sun_audio_device = "/dev/audio"; -static int sun_audio_fd = -1; - -// The total number of 16-bit samples sent to be played via the -// wave_write method. -// -static uint32_t total_samples_sent; - -// The total number of samples sent to be played via the wave_write -// method, but which were never played because of a call to -// wave_close. -// -static uint32_t total_samples_skipped; - -// The last known playing index after a call to wave_close. -// -static uint32_t last_play_position=0; - -//> -// wave_init -// -// DESCRIPTION: -// -// initializes the audio subsytem. -// -// GLOBALS USED/MODIFIED: -// -// sun_audio_fd: modified to hold the file descriptor of the opened -// audio device. -// -//<wave_init - -void wave_init() { - ENTER("wave_init"); - - audio_info_t ainfo; - char *audio_device = NULL; - - audio_device = getenv("AUDIODEV"); - if (audio_device != NULL) { - if ((sun_audio_fd = open(audio_device, O_WRONLY)) < 0) { - SHOW("wave_init() could not open: %s (%d)\n", - audio_device, sun_audio_fd); - } - } - - if (sun_audio_fd < 0) { - if ((sun_audio_fd = open(sun_audio_device, O_WRONLY)) < 0) { - SHOW("wave_init() could not open: %s (%d)\n", - sun_audio_device, sun_audio_fd); - } - } - - SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd); - - if (sun_audio_fd < 0) { - return; - } - - ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo); - SHOW("wave_init() play buffer size: %d\n", ainfo.play.buffer_size); - ainfo.play.encoding = AUDIO_ENCODING_LINEAR; - ainfo.play.channels = 1; - ainfo.play.sample_rate = SAMPLE_RATE; - ainfo.play.precision = SAMPLE_SIZE; - - if (ioctl(sun_audio_fd, AUDIO_SETINFO, &ainfo) == -1) { - SHOW("wave_init() failed to set audio params: %s\n", strerror(errno)); - close(sun_audio_fd); - return; - } -} - -//> -// wave_open -// -// DESCRIPTION: -// -// opens the audio subsystem given a specific API (e.g., "alsa", -// "oss", ...). We ignore the_api and just return the sun_audio_fd we -// opened in wave_init. This return value will be passed in as the -// theHandler parameter in all other methods. -// -// PARAMETERS: -// -// the_api: "alsa", "oss" (ignored) -// -// GLOBALS USED/MODIFIED: -// -// sun_audio_fd: used as return value -// -// RETURNS: -// -// sun_audio_fd opened in wave_init, which is passed in as theHandler -// parameter in all other methods -// -//<wave_open - -void* wave_open(const char* the_api) -{ - ENTER("wave_open"); - return((void*) sun_audio_fd); -} - -//> -// wave_write -// -// DESCRIPTION: -// -// Meant to be asynchronous, it supplies the wave sample to the lower -// audio layer and returns. The sample is played later on. [[[WDW - -// we purposely do not open the audio device as non-blocking because -// managing that would be a pain. So, we rely a lot upon fifo.cpp and -// event.cpp to not overload us, allowing us to get away with a -// blocking write. event.cpp:polling_thread in particular appears to -// use get_remaining_time to prevent flooding.]]] -// -// PARAMETERS: -// -// theHandler: the audio device file descriptor -// theMono16BitsWaveBuffer: the audio data -// theSize: the number of bytes (not 16-bit samples) -// -// GLOBALS USED/MODIFIED: -// -// total_samples_sent: modified based upon 16-bit samples sent -// -// RETURNS: -// -// the number of bytes (not 16-bit samples) sent -// -//<wave_write - -size_t wave_write(void* theHandler, - char* theMono16BitsWaveBuffer, - size_t theSize) -{ - size_t num; - ENTER("wave_write"); - if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) { - SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); - return 0; - } - -#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN - { - // BIG-ENDIAN, swap the order of bytes in each sound sample - int c; - char *out_ptr; - char *out_end; - out_ptr = (char *)theMono16BitsWaveBuffer; - out_end = out_ptr + theSize; - while(out_ptr < out_end) - { - c = out_ptr[0]; - out_ptr[0] = out_ptr[1]; - out_ptr[1] = c; - out_ptr += 2; - } - } -#endif - - num = write((int) theHandler, theMono16BitsWaveBuffer, theSize); - - // Keep track of the total number of samples sent -- we use this in - // wave_get_read_position and also use it to help calculate the - // total_samples_skipped in wave_close. - // - total_samples_sent += num / 2; - - if (num < theSize) { - SHOW("ERROR: wave_write only wrote %d of %d bytes\n", num, theSize); - } else { - SHOW("wave_write wrote %d bytes\n", theSize); - } - - SHOW_TIME("wave_write > LEAVE"); - return num; -} - -//> -// wave_close -// -// DESCRIPTION: -// -// Does what SADA normally would call a flush, which means to cease -// all audio production in progress and throw any remaining audio -// away. [[[WDW - see comment in wave_flush.]]] -// -// PARAMETERS: -// -// theHandler: the audio device file descriptor -// -// GLOBALS USED/MODIFIED: -// -// last_play_position: modified to reflect play position the last time -// this method was called -// total_samples_sent: used to help calculate total_samples_skipped -// total_samples_skipped: modified to hold the total number of 16-bit -// samples sent to wave_write, but which were -// never played -// sun_audio_fd: used because some calls to wave_close seem to -// pass a NULL for theHandler for some odd reason -// -// RETURNS: -// -// The result of the ioctl call (non-0 means failure) -// -//<wave_close - -int wave_close(void* theHandler) -{ - int ret; - audio_info_t ainfo; - int audio_fd = (int) theHandler; - if (!audio_fd) { - audio_fd = sun_audio_fd; - } - ENTER("wave_close"); - // [[[WDW: maybe do a pause/resume ioctl???]]] - ret = ioctl(audio_fd, I_FLUSH, FLUSHRW); - ioctl(audio_fd, AUDIO_GETINFO, &ainfo); - - // Calculate the number of samples that won't get - // played. We also keep track of the last_play_position - // because wave_close can be called multiple times - // before another call to wave_write. - // - if (last_play_position != ainfo.play.samples) { - last_play_position = ainfo.play.samples; - total_samples_skipped = total_samples_sent - last_play_position; - } - SHOW_TIME("wave_close > LEAVE"); - return ret; -} - -//> -// wave_is_busy -// -// DESCRIPTION: -// -// Returns a non-0 value if audio is being played. -// -// PARAMETERS: -// -// theHandler: the audio device file descriptor -// -// GLOBALS USED/MODIFIED: -// -// sun_audio_fd: used because some calls to wave_is_busy seem to -// pass a NULL for theHandler for some odd reason -// -// RETURNS: -// -// A non-0 value if audio is being played -// -//<wave_is_busy - -int wave_is_busy(void* theHandler) -{ - uint32_t time; - wave_get_remaining_time(total_samples_sent - 1, &time); - return time != 0; -} - -//> -// wave_terminate -// -// DESCRIPTION: -// -// Used to end our session with eSpeak. -// -// GLOBALS USED/MODIFIED: -// -// sun_audio_fd: modified - closed and set to -1 -// -//<wave_terminate - -void wave_terminate() -{ - ENTER("wave_terminate"); - close(sun_audio_fd); - sun_audio_fd = -1; - SHOW_TIME("wave_terminate > LEAVE"); -} - -//> -// wave_flush -// -// DESCRIPTION: -// -// Appears to want to tell the audio subsystem to make sure it plays -// the audio. In our case, the system is already doing this, so this -// is basically a no-op. [[[WDW - if you do a drain, you block, so -// don't do that. In addition the typical SADA notion of flush is -// currently handled by wave_close. I think this is most likely just -// terminology conflict between eSpeak and SADA.]]] -// -// PARAMETERS: -// -// theHandler: the audio device file descriptor -// -//<wave_flush - -void wave_flush(void* theHandler) -{ - ENTER("wave_flush"); - //ioctl((int) theHandler, AUDIO_DRAIN, 0); - SHOW_TIME("wave_flush > LEAVE"); -} - -//> -// wave_set_callback_is_output_enabled -// -// DESCRIPTION: -// -// Sets the callback to call from wave_write before it sends data to -// be played. It helps wave_write determine if the data should be -// thrown away or not. -// -// PARAMETERS: -// -// cb: the callback to call from wave_write -// -//<wave_set_callback_is_output_enabled - -void wave_set_callback_is_output_enabled(t_wave_callback* cb) -{ - my_callback_is_output_enabled = cb; -} - -//> -// wave_test_get_write_buffer -// -// DESCRIPTION: -// -// Unnecessary and is used for debug output from -// speak_lib.cpp:dispatch_audio. -// -// RETURNS: -// -// NULL -// -//<wave_test_get_write_buffer - -void *wave_test_get_write_buffer() -{ - return NULL; -} - -//> -// wave_get_read_position -// -// DESCRIPTION: -// -// Concerns the sample which is currently played by the audio layer, -// where 'sample' is a small buffer of synthesized wave data, -// identified so that the user callback could be called when the -// 'sample' is really played. The identifier is returned by -// wave_get_write_position. This method is unused. -// -// PARAMETERS: -// -// theHandler: the audio device file descriptor -// -// RETURNS: -// -// The total number of 16-bit samples played by the audio system -// so far. -// -//<wave_get_read_position - -uint32_t wave_get_read_position(void* theHandler) -{ - audio_info_t ainfo; - ENTER("wave_get_read_position"); - ioctl((int) theHandler, AUDIO_GETINFO, &ainfo); - SHOW("wave_get_read_position: %d\n", ainfo.play.samples); - SHOW_TIME("wave_get_read_position > LEAVE"); - return ainfo.play.samples; -} - -//> -// wave_get_write_position -// -// DESCRIPTION: -// -// Returns an identifier for a new sample, where 'sample' is a small -// buffer of synthesized wave data, identified so that the user -// callback could be called when the 'sample' is really played. This -// implementation views the audio as one long continuous stream of -// 16-bit samples. -// -// PARAMETERS: -// -// theHandler: the audio device file descriptor -// -// GLOBALS USED/MODIFIED: -// -// total_samples_sent: used as the return value -// -// RETURNS: -// -// total_samples_sent, which is the index for the end of this long -// continuous stream. [[[WDW: with a unit32_t managing 16-bit -// samples at 22050Hz, we have about 54 hours of play time before -// the index wraps back to 0. We don't handle that wrapping, so -// the behavior after 54 hours of play time is undefined.]]] -// -//<wave_get_write_position - -uint32_t wave_get_write_position(void* theHandler) -{ - ENTER("wave_get_write_position"); - SHOW("wave_get_write_position: %d\n", total_samples_sent); - SHOW_TIME("wave_get_write_position > LEAVE"); - return total_samples_sent; -} - -//> -// wave_get_remaining_time -// -// DESCRIPTION: -// -// Returns the remaining time (in ms) before the sample is played. -// The sample in this case is a return value from a previous call to -// wave_get_write_position. -// -// PARAMETERS: -// -// sample: an index returned from wave_get_write_position representing -// an index into the long continuous stream of 16-bit samples -// time: a return value representing the delay in milliseconds until -// sample is played. A value of 0 means the sample is either -// currently being played or it has already been played. -// -// GLOBALS USED/MODIFIED: -// -// sun_audio_fd: used to determine total number of samples played by -// the audio system -// total_samples_skipped: used in remaining time calculation -// -// RETURNS: -// -// Time in milliseconds before the sample is played or 0 if the sample -// is currently playing or has already been played. -// -//<wave_get_remaining_time - -int wave_get_remaining_time(uint32_t sample, uint32_t* time) -{ - uint32_t a_time=0; - uint32_t actual_index; - - audio_info_t ainfo; - ENTER("wave_get_remaining_time"); - if (!time) { - return(-1); - SHOW_TIME("wave_get_remaining_time > LEAVE"); - } - - ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo); - - // See if this sample has already been played or is currently - // playing. - // - actual_index = sample - total_samples_skipped; - if ((sample < total_samples_skipped) || - (actual_index <= ainfo.play.samples)) { - *time = 0; - } else { - a_time = ((actual_index - ainfo.play.samples) * 1000) / SAMPLE_RATE; - *time = (uint32_t) a_time; - } - SHOW("wave_get_remaining_time for %d: %d\n", sample, *time); - SHOW_TIME("wave_get_remaining_time > LEAVE"); - return 0; -} - -#else -// notdef USE_SADA - -void wave_init() {} -void* wave_open(const char* the_api) {return (void *)1;} -size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {return theSize;} -int wave_close(void* theHandler) {return 0;} -int wave_is_busy(void* theHandler) {return 0;} -void wave_terminate() {} -uint32_t wave_get_read_position(void* theHandler) {return 0;} -uint32_t wave_get_write_position(void* theHandler) {return 0;} -void wave_flush(void* theHandler) {} -typedef int (t_wave_callback)(void); -void wave_set_callback_is_output_enabled(t_wave_callback* cb) {} -extern void* wave_test_get_write_buffer() {return NULL;} - -int wave_get_remaining_time(uint32_t sample, uint32_t* time) -{ - if (!time) return(-1); - *time = (uint32_t)0; - return 0; -} - -#endif // of USE_PORTAUDIO - -//> -//<clock_gettime2, add_time_in_ms - -void clock_gettime2(struct timespec *ts) -{ - struct timeval tv; - - if (!ts) - { - return; - } - - assert (gettimeofday(&tv, NULL) != -1); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec*1000; -} - -void add_time_in_ms(struct timespec *ts, int time_in_ms) -{ - if (!ts) - { - return; - } - - uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms; - while(t_ns >= ONE_BILLION) - { - SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns); - ts->tv_sec += 1; - t_ns -= ONE_BILLION; - } - ts->tv_nsec = (long int)t_ns; -} - -#endif // USE_ASYNC - -//> diff --git a/navit/support/espeak/wavegen.c b/navit/support/espeak/wavegen.c deleted file mode 100755 index a5467ca1e..000000000 --- a/navit/support/espeak/wavegen.c +++ /dev/null @@ -1,1941 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * - * email: jonsd@users.sourceforge.net * - * * - * 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 * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see: * - * <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include "StdAfx.h" - -// this version keeps wavemult window as a constant fraction -// of the cycle length - but that spreads out the HF peaks too much - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> - - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "voice.h" - -//#undef INCLUDE_KLATT - -#ifdef USE_PORTAUDIO -#include "portaudio.h" -#undef USE_PORTAUDIO -// determine portaudio version by looking for a #define which is not in V18 -#ifdef paNeverDropInput -#define USE_PORTAUDIO 19 -#else -#define USE_PORTAUDIO 18 -#endif -#endif - -#define N_SINTAB 2048 -#include "sintab.h" - - -#define PI 3.1415927 -#define PI2 6.283185307 -#define N_WAV_BUF 10 - -voice_t *wvoice; - -FILE *f_log = NULL; -int option_waveout = 0; -static int option_harmonic1 = 10; // 10 -int option_log_frames = 0; -static int flutter_amp = 64; - -static int general_amplitude = 60; -static int consonant_amp = 26; // 24 - -int embedded_value[N_EMBEDDED_VALUES]; - -static int PHASE_INC_FACTOR; -int samplerate = 0; // this is set by Wavegeninit() -int samplerate_native=0; -extern int option_device_number; -extern int option_quiet; - -static wavegen_peaks_t peaks[N_PEAKS]; -static int peak_harmonic[N_PEAKS]; -static int peak_height[N_PEAKS]; - -#define N_ECHO_BUF 5500 // max of 250mS at 22050 Hz -static int echo_head; -static int echo_tail; -static int echo_length = 0; // period (in sample\) to ensure completion of echo at the end of speech, set in WavegenSetEcho() -static int echo_amp = 0; -static short echo_buf[N_ECHO_BUF]; - -static int voicing; -static RESONATOR rbreath[N_PEAKS]; - -static int harm_sqrt_n = 0; - - -#define N_LOWHARM 30 -static int harm_inc[N_LOWHARM]; // only for these harmonics do we interpolate amplitude between steps -static int *harmspect; -static int hswitch=0; -static int hspect[2][MAX_HARMONIC]; // 2 copies, we interpolate between then -static int max_hval=0; - -static int nsamples=0; // number to do -static int modulation_type = 0; -static int glottal_flag = 0; -static int glottal_reduce = 0; - - -WGEN_DATA wdata; - -static int amp_ix; -static int amp_inc; -static unsigned char *amplitude_env = NULL; - -static int samplecount=0; // number done -static int samplecount_start=0; // count at start of this segment -static int end_wave=0; // continue to end of wave cycle -static int wavephase; -static int phaseinc; -static int cycle_samples; // number of samples in a cycle at current pitch -static int cbytes; -static int hf_factor; - -static double minus_pi_t; -static double two_pi_t; - - -unsigned char *out_ptr; -unsigned char *out_start; -unsigned char *out_end; -int outbuf_size = 0; - -// the queue of operations passed to wavegen from sythesize -long wcmdq[N_WCMDQ][4]; -int wcmdq_head=0; -int wcmdq_tail=0; - -// pitch,speed, -int embedded_default[N_EMBEDDED_VALUES] = {0,50,170,100,50, 0,0, 0,170,0,0,0,0,0}; -static int embedded_max[N_EMBEDDED_VALUES] = {0,0x7fff,600,300,99,99,99, 0,600,0,0,0,0,4}; - -#define N_CALLBACK_IX N_WAV_BUF-2 // adjust this delay to match display with the currently spoken word -int current_source_index=0; - -extern FILE *f_wave; - -#if (USE_PORTAUDIO == 18) -static PortAudioStream *pa_stream=NULL; -#endif -#if (USE_PORTAUDIO == 19) -static PaStream *pa_stream=NULL; -#endif - -/* default pitch envelope, a steady fall */ -#define ENV_LEN 128 - -#define int(x) (int)(x) -/* -unsigned char Pitch_env0[ENV_LEN] = { - 255,253,251,249,247,245,243,241,239,237,235,233,231,229,227,225, - 223,221,219,217,215,213,211,209,207,205,203,201,199,197,195,193, - 191,189,187,185,183,181,179,177,175,173,171,169,167,165,163,161, - 159,157,155,153,151,149,147,145,143,141,139,137,135,133,131,129, - 127,125,123,121,119,117,115,113,111,109,107,105,103,101, 99, 97, - 95, 93, 91, 89, 87, 85, 83, 81, 79, 77, 75, 73, 71, 69, 67, 65, - 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, - 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1 -}; -*/ - -/* -unsigned char Pitch_long[ENV_LEN] = { - 254,249,250,251,252,253,254,254, 255,255,255,255,254,254,253,252, - 251,250,249,247,244,242,238,234, 230,225,221,217,213,209,206,203, - 199,195,191,187,183,179,175,172, 168,165,162,159,156,153,150,148, - 145,143,140,138,136,134,132,130, 128,126,123,120,117,114,111,107, - 104,100,96,91, 86,82,77,73, 70,66,63,60, 58,55,53,51, - 49,47,46,45, 43,42,40,38, 36,34,31,28, 26,24,22,20, - 18,16,14,12, 11,10,9,8, 8,8,8,8, 9,8,8,8, - 8,8,7,7, 6,6,6,5, 4,4,3,3, 2,1,1,0 -}; -*/ - -// 1st index=roughness -// 2nd index=modulation_type -// value: bits 0-3 amplitude (16ths), bits 4-7 every n cycles -#define N_ROUGHNESS 8 -static unsigned char modulation_tab[N_ROUGHNESS][8] = { - {0, 0x00, 0x00, 0x00, 0, 0x46, 0xf2, 0x29}, - {0, 0x2f, 0x00, 0x2f, 0, 0x45, 0xf2, 0x29}, - {0, 0x2f, 0x00, 0x2e, 0, 0x45, 0xf2, 0x28}, - {0, 0x2e, 0x00, 0x2d, 0, 0x34, 0xf2, 0x28}, - {0, 0x2d, 0x2d, 0x2c, 0, 0x34, 0xf2, 0x28}, - {0, 0x2b, 0x2b, 0x2b, 0, 0x34, 0xf2, 0x28}, - {0, 0x2a, 0x2a, 0x2a, 0, 0x34, 0xf2, 0x28}, - {0, 0x29, 0x29, 0x29, 0, 0x34, 0xf2, 0x28}, -}; - -// Flutter table, to add natural variations to the pitch -#define N_FLUTTER 0x170 -static int Flutter_inc; -static const unsigned char Flutter_tab[N_FLUTTER] = { - 0x80, 0x9b, 0xb5, 0xcb, 0xdc, 0xe8, 0xed, 0xec, - 0xe6, 0xdc, 0xce, 0xbf, 0xb0, 0xa3, 0x98, 0x90, - 0x8c, 0x8b, 0x8c, 0x8f, 0x92, 0x94, 0x95, 0x92, - 0x8c, 0x83, 0x78, 0x69, 0x59, 0x49, 0x3c, 0x31, - 0x2a, 0x29, 0x2d, 0x36, 0x44, 0x56, 0x69, 0x7d, - 0x8f, 0x9f, 0xaa, 0xb1, 0xb2, 0xad, 0xa4, 0x96, - 0x87, 0x78, 0x69, 0x5c, 0x53, 0x4f, 0x4f, 0x55, - 0x5e, 0x6b, 0x7a, 0x88, 0x96, 0xa2, 0xab, 0xb0, - - 0xb1, 0xae, 0xa8, 0xa0, 0x98, 0x91, 0x8b, 0x88, - 0x89, 0x8d, 0x94, 0x9d, 0xa8, 0xb2, 0xbb, 0xc0, - 0xc1, 0xbd, 0xb4, 0xa5, 0x92, 0x7c, 0x63, 0x4a, - 0x32, 0x1e, 0x0e, 0x05, 0x02, 0x05, 0x0f, 0x1e, - 0x30, 0x44, 0x59, 0x6d, 0x7f, 0x8c, 0x96, 0x9c, - 0x9f, 0x9f, 0x9d, 0x9b, 0x99, 0x99, 0x9c, 0xa1, - 0xa9, 0xb3, 0xbf, 0xca, 0xd5, 0xdc, 0xe0, 0xde, - 0xd8, 0xcc, 0xbb, 0xa6, 0x8f, 0x77, 0x60, 0x4b, - - 0x3a, 0x2e, 0x28, 0x29, 0x2f, 0x3a, 0x48, 0x59, - 0x6a, 0x7a, 0x86, 0x90, 0x94, 0x95, 0x91, 0x89, - 0x80, 0x75, 0x6b, 0x62, 0x5c, 0x5a, 0x5c, 0x61, - 0x69, 0x74, 0x80, 0x8a, 0x94, 0x9a, 0x9e, 0x9d, - 0x98, 0x90, 0x86, 0x7c, 0x71, 0x68, 0x62, 0x60, - 0x63, 0x6b, 0x78, 0x88, 0x9b, 0xaf, 0xc2, 0xd2, - 0xdf, 0xe6, 0xe7, 0xe2, 0xd7, 0xc6, 0xb2, 0x9c, - 0x84, 0x6f, 0x5b, 0x4b, 0x40, 0x39, 0x37, 0x38, - - 0x3d, 0x43, 0x4a, 0x50, 0x54, 0x56, 0x55, 0x52, - 0x4d, 0x48, 0x42, 0x3f, 0x3e, 0x41, 0x49, 0x56, - 0x67, 0x7c, 0x93, 0xab, 0xc3, 0xd9, 0xea, 0xf6, - 0xfc, 0xfb, 0xf4, 0xe7, 0xd5, 0xc0, 0xaa, 0x94, - 0x80, 0x71, 0x64, 0x5d, 0x5a, 0x5c, 0x61, 0x68, - 0x70, 0x77, 0x7d, 0x7f, 0x7f, 0x7b, 0x74, 0x6b, - 0x61, 0x57, 0x4e, 0x48, 0x46, 0x48, 0x4e, 0x59, - 0x66, 0x75, 0x84, 0x93, 0x9f, 0xa7, 0xab, 0xaa, - - 0xa4, 0x99, 0x8b, 0x7b, 0x6a, 0x5b, 0x4e, 0x46, - 0x43, 0x45, 0x4d, 0x5a, 0x6b, 0x7f, 0x92, 0xa6, - 0xb8, 0xc5, 0xcf, 0xd3, 0xd2, 0xcd, 0xc4, 0xb9, - 0xad, 0xa1, 0x96, 0x8e, 0x89, 0x87, 0x87, 0x8a, - 0x8d, 0x91, 0x92, 0x91, 0x8c, 0x84, 0x78, 0x68, - 0x55, 0x41, 0x2e, 0x1c, 0x0e, 0x05, 0x01, 0x05, - 0x0f, 0x1f, 0x34, 0x4d, 0x68, 0x81, 0x9a, 0xb0, - 0xc1, 0xcd, 0xd3, 0xd3, 0xd0, 0xc8, 0xbf, 0xb5, - - 0xab, 0xa4, 0x9f, 0x9c, 0x9d, 0xa0, 0xa5, 0xaa, - 0xae, 0xb1, 0xb0, 0xab, 0xa3, 0x96, 0x87, 0x76, - 0x63, 0x51, 0x42, 0x36, 0x2f, 0x2d, 0x31, 0x3a, - 0x48, 0x59, 0x6b, 0x7e, 0x8e, 0x9c, 0xa6, 0xaa, - 0xa9, 0xa3, 0x98, 0x8a, 0x7b, 0x6c, 0x5d, 0x52, - 0x4a, 0x48, 0x4a, 0x50, 0x5a, 0x67, 0x75, 0x82 -}; - -// waveform shape table for HF peaks, formants 6,7,8 -#define N_WAVEMULT 128 -static int wavemult_offset=0; -static int wavemult_max=0; - -// the presets are for 22050 Hz sample rate. -// A different rate will need to recalculate the presets in WavegenInit() -static unsigned char wavemult[N_WAVEMULT] = { - 0, 0, 0, 2, 3, 5, 8, 11, 14, 18, 22, 27, 32, 37, 43, 49, - 55, 62, 69, 76, 83, 90, 98,105,113,121,128,136,144,152,159,166, - 174,181,188,194,201,207,213,218,224,228,233,237,240,244,246,249, - 251,252,253,253,253,253,252,251,249,246,244,240,237,233,228,224, - 218,213,207,201,194,188,181,174,166,159,152,144,136,128,121,113, - 105, 98, 90, 83, 76, 69, 62, 55, 49, 43, 37, 32, 27, 22, 18, 14, - 11, 8, 5, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - -// set from y = pow(2,x) * 128, x=-1 to 1 -unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1] = { - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 86, 87, 88, - 89, 91, 92, 93, 94, 96, 97, 98, - 100,101,103,104,105,107,108,110, - 111,113,115,116,118,119,121,123, - 124,126,128,130,132,133,135,137, - 139,141,143,145,147,149,151,153, - 155,158,160,162,164,167,169,171, - 174,176,179,181,184,186,189,191, - 194,197,199,202,205,208,211,214, - 217,220,223,226,229,232,236,239, - 242,246,249,252, 254,255 }; - -int WavegenFill(int fill_zeros); - - -#ifdef LOG_FRAMES -static void LogMarker(int type, int value) -{//======================================= - if(option_log_frames == 0) - return; - - if((type == espeakEVENT_PHONEME) || (type == espeakEVENT_SENTENCE)) - { - f_log=fopen("log-espeakedit","a"); - if(f_log) - { - if(type == espeakEVENT_PHONEME) - fprintf(f_log,"Phoneme [%s]\n",WordToString(value)); - else - fprintf(f_log,"\n"); - fclose(f_log); - f_log = NULL; - } - } -} -#endif - -void WcmdqStop() -{//============= - wcmdq_head = 0; - wcmdq_tail = 0; -#ifdef USE_PORTAUDIO - Pa_AbortStream(pa_stream); -#endif -} - - -int WcmdqFree() -{//============ - int i; - i = wcmdq_head - wcmdq_tail; - if(i <= 0) i += N_WCMDQ; - return(i); -} - -int WcmdqUsed() -{//============ - return(N_WCMDQ - WcmdqFree()); -} - - -void WcmdqInc() -{//============ - wcmdq_tail++; - if(wcmdq_tail >= N_WCMDQ) wcmdq_tail=0; -} - -static void WcmdqIncHead() -{//======================= - wcmdq_head++; - if(wcmdq_head >= N_WCMDQ) wcmdq_head=0; -} - - - -// data points from which to make the presets for pk_shape1 and pk_shape2 -#define PEAKSHAPEW 256 -static const float pk_shape_x[2][8] = { - {0,-0.6f, 0.0f, 0.6f, 1.4f, 2.5f, 4.5f, 5.5f}, - {0,-0.6f, 0.0f, 0.6f, 1.4f, 2.0f, 4.5f, 5.5f }}; -static const float pk_shape_y[2][8] = { - {0, 67, 81, 67, 31, 14, 0, -6} , - {0, 77, 81, 77, 31, 7, 0, -6 }}; - -unsigned char pk_shape1[PEAKSHAPEW+1] = { - 255,254,254,254,254,254,253,253,252,251,251,250,249,248,247,246, - 245,244,242,241,239,238,236,234,233,231,229,227,225,223,220,218, - 216,213,211,209,207,205,203,201,199,197,195,193,191,189,187,185, - 183,180,178,176,173,171,169,166,164,161,159,156,154,151,148,146, - 143,140,138,135,132,129,126,123,120,118,115,112,108,105,102, 99, - 96, 95, 93, 91, 90, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, - 72, 70, 69, 68, 67, 66, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, - 55, 54, 53, 52, 52, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 46, - 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 44, 43, - 42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33, - 32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24, - 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 18, 17, 17, 16, - 16, 15, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10, - 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, - 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }; - -static unsigned char pk_shape2[PEAKSHAPEW+1] = { - 255,254,254,254,254,254,254,254,254,254,253,253,253,253,252,252, - 252,251,251,251,250,250,249,249,248,248,247,247,246,245,245,244, - 243,243,242,241,239,237,235,233,231,229,227,225,223,221,218,216, - 213,211,208,205,203,200,197,194,191,187,184,181,178,174,171,167, - 163,160,156,152,148,144,140,136,132,127,123,119,114,110,105,100, - 96, 94, 91, 88, 86, 83, 81, 78, 76, 74, 71, 69, 66, 64, 62, 60, - 57, 55, 53, 51, 49, 47, 44, 42, 40, 38, 36, 34, 32, 30, 29, 27, - 25, 23, 21, 19, 18, 16, 14, 12, 11, 9, 7, 6, 4, 3, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }; - -static unsigned char *pk_shape; - - -static void WavegenInitPkData(int which) -{//===================================== -// this is only needed to set up the presets for pk_shape1 and pk_shape2 -// These have already been pre-calculated and preset -#ifdef deleted - int ix; - int p; - float x; - float y[PEAKSHAPEW]; - float maxy=0; - - if(which==0) - pk_shape = pk_shape1; - else - pk_shape = pk_shape2; - - p = 0; - for(ix=0;ix<PEAKSHAPEW;ix++) - { - x = (4.5*ix)/PEAKSHAPEW; - if(x >= pk_shape_x[which][p+3]) p++; - y[ix] = polint(&pk_shape_x[which][p],&pk_shape_y[which][p],3,x); - if(y[ix] > maxy) maxy = y[ix]; - } - for(ix=0;ix<PEAKSHAPEW;ix++) - { - p = (int)(y[ix]*255/maxy); - pk_shape[ix] = (p >= 0) ? p : 0; - } - pk_shape[PEAKSHAPEW]=0; -#endif -} // end of WavegenInitPkData - - - -#ifdef USE_PORTAUDIO -// PortAudio interface - -static int userdata[4]; -static PaError pa_init_err=0; -static int out_channels=1; - -#if USE_PORTAUDIO == 18 -static int WaveCallback(void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, PaTimestamp outTime, void *userData ) -#else -static int WaveCallback(const void *inputBuffer, void *outputBuffer, - long unsigned int framesPerBuffer, const PaStreamCallbackTimeInfo *outTime, - PaStreamCallbackFlags flags, void *userData ) -#endif -{ - int ix; - int result; - unsigned char *p; - - out_ptr = out_start = (unsigned char *)outputBuffer; - out_end = out_ptr + framesPerBuffer*2; - -#ifdef LIBRARY - event_list_ix = 0; -#endif - - result = WavegenFill(1); - -#ifdef LIBRARY - count_samples += framesPerBuffer; - if(synth_callback) - { - // synchronous-playback mode, allow the calling process to abort the speech - event_list[event_list_ix].type = espeakEVENT_LIST_TERMINATED; // indicates end of event list - event_list[event_list_ix].user_data = 0; - - if(synth_callback(NULL,0,event_list) == 1) - { - SpeakNextClause(NULL,NULL,2); // stop speaking - result = 1; - } - } -#endif - -#ifdef ARCH_BIG - { - // swap the order of bytes in each sound sample in the portaudio buffer - int c; - out_ptr = (unsigned char *)outputBuffer; - out_end = out_ptr + framesPerBuffer*2; - while(out_ptr < out_end) - { - c = out_ptr[0]; - out_ptr[0] = out_ptr[1]; - out_ptr[1] = c; - out_ptr += 2; - } - } -#endif - - if(out_channels == 2) - { - // sound output can only do stereo, not mono. Duplicate each sound sample to - // produce 2 channels. - out_ptr = (unsigned char *)outputBuffer; - for(ix=framesPerBuffer-1; ix>=0; ix--) - { - p = &out_ptr[ix*4]; - p[3] = p[1] = out_ptr[ix*2 + 1]; - p[2] = p[0] = out_ptr[ix*2]; - } - } - -#if USE_PORTAUDIO == 18 -#ifdef PLATFORM_WINDOWS - return(result); -#endif - if(result != 0) - { - static int end_timer = 0; - if(end_timer == 0) - end_timer = 4; - if(end_timer > 0) - { - end_timer--; - if(end_timer == 0) - return(1); - } - } - return(0); -#else - return(result); -#endif - -} // end of WaveCallBack - - -#if USE_PORTAUDIO == 19 -/* This is a fixed version of Pa_OpenDefaultStream() for use if the version in portaudio V19 - is broken */ - -static PaError Pa_OpenDefaultStream2( PaStream** stream, - int inputChannelCount, - int outputChannelCount, - PaSampleFormat sampleFormat, - double sampleRate, - unsigned long framesPerBuffer, - PaStreamCallback *streamCallback, - void *userData ) -{ - PaError result; - PaStreamParameters hostApiOutputParameters; - - if(option_device_number >= 0) - hostApiOutputParameters.device = option_device_number; - else - hostApiOutputParameters.device = Pa_GetDefaultOutputDevice(); - - if( hostApiOutputParameters.device == paNoDevice ) - return paDeviceUnavailable; - - hostApiOutputParameters.channelCount = outputChannelCount; - hostApiOutputParameters.sampleFormat = sampleFormat; - /* defaultHighOutputLatency is used below instead of - defaultLowOutputLatency because it is more important for the default - stream to work reliably than it is for it to work with the lowest - latency. - */ - hostApiOutputParameters.suggestedLatency = - Pa_GetDeviceInfo( hostApiOutputParameters.device )->defaultHighOutputLatency; - hostApiOutputParameters.hostApiSpecificStreamInfo = NULL; - - result = Pa_OpenStream( - stream, NULL, &hostApiOutputParameters, sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData ); - - return(result); -} -#endif - - -int WavegenOpenSound() -{//=================== - PaError err, err2; - PaError active; - - if(option_waveout || option_quiet) - { - // writing to WAV file, not to portaudio - return(0); - } - -#if USE_PORTAUDIO == 18 - active = Pa_StreamActive(pa_stream); -#else - active = Pa_IsStreamActive(pa_stream); -#endif - - if(active == 1) - return(0); - if(active < 0) - { - out_channels = 1; - -#if USE_PORTAUDIO == 18 - err2 = Pa_OpenDefaultStream(&pa_stream,0,1,paInt16,samplerate,512,N_WAV_BUF,WaveCallback,(void *)userdata); - - if(err2 == paInvalidChannelCount) - { - // failed to open with mono, try stereo - out_channels=2; - err2 = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,samplerate,512,N_WAV_BUF,WaveCallback,(void *)userdata); - } -#else - err2 = Pa_OpenDefaultStream2(&pa_stream,0,1,paInt16,(double)samplerate,512,WaveCallback,(void *)userdata); - - if(err2 == paInvalidChannelCount) - { - // failed to open with mono, try stereo - out_channels=2; - err2 = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,(double)samplerate,512,WaveCallback,(void *)userdata); - } -#endif - } - err = Pa_StartStream(pa_stream); - -#if USE_PORTAUDIO == 19 - if(err == paStreamIsNotStopped) - { - // not sure why we need this, but PA v19 seems to need it - err = Pa_StopStream(pa_stream); - err = Pa_StartStream(pa_stream); - } -#endif - - if(err != paNoError) - { - // exit speak if we can't open the sound device - this is OK if speak is being run for each utterance - exit(2); - } - - return(0); -} - - - -int WavegenCloseSound() -{//==================== - PaError active; - - // check whether speaking has finished, and close the stream - if(pa_stream != NULL) - { -#if USE_PORTAUDIO == 18 - active = Pa_StreamActive(pa_stream); -#else - active = Pa_IsStreamActive(pa_stream); -#endif - if(WcmdqUsed() == 0) // also check that the queue is empty - { - if(active == 0) - { - Pa_CloseStream(pa_stream); - pa_stream = NULL; - return(1); - } - } - else - { - WavegenOpenSound(); // still items in the queue, shouldn't be closed - } - } - return(0); -} - - -int WavegenInitSound() -{//=================== - PaError err; - - if(option_quiet) - return(0); - - // PortAudio sound output library - err = Pa_Initialize(); - pa_init_err = err; - if(err != paNoError) - { - fprintf(stderr,"Failed to initialise the PortAudio sound\n"); - return(1); - } - return(0); -} -#else -int WavegenOpenSound() -{//=================== - return(0); -} -int WavegenCloseSound() -{//==================== - return(0); -} -int WavegenInitSound() -{//=================== - return(0); -} -#endif - - -void WavegenInit(int rate, int wavemult_fact) -{//========================================== - int ix; - double x; - - if(wavemult_fact == 0) - wavemult_fact=60; // default - - wvoice = NULL; - samplerate = samplerate_native = rate; - PHASE_INC_FACTOR = 0x8000000 / samplerate; // assumes pitch is Hz*32 - Flutter_inc = (64 * samplerate)/rate; - samplecount = 0; - nsamples = 0; - wavephase = 0x7fffffff; - max_hval = 0; - - wdata.amplitude = 32; - wdata.prev_was_synth = 0; - - for(ix=0; ix<N_EMBEDDED_VALUES; ix++) - embedded_value[ix] = embedded_default[ix]; - - - // set up window to generate a spread of harmonics from a - // single peak for HF peaks - wavemult_max = (samplerate * wavemult_fact)/(256 * 50); - if(wavemult_max > N_WAVEMULT) wavemult_max = N_WAVEMULT; - - wavemult_offset = wavemult_max/2; - - if(samplerate != 22050) - { - // wavemult table has preset values for 22050 Hz, we only need to - // recalculate them if we have a different sample rate - for(ix=0; ix<wavemult_max; ix++) - { - x = 127*(1.0 - cos(PI2*ix/wavemult_max)); - wavemult[ix] = (int)x; - } - } - - WavegenInitPkData(1); - WavegenInitPkData(0); - pk_shape = pk_shape2; // pk_shape2 - -#ifdef INCLUDE_KLATT - KlattInit(); -#endif - -#ifdef LOG_FRAMES -remove("log-espeakedit"); -#endif -} // end of WavegenInit - - -int GetAmplitude(void) -{//=================== - int amp; - - // normal, none, reduced, moderate, strong - static const unsigned char amp_emphasis[5] = {16, 16, 10, 16, 22}; - - amp = (embedded_value[EMBED_A])*55/100; - general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16; - return(general_amplitude); -} - - -static void WavegenSetEcho(void) -{//============================= - int delay; - int amp; - - voicing = wvoice->voicing; - delay = wvoice->echo_delay; - amp = wvoice->echo_amp; - - if(delay >= N_ECHO_BUF) - delay = N_ECHO_BUF-1; - if(amp > 100) - amp = 100; - - memset(echo_buf,0,sizeof(echo_buf)); - echo_tail = 0; - - if(embedded_value[EMBED_H] > 0) - { - // set echo from an embedded command in the text - amp = embedded_value[EMBED_H]; - delay = 130; - } - if(embedded_value[EMBED_T] > 0) - { - // announcing punctuation - amp = embedded_value[EMBED_T] * 8; - delay = 60; - } - - if(delay == 0) - amp = 0; - - echo_head = (delay * samplerate)/1000; - echo_length = echo_head; // ensure completion of echo at the end of speech. Use 1 delay period? - if(amp == 0) - echo_length = 0; - if(amp > 20) - echo_length = echo_head * 2; // perhaps allow 2 echo periods if the echo is loud. - - // echo_amp units are 1/256ths of the amplitude of the original sound. - echo_amp = amp; - // compensate (partially) for increase in amplitude due to echo - general_amplitude = GetAmplitude(); - general_amplitude = ((general_amplitude * (500-amp))/500); -} // end of WavegenSetEcho - - - -int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) -{//============================================================================ -// Calculate the amplitude of each harmonics from the formants -// Only for formants 0 to 5 - -// control 0=initial call, 1=every 64 cycles - - // pitch and freqs are Hz<<16 - - int f; - wavegen_peaks_t *p; - int fp; // centre freq of peak - int fhi; // high freq of peak - int h; // harmonic number - int pk; - int hmax; - int hmax_samplerate; // highest harmonic allowed for the samplerate - int x; - int ix; - int h1; - -#ifdef SPECT_EDITOR - if(harm_sqrt_n > 0) - return(HarmToHarmspect(pitch,htab)); -#endif - - // initialise as much of *out as we will need - if(wvoice == NULL) - return(1); - hmax = (peaks[wvoice->n_harmonic_peaks].freq + peaks[wvoice->n_harmonic_peaks].right)/pitch; - if(hmax >= MAX_HARMONIC) - hmax = MAX_HARMONIC-1; - - // restrict highest harmonic to half the samplerate - hmax_samplerate = (((samplerate * 19)/40) << 16)/pitch; // only 95% of Nyquist freq -// hmax_samplerate = (samplerate << 16)/(pitch*2); - - if(hmax > hmax_samplerate) - hmax = hmax_samplerate; - - for(h=0;h<=hmax;h++) - htab[h]=0; - - h=0; - for(pk=0; pk<=wvoice->n_harmonic_peaks; pk++) - { - p = &peaks[pk]; - if((p->height == 0) || (fp = p->freq)==0) - continue; - - fhi = p->freq + p->right; - h = ((p->freq - p->left) / pitch) + 1; - if(h <= 0) h = 1; - - for(f=pitch*h; f < fp; f+=pitch) - { - htab[h++] += pk_shape[(fp-f)/(p->left>>8)] * p->height; - } - for(; f < fhi; f+=pitch) - { - htab[h++] += pk_shape[(f-fp)/(p->right>>8)] * p->height; - } - } - -{ -int y; -int h2; - // increase bass - y = peaks[1].height * 10; // addition as a multiple of 1/256s - h2 = (1000<<16)/pitch; // decrease until 1000Hz - if(h2 > 0) - { - x = y/h2; - h = 1; - while(y > 0) - { - htab[h++] += y; - y -= x; - } - } -} - - // find the nearest harmonic for HF peaks where we don't use shape - for(; pk<N_PEAKS; pk++) - { - x = peaks[pk].height >> 14; - peak_height[pk] = (x * x * 5)/2; - - // find the nearest harmonic for HF peaks where we don't use shape - if(control == 0) - { - // set this initially, but make changes only at the quiet point - peak_harmonic[pk] = peaks[pk].freq / pitch; - } - // only use harmonics up to half the samplerate - if(peak_harmonic[pk] >= hmax_samplerate) - peak_height[pk] = 0; - } - - // convert from the square-rooted values - f = 0; - for(h=0; h<=hmax; h++, f+=pitch) - { - x = htab[h] >> 15; - htab[h] = (x * x) >> 8; - - if((ix = (f >> 19)) < N_TONE_ADJUST) - { - htab[h] = (htab[h] * wvoice->tone_adjust[ix]) >> 13; // index tone_adjust with Hz/8 - } - } - - // adjust the amplitude of the first harmonic, affects tonal quality - h1 = htab[1] * option_harmonic1; - htab[1] = h1/8; - - - // calc intermediate increments of LF harmonics - if(control & 1) - { - for(h=1; h<N_LOWHARM; h++) - { - harm_inc[h] = (htab[h] - harmspect[h]) >> 3; - } - } - - return(hmax); // highest harmonic number -} // end of PeaksToHarmspect - - - -static void AdvanceParameters() -{//============================ -// Called every 64 samples to increment the formant freq, height, and widths - - int x; - int ix; - static int Flutter_ix = 0; - - // advance the pitch - wdata.pitch_ix += wdata.pitch_inc; - if((ix = wdata.pitch_ix>>8) > 127) ix = 127; - x = wdata.pitch_env[ix] * wdata.pitch_range; - wdata.pitch = (x>>8) + wdata.pitch_base; - - amp_ix += amp_inc; - - /* add pitch flutter */ - if(Flutter_ix >= (N_FLUTTER*64)) - Flutter_ix = 0; - x = ((int)(Flutter_tab[Flutter_ix >> 6])-0x80) * flutter_amp; - Flutter_ix += Flutter_inc; - wdata.pitch += x; - if(wdata.pitch < 102400) - wdata.pitch = 102400; // min pitch, 25 Hz (25 << 12) - - if(samplecount == samplecount_start) - return; - - for(ix=0; ix <= wvoice->n_harmonic_peaks; ix++) - { - peaks[ix].freq1 += peaks[ix].freq_inc; - peaks[ix].freq = (int)(peaks[ix].freq1); - peaks[ix].height1 += peaks[ix].height_inc; - if((peaks[ix].height = (int)(peaks[ix].height1)) < 0) - peaks[ix].height = 0; - peaks[ix].left1 += peaks[ix].left_inc; - peaks[ix].left = (int)(peaks[ix].left1); - if(ix < 3) - { - peaks[ix].right1 += peaks[ix].right_inc; - peaks[ix].right = (int)(peaks[ix].right1); - } - else - { - peaks[ix].right = peaks[ix].left; - } - } - for(;ix < 8; ix++) - { - // formants 6,7,8 don't have a width parameter - if(ix < 7) - { - peaks[ix].freq1 += peaks[ix].freq_inc; - peaks[ix].freq = (int)(peaks[ix].freq1); - } - peaks[ix].height1 += peaks[ix].height_inc; - if((peaks[ix].height = (int)(peaks[ix].height1)) < 0) - peaks[ix].height = 0; - } - -#ifdef SPECT_EDITOR - if(harm_sqrt_n != 0) - { - // We are generating from a harmonic spectrum at a given pitch, not from formant peaks - for(ix=0; ix<harm_sqrt_n; ix++) - harm_sqrt[ix] += harm_sqrt_inc[ix]; - } -#endif -} // end of AdvanceParameters - - -#ifndef PLATFORM_RISCOS -static double resonator(RESONATOR *r, double input) -{//================================================ - double x; - - x = r->a * input + r->b * r->x1 + r->c * r->x2; - r->x2 = r->x1; - r->x1 = x; - - return x; -} - - - -static void setresonator(RESONATOR *rp, int freq, int bwidth, int init) -{//==================================================================== -// freq Frequency of resonator in Hz -// bwidth Bandwidth of resonator in Hz -// init Initialize internal data - - double x; - double arg; - - if(init) - { - rp->x1 = 0; - rp->x2 = 0; - } - - // x = exp(-pi * bwidth * t) - arg = minus_pi_t * bwidth; - x = exp(arg); - - // c = -(x*x) - rp->c = -(x * x); - - // b = x * 2*cos(2 pi * freq * t) - - arg = two_pi_t * freq; - rp->b = x * cos(arg) * 2.0; - - // a = 1.0 - b - c - rp->a = 1.0 - rp->b - rp->c; -} // end if setresonator -#endif - - -void InitBreath(void) -{//================== -#ifndef PLATFORM_RISCOS - int ix; - - minus_pi_t = -PI / samplerate; - two_pi_t = -2.0 * minus_pi_t; - - for(ix=0; ix<N_PEAKS; ix++) - { - setresonator(&rbreath[ix],2000,200,1); - } -#endif -} // end of InitBreath - - - -static void SetBreath() -{//==================== -#ifndef PLATFORM_RISCOS - int pk; - - if(wvoice->breath[0] == 0) - return; - - for(pk=1; pk<N_PEAKS; pk++) - { - if(wvoice->breath[pk] != 0) - { - // breath[0] indicates that some breath formants are needed - // set the freq from the current ynthesis formant and the width from the voice data - setresonator(&rbreath[pk], peaks[pk].freq >> 16, wvoice->breathw[pk],0); - } - } -#endif -} // end of SetBreath - - -static int ApplyBreath(void) -{//========================= - int value = 0; -#ifndef PLATFORM_RISCOS - int noise; - int ix; - int amp; - - // use two random numbers, for alternate formants - noise = (rand() & 0x3fff) - 0x2000; - - for(ix=1; ix < N_PEAKS; ix++) - { - if((amp = wvoice->breath[ix]) != 0) - { - amp *= (peaks[ix].height >> 14); - value += (int)(resonator(&rbreath[ix],noise) * amp); - } - } -#endif - return (value); -} - - - -int Wavegen() -{//========== - unsigned short waveph; - unsigned short theta; - int total; - int h; - int ix; - int z, z1, z2; - int echo; - int ov; - static int maxh, maxh2; - int pk; - signed char c; - int sample; - int amp; - int modn_amp, modn_period; - static int agc = 256; - static int h_switch_sign = 0; - static int cycle_count = 0; - static int amplitude2 = 0; // adjusted for pitch - - // continue until the output buffer is full, or - // the required number of samples have been produced - - for(;;) - { - if((end_wave==0) && (samplecount==nsamples)) - return(0); - - if((samplecount & 0x3f) == 0) - { - // every 64 samples, adjust the parameters - if(samplecount == 0) - { - hswitch = 0; - harmspect = hspect[0]; - maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[0], 0); - - // adjust amplitude to compensate for fewer harmonics at higher pitch - amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11); - - // switch sign of harmonics above about 900Hz, to reduce max peak amplitude - h_switch_sign = 890 / (wdata.pitch >> 12); - } - else - AdvanceParameters(); - - // pitch is Hz<<12 - phaseinc = (wdata.pitch>>7) * PHASE_INC_FACTOR; - cycle_samples = samplerate/(wdata.pitch >> 12); // sr/(pitch*2) - hf_factor = wdata.pitch >> 11; - - maxh = maxh2; - harmspect = hspect[hswitch]; - hswitch ^= 1; - maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[hswitch], 1); - - SetBreath(); - } - else - if((samplecount & 0x07) == 0) - { - for(h=1; h<N_LOWHARM && h<=maxh2 && h<=maxh; h++) - { - harmspect[h] += harm_inc[h]; - } - - // bring automctic gain control back towards unity - if(agc < 256) agc++; - } - - samplecount++; - - if(wavephase > 0) - { - wavephase += phaseinc; - if(wavephase < 0) - { - // sign has changed, reached a quiet point in the waveform - cbytes = wavemult_offset - (cycle_samples)/2; - if(samplecount > nsamples) - return(0); - - cycle_count++; - - for(pk=wvoice->n_harmonic_peaks+1; pk<N_PEAKS; pk++) - { - // find the nearest harmonic for HF peaks where we don't use shape - peak_harmonic[pk] = peaks[pk].freq / (wdata.pitch*16); - } - - // adjust amplitude to compensate for fewer harmonics at higher pitch - amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11); - - if(glottal_flag > 0) - { - if(glottal_flag == 3) - { - if((nsamples-samplecount) < (cycle_samples*2)) - { - // Vowel before glottal-stop. - // This is the start of the penultimate cycle, reduce its amplitude - glottal_flag = 2; - amplitude2 = (amplitude2 * glottal_reduce)/256; - } - } - else - if(glottal_flag == 4) - { - // Vowel following a glottal-stop. - // This is the start of the second cycle, reduce its amplitude - glottal_flag = 2; - amplitude2 = (amplitude2 * glottal_reduce)/256; - } - else - { - glottal_flag--; - } - } - - if(amplitude_env != NULL) - { - // amplitude envelope is only used for creaky voice effect on certain vowels/tones - if((ix = amp_ix>>8) > 127) ix = 127; - amp = amplitude_env[ix]; - amplitude2 = (amplitude2 * amp)/128; -// if(amp < 255) -// modulation_type = 7; - } - - // introduce roughness into the sound by reducing the amplitude of - modn_period = 0; - if(voice->roughness < N_ROUGHNESS) - { - modn_period = modulation_tab[voice->roughness][modulation_type]; - modn_amp = modn_period & 0xf; - modn_period = modn_period >> 4; - } - - if(modn_period != 0) - { - if(modn_period==0xf) - { - // just once */ - amplitude2 = (amplitude2 * modn_amp)/16; - modulation_type = 0; - } - else - { - // reduce amplitude every [modn_period} cycles - if((cycle_count % modn_period)==0) - amplitude2 = (amplitude2 * modn_amp)/16; - } - } - } - } - else - { - wavephase += phaseinc; - } - waveph = (unsigned short)(wavephase >> 16); - total = 0; - - // apply HF peaks, formants 6,7,8 - // add a single harmonic and then spread this my multiplying by a - // window. This is to reduce the processing power needed to add the - // higher frequence harmonics. - cbytes++; - if(cbytes >=0 && cbytes<wavemult_max) - { - for(pk=wvoice->n_harmonic_peaks+1; pk<N_PEAKS; pk++) - { - theta = peak_harmonic[pk] * waveph; - total += (long)sin_tab[theta >> 5] * peak_height[pk]; - } - - // spread the peaks by multiplying by a window - total = (long)(total / hf_factor) * wavemult[cbytes]; - } - - // apply main peaks, formants 0 to 5 -#ifdef USE_ASSEMBLER_1 - // use an optimised routine for this loop, if available - total += AddSineWaves(waveph, h_switch_sign, maxh, harmspect); // call an assembler code routine -#else - theta = waveph; - - for(h=1; h<=h_switch_sign; h++) - { - total += ((int)(sin_tab[theta >> 5]) * harmspect[h]); - theta += waveph; - } - while(h<=maxh) - { - total -= ((int)(sin_tab[theta >> 5]) * harmspect[h]); - theta += waveph; - h++; - } -#endif - - if(voicing != 64) - { - total = (total >> 6) * voicing; - } - -#ifndef PLATFORM_RISCOS - if(wvoice->breath[0]) - { - total += ApplyBreath(); - } -#endif - - // mix with sampled wave if required - z2 = 0; - if(wdata.mix_wavefile_ix < wdata.n_mix_wavefile) - { - if(wdata.mix_wave_scale == 0) - { - // a 16 bit sample - c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1]; - sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256); - wdata.mix_wavefile_ix += 2; - } - else - { - // a 8 bit sample, scaled - sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale; - } - z2 = (sample * wdata.amplitude_v) >> 10; - z2 = (z2 * wdata.mix_wave_amp)/32; - } - - z1 = z2 + (((total>>8) * amplitude2) >> 13); - - echo = (echo_buf[echo_tail++] * echo_amp); - z1 += echo >> 8; - if(echo_tail >= N_ECHO_BUF) - echo_tail=0; - - z = (z1 * agc) >> 8; - - // check for overflow, 16bit signed samples - if(z >= 32768) - { - ov = 8388608/z1 - 1; // 8388608 is 2^23, i.e. max value * 256 - if(ov < agc) agc = ov; // set agc to number of 1/256ths to multiply the sample by - z = (z1 * agc) >> 8; // reduce sample by agc value to prevent overflow - } - else - if(z <= -32768) - { - ov = -8388608/z1 - 1; - if(ov < agc) agc = ov; - z = (z1 * agc) >> 8; - } - *out_ptr++ = z; - *out_ptr++ = z >> 8; - - echo_buf[echo_head++] = z; - if(echo_head >= N_ECHO_BUF) - echo_head = 0; - - if(out_ptr >= out_end) - return(1); - } - return(0); -} // end of Wavegen - - -static int PlaySilence(int length, int resume) -{//=========================================== - static int n_samples; - int value=0; - - if(length == 0) - return(0); - - nsamples = 0; - samplecount = 0; - - if(resume==0) - n_samples = length; - - while(n_samples-- > 0) - { - value = (echo_buf[echo_tail++] * echo_amp) >> 8; - - if(echo_tail >= N_ECHO_BUF) - echo_tail = 0; - - *out_ptr++ = value; - *out_ptr++ = value >> 8; - - echo_buf[echo_head++] = value; - if(echo_head >= N_ECHO_BUF) - echo_head = 0; - - if(out_ptr >= out_end) - return(1); - } - return(0); -} // end of PlaySilence - - - -static int PlayWave(int length, int resume, unsigned char *data, int scale, int amp) -{//================================================================================= - static int n_samples; - static int ix=0; - int value; - signed char c; - - if(resume==0) - { - n_samples = length; - ix = 0; - } - - nsamples = 0; - samplecount = 0; - - while(n_samples-- > 0) - { - if(scale == 0) - { - // 16 bits data - c = data[ix+1]; - value = data[ix] + (c * 256); - ix+=2; - } - else - { - // 8 bit data, shift by the specified scale factor - value = (signed char)data[ix++] * scale; - } - value *= (consonant_amp * general_amplitude); // reduce strength of consonant - value = value >> 10; - value = (value * amp)/32; - - value += ((echo_buf[echo_tail++] * echo_amp) >> 8); - - if(value > 32767) - value = 32768; - else - if(value < -32768) - value = -32768; - - if(echo_tail >= N_ECHO_BUF) - echo_tail = 0; - - out_ptr[0] = value; - out_ptr[1] = value >> 8; - out_ptr+=2; - - echo_buf[echo_head++] = (value*3)/4; - if(echo_head >= N_ECHO_BUF) - echo_head = 0; - - if(out_ptr >= out_end) - return(1); - } - return(0); -} - - -static int SetWithRange0(int value, int max) -{//========================================= - if(value < 0) - return(0); - if(value > max) - return(max); - return(value); -} - - -void SetEmbedded(int control, int value) -{//===================================== - // there was an embedded command in the text at this point - int sign=0; - int command; - int ix; - int factor; - int pitch_value; - - command = control & 0x1f; - if((control & 0x60) == 0x60) - sign = -1; - else - if((control & 0x60) == 0x40) - sign = 1; - - if(command < N_EMBEDDED_VALUES) - { - if(sign == 0) - embedded_value[command] = value; - else - embedded_value[command] += (value * sign); - embedded_value[command] = SetWithRange0(embedded_value[command],embedded_max[command]); - } - - switch(command) - { - case EMBED_T: - WavegenSetEcho(); // and drop through to case P - case EMBED_P: - // adjust formants to give better results for a different voice pitch - if((pitch_value = embedded_value[EMBED_P]) > MAX_PITCH_VALUE) - pitch_value = MAX_PITCH_VALUE; - - factor = 256 + (25 * (pitch_value - 50))/50; - for(ix=0; ix<=5; ix++) - { - wvoice->freq[ix] = (wvoice->freq2[ix] * factor)/256; - } - factor = embedded_value[EMBED_T]*3; - wvoice->height[0] = (wvoice->height2[0] * (256 - factor*2))/256; - wvoice->height[1] = (wvoice->height2[1] * (256 - factor))/256; - break; - - case EMBED_A: // amplitude - general_amplitude = GetAmplitude(); - break; - - case EMBED_F: // emphasiis - general_amplitude = GetAmplitude(); - break; - - case EMBED_H: - WavegenSetEcho(); - break; - } -} - - -void WavegenSetVoice(voice_t *v) -{//============================= - static voice_t v2; - - memcpy(&v2,v,sizeof(v2)); - wvoice = &v2; - - if(v->peak_shape==0) - pk_shape = pk_shape1; - else - pk_shape = pk_shape2; - - consonant_amp = (v->consonant_amp * 26) /100; - if(samplerate <= 11000) - { - consonant_amp = consonant_amp*2; // emphasize consonants at low sample rates - option_harmonic1 = 6; - } - WavegenSetEcho(); -} - - -static void SetAmplitude(int length, unsigned char *amp_env, int value) -{//==================================================================== - amp_ix = 0; - if(length==0) - amp_inc = 0; - else - amp_inc = (256 * ENV_LEN * STEPSIZE)/length; - - wdata.amplitude = (value * general_amplitude)/16; - wdata.amplitude_v = (wdata.amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds - - amplitude_env = amp_env; -} - - -void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pitch_range) -{//====================================================================================== - int x; - int base; - int range; - int pitch_value; - - if(pitch1 > pitch2) - { - x = pitch1; // swap values - pitch1 = pitch2; - pitch2 = x; - } - - if((pitch_value = embedded_value[EMBED_P]) > MAX_PITCH_VALUE) - pitch_value = MAX_PITCH_VALUE; - pitch_value -= embedded_value[EMBED_T]; // adjust tone for announcing punctuation - if(pitch_value < 0) - pitch_value = 0; - - base = (voice->pitch_base * pitch_adjust_tab[pitch_value])/128; - range = (voice->pitch_range * embedded_value[EMBED_R])/50; - - // compensate for change in pitch when the range is narrowed or widened - base -= (range - voice->pitch_range)*18; - - *pitch_base = base + (pitch1 * range); - *pitch_range = base + (pitch2 * range) - *pitch_base; -} - - -void SetPitch(int length, unsigned char *env, int pitch1, int pitch2) -{//================================================================== -// length in samples - -#ifdef LOG_FRAMES -if(option_log_frames) -{ - f_log=fopen("log-espeakedit","a"); - if(f_log != NULL) - { - fprintf(f_log," pitch %3d %3d %3dmS\n",pitch1,pitch2,(length*1000)/samplerate); - fclose(f_log); - f_log=NULL; - } -} -#endif - if((wdata.pitch_env = env)==NULL) - wdata.pitch_env = env_fall; // default - - wdata.pitch_ix = 0; - if(length==0) - wdata.pitch_inc = 0; - else - wdata.pitch_inc = (256 * ENV_LEN * STEPSIZE)/length; - - SetPitch2(wvoice, pitch1, pitch2, &wdata.pitch_base, &wdata.pitch_range); - // set initial pitch - wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12 - - flutter_amp = wvoice->flutter; - -} // end of SetPitch - - - - - -void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) -{//======================================================================== - int ix; - DOUBLEX next; - int length2; - int length4; - int qix; - int cmd; - static int glottal_reduce_tab1[4] = {0x30, 0x30, 0x40, 0x50}; // vowel before [?], amp * 1/256 -// static int glottal_reduce_tab1[4] = {0x30, 0x40, 0x50, 0x60}; // vowel before [?], amp * 1/256 - static int glottal_reduce_tab2[4] = {0x90, 0xa0, 0xb0, 0xc0}; // vowel after [?], amp * 1/256 - -#ifdef LOG_FRAMES -if(option_log_frames) -{ - f_log=fopen("log-espeakedit","a"); - if(f_log != NULL) - { - fprintf(f_log,"%3dmS %3d %3d %4d %4d (%3d %3d %3d %3d) to %3d %3d %4d %4d (%3d %3d %3d %3d)\n",length*1000/samplerate, - fr1->ffreq[0],fr1->ffreq[1],fr1->ffreq[2],fr1->ffreq[3], fr1->fheight[0],fr1->fheight[1],fr1->fheight[2],fr1->fheight[3], - fr2->ffreq[0],fr2->ffreq[1],fr2->ffreq[2],fr2->ffreq[3], fr2->fheight[0],fr2->fheight[1],fr2->fheight[2],fr2->fheight[3] ); - - fclose(f_log); - f_log=NULL; - } -} -#endif - - harm_sqrt_n = 0; - end_wave = 1; - - // any additional information in the param1 ? - modulation_type = modn & 0xff; - - glottal_flag = 0; - if(modn & 0x400) - { - glottal_flag = 3; // before a glottal stop - glottal_reduce = glottal_reduce_tab1[(modn >> 8) & 3]; - } - if(modn & 0x800) - { - glottal_flag = 4; // after a glottal stop - glottal_reduce = glottal_reduce_tab2[(modn >> 8) & 3]; - } - - for(qix=wcmdq_head+1;;qix++) - { - if(qix >= N_WCMDQ) qix = 0; - if(qix == wcmdq_tail) break; - - cmd = wcmdq[qix][0]; - if(cmd==WCMD_SPECT) - { - end_wave = 0; // next wave generation is from another spectrum - break; - } - if((cmd==WCMD_WAVE) || (cmd==WCMD_PAUSE)) - break; // next is not from spectrum, so continue until end of wave cycle - } - - // round the length to a multiple of the stepsize - length2 = (length + STEPSIZE/2) & ~0x3f; - if(length2 == 0) - length2 = STEPSIZE; - - // add this length to any left over from the previous synth - samplecount_start = samplecount; - nsamples += length2; - - length4 = length2/4; - - peaks[7].freq = (7800 * v->freq[7] + v->freqadd[7]*256) << 8; - peaks[8].freq = (9000 * v->freq[8] + v->freqadd[8]*256) << 8; - - for(ix=0; ix < 8; ix++) - { - if(ix < 7) - { - peaks[ix].freq1 = (fr1->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8; - peaks[ix].freq = (int)(peaks[ix].freq1); - next = (fr2->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8; - peaks[ix].freq_inc = ((next - peaks[ix].freq1) * (STEPSIZE/4)) / length4; // lower headroom for fixed point math - } - - peaks[ix].height1 = (fr1->fheight[ix] * v->height[ix]) << 6; - peaks[ix].height = (int)(peaks[ix].height1); - next = (fr2->fheight[ix] * v->height[ix]) << 6; - peaks[ix].height_inc = ((next - peaks[ix].height1) * STEPSIZE) / length2; - - if(ix <= wvoice->n_harmonic_peaks) - { - peaks[ix].left1 = (fr1->fwidth[ix] * v->width[ix]) << 10; - peaks[ix].left = int(peaks[ix].left1); - next = (fr2->fwidth[ix] * v->width[ix]) << 10; - peaks[ix].left_inc = ((next - peaks[ix].left1) * STEPSIZE) / length2; - - if(ix < 3) - { - peaks[ix].right1 = (fr1->fright[ix] * v->width[ix]) << 10; - peaks[ix].right = int(peaks[ix].right1); - next = (fr2->fright[ix] * v->width[ix]) << 10; - peaks[ix].right_inc = ((next - peaks[ix].right1) * STEPSIZE) / length2; - } - else - { - peaks[ix].right = peaks[ix].left; - } - } - } -} // end of SetSynth - - -static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2) -{//==================================================================================== - if(resume==0) - SetSynth(length, modulation, fr1, fr2, wvoice); - - return(Wavegen()); -} - -void Write4Bytes(FILE *f, int value) -{//================================= -// Write 4 bytes to a file, least significant first - int ix; - - for(ix=0; ix<4; ix++) - { - fputc(value & 0xff,f); - value = value >> 8; - } -} - - - - -int WavegenFill(int fill_zeros) -{//============================ -// Pick up next wavegen commands from the queue -// return: 0 output buffer has been filled -// return: 1 input command queue is now empty - - long *q; - int length; - int result; - static int resume=0; - static int echo_complete=0; - -#ifdef TEST_MBROLA - if(mbrola_name[0] != 0) - return(MbrolaFill(fill_zeros)); -#endif - - while(out_ptr < out_end) - { - if(WcmdqUsed() <= 0) - { - if(echo_complete > 0) - { - // continue to play silence until echo is completed - resume = PlaySilence(echo_complete,resume); - if(resume == 1) - return(0); // not yet finished - } - - if(fill_zeros) - { - while(out_ptr < out_end) - *out_ptr++ = 0; - } - return(1); // queue empty, close sound channel - } - - result = 0; - q = wcmdq[wcmdq_head]; - length = q[1]; - - switch(q[0]) - { - case WCMD_PITCH: - SetPitch(length,(unsigned char *)q[2],q[3] >> 16,q[3] & 0xffff); - break; - - case WCMD_PAUSE: - if(resume==0) - { - echo_complete -= length; - } - wdata.n_mix_wavefile = 0; - wdata.prev_was_synth = 0; - result = PlaySilence(length,resume); - break; - - case WCMD_WAVE: - echo_complete = echo_length; - wdata.n_mix_wavefile = 0; - wdata.prev_was_synth = 0; - result = PlayWave(length,resume,(unsigned char*)q[2], q[3] & 0xff, q[3] >> 8); - break; - - case WCMD_WAVE2: - // wave file to be played at the same time as synthesis - wdata.mix_wave_amp = q[3] >> 8; - wdata.mix_wave_scale = q[3] & 0xff; - if(wdata.mix_wave_scale == 0) - wdata.n_mix_wavefile = length*2; - else - wdata.n_mix_wavefile = length; - wdata.mix_wavefile_ix = 0; - wdata.mix_wavefile = (unsigned char *)q[2]; - break; - - case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file - wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case - case WCMD_SPECT: - echo_complete = echo_length; - result = Wavegen2(length & 0xffff,q[1] >> 16,resume,(frame_t *)q[2],(frame_t *)q[3]); - break; - -#ifdef INCLUDE_KLATT - case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file - wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case - case WCMD_KLATT: - echo_complete = echo_length; - result = Wavegen_Klatt2(length & 0xffff,q[1] >> 16,resume,(frame_t *)q[2],(frame_t *)q[3]); - break; -#endif - - case WCMD_MARKER: - MarkerEvent(q[1],q[2],q[3],out_ptr); -#ifdef LOG_FRAMES - LogMarker(q[1],q[3]); -#endif - if(q[1] == 1) - { - current_source_index = q[2] & 0xffffff; - } - break; - - case WCMD_AMPLITUDE: - SetAmplitude(length,(unsigned char *)q[2],q[3]); - break; - - case WCMD_VOICE: - WavegenSetVoice((voice_t *)q[1]); - free((voice_t *)q[1]); - break; - - case WCMD_EMBEDDED: - SetEmbedded(q[1],q[2]); - break; - } - - if(result==0) - { - WcmdqIncHead(); - resume=0; - } - else - { - resume=1; - } - } - - return(0); -} // end of WavegenFill - - |