Some warnings, some globals hunting. Including fixes for asserts misuse (possible fatal for async in release builds).master
| "-Wmissing-prototypes" | "-Wmissing-prototypes" | ||||
| "-Wint-conversion" | "-Wint-conversion" | ||||
| "-Wimplicit" | "-Wimplicit" | ||||
| "-Wmisleading-indentation" | |||||
| ) | ) | ||||
| endif() | endif() | ||||
| target_compile_definitions(espeak-ng PRIVATE "LIBESPEAK_NG_EXPORT=1") | target_compile_definitions(espeak-ng PRIVATE "LIBESPEAK_NG_EXPORT=1") |
| c2 = c2 >> 16; // sign extend | c2 = c2 >> 16; // sign extend | ||||
| return (c1 & 0xff) + c2; | return (c1 & 0xff) + c2; | ||||
| } | |||||
| } |
| } | } | ||||
| c = ' '; | c = ' '; | ||||
| } else if (rb == RULE_ENDING) { | } else if (rb == RULE_ENDING) { | ||||
| static const char *flag_chars = "eipvdfq tba "; | |||||
| static const char flag_chars[] = "eipvdfq tba "; | |||||
| flags = ((rule[0] & 0x7f)<< 8) + (rule[1] & 0x7f); | flags = ((rule[0] & 0x7f)<< 8) + (rule[1] & 0x7f); | ||||
| suffix_char = 'S'; | suffix_char = 'S'; | ||||
| if (flags & (SUFX_P >> 8)) | if (flags & (SUFX_P >> 8)) |
| #include "synthesize.h" // for STRESS_IS_PRIMARY, phoneme... | #include "synthesize.h" // for STRESS_IS_PRIMARY, phoneme... | ||||
| #include "translate.h" // for Translator, utf8_in, LANGU... | #include "translate.h" // for Translator, utf8_in, LANGU... | ||||
| static int LookupFlags(Translator *tr, const char *word, unsigned int **flags_out); | |||||
| static void DollarRule(char *word[], char *word_start, int consumed, int group_length, char *word_buf, Translator *tr, unsigned int *flags, int command, int *failed, int *add_points); | |||||
| static int LookupFlags(Translator *tr, const char *word, unsigned int flags_out[2]); | |||||
| static void DollarRule(char *word[], char *word_start, int consumed, int group_length, char *word_buf, Translator *tr, int command, int *failed, int *add_points); | |||||
| typedef struct { | typedef struct { | ||||
| int points; | int points; | ||||
| // convert characters to an approximate 7 bit ascii equivalent | // convert characters to an approximate 7 bit ascii equivalent | ||||
| // used for checking for vowels (up to 0x259=schwa) | // used for checking for vowels (up to 0x259=schwa) | ||||
| #define N_REMOVE_ACCENT 0x25e | #define N_REMOVE_ACCENT 0x25e | ||||
| static unsigned char remove_accent[N_REMOVE_ACCENT] = { | |||||
| static const unsigned char remove_accent[N_REMOVE_ACCENT] = { | |||||
| 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', // 0c0 | '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 | '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 | 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', // 0e0 | ||||
| unsigned char c; | unsigned char c; | ||||
| unsigned int mnem; | unsigned int mnem; | ||||
| PHONEME_TAB *ph; | PHONEME_TAB *ph; | ||||
| static const char *stress_chars = "==,,'* "; | |||||
| static const char stress_chars[] = "==,,'* "; | |||||
| sprintf(outptr, "* "); | sprintf(outptr, "* "); | ||||
| while ((phcode = *inptr++) > 0) { | while ((phcode = *inptr++) > 0) { | ||||
| char phon_buf2[30]; | char phon_buf2[30]; | ||||
| PHONEME_LIST *plist; | PHONEME_LIST *plist; | ||||
| static const char *stress_chars = "==,,''"; | |||||
| static const char stress_chars[] = "==,,''"; | |||||
| if (phon_out_buf == NULL) { | if (phon_out_buf == NULL) { | ||||
| phon_out_size = N_PHON_OUT; | phon_out_size = N_PHON_OUT; | ||||
| int n_bytes; | int n_bytes; | ||||
| int add_points; | int add_points; | ||||
| int command; | int command; | ||||
| unsigned int *flags = NULL; | |||||
| MatchRecord match; | MatchRecord match; | ||||
| static MatchRecord best; | |||||
| MatchRecord best; | |||||
| int total_consumed; // letters consumed for best match | int total_consumed; // letters consumed for best match | ||||
| else | else | ||||
| failed = 1; | failed = 1; | ||||
| } else if (((command & 0xf0) == 0x20) || (command == DOLLAR_LIST)) { | } else if (((command & 0xf0) == 0x20) || (command == DOLLAR_LIST)) { | ||||
| DollarRule(word, word_start, consumed, group_length, word_buf, tr, flags, command, &failed, &add_points); | |||||
| DollarRule(word, word_start, consumed, group_length, word_buf, tr, command, &failed, &add_points); | |||||
| } | } | ||||
| break; | break; | ||||
| pre_ptr++; | pre_ptr++; | ||||
| command = *rule++; | command = *rule++; | ||||
| if ((command == DOLLAR_LIST) || ((command & 0xf0) == 0x20)) { | if ((command == DOLLAR_LIST) || ((command & 0xf0) == 0x20)) { | ||||
| DollarRule(word, word_start, consumed, group_length, word_buf, tr, flags, command, &failed, &add_points); | |||||
| DollarRule(word, word_start, consumed, group_length, word_buf, tr, command, &failed, &add_points); | |||||
| } | } | ||||
| break; | break; | ||||
| case RULE_SYLLABLE: | case RULE_SYLLABLE: | ||||
| return flags0; | return flags0; | ||||
| } | } | ||||
| static int LookupFlags(Translator *tr, const char *word, unsigned int **flags_out) | |||||
| static int LookupFlags(Translator *tr, const char *word, unsigned int flags_out[2]) | |||||
| { | { | ||||
| char buf[100]; | char buf[100]; | ||||
| static unsigned int flags[2]; | static unsigned int flags[2]; | ||||
| flags[0] = flags[1] = 0; | flags[0] = flags[1] = 0; | ||||
| LookupDictList(tr, &word1, buf, flags, 0, NULL); | LookupDictList(tr, &word1, buf, flags, 0, NULL); | ||||
| *flags_out = flags; | |||||
| flags_out[0] = flags[0]; | |||||
| flags_out[1] = flags[1]; | |||||
| return flags[0]; | return flags[0]; | ||||
| } | } | ||||
| return end_flags; | return end_flags; | ||||
| } | } | ||||
| static void DollarRule(char *word[], char *word_start, int consumed, int group_length, char *word_buf, Translator *tr, unsigned int *flags, int command, int *failed, int *add_points) { | |||||
| static void DollarRule(char *word[], char *word_start, int consumed, int group_length, char *word_buf, Translator *tr, int command, int *failed, int *add_points) { | |||||
| // $list or $p_alt | // $list or $p_alt | ||||
| // make a copy of the word up to the post-match characters | // make a copy of the word up to the post-match characters | ||||
| int ix = *word - word_start + consumed + group_length + 1; | int ix = *word - word_start + consumed + group_length + 1; | ||||
| memcpy(word_buf, word_start-1, ix); | memcpy(word_buf, word_start-1, ix); | ||||
| word_buf[ix] = ' '; | word_buf[ix] = ' '; | ||||
| word_buf[ix+1] = 0; | word_buf[ix+1] = 0; | ||||
| LookupFlags(tr, &word_buf[1], &flags); | |||||
| unsigned int flags[2]; | |||||
| LookupFlags(tr, &word_buf[1], flags); | |||||
| if ((command == DOLLAR_LIST) && (flags[0] & FLAG_FOUND) && !(flags[1] & FLAG_ONLY)) | if ((command == DOLLAR_LIST) && (flags[0] & FLAG_FOUND) && !(flags[1] & FLAG_ONLY)) | ||||
| *add_points = 23; | *add_points = 23; | ||||
| *add_points = 23; | *add_points = 23; | ||||
| else | else | ||||
| *failed = 1; | *failed = 1; | ||||
| } | |||||
| } |
| pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); | pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); | ||||
| init(); | init(); | ||||
| assert(-1 != pthread_cond_init(&my_cond_start_is_required, NULL)); | |||||
| assert(-1 != pthread_cond_init(&my_cond_stop_is_required, NULL)); | |||||
| assert(-1 != pthread_cond_init(&my_cond_stop_is_acknowledged, NULL)); | |||||
| int a_status; | |||||
| a_status = pthread_cond_init(&my_cond_start_is_required, NULL); | |||||
| assert(-1 != a_status); | |||||
| a_status = pthread_cond_init(&my_cond_stop_is_required, NULL); | |||||
| assert(-1 != a_status); | |||||
| a_status = pthread_cond_init(&my_cond_stop_is_acknowledged, NULL); | |||||
| assert(-1 != a_status); | |||||
| (void)a_status; | |||||
| pthread_attr_t a_attrib; | pthread_attr_t a_attrib; | ||||
| return status; | return status; | ||||
| } | } | ||||
| espeak_ng_STATUS event_clear_all() | |||||
| espeak_ng_STATUS event_clear_all(void) | |||||
| { | { | ||||
| espeak_ng_STATUS status; | espeak_ng_STATUS status; | ||||
| if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | ||||
| return ENS_OK; | return ENS_OK; | ||||
| } | } | ||||
| static void *pop() | |||||
| static void *pop(void) | |||||
| { | { | ||||
| void *the_data = NULL; | void *the_data = NULL; | ||||
| } | } | ||||
| static void init() | |||||
| static void init(void) | |||||
| { | { | ||||
| while (event_delete((espeak_EVENT *)pop())) | while (event_delete((espeak_EVENT *)pop())) | ||||
| ; | ; | ||||
| node_counter = 0; | node_counter = 0; | ||||
| } | } | ||||
| void event_terminate() | |||||
| void event_terminate(void) | |||||
| { | { | ||||
| if (thread_inited) { | if (thread_inited) { | ||||
| my_terminate_is_required = true; | my_terminate_is_required = true; | ||||
| if (!ts) | if (!ts) | ||||
| return; | return; | ||||
| assert(gettimeofday(&tv, NULL) != -1); | |||||
| int a_status = gettimeofday(&tv, NULL); | |||||
| assert(a_status != -1); | |||||
| (void)a_status; | |||||
| ts->tv_sec = tv.tv_sec; | ts->tv_sec = tv.tv_sec; | ||||
| ts->tv_nsec = tv.tv_usec*1000; | ts->tv_nsec = tv.tv_usec*1000; | ||||
| } | } |
| MAX_INACTIVITY_CHECK = 2 | MAX_INACTIVITY_CHECK = 2 | ||||
| }; | }; | ||||
| void fifo_init() | |||||
| void fifo_init(void) | |||||
| { | { | ||||
| // security | // security | ||||
| pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); | pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); | ||||
| init(0); | init(0); | ||||
| assert(-1 != pthread_cond_init(&my_cond_command_is_running, NULL)); | |||||
| assert(-1 != pthread_cond_init(&my_cond_start_is_required, NULL)); | |||||
| assert(-1 != pthread_cond_init(&my_cond_stop_is_acknowledged, NULL)); | |||||
| int a_status; | |||||
| a_status = pthread_cond_init(&my_cond_command_is_running, NULL); | |||||
| assert(-1 != a_status); | |||||
| a_status = pthread_cond_init(&my_cond_start_is_required, NULL); | |||||
| assert(-1 != a_status); | |||||
| a_status = pthread_cond_init(&my_cond_stop_is_acknowledged, NULL); | |||||
| assert(-1 != a_status); | |||||
| pthread_attr_t a_attrib; | pthread_attr_t a_attrib; | ||||
| if (pthread_attr_init(&a_attrib) | if (pthread_attr_init(&a_attrib) | ||||
| pthread_attr_destroy(&a_attrib); | pthread_attr_destroy(&a_attrib); | ||||
| // leave once the thread is actually started | // leave once the thread is actually started | ||||
| assert(-1 != pthread_mutex_lock(&my_mutex)); | |||||
| a_status = pthread_mutex_lock(&my_mutex); | |||||
| assert(-1 != a_status); | |||||
| (void)a_status; | |||||
| while (my_stop_is_acknowledged == false) { | while (my_stop_is_acknowledged == false) { | ||||
| while ((pthread_cond_wait(&my_cond_stop_is_acknowledged, &my_mutex) == -1) && errno == EINTR) | while ((pthread_cond_wait(&my_cond_stop_is_acknowledged, &my_mutex) == -1) && errno == EINTR) | ||||
| ; | ; | ||||
| return ENS_OK; | return ENS_OK; | ||||
| } | } | ||||
| espeak_ng_STATUS fifo_stop() | |||||
| espeak_ng_STATUS fifo_stop(void) | |||||
| { | { | ||||
| if (!thread_inited) return ENS_OK; | if (!thread_inited) return ENS_OK; | ||||
| espeak_ng_STATUS status; | espeak_ng_STATUS status; | ||||
| return ENS_OK; | return ENS_OK; | ||||
| } | } | ||||
| int fifo_is_busy() | |||||
| int fifo_is_busy(void) | |||||
| { | { | ||||
| if (!thread_inited) return false; | if (!thread_inited) return false; | ||||
| pthread_mutex_lock(&my_mutex); | pthread_mutex_lock(&my_mutex); | ||||
| return running; | return running; | ||||
| } | } | ||||
| static int sleep_until_start_request_or_inactivity() | |||||
| static int sleep_until_start_request_or_inactivity(void) | |||||
| { | { | ||||
| int a_start_is_required = false; | int a_start_is_required = false; | ||||
| i++; | i++; | ||||
| struct timespec ts; | struct timespec ts; | ||||
| struct timeval tv; | |||||
| clock_gettime2(&ts); | clock_gettime2(&ts); | ||||
| && errno == EINTR) | && errno == EINTR) | ||||
| continue; | continue; | ||||
| assert(gettimeofday(&tv, NULL) != -1); | |||||
| if (err == 0) | if (err == 0) | ||||
| a_start_is_required = true; | a_start_is_required = true; | ||||
| } | } | ||||
| return a_start_is_required; | return a_start_is_required; | ||||
| } | } | ||||
| static espeak_ng_STATUS close_stream() | |||||
| static espeak_ng_STATUS close_stream(void) | |||||
| { | { | ||||
| espeak_ng_STATUS status = pthread_mutex_lock(&my_mutex); | espeak_ng_STATUS status = pthread_mutex_lock(&my_mutex); | ||||
| if (status != ENS_OK) | if (status != ENS_OK) | ||||
| { | { | ||||
| (void)p; // unused | (void)p; // unused | ||||
| int a_status; | |||||
| // announce that thread is started | // announce that thread is started | ||||
| assert(-1 != pthread_mutex_lock(&my_mutex)); | |||||
| a_status = pthread_mutex_lock(&my_mutex); | |||||
| assert(-1 != a_status); | |||||
| my_stop_is_acknowledged = true; | my_stop_is_acknowledged = true; | ||||
| assert(-1 != pthread_cond_signal(&my_cond_stop_is_acknowledged)); | |||||
| assert(-1 != pthread_mutex_unlock(&my_mutex)); | |||||
| a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged); | |||||
| assert(-1 != a_status); | |||||
| a_status = pthread_mutex_unlock(&my_mutex); | |||||
| assert(-1 != a_status); | |||||
| bool look_for_inactivity = false; | bool look_for_inactivity = false; | ||||
| } | } | ||||
| look_for_inactivity = true; | look_for_inactivity = true; | ||||
| int a_status = pthread_mutex_lock(&my_mutex); | |||||
| a_status = pthread_mutex_lock(&my_mutex); | |||||
| assert(!a_status); | assert(!a_status); | ||||
| if (!a_start_is_required) { | if (!a_start_is_required) { | ||||
| my_command_is_running = true; | my_command_is_running = true; | ||||
| assert(-1 != pthread_cond_broadcast(&my_cond_command_is_running)); | |||||
| assert(-1 != pthread_mutex_unlock(&my_mutex)); | |||||
| a_status = pthread_cond_broadcast(&my_cond_command_is_running); | |||||
| assert(-1 != a_status); | |||||
| a_status = pthread_mutex_unlock(&my_mutex); | |||||
| assert(-1 != a_status); | |||||
| while (my_command_is_running && !my_terminate_is_required) { | while (my_command_is_running && !my_terminate_is_required) { | ||||
| int a_status = pthread_mutex_lock(&my_mutex); | |||||
| a_status = pthread_mutex_lock(&my_mutex); | |||||
| assert(!a_status); | assert(!a_status); | ||||
| t_espeak_command *a_command = (t_espeak_command *)pop(); | t_espeak_command *a_command = (t_espeak_command *)pop(); | ||||
| // and waiting for my_cond_stop_is_acknowledged | // and waiting for my_cond_stop_is_acknowledged | ||||
| init(1); | init(1); | ||||
| assert(-1 != pthread_mutex_lock(&my_mutex)); | |||||
| a_status = pthread_mutex_lock(&my_mutex); | |||||
| assert(-1 != a_status); | |||||
| my_start_is_required = false; | my_start_is_required = false; | ||||
| // acknowledge the stop request | // acknowledge the stop request | ||||
| my_stop_is_acknowledged = true; | my_stop_is_acknowledged = true; | ||||
| int a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged); | |||||
| a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged); | |||||
| assert(a_status != -1); | assert(a_status != -1); | ||||
| pthread_mutex_unlock(&my_mutex); | pthread_mutex_unlock(&my_mutex); | ||||
| } | } | ||||
| // and wait for the next start | // and wait for the next start | ||||
| } | } | ||||
| (void)a_status; | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| int fifo_is_command_enabled() | |||||
| int fifo_is_command_enabled(void) | |||||
| { | { | ||||
| return 0 == my_stop_is_required; | return 0 == my_stop_is_required; | ||||
| } | } | ||||
| return ENS_OK; | return ENS_OK; | ||||
| } | } | ||||
| static t_espeak_command *pop() | |||||
| static t_espeak_command *pop(void) | |||||
| { | { | ||||
| t_espeak_command *the_command = NULL; | t_espeak_command *the_command = NULL; | ||||
| node_counter = 0; | node_counter = 0; | ||||
| } | } | ||||
| void fifo_terminate() | |||||
| void fifo_terminate(void) | |||||
| { | { | ||||
| if (!thread_inited) return; | if (!thread_inited) return; | ||||
| { | { | ||||
| PHONEME_LIST *p; | PHONEME_LIST *p; | ||||
| int ix; | int ix; | ||||
| int count_stressed = 0; | |||||
| int final_stressed = 0; | int final_stressed = 0; | ||||
| int tone_ph; | int tone_ph; | ||||
| for (ix = 0; ix < n_phoneme_list; ix++, p++) { | for (ix = 0; ix < n_phoneme_list; ix++, p++) { | ||||
| if ((p->type == phVOWEL) && (p->stresslevel >= 4)) { | if ((p->type == phVOWEL) && (p->stresslevel >= 4)) { | ||||
| final_stressed = ix; | final_stressed = ix; | ||||
| count_stressed++; | |||||
| } | } | ||||
| } | } | ||||
| #define NUMBER_OF_SAMPLES 100 | #define NUMBER_OF_SAMPLES 100 | ||||
| static int scale_wav_tab[] = { 45, 38, 45, 45, 55, 45 }; // scale output from different voicing sources | |||||
| static const int scale_wav_tab[] = { 45, 38, 45, 45, 55, 45 }; // scale output from different voicing sources | |||||
| // For testing, this can be overwritten in KlattInit() | // For testing, this can be overwritten in KlattInit() | ||||
| static const short natural_samples2[256] = { | static const short natural_samples2[256] = { | ||||
| to Kopen. | to Kopen. | ||||
| */ | */ | ||||
| static double impulsive_source() | |||||
| static double impulsive_source(void) | |||||
| { | { | ||||
| static const double doublet[] = { 0.0, 13000000.0, -13000000.0 }; | static const double doublet[] = { 0.0, 13000000.0, -13000000.0 }; | ||||
| static double vwave; | static double vwave; | ||||
| spectral zero around 800 Hz, magic constants a,b reset pitch synchronously. | spectral zero around 800 Hz, magic constants a,b reset pitch synchronously. | ||||
| */ | */ | ||||
| static double natural_source() | |||||
| static double natural_source(void) | |||||
| { | { | ||||
| double lgtemp; | double lgtemp; | ||||
| static double vwave; | static double vwave; | ||||
| } | } | ||||
| } | } | ||||
| void KlattInit() | |||||
| void KlattInit(void) | |||||
| { | { | ||||
| static const short formant_hz[10] = { 280, 688, 1064, 2806, 3260, 3700, 6500, 7000, 8000, 280 }; | static const short formant_hz[10] = { 280, 688, 1064, 2806, 3260, 3700, 6500, 7000, 8000, 280 }; |
| static int CheckTranslator(Translator *tr, const MNEM_TAB *keyword_tab, int key); | static int CheckTranslator(Translator *tr, const MNEM_TAB *keyword_tab, int key); | ||||
| static int LookupTune(const char *name); | static int LookupTune(const char *name); | ||||
| extern const MNEM_TAB langopts_tab[]; | |||||
| void LoadLanguageOptions(Translator *translator, int key, char *keyValue ) { | void LoadLanguageOptions(Translator *translator, int key, char *keyValue ) { | ||||
| if (CheckTranslator(translator, langopts_tab, key) != 0) { | if (CheckTranslator(translator, langopts_tab, key) != 0) { | ||||
| return; | return; | ||||
| fprintf(stderr, "Cannot set %s: language not set, or is invalid.\n", LookupMnemName(keyword_tab, key)); | fprintf(stderr, "Cannot set %s: language not set, or is invalid.\n", LookupMnemName(keyword_tab, key)); | ||||
| return 1; | return 1; | ||||
| } | |||||
| } |
| // this list must be in ascending order | // this list must be in ascending order | ||||
| static unsigned short derived_letters[] = { | |||||
| static const unsigned short derived_letters[] = { | |||||
| 0x00aa, 'a'+L_SUP, | 0x00aa, 'a'+L_SUP, | ||||
| 0x00b2, '2'+L_SUP, | 0x00b2, '2'+L_SUP, | ||||
| 0x00b3, '3'+L_SUP, | 0x00b3, '3'+L_SUP, | ||||
| int value; | int value; | ||||
| int subtract; | int subtract; | ||||
| int repeat = 0; | int repeat = 0; | ||||
| int n_digits = 0; | |||||
| char *word_start; | char *word_start; | ||||
| int num_control = 0; | int num_control = 0; | ||||
| unsigned int flags[2]; | unsigned int flags[2]; | ||||
| char ph_roman[30]; | char ph_roman[30]; | ||||
| char number_chars[N_WORD_BYTES]; | char number_chars[N_WORD_BYTES]; | ||||
| static const char *roman_numbers = "ixcmvld"; | |||||
| static const char roman_numbers[] = "ixcmvld"; | |||||
| static const int roman_values[] = { 1, 10, 100, 1000, 5, 50, 500 }; | static const int roman_values[] = { 1, 10, 100, 1000, 5, 50, 500 }; | ||||
| acc = 0; | acc = 0; | ||||
| else | else | ||||
| acc += prev; | acc += prev; | ||||
| prev = value; | prev = value; | ||||
| n_digits++; | |||||
| } | } | ||||
| if (IsDigit09(word[0])) | if (IsDigit09(word[0])) |
| // re-interpret the changed phoneme | // re-interpret the changed phoneme | ||||
| // But it doesn't obey a second ChangePhoneme() | // But it doesn't obey a second ChangePhoneme() | ||||
| InterpretPhoneme(tr, 0x100, plist3, phdata, worddata); | InterpretPhoneme(tr, 0x100, plist3, phdata, worddata); | ||||
| } | |||||
| } |
| } | } | ||||
| } | } | ||||
| static bool isKlattFrameFollowing() { | |||||
| static bool isKlattFrameFollowing(void) { | |||||
| // eSpeak implements its command queue with a circular buffer. | // eSpeak implements its command queue with a circular buffer. | ||||
| // Thus to walk it, we start from the head, walking to the tail, which may wrap around to the beginning of the buffer as it is circular. | // Thus to walk it, we start from the head, walking to the tail, which may wrap around to the beginning of the buffer as it is circular. | ||||
| for(int i=(wcmdq_head+1)%N_WCMDQ;i!=wcmdq_tail;i=(i+1)%N_WCMDQ) { | for(int i=(wcmdq_head+1)%N_WCMDQ;i!=wcmdq_tail;i=(i+1)%N_WCMDQ) { | ||||
| spFrame->endVoicePitch=spFrame->voicePitch; | spFrame->endVoicePitch=spFrame->voicePitch; | ||||
| } | } | ||||
| void KlattInitSP() { | |||||
| void KlattInitSP(void) { | |||||
| speechPlayerHandle=speechPlayer_initialize(22050); | speechPlayerHandle=speechPlayer_initialize(22050); | ||||
| } | } | ||||
| void KlattFiniSP() { | |||||
| void KlattFiniSP(void) { | |||||
| if (speechPlayerHandle) | if (speechPlayerHandle) | ||||
| speechPlayer_terminate(speechPlayerHandle); | speechPlayer_terminate(speechPlayerHandle); | ||||
| speechPlayerHandle = NULL; | speechPlayerHandle = NULL; | ||||
| } | } | ||||
| void KlattResetSP() { | |||||
| void KlattResetSP(void) { | |||||
| KlattFiniSP(); | KlattFiniSP(); | ||||
| KlattInitSP(); | KlattInitSP(); | ||||
| } | } |
| #include "synthesize.h" | #include "synthesize.h" | ||||
| #include "translate.h" | #include "translate.h" | ||||
| static void SetSpeedFactors(voice_t *voice, int x, int *speed1, int *speed2, int *speed3); | |||||
| static void SetSpeedFactors(voice_t *voice, int x, int speeds[3]); | |||||
| static void SetSpeedMods(SPEED_FACTORS *speed, int voiceSpeedF1, int wpm, int x); | static void SetSpeedMods(SPEED_FACTORS *speed, int voiceSpeedF1, int wpm, int x); | ||||
| static void SetSpeedMultiplier(int *x, int *wpm); | static void SetSpeedMultiplier(int *x, int *wpm); | ||||
| // convert from words-per-minute to internal speed factor | // convert from words-per-minute to internal speed factor | ||||
| // Use this to calibrate speed for wpm 80-450 (espeakRATE_MINIMUM - espeakRATE_MAXIMUM) | // Use this to calibrate speed for wpm 80-450 (espeakRATE_MINIMUM - espeakRATE_MAXIMUM) | ||||
| static unsigned char speed_lookup[] = { | |||||
| static const unsigned char speed_lookup[] = { | |||||
| 255, 255, 255, 255, 255, // 80 | 255, 255, 255, 255, 255, // 80 | ||||
| 253, 249, 245, 242, 238, // 85 | 253, 249, 245, 242, 238, // 85 | ||||
| 235, 232, 228, 225, 222, // 90 | 235, 232, 228, 225, 222, // 90 | ||||
| }; | }; | ||||
| // speed_factor1 adjustments for speeds 350 to 374: pauses | // speed_factor1 adjustments for speeds 350 to 374: pauses | ||||
| static unsigned char pause_factor_350[] = { | |||||
| static const unsigned char pause_factor_350[] = { | |||||
| 22, 22, 22, 22, 22, 22, 22, 21, 21, 21, // 350 | 22, 22, 22, 22, 22, 22, 22, 21, 21, 21, // 350 | ||||
| 21, 20, 20, 19, 19, 18, 17, 16, 15, 15, // 360 | 21, 20, 20, 19, 19, 18, 17, 16, 15, 15, // 360 | ||||
| 15, 15, 15, 15, 15 // 370 | 15, 15, 15, 15, 15 // 370 | ||||
| // wav_factor adjustments for speeds 350 to 450 | // wav_factor adjustments for speeds 350 to 450 | ||||
| // Use this to calibrate speed for wpm 350-450 | // Use this to calibrate speed for wpm 350-450 | ||||
| static unsigned char wav_factor_350[] = { | |||||
| static const unsigned char wav_factor_350[] = { | |||||
| 120, 121, 120, 119, 119, // 350 | 120, 121, 120, 119, 119, // 350 | ||||
| 118, 118, 117, 116, 116, // 355 | 118, 118, 117, 116, 116, // 355 | ||||
| 115, 114, 113, 112, 112, // 360 | 115, 114, 113, 112, 112, // 360 | ||||
| 45 // 450 | 45 // 450 | ||||
| }; | }; | ||||
| static int speed1 = 130; | |||||
| static int speed2 = 121; | |||||
| static int speed3 = 118; | |||||
| static int len_speeds[3] = { 130, 121, 118 }; | |||||
| void SetSpeed(int control) | void SetSpeed(int control) | ||||
| { | { | ||||
| // The eSpeak output will be speeded up by at least x2 | // The eSpeak output will be speeded up by at least x2 | ||||
| x = 73; | x = 73; | ||||
| if (control & 1) { | if (control & 1) { | ||||
| speed1 = (x * voice->speedf1)/256; | |||||
| speed2 = (x * voice->speedf2)/256; | |||||
| speed3 = (x * voice->speedf3)/256; | |||||
| len_speeds[0] = (x * voice->speedf1)/256; | |||||
| len_speeds[1] = (x * voice->speedf2)/256; | |||||
| len_speeds[2] = (x * voice->speedf3)/256; | |||||
| } | } | ||||
| if (control & 2) { | if (control & 2) { | ||||
| double sonic; | double sonic; | ||||
| SetSpeedMultiplier(&x, &wpm); | SetSpeedMultiplier(&x, &wpm); | ||||
| if (control & 1) { | if (control & 1) { | ||||
| SetSpeedFactors(voice, x, &speed1, &speed2, &speed3); | |||||
| SetSpeedFactors(voice, x, len_speeds); | |||||
| } | } | ||||
| if (control & 2) { | if (control & 2) { | ||||
| *x = 6; | *x = 6; | ||||
| } | } | ||||
| static void SetSpeedFactors(voice_t *voice, int x, int *speed1, int *speed2, int *speed3) { | |||||
| static void SetSpeedFactors(voice_t *voice, int x, int speeds[3]) { | |||||
| // set speed factors for different syllable positions within a word | // set speed factors for different syllable positions within a word | ||||
| // these are used in CalcLengths() | // these are used in CalcLengths() | ||||
| *speed1 = (x * voice->speedf1)/256; | |||||
| *speed2 = (x * voice->speedf2)/256; | |||||
| *speed3 = (x * voice->speedf3)/256; | |||||
| speeds[0] = (x * voice->speedf1)/256; | |||||
| speeds[1] = (x * voice->speedf2)/256; | |||||
| speeds[2] = (x * voice->speedf3)/256; | |||||
| if (x <= 7) { | if (x <= 7) { | ||||
| *speed1 = x; | |||||
| *speed2 = *speed3 = x - 1; | |||||
| speeds[0] = x; | |||||
| speeds[1] = speeds[2] = x - 1; | |||||
| } | } | ||||
| } | } | ||||
| p->length = prev->length; | p->length = prev->length; | ||||
| if (p->type == phLIQUID) | if (p->type == phLIQUID) | ||||
| p->length = speed1; | |||||
| p->length = len_speeds[0]; | |||||
| if (next->type == phVSTOP) | if (next->type == phVSTOP) | ||||
| p->length = (p->length * 160)/100; | p->length = (p->length * 160)/100; | ||||
| } | } | ||||
| if (more_syllables == 0) | if (more_syllables == 0) | ||||
| length_mod *= speed1; | |||||
| length_mod *= len_speeds[0]; | |||||
| else if (more_syllables == 1) | else if (more_syllables == 1) | ||||
| length_mod *= speed2; | |||||
| length_mod *= len_speeds[1]; | |||||
| else | else | ||||
| length_mod *= speed3; | |||||
| length_mod *= len_speeds[2]; | |||||
| length_mod = length_mod / 128; | length_mod = length_mod / 128; | ||||
| length_mod = length_mod * (256 + (280 - len)/3)/256; | length_mod = length_mod * (256 + (280 - len)/3)/256; | ||||
| } | } | ||||
| if (length_mod > tr->langopts.max_lengthmod*speed1) { | |||||
| if (length_mod > tr->langopts.max_lengthmod*len_speeds[0]) { | |||||
| // limit the vowel length adjustment for some languages | // limit the vowel length adjustment for some languages | ||||
| length_mod = (tr->langopts.max_lengthmod*speed1); | |||||
| length_mod = (tr->langopts.max_lengthmod*len_speeds[0]); | |||||
| } | } | ||||
| length_mod = length_mod / 128; | length_mod = length_mod / 128; |
| #include "synthesize.h" // for KLATT_AV, KLATT_Kopen, N_KLATTP2 | #include "synthesize.h" // for KLATT_AV, KLATT_Kopen, N_KLATTP2 | ||||
| #include "voice.h" // for N_PEAKS | #include "voice.h" // for N_PEAKS | ||||
| static int frame_width; | |||||
| static int default_freq[N_PEAKS] = | |||||
| static const int default_freq[N_PEAKS] = | |||||
| { 200, 500, 1200, 3000, 3500, 4000, 6900, 7800, 9000 }; | { 200, 500, 1200, 3000, 3500, 4000, 6900, 7800, 9000 }; | ||||
| static int default_width[N_PEAKS] = | |||||
| static const int default_width[N_PEAKS] = | |||||
| { 750, 500, 550, 550, 600, 700, 700, 700, 700 }; | { 750, 500, 550, 550, 600, 700, 700, 700, 700 }; | ||||
| static int default_klt_bw[N_PEAKS] = | |||||
| static const int default_klt_bw[N_PEAKS] = | |||||
| { 89, 90, 140, 260, 260, 260, 500, 500, 500 }; | { 89, 90, 140, 260, 260, 260, 500, 500, 500 }; | ||||
| static double read_double(FILE *stream) | static double read_double(FILE *stream) | ||||
| return y; | return y; | ||||
| } | } | ||||
| static SpectFrame *SpectFrameCreate() | |||||
| static SpectFrame *SpectFrameCreate(void) | |||||
| { | { | ||||
| int ix; | int ix; | ||||
| SpectFrame *frame; | SpectFrame *frame; | ||||
| } | } | ||||
| #pragma GCC visibility push(default) | #pragma GCC visibility push(default) | ||||
| SpectSeq *SpectSeqCreate() | |||||
| SpectSeq *SpectSeqCreate(void) | |||||
| { | { | ||||
| SpectSeq *spect = malloc(sizeof(SpectSeq)); | SpectSeq *spect = malloc(sizeof(SpectSeq)); | ||||
| if (!spect) | if (!spect) | ||||
| } | } | ||||
| spect->max_x = 9000; // disable auto-xscaling | spect->max_x = 9000; // disable auto-xscaling | ||||
| frame_width = (int)((FRAME_WIDTH*spect->max_x)/MAX_DISPLAY_FREQ); | |||||
| if (frame_width > FRAME_WIDTH) frame_width = FRAME_WIDTH; | |||||
| // start times from zero | // start times from zero | ||||
| time_offset = spect->frames[0]->time; | time_offset = spect->frames[0]->time; | ||||
| for (ix = 0; ix < spect->numframes; ix++) | for (ix = 0; ix < spect->numframes; ix++) |
| static espeak_ng_OUTPUT_MODE my_mode = ENOUTPUT_MODE_SYNCHRONOUS; | static espeak_ng_OUTPUT_MODE my_mode = ENOUTPUT_MODE_SYNCHRONOUS; | ||||
| static int out_samplerate = 0; | static int out_samplerate = 0; | ||||
| static int voice_samplerate = 22050; | static int voice_samplerate = 22050; | ||||
| static int min_buffer_length = 60; // minimum buffer length in ms | |||||
| static const int min_buffer_length = 60; // minimum buffer length in ms | |||||
| static espeak_ng_STATUS err = ENS_OK; | static espeak_ng_STATUS err = ENS_OK; | ||||
| static t_espeak_callback *synth_callback = NULL; | static t_espeak_callback *synth_callback = NULL; | ||||
| // Fill the buffer with output sound | // Fill the buffer with output sound | ||||
| int length; | int length; | ||||
| int finished = 0; | int finished = 0; | ||||
| int count_buffers = 0; | |||||
| if ((outbuf == NULL) || (event_list == NULL)) | if ((outbuf == NULL) || (event_list == NULL)) | ||||
| return ENS_NOT_INITIALIZED; | return ENS_NOT_INITIALIZED; | ||||
| event_list[event_list_ix].unique_identifier = unique_identifier; | event_list[event_list_ix].unique_identifier = unique_identifier; | ||||
| event_list[event_list_ix].user_data = my_user_data; | event_list[event_list_ix].user_data = my_user_data; | ||||
| count_buffers++; | |||||
| if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | ||||
| finished = create_events((short *)outbuf, length, event_list); | finished = create_events((short *)outbuf, length, event_list); | ||||
| if (finished < 0) | if (finished < 0) | ||||
| { | { | ||||
| (void)size; // unused in non-async modes | (void)size; // unused in non-async modes | ||||
| static unsigned int temp_identifier; | |||||
| unsigned int temp_identifier; | |||||
| if (unique_identifier == NULL) | if (unique_identifier == NULL) | ||||
| unique_identifier = &temp_identifier; | unique_identifier = &temp_identifier; | ||||
| { | { | ||||
| (void)size; // unused in non-async modes | (void)size; // unused in non-async modes | ||||
| static unsigned int temp_identifier; | |||||
| unsigned int temp_identifier; | |||||
| if (unique_identifier == NULL) | if (unique_identifier == NULL) | ||||
| unique_identifier = &temp_identifier; | unique_identifier = &temp_identifier; |
| return buf; | return buf; | ||||
| } | } | ||||
| void SynthesizeInit() | |||||
| void SynthesizeInit(void) | |||||
| { | { | ||||
| last_pitch_cmd = 0; | last_pitch_cmd = 0; | ||||
| last_amp_cmd = 0; | last_amp_cmd = 0; | ||||
| return len; | return len; | ||||
| } | } | ||||
| static frame_t *AllocFrame() | |||||
| static frame_t *AllocFrame(void) | |||||
| { | { | ||||
| // Allocate a temporary spectrum frame for the wavegen queue. Use a pool which is big | // Allocate a temporary spectrum frame for the wavegen queue. Use a pool which is big | ||||
| // enough to use a round-robin without checks. | // enough to use a round-robin without checks. | ||||
| if (WcmdqFree() <= free_min) | if (WcmdqFree() <= free_min) | ||||
| return 1; // wait | return 1; // wait | ||||
| PHONEME_LIST *prev; | |||||
| PHONEME_LIST *next; | |||||
| PHONEME_LIST *next2; | |||||
| PHONEME_LIST *prev; | |||||
| PHONEME_LIST *next; | |||||
| PHONEME_LIST *next2; | |||||
| prev = &phoneme_list[ix-1]; | prev = &phoneme_list[ix-1]; | ||||
| next = &phoneme_list[ix+1]; | next = &phoneme_list[ix+1]; |
| case L('s', 'k'): // Slovak | case L('s', 'k'): // Slovak | ||||
| case L('c', 's'): // Czech | case L('c', 's'): // Czech | ||||
| { | { | ||||
| static const char *sk_voiced = "bdgjlmnrvwzaeiouy"; | |||||
| static const char sk_voiced[] = "bdgjlmnrvwzaeiouy"; | |||||
| SetupTranslator(tr, stress_lengths_sk, stress_amps_sk); | SetupTranslator(tr, stress_lengths_sk, stress_amps_sk); | ||||
| tr->encoding = ESPEAKNG_ENCODING_ISO_8859_2; | tr->encoding = ESPEAKNG_ENCODING_ISO_8859_2; |
| return count; | return count; | ||||
| } | } | ||||
| static void Word_EmbeddedCmd() | |||||
| static void Word_EmbeddedCmd(void) | |||||
| { | { | ||||
| // Process embedded commands for emphasis, sayas, and break | // Process embedded commands for emphasis, sayas, and break | ||||
| int embedded_cmd; | int embedded_cmd; |
| int tone_points[12] = { 600, 170, 1200, 135, 2000, 110, 3000, 110, -1, 0 }; | int tone_points[12] = { 600, 170, 1200, 135, 2000, 110, 3000, 110, -1, 0 }; | ||||
| // limit the rate of change for each formant number | // limit the rate of change for each formant number | ||||
| static int formant_rate_22050[9] = { 240, 170, 170, 170, 170, 170, 170, 170, 170 }; // values for 22kHz sample rate | |||||
| static const 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 | int formant_rate[9]; // values adjusted for actual sample rate | ||||
| #define DEFAULT_LANGUAGE_PRIORITY 5 | #define DEFAULT_LANGUAGE_PRIORITY 5 | ||||
| #pragma GCC visibility pop | #pragma GCC visibility pop | ||||
| void FreeVoiceList() | |||||
| void FreeVoiceList(void) | |||||
| { | { | ||||
| int ix; | int ix; | ||||
| for (ix = 0; ix < n_voices_list; ix++) { | for (ix = 0; ix < n_voices_list; ix++) { | ||||
| if (voice_data != NULL) | if (voice_data != NULL) | ||||
| voices_list[n_voices_list++] = voice_data; | voices_list[n_voices_list++] = voice_data; | ||||
| return 0; | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } |
| // pitch,speed, | // pitch,speed, | ||||
| const int embedded_default[N_EMBEDDED_VALUES] = { 0, 50, espeakRATE_NORMAL, 100, 50, 0, 0, 0, espeakRATE_NORMAL, 0, 0, 0, 0, 0, 0 }; | const int embedded_default[N_EMBEDDED_VALUES] = { 0, 50, espeakRATE_NORMAL, 100, 50, 0, 0, 0, espeakRATE_NORMAL, 0, 0, 0, 0, 0, 0 }; | ||||
| static int embedded_max[N_EMBEDDED_VALUES] = { 0, 0x7fff, 750, 300, 99, 99, 99, 0, 750, 0, 0, 0, 0, 4, 0 }; | |||||
| static const int embedded_max[N_EMBEDDED_VALUES] = { 0, 0x7fff, 750, 300, 99, 99, 99, 0, 750, 0, 0, 0, 0, 4, 0 }; | |||||
| #if USE_LIBSONIC | #if USE_LIBSONIC | ||||
| static sonicStream sonicSpeedupStream = NULL; | static sonicStream sonicSpeedupStream = NULL; | ||||
| // 2nd index=modulation_type | // 2nd index=modulation_type | ||||
| // value: bits 0-3 amplitude (16ths), bits 4-7 every n cycles | // value: bits 0-3 amplitude (16ths), bits 4-7 every n cycles | ||||
| #define N_ROUGHNESS 8 | #define N_ROUGHNESS 8 | ||||
| static unsigned char modulation_tab[N_ROUGHNESS][8] = { | |||||
| static const unsigned char modulation_tab[N_ROUGHNESS][8] = { | |||||
| { 0, 0x00, 0x00, 0x00, 0, 0x46, 0xf2, 0x29 }, | { 0, 0x00, 0x00, 0x00, 0, 0x46, 0xf2, 0x29 }, | ||||
| { 0, 0x2f, 0x00, 0x2f, 0, 0x45, 0xf2, 0x29 }, | { 0, 0x2f, 0x00, 0x2f, 0, 0x45, 0xf2, 0x29 }, | ||||
| { 0, 0x2f, 0x00, 0x2e, 0, 0x45, 0xf2, 0x28 }, | { 0, 0x2f, 0x00, 0x2e, 0, 0x45, 0xf2, 0x28 }, | ||||
| 242, 246, 249, 252, 254, 255 | 242, 246, 249, 252, 254, 255 | ||||
| }; | }; | ||||
| void WcmdqStop() | |||||
| void WcmdqStop(void) | |||||
| { | { | ||||
| wcmdq_head = 0; | wcmdq_head = 0; | ||||
| wcmdq_tail = 0; | wcmdq_tail = 0; | ||||
| #endif | #endif | ||||
| } | } | ||||
| int WcmdqFree() | |||||
| int WcmdqFree(void) | |||||
| { | { | ||||
| int i; | int i; | ||||
| i = wcmdq_head - wcmdq_tail; | i = wcmdq_head - wcmdq_tail; | ||||
| return i; | return i; | ||||
| } | } | ||||
| int WcmdqUsed() | |||||
| int WcmdqUsed(void) | |||||
| { | { | ||||
| return N_WCMDQ - WcmdqFree(); | return N_WCMDQ - WcmdqFree(); | ||||
| } | } | ||||
| void WcmdqInc() | |||||
| void WcmdqInc(void) | |||||
| { | { | ||||
| wcmdq_tail++; | wcmdq_tail++; | ||||
| if (wcmdq_tail >= N_WCMDQ) wcmdq_tail = 0; | if (wcmdq_tail >= N_WCMDQ) wcmdq_tail = 0; | ||||
| } | } | ||||
| static void WcmdqIncHead() | |||||
| static void WcmdqIncHead(void) | |||||
| { | { | ||||
| MAKE_MEM_UNDEFINED(&wcmdq[wcmdq_head], sizeof(wcmdq[wcmdq_head])); | MAKE_MEM_UNDEFINED(&wcmdq[wcmdq_head], sizeof(wcmdq[wcmdq_head])); | ||||
| wcmdq_head++; | wcmdq_head++; | ||||
| return hmax; // highest harmonic number | return hmax; // highest harmonic number | ||||
| } | } | ||||
| static void AdvanceParameters() | |||||
| static void AdvanceParameters(void) | |||||
| { | { | ||||
| // Called every 64 samples to increment the formant freq, height, and widths | // Called every 64 samples to increment the formant freq, height, and widths | ||||
| if (wvoice == NULL) | if (wvoice == NULL) | ||||
| setresonator(&rbreath[ix], 2000, 200, 1); | setresonator(&rbreath[ix], 2000, 200, 1); | ||||
| } | } | ||||
| static void SetBreath() | |||||
| static void SetBreath(void) | |||||
| { | { | ||||
| int pk; | int pk; | ||||
| return value; | return value; | ||||
| } | } | ||||
| static void SetPitchFormants() | |||||
| static void SetPitchFormants(void) | |||||
| { | { | ||||
| if (wvoice == NULL) | if (wvoice == NULL) | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| static int WavegenFill2() | |||||
| static int WavegenFill2(void) | |||||
| { | { | ||||
| // Pick up next wavegen commands from the queue | // Pick up next wavegen commands from the queue | ||||
| // return: 0 output buffer has been filled | // return: 0 output buffer has been filled |