"-h, --help Show this help.\n"; | "-h, --help Show this help.\n"; | ||||
int samplerate; | int samplerate; | ||||
int quiet = 0; | |||||
bool quiet = false; | |||||
unsigned int samples_total = 0; | unsigned int samples_total = 0; | ||||
unsigned int samples_split = 0; | unsigned int samples_split = 0; | ||||
unsigned int samples_split_seconds = 0; | unsigned int samples_split_seconds = 0; | ||||
pitch = atoi(optarg2); | pitch = atoi(optarg2); | ||||
break; | break; | ||||
case 'q': | case 'q': | ||||
quiet = 1; | |||||
quiet = true; | |||||
break; | break; | ||||
case 'f': | case 'f': | ||||
strncpy0(filename, optarg2, sizeof(filename)); | strncpy0(filename, optarg2, sizeof(filename)); | ||||
case 0x102: // --compile | case 0x102: // --compile | ||||
strncpy0(voicename, optarg2, sizeof(voicename)); | strncpy0(voicename, optarg2, sizeof(voicename)); | ||||
flag_compile = c; | flag_compile = c; | ||||
quiet = 1; | |||||
quiet = true; | |||||
break; | break; | ||||
case 0x103: // --punct | case 0x103: // --punct | ||||
option_punctuation = 1; | option_punctuation = 1; |
// my_mutex: protects my_thread_is_talking, | // my_mutex: protects my_thread_is_talking, | ||||
static pthread_mutex_t my_mutex; | static pthread_mutex_t my_mutex; | ||||
static pthread_cond_t my_cond_start_is_required; | static pthread_cond_t my_cond_start_is_required; | ||||
static int my_start_is_required = 0; | |||||
static bool my_start_is_required = false; | |||||
static pthread_cond_t my_cond_stop_is_required; | static pthread_cond_t my_cond_stop_is_required; | ||||
static int my_stop_is_required = 0; | |||||
static bool my_stop_is_required = false; | |||||
static pthread_cond_t my_cond_stop_is_acknowledged; | static pthread_cond_t my_cond_stop_is_acknowledged; | ||||
static int my_stop_is_acknowledged = 0; | |||||
static bool my_stop_is_acknowledged = false; | |||||
// my_thread: polls the audio duration and compares it to the duration of the first event. | // my_thread: polls the audio duration and compares it to the duration of the first event. | ||||
static pthread_t my_thread; | static pthread_t my_thread; | ||||
static bool thread_inited; | static bool thread_inited; | ||||
static t_espeak_callback *my_callback = NULL; | static t_espeak_callback *my_callback = NULL; | ||||
static int my_event_is_running = 0; | |||||
static bool my_event_is_running = false; | |||||
enum { | enum { | ||||
MIN_TIMEOUT_IN_MS = 10, | MIN_TIMEOUT_IN_MS = 10, | ||||
void event_init(void) | void event_init(void) | ||||
{ | { | ||||
my_event_is_running = 0; | |||||
my_event_is_running = false; | |||||
// security | // security | ||||
pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); | pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); | ||||
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) { | ||||
my_start_is_required = 1; | |||||
my_start_is_required = true; | |||||
return status; | return status; | ||||
} | } | ||||
event_delete(a_event); | event_delete(a_event); | ||||
pthread_mutex_unlock(&my_mutex); | pthread_mutex_unlock(&my_mutex); | ||||
} else { | } else { | ||||
my_start_is_required = 1; | |||||
my_start_is_required = true; | |||||
pthread_cond_signal(&my_cond_start_is_required); | pthread_cond_signal(&my_cond_start_is_required); | ||||
status = pthread_mutex_unlock(&my_mutex); | status = pthread_mutex_unlock(&my_mutex); | ||||
} | } | ||||
int a_event_is_running = 0; | int a_event_is_running = 0; | ||||
if (my_event_is_running) { | if (my_event_is_running) { | ||||
my_stop_is_required = 1; | |||||
my_stop_is_required = true; | |||||
pthread_cond_signal(&my_cond_stop_is_required); | pthread_cond_signal(&my_cond_stop_is_required); | ||||
a_event_is_running = 1; | a_event_is_running = 1; | ||||
} else | } else | ||||
init(); // clear pending events | init(); // clear pending events | ||||
if (a_event_is_running) { | if (a_event_is_running) { | ||||
while (my_stop_is_acknowledged == 0) { | |||||
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) | ||||
continue; // Restart when interrupted by handler | continue; // Restart when interrupted by handler | ||||
} | } | ||||
(void)p; // unused | (void)p; // unused | ||||
while (1) { | while (1) { | ||||
int a_stop_is_required = 0; | |||||
bool a_stop_is_required = false; | |||||
(void)pthread_mutex_lock(&my_mutex); | (void)pthread_mutex_lock(&my_mutex); | ||||
my_event_is_running = 0; | |||||
my_event_is_running = false; | |||||
while (my_start_is_required == 0) { | |||||
while (my_start_is_required == false) { | |||||
while ((pthread_cond_wait(&my_cond_start_is_required, &my_mutex) == -1) && errno == EINTR) | while ((pthread_cond_wait(&my_cond_start_is_required, &my_mutex) == -1) && errno == EINTR) | ||||
continue; // Restart when interrupted by handler | continue; // Restart when interrupted by handler | ||||
} | } | ||||
my_event_is_running = 1; | |||||
a_stop_is_required = 0; | |||||
my_start_is_required = 0; | |||||
my_event_is_running = true; | |||||
a_stop_is_required = false; | |||||
my_start_is_required = false; | |||||
pthread_mutex_unlock(&my_mutex); | pthread_mutex_unlock(&my_mutex); | ||||
// In this loop, my_event_is_running = 1 | |||||
while (head && (a_stop_is_required == 0)) { | |||||
// In this loop, my_event_is_running = true | |||||
while (head && (a_stop_is_required == false)) { | |||||
espeak_EVENT *event = (espeak_EVENT *)(head->data); | espeak_EVENT *event = (espeak_EVENT *)(head->data); | ||||
assert(event); | assert(event); | ||||
(void)pthread_mutex_lock(&my_mutex); | (void)pthread_mutex_lock(&my_mutex); | ||||
event_delete((espeak_EVENT *)pop()); | event_delete((espeak_EVENT *)pop()); | ||||
a_stop_is_required = my_stop_is_required; | a_stop_is_required = my_stop_is_required; | ||||
if (a_stop_is_required > 0) | |||||
my_stop_is_required = 0; | |||||
if (a_stop_is_required == true) | |||||
my_stop_is_required = false; | |||||
(void)pthread_mutex_unlock(&my_mutex); | (void)pthread_mutex_unlock(&my_mutex); | ||||
} | } | ||||
(void)pthread_mutex_lock(&my_mutex); | (void)pthread_mutex_lock(&my_mutex); | ||||
my_event_is_running = 0; | |||||
my_event_is_running = false; | |||||
if (a_stop_is_required == 0) { | |||||
if (a_stop_is_required == false) { | |||||
a_stop_is_required = my_stop_is_required; | a_stop_is_required = my_stop_is_required; | ||||
if (a_stop_is_required > 0) | |||||
my_stop_is_required = 0; | |||||
if (a_stop_is_required == true) | |||||
my_stop_is_required = false; | |||||
} | } | ||||
(void)pthread_mutex_unlock(&my_mutex); | (void)pthread_mutex_unlock(&my_mutex); | ||||
if (a_stop_is_required > 0) { | |||||
if (a_stop_is_required == true) { | |||||
// no mutex required since the stop command is synchronous | // no mutex required since the stop command is synchronous | ||||
// and waiting for my_cond_stop_is_acknowledged | // and waiting for my_cond_stop_is_acknowledged | ||||
init(); | init(); | ||||
// acknowledge the stop request | // acknowledge the stop request | ||||
(void)pthread_mutex_lock(&my_mutex); | (void)pthread_mutex_lock(&my_mutex); | ||||
my_stop_is_acknowledged = 1; | |||||
my_stop_is_acknowledged = true; | |||||
(void)pthread_cond_signal(&my_cond_stop_is_acknowledged); | (void)pthread_cond_signal(&my_cond_stop_is_acknowledged); | ||||
(void)pthread_mutex_unlock(&my_mutex); | (void)pthread_mutex_unlock(&my_mutex); | ||||
} | } |
#include <assert.h> | #include <assert.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <pthread.h> | #include <pthread.h> | ||||
#include <stdbool.h> | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
// my_mutex: protects my_thread_is_talking, | // my_mutex: protects my_thread_is_talking, | ||||
// my_stop_is_required, and the command fifo | // my_stop_is_required, and the command fifo | ||||
static pthread_mutex_t my_mutex; | static pthread_mutex_t my_mutex; | ||||
static int my_command_is_running = 0; | |||||
static bool my_command_is_running = false; | |||||
static pthread_cond_t my_cond_command_is_running; | static pthread_cond_t my_cond_command_is_running; | ||||
static int my_stop_is_required = 0; | |||||
static bool my_stop_is_required = false; | |||||
// my_thread: reads commands from the fifo, and runs them. | // my_thread: reads commands from the fifo, and runs them. | ||||
static pthread_t my_thread; | static pthread_t my_thread; | ||||
static pthread_cond_t my_cond_start_is_required; | static pthread_cond_t my_cond_start_is_required; | ||||
static int my_start_is_required = 0; | |||||
static bool my_start_is_required = false; | |||||
static pthread_cond_t my_cond_stop_is_acknowledged; | static pthread_cond_t my_cond_stop_is_acknowledged; | ||||
static int my_stop_is_acknowledged = 0; | |||||
static bool my_stop_is_acknowledged = false; | |||||
static void *say_thread(void *); | static void *say_thread(void *); | ||||
// leave once the thread is actually started | // leave once the thread is actually started | ||||
assert(-1 != pthread_mutex_lock(&my_mutex)); | assert(-1 != pthread_mutex_lock(&my_mutex)); | ||||
while (my_stop_is_acknowledged == 0) { | |||||
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) | ||||
; | ; | ||||
} | } | ||||
my_stop_is_acknowledged = 0; | |||||
my_stop_is_acknowledged = false; | |||||
pthread_mutex_unlock(&my_mutex); | pthread_mutex_unlock(&my_mutex); | ||||
} | } | ||||
return status; | return status; | ||||
} | } | ||||
my_start_is_required = 1; | |||||
my_start_is_required = true; | |||||
pthread_cond_signal(&my_cond_start_is_required); | pthread_cond_signal(&my_cond_start_is_required); | ||||
while (my_start_is_required && !my_command_is_running) { | while (my_start_is_required && !my_command_is_running) { | ||||
return status; | return status; | ||||
} | } | ||||
my_start_is_required = 1; | |||||
my_start_is_required = true; | |||||
pthread_cond_signal(&my_cond_start_is_required); | pthread_cond_signal(&my_cond_start_is_required); | ||||
while (my_start_is_required && !my_command_is_running) { | while (my_start_is_required && !my_command_is_running) { | ||||
if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | ||||
return status; | return status; | ||||
int a_command_is_running = 0; | |||||
bool a_command_is_running = false; | |||||
if (my_command_is_running) { | if (my_command_is_running) { | ||||
a_command_is_running = 1; | |||||
my_stop_is_required = 1; | |||||
my_stop_is_acknowledged = 0; | |||||
a_command_is_running = true; | |||||
my_stop_is_required = true; | |||||
my_stop_is_acknowledged = false; | |||||
} | } | ||||
if (a_command_is_running) { | if (a_command_is_running) { | ||||
while (my_stop_is_acknowledged == 0) { | |||||
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) | ||||
continue; // Restart when interrupted by handler | continue; // Restart when interrupted by handler | ||||
} | } | ||||
} | } | ||||
my_stop_is_required = 0; | |||||
my_stop_is_required = false; | |||||
if ((status = pthread_mutex_unlock(&my_mutex)) != ENS_OK) | if ((status = pthread_mutex_unlock(&my_mutex)) != ENS_OK) | ||||
return status; | return status; | ||||
static int sleep_until_start_request_or_inactivity() | static int sleep_until_start_request_or_inactivity() | ||||
{ | { | ||||
int a_start_is_required = 0; | |||||
int a_start_is_required = false; | |||||
// Wait for the start request (my_cond_start_is_required). | // Wait for the start request (my_cond_start_is_required). | ||||
// Besides this, if the audio stream is still busy, | // Besides this, if the audio stream is still busy, | ||||
assert(gettimeofday(&tv, NULL) != -1); | assert(gettimeofday(&tv, NULL) != -1); | ||||
if (err == 0) | if (err == 0) | ||||
a_start_is_required = 1; | |||||
a_start_is_required = true; | |||||
} | } | ||||
pthread_mutex_unlock(&my_mutex); | pthread_mutex_unlock(&my_mutex); | ||||
return a_start_is_required; | return a_start_is_required; | ||||
if (status != ENS_OK) | if (status != ENS_OK) | ||||
return status; | return status; | ||||
int a_stop_is_required = my_stop_is_required; | |||||
bool a_stop_is_required = my_stop_is_required; | |||||
if (!a_stop_is_required) | if (!a_stop_is_required) | ||||
my_command_is_running = 1; | |||||
my_command_is_running = true; | |||||
status = pthread_mutex_unlock(&my_mutex); | status = pthread_mutex_unlock(&my_mutex); | ||||
if (status == ENS_OK) | if (status == ENS_OK) | ||||
status = a_status; | status = a_status; | ||||
my_command_is_running = 0; | |||||
my_command_is_running = false; | |||||
a_stop_is_required = my_stop_is_required; | a_stop_is_required = my_stop_is_required; | ||||
a_status = pthread_mutex_unlock(&my_mutex); | a_status = pthread_mutex_unlock(&my_mutex); | ||||
if((a_status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | if((a_status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | ||||
return a_status; | return a_status; | ||||
my_stop_is_acknowledged = 1; | |||||
my_stop_is_acknowledged = true; | |||||
a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged); | a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged); | ||||
if(a_status != ENS_OK) | if(a_status != ENS_OK) | ||||
return a_status; | return a_status; | ||||
// announce that thread is started | // announce that thread is started | ||||
assert(-1 != pthread_mutex_lock(&my_mutex)); | assert(-1 != pthread_mutex_lock(&my_mutex)); | ||||
my_stop_is_acknowledged = 1; | |||||
my_stop_is_acknowledged = true; | |||||
assert(-1 != pthread_cond_signal(&my_cond_stop_is_acknowledged)); | assert(-1 != pthread_cond_signal(&my_cond_stop_is_acknowledged)); | ||||
assert(-1 != pthread_mutex_unlock(&my_mutex)); | assert(-1 != pthread_mutex_unlock(&my_mutex)); | ||||
int look_for_inactivity = 0; | |||||
bool look_for_inactivity = false; | |||||
while (1) { | while (1) { | ||||
int a_start_is_required = 0; | |||||
bool a_start_is_required = false; | |||||
if (look_for_inactivity) { | if (look_for_inactivity) { | ||||
a_start_is_required = sleep_until_start_request_or_inactivity(); | a_start_is_required = sleep_until_start_request_or_inactivity(); | ||||
if (!a_start_is_required) | if (!a_start_is_required) | ||||
close_stream(); | close_stream(); | ||||
} | } | ||||
look_for_inactivity = 1; | |||||
look_for_inactivity = true; | |||||
int a_status = pthread_mutex_lock(&my_mutex); | int a_status = pthread_mutex_lock(&my_mutex); | ||||
assert(!a_status); | assert(!a_status); | ||||
if (!a_start_is_required) { | if (!a_start_is_required) { | ||||
while (my_start_is_required == 0) { | |||||
while (my_start_is_required == false) { | |||||
while ((pthread_cond_wait(&my_cond_start_is_required, &my_mutex) == -1) && errno == EINTR) | while ((pthread_cond_wait(&my_cond_start_is_required, &my_mutex) == -1) && errno == EINTR) | ||||
continue; // Restart when interrupted by handler | continue; // Restart when interrupted by handler | ||||
} | } | ||||
} | } | ||||
my_command_is_running = 1; | |||||
my_command_is_running = true; | |||||
assert(-1 != pthread_cond_broadcast(&my_cond_command_is_running)); | assert(-1 != pthread_cond_broadcast(&my_cond_command_is_running)); | ||||
assert(-1 != pthread_mutex_unlock(&my_mutex)); | assert(-1 != pthread_mutex_unlock(&my_mutex)); | ||||
t_espeak_command *a_command = (t_espeak_command *)pop(); | t_espeak_command *a_command = (t_espeak_command *)pop(); | ||||
if (a_command == NULL) { | if (a_command == NULL) { | ||||
my_command_is_running = 0; | |||||
my_command_is_running = false; | |||||
a_status = pthread_mutex_unlock(&my_mutex); | a_status = pthread_mutex_unlock(&my_mutex); | ||||
} else { | } else { | ||||
my_start_is_required = 0; | |||||
my_start_is_required = false; | |||||
if (my_stop_is_required) | if (my_stop_is_required) | ||||
my_command_is_running = 0; | |||||
my_command_is_running = false; | |||||
a_status = pthread_mutex_unlock(&my_mutex); | a_status = pthread_mutex_unlock(&my_mutex); | ||||
if (my_command_is_running) | if (my_command_is_running) | ||||
init(1); | init(1); | ||||
assert(-1 != pthread_mutex_lock(&my_mutex)); | assert(-1 != pthread_mutex_lock(&my_mutex)); | ||||
my_start_is_required = 0; | |||||
my_start_is_required = false; | |||||
// acknowledge the stop request | // acknowledge the stop request | ||||
my_stop_is_acknowledged = 1; | |||||
my_stop_is_acknowledged = true; | |||||
int a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged); | int 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); |
#include "config.h" | #include "config.h" | ||||
#include <stdbool.h> | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
int alternative; | int alternative; | ||||
int delete_count; | int delete_count; | ||||
int word_start; | int word_start; | ||||
int inserted; | |||||
int deleted; | |||||
bool inserted; | |||||
bool deleted; | |||||
PHONEME_DATA phdata; | PHONEME_DATA phdata; | ||||
int n_ph_list3; | int n_ph_list3; | ||||
for (j = 0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) { | for (j = 0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) { | ||||
plist3 = &ph_list3[j]; | plist3 = &ph_list3[j]; | ||||
inserted = 0; | |||||
deleted = 0; | |||||
inserted = false; | |||||
deleted = false; | |||||
if (insert_ph != 0) { | if (insert_ph != 0) { | ||||
// we have a (linking) phoneme which we need to insert here | // we have a (linking) phoneme which we need to insert here | ||||
next = phoneme_tab[plist3->phcode]; // this phoneme, i.e. after the insert | next = phoneme_tab[plist3->phcode]; // this phoneme, i.e. after the insert | ||||
ph = phoneme_tab[insert_ph]; | ph = phoneme_tab[insert_ph]; | ||||
plist3->ph = ph; | plist3->ph = ph; | ||||
insert_ph = 0; | insert_ph = 0; | ||||
inserted = 1; // don't insert the same phoneme repeatedly | |||||
inserted = true; // don't insert the same phoneme repeatedly | |||||
} else { | } else { | ||||
// otherwise get the next phoneme from the list | // otherwise get the next phoneme from the list | ||||
if (plist3->sourceix != 0) | if (plist3->sourceix != 0) | ||||
next = phoneme_tab[alternative]; | next = phoneme_tab[alternative]; | ||||
} | } | ||||
if (((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == 0)) { | |||||
if (((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == false)) { | |||||
// PROBLEM: if we insert a phoneme before a vowel then we loose the stress. | // PROBLEM: if we insert a phoneme before a vowel then we loose the stress. | ||||
PHONEME_TAB *ph2; | PHONEME_TAB *ph2; | ||||
ph2 = ph; | ph2 = ph; | ||||
plist3->phcode = alternative; | plist3->phcode = alternative; | ||||
if (alternative == 1) | if (alternative == 1) | ||||
deleted = 1; // NULL phoneme, discard | |||||
deleted = true; // NULL phoneme, discard | |||||
else { | else { | ||||
if (ph->type == phVOWEL) { | if (ph->type == phVOWEL) { | ||||
plist3->synthflags |= SFLAG_SYLLABLE; | plist3->synthflags |= SFLAG_SYLLABLE; | ||||
} | } | ||||
} | } | ||||
if ((ph->type == phVOWEL) && (deleted == 0)) { | |||||
if ((ph->type == phVOWEL) && (deleted == false)) { | |||||
PHONEME_LIST *p; | PHONEME_LIST *p; | ||||
// Check for consecutive unstressed syllables, even across word boundaries. | // Check for consecutive unstressed syllables, even across word boundaries. | ||||
if ((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0)) | if ((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0)) | ||||
insert_ph = phdata.pd_param[pd_APPENDPHONEME]; | insert_ph = phdata.pd_param[pd_APPENDPHONEME]; | ||||
if (deleted == 0) { | |||||
if (deleted == false) { | |||||
phlist[ix].ph = ph; | phlist[ix].ph = ph; | ||||
phlist[ix].type = ph->type; | phlist[ix].type = ph->type; | ||||
phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module | phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module |
#include <ctype.h> | #include <ctype.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <math.h> | #include <math.h> | ||||
#include <stdbool.h> | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
return output; | return output; | ||||
} | } | ||||
int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbrola) | |||||
int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, bool resume, FILE *f_mbrola) | |||||
{ | { | ||||
// Generate a mbrola pho file | // Generate a mbrola pho file | ||||
unsigned int name; | unsigned int name; | ||||
PHONEME_DATA phdata; | PHONEME_DATA phdata; | ||||
FMT_PARAMS fmtp; | FMT_PARAMS fmtp; | ||||
int pause = 0; | int pause = 0; | ||||
int released; | |||||
bool released; | |||||
int name2; | int name2; | ||||
int control; | int control; | ||||
int done; | int done; | ||||
done = 1; | done = 1; | ||||
break; | break; | ||||
case phSTOP: | case phSTOP: | ||||
released = 0; | |||||
if (next->type == phVOWEL) released = 1; | |||||
if (next->type == phLIQUID && !next->newword) released = 1; | |||||
released = false; | |||||
if (next->type == phVOWEL) released = true; | |||||
if (next->type == phLIQUID && !next->newword) released = true; | |||||
if (released == 0) | |||||
if (released == false) | |||||
p->synthflags |= SFLAG_NEXT_PAUSE; | p->synthflags |= SFLAG_NEXT_PAUSE; | ||||
InterpretPhoneme(NULL, 0, p, &phdata, NULL); | InterpretPhoneme(NULL, 0, p, &phdata, NULL); | ||||
len = DoSample3(&phdata, 0, -1); | len = DoSample3(&phdata, 0, -1); | ||||
return 0; | return 0; | ||||
} | } | ||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume) | |||||
{ | { | ||||
FILE *f_mbrola = NULL; | FILE *f_mbrola = NULL; | ||||
f_mbrola = f_trans; | f_mbrola = f_trans; | ||||
} | } | ||||
int again = MbrolaTranslate(phoneme_list, *n_ph, resume, f_mbrola); | |||||
int again = MbrolaTranslate(phoneme_list, *n_ph, resume, f_mbrola); | |||||
if (!again) | if (!again) | ||||
*n_ph = 0; | *n_ph = 0; | ||||
return again; | return again; | ||||
} | } | ||||
int MbrolaFill(int length, int resume, int amplitude) | |||||
int MbrolaFill(int length, bool resume, int amplitude) | |||||
{ | { | ||||
// Read audio data from Mbrola (length is in millisecs) | // Read audio data from Mbrola (length is in millisecs) | ||||
return ENS_NOT_SUPPORTED; | return ENS_NOT_SUPPORTED; | ||||
} | } | ||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume) | |||||
{ | { | ||||
(void)phoneme_list; // unused parameter | (void)phoneme_list; // unused parameter | ||||
(void)n_ph; // unused parameter | (void)n_ph; // unused parameter | ||||
return 0; | return 0; | ||||
} | } | ||||
int MbrolaFill(int length, int resume, int amplitude) | |||||
int MbrolaFill(int length, bool resume, int amplitude) | |||||
{ | { | ||||
(void)length; // unused parameter | (void)length; // unused parameter | ||||
(void)resume; // unused parameter | (void)resume; // unused parameter |
return (unsigned char *)&phondata_ptr[index]; | return (unsigned char *)&phondata_ptr[index]; | ||||
} | } | ||||
static void SetUpPhonemeTable(int number, int recursing) | |||||
static void SetUpPhonemeTable(int number, bool recursing) | |||||
{ | { | ||||
int ix; | int ix; | ||||
int includes; | int includes; | ||||
int ph_code; | int ph_code; | ||||
PHONEME_TAB *phtab; | PHONEME_TAB *phtab; | ||||
if (recursing == 0) | |||||
if (recursing == false) | |||||
memset(phoneme_tab_flags, 0, sizeof(phoneme_tab_flags)); | memset(phoneme_tab_flags, 0, sizeof(phoneme_tab_flags)); | ||||
if ((includes = phoneme_tab_list[number].includes) > 0) { | if ((includes = phoneme_tab_list[number].includes) > 0) { | ||||
// recursively include base phoneme tables | // recursively include base phoneme tables | ||||
SetUpPhonemeTable(includes-1, 1); | |||||
SetUpPhonemeTable(includes-1, true); | |||||
} | } | ||||
// now add the phonemes from this table | // now add the phonemes from this table | ||||
void SelectPhonemeTable(int number) | void SelectPhonemeTable(int number) | ||||
{ | { | ||||
n_phoneme_tab = 0; | n_phoneme_tab = 0; | ||||
SetUpPhonemeTable(number, 0); // recursively for included phoneme tables | |||||
SetUpPhonemeTable(number, false); // recursively for included phoneme tables | |||||
n_phoneme_tab++; | n_phoneme_tab++; | ||||
current_phoneme_table = number; | current_phoneme_table = number; | ||||
} | } |
#include <ctype.h> | #include <ctype.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <math.h> | #include <math.h> | ||||
#include <stdbool.h> | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
} while ((word & 0x80) == 0); | } while ((word & 0x80) == 0); | ||||
} | } | ||||
int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||||
int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume) | |||||
{ | { | ||||
static int ix; | static int ix; | ||||
static int embedded_ix; | static int embedded_ix; | ||||
PHONEME_LIST *next; | PHONEME_LIST *next; | ||||
PHONEME_LIST *next2; | PHONEME_LIST *next2; | ||||
PHONEME_LIST *p; | PHONEME_LIST *p; | ||||
int released; | |||||
bool released; | |||||
int stress; | int stress; | ||||
int modulation; | int modulation; | ||||
int pre_voiced; | |||||
bool pre_voiced; | |||||
int free_min; | int free_min; | ||||
int value; | int value; | ||||
unsigned char *pitch_env = NULL; | unsigned char *pitch_env = NULL; | ||||
if (mbrola_name[0] != 0) | if (mbrola_name[0] != 0) | ||||
return MbrolaGenerate(phoneme_list, n_ph, resume); | return MbrolaGenerate(phoneme_list, n_ph, resume); | ||||
if (resume == 0) { | |||||
if (resume == false) { | |||||
ix = 1; | ix = 1; | ||||
embedded_ix = 0; | embedded_ix = 0; | ||||
word_count = 0; | word_count = 0; | ||||
p->std_length = p->ph->std_length; | p->std_length = p->ph->std_length; | ||||
break; | break; | ||||
case phSTOP: | case phSTOP: | ||||
released = 0; | |||||
released = false; | |||||
ph = p->ph; | ph = p->ph; | ||||
if (next->type == phVOWEL) | if (next->type == phVOWEL) | ||||
released = 1; | |||||
released = true; | |||||
else if (!next->newword) { | else if (!next->newword) { | ||||
if (next->type == phLIQUID) released = 1; | |||||
if (next->type == phLIQUID) released = true; | |||||
} | } | ||||
if (released == 0) | |||||
if (released == false) | |||||
p->synthflags |= SFLAG_NEXT_PAUSE; | p->synthflags |= SFLAG_NEXT_PAUSE; | ||||
if (ph->phflags & phPREVOICE) { | if (ph->phflags & phPREVOICE) { | ||||
memset(&fmtp, 0, sizeof(fmtp)); | memset(&fmtp, 0, sizeof(fmtp)); | ||||
fmtp.fmt_control = pd_DONTLENGTHEN; | fmtp.fmt_control = pd_DONTLENGTHEN; | ||||
pre_voiced = 0; | |||||
pre_voiced = false; | |||||
if (next->type == phVOWEL) { | if (next->type == phVOWEL) { | ||||
DoAmplitude(p->amp, NULL); | DoAmplitude(p->amp, NULL); | ||||
DoPitch(envelope_data[p->env], p->pitch1, p->pitch2); | DoPitch(envelope_data[p->env], p->pitch1, p->pitch2); | ||||
pre_voiced = 1; | |||||
pre_voiced = true; | |||||
} else if ((next->type == phLIQUID) && !next->newword) { | } else if ((next->type == phLIQUID) && !next->newword) { | ||||
DoAmplitude(next->amp, NULL); | DoAmplitude(next->amp, NULL); | ||||
DoPitch(envelope_data[next->env], next->pitch1, next->pitch2); | DoPitch(envelope_data[next->env], next->pitch1, next->pitch2); | ||||
pre_voiced = 1; | |||||
pre_voiced = true; | |||||
} else { | } else { | ||||
if (last_pitch_cmd < 0) { | if (last_pitch_cmd < 0) { | ||||
DoAmplitude(next->amp, NULL); | DoAmplitude(next->amp, NULL); |
* along with this program; if not, see: <http://www.gnu.org/licenses/>. | * along with this program; if not, see: <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include <stdbool.h> | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" | extern "C" | ||||
{ | { | ||||
espeak_ng_STATUS LoadPhData(int *srate, espeak_ng_ERROR_CONTEXT *context); | espeak_ng_STATUS LoadPhData(int *srate, espeak_ng_ERROR_CONTEXT *context); | ||||
void SynthesizeInit(void); | void SynthesizeInit(void); | ||||
int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume); | |||||
int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume); | |||||
void MakeWave2(PHONEME_LIST *p, int n_ph); | void MakeWave2(PHONEME_LIST *p, int n_ph); | ||||
int SpeakNextClause(int control); | int SpeakNextClause(int control); | ||||
void SetSpeed(int control); | void SetSpeed(int control); | ||||
espeak_ng_STATUS LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate); | espeak_ng_STATUS LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate); | ||||
espeak_ng_STATUS SetParameter(int parameter, int value, int relative); | espeak_ng_STATUS SetParameter(int parameter, int value, int relative); | ||||
int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbrola); | |||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume); | |||||
int MbrolaFill(int length, int resume, int amplitude); | |||||
int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, bool resume, FILE *f_mbrola); | |||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume); | |||||
int MbrolaFill(int length, bool resume, int amplitude); | |||||
void MbrolaReset(void); | void MbrolaReset(void); | ||||
void DoEmbedded(int *embix, int sourceix); | void DoEmbedded(int *embix, int sourceix); | ||||
void DoMarker(int type, int char_posn, int length, int value); | void DoMarker(int type, int char_posn, int length, int value); |
#include "config.h" | #include "config.h" | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <stdbool.h> | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
char word_copy2[N_WORD_BYTES]; | char word_copy2[N_WORD_BYTES]; | ||||
int word_copy_length; | int word_copy_length; | ||||
char prefix_chars[0x3f + 2]; | char prefix_chars[0x3f + 2]; | ||||
int found = 0; | |||||
bool found = false; | |||||
int end_flags; | int end_flags; | ||||
int c_temp; // save a character byte while we temporarily replace it with space | int c_temp; // save a character byte while we temporarily replace it with space | ||||
int first_char; | int first_char; | ||||
strcpy(word_out, word1); | strcpy(word_out, word1); | ||||
return dictionary_flags[0]; | return dictionary_flags[0]; | ||||
} else if ((found == 0) && (dictionary_flags[0] & FLAG_SKIPWORDS) && !(dictionary_flags[0] & FLAG_ABBREV)) { | |||||
} else if ((found == false) && (dictionary_flags[0] & FLAG_SKIPWORDS) && !(dictionary_flags[0] & FLAG_ABBREV)) { | |||||
// grouped words, but no translation. Join the words with hyphens. | // grouped words, but no translation. Join the words with hyphens. | ||||
wordx = word1; | wordx = word1; | ||||
ix = 0; | ix = 0; | ||||
if (wflags & FLAG_TRANSLATOR2) | if (wflags & FLAG_TRANSLATOR2) | ||||
return 0; | return 0; | ||||
return dictionary_flags[0] & FLAG_SKIPWORDS; // for "b.c.d" | return dictionary_flags[0] & FLAG_SKIPWORDS; // for "b.c.d" | ||||
} else if (found == 0) { | |||||
} else if (found == false) { | |||||
// word's pronunciation is not given in the dictionary list, although | // word's pronunciation is not given in the dictionary list, although | ||||
// dictionary_flags may have ben set there | // dictionary_flags may have ben set there | ||||
c_temp = wordx[-1]; | c_temp = wordx[-1]; | ||||
found = 0; | |||||
found = false; | |||||
confirm_prefix = 1; | confirm_prefix = 1; | ||||
for (loopcount = 0; (loopcount < 50) && (end_type & SUFX_P); loopcount++) { | for (loopcount = 0; (loopcount < 50) && (end_type & SUFX_P); loopcount++) { | ||||
// Found a standard prefix, remove it and retranslate | // Found a standard prefix, remove it and retranslate | ||||
dictionary_flags[1] = dictionary_flags2[1]; | dictionary_flags[1] = dictionary_flags2[1]; | ||||
} else | } else | ||||
prefix_flags = 1; | prefix_flags = 1; | ||||
if (found == 0) { | |||||
if (found == false) { | |||||
end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags & (FLAG_HYPHEN_AFTER | FLAG_PREFIX_REMOVED), dictionary_flags); | end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags & (FLAG_HYPHEN_AFTER | FLAG_PREFIX_REMOVED), dictionary_flags); | ||||
if (phonemes[0] == phonSWITCH) { | if (phonemes[0] == phonSWITCH) { | ||||
if (found) | if (found) | ||||
prefix_phonemes[0] = 0; // matched whole word, don't need prefix now | prefix_phonemes[0] = 0; // matched whole word, don't need prefix now | ||||
if ((found == 0) && (dictionary_flags2[0] != 0)) | |||||
if ((found == false) && (dictionary_flags2[0] != 0)) | |||||
prefix_flags = 1; | prefix_flags = 1; | ||||
} | } | ||||
if (found == 0) { | |||||
if (found == false) { | |||||
found = LookupDictList(tr, &wordx, phonemes, dictionary_flags2, end_flags, wtab); // without prefix and suffix | found = LookupDictList(tr, &wordx, phonemes, dictionary_flags2, end_flags, wtab); // without prefix and suffix | ||||
if (phonemes[0] == phonSWITCH) { | if (phonemes[0] == phonSWITCH) { | ||||
// change to another language in order to translate this word | // change to another language in order to translate this word | ||||
dictionary_flags[1] = dictionary_flags2[1]; | dictionary_flags[1] = dictionary_flags2[1]; | ||||
} | } | ||||
} | } | ||||
if (found == 0) { | |||||
if (found == false) { | |||||
if (end_type & SUFX_Q) { | if (end_type & SUFX_Q) { | ||||
// don't retranslate, use the original lookup result | // don't retranslate, use the original lookup result | ||||
strcpy(phonemes, phonemes2); | strcpy(phonemes, phonemes2); |
#include "config.h" | #include "config.h" | ||||
#include <math.h> | #include <math.h> | ||||
#include <stdbool.h> | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
} | } | ||||
} | } | ||||
static int PlaySilence(int length, int resume) | |||||
static int PlaySilence(int length, bool resume) | |||||
{ | { | ||||
static int n_samples; | static int n_samples; | ||||
int value = 0; | int value = 0; | ||||
if (length == 0) | if (length == 0) | ||||
return 0; | return 0; | ||||
if (resume == 0) | |||||
if (resume == false) | |||||
n_samples = length; | n_samples = length; | ||||
while (n_samples-- > 0) { | while (n_samples-- > 0) { | ||||
return 0; | return 0; | ||||
} | } | ||||
static int PlayWave(int length, int resume, unsigned char *data, int scale, int amp) | |||||
static int PlayWave(int length, bool resume, unsigned char *data, int scale, int amp) | |||||
{ | { | ||||
static int n_samples; | static int n_samples; | ||||
static int ix = 0; | static int ix = 0; | ||||
int value; | int value; | ||||
signed char c; | signed char c; | ||||
if (resume == 0) { | |||||
if (resume == false) { | |||||
n_samples = length; | n_samples = length; | ||||
ix = 0; | ix = 0; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2) | |||||
static int Wavegen2(int length, int modulation, bool resume, frame_t *fr1, frame_t *fr2) | |||||
{ | { | ||||
if (resume == 0) | |||||
if (resume == false) | |||||
SetSynth(length, modulation, fr1, fr2, wvoice); | SetSynth(length, modulation, fr1, fr2, wvoice); | ||||
return Wavegen(); | return Wavegen(); | ||||
int length; | int length; | ||||
int result; | int result; | ||||
int marker_type; | int marker_type; | ||||
static int resume = 0; | |||||
static bool resume = false; | |||||
static int echo_complete = 0; | static int echo_complete = 0; | ||||
while (out_ptr < out_end) { | while (out_ptr < out_end) { | ||||
if (echo_complete > 0) { | if (echo_complete > 0) { | ||||
// continue to play silence until echo is completed | // continue to play silence until echo is completed | ||||
resume = PlaySilence(echo_complete, resume); | resume = PlaySilence(echo_complete, resume); | ||||
if (resume == 1) | |||||
if (resume == true) | |||||
return 0; // not yet finished | return 0; // not yet finished | ||||
} | } | ||||
return 1; // queue empty, close sound channel | return 1; // queue empty, close sound channel | ||||
SetPitch(length, (unsigned char *)q[2], q[3] >> 16, q[3] & 0xffff); | SetPitch(length, (unsigned char *)q[2], q[3] >> 16, q[3] & 0xffff); | ||||
break; | break; | ||||
case WCMD_PAUSE: | case WCMD_PAUSE: | ||||
if (resume == 0) | |||||
if (resume == false) | |||||
echo_complete -= length; | echo_complete -= length; | ||||
wdata.n_mix_wavefile = 0; | wdata.n_mix_wavefile = 0; | ||||
wdata.amplitude_fmt = 100; | wdata.amplitude_fmt = 100; | ||||
if (result == 0) { | if (result == 0) { | ||||
WcmdqIncHead(); | WcmdqIncHead(); | ||||
resume = 0; | |||||
resume = false; | |||||
} else | } else | ||||
resume = 1; | |||||
resume = true; | |||||
} | } | ||||
return 0; | return 0; |