00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "synth_thread.h"
00024
00025 #include <interfaces/SpeechSynthInterface.h>
00026 #include <utils/time/wait.h>
00027
00028 #include <festival/festival.h>
00029
00030 using namespace fawkes;
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 FestivalSynthThread::FestivalSynthThread()
00041 : Thread("FestivalSynthThread", Thread::OPMODE_WAITFORWAKEUP),
00042 BlackBoardInterfaceListener("FestivalSynthThread")
00043 {
00044 }
00045
00046
00047 void
00048 FestivalSynthThread::init()
00049 {
00050 try {
00051 __cfg_voice = config->get_string("/plugins/festival/voice");
00052 } catch (Exception &e) {
00053 __cfg_voice = "";
00054 }
00055 try {
00056 __cfg_extra_code = config->get_string("/plugins/festival/extra_code");
00057 } catch (Exception &e) {
00058 __cfg_extra_code = "";
00059 }
00060
00061 __speechsynth_if = blackboard->open_for_writing<SpeechSynthInterface>("Festival");
00062
00063 bbil_add_message_interface(__speechsynth_if);
00064 blackboard->register_listener(this, BlackBoard::BBIL_FLAG_MESSAGES);
00065
00066 }
00067
00068
00069 void FestivalSynthThread::once()
00070 {
00071 festival_initialize( 1, FESTIVAL_HEAP_SIZE);
00072 if (__cfg_voice != "") {
00073 std::string voice_cmd = "(voice_" + __cfg_voice + ")";
00074 if (! festival_eval_command(voice_cmd.c_str())) {
00075 logger->log_error(name(), "Failed to load voice %s", __cfg_voice.c_str());
00076 }
00077 }
00078
00079 if (__cfg_extra_code != "") {
00080 logger->log_debug(name(), "Executing extra code '%s'", __cfg_extra_code.c_str());
00081 if (! festival_eval_command(__cfg_extra_code.c_str())) {
00082 logger->log_error(name(), "Failed to execute extra code '%s'", __cfg_extra_code.c_str());
00083 }
00084 }
00085
00086 say("Festival speech synth loaded");
00087 }
00088
00089 void
00090 FestivalSynthThread::finalize()
00091 {
00092 festival_tidy_up();
00093 blackboard->unregister_listener(this);
00094 blackboard->close(__speechsynth_if);
00095 }
00096
00097 void
00098 FestivalSynthThread::loop()
00099 {
00100
00101 while ( __speechsynth_if->msgq_empty() ) {
00102 usleep(100);
00103 }
00104
00105
00106 if ( ! __speechsynth_if->msgq_empty() ) {
00107 if ( __speechsynth_if->msgq_first_is<SpeechSynthInterface::SayMessage>() ) {
00108 SpeechSynthInterface::SayMessage *msg = __speechsynth_if->msgq_first<SpeechSynthInterface::SayMessage>();
00109 __speechsynth_if->set_msgid(msg->id());
00110 say(msg->text());
00111 }
00112
00113 __speechsynth_if->msgq_pop();
00114 }
00115 }
00116
00117
00118 bool
00119 FestivalSynthThread::bb_interface_message_received(Interface *interface,
00120 Message *message) throw()
00121 {
00122 wakeup();
00123 return true;
00124 }
00125
00126
00127
00128
00129
00130 void
00131 FestivalSynthThread::say(const char *text)
00132 {
00133 EST_Wave wave;
00134 festival_text_to_wave(text, wave);
00135
00136 float duration = (float)wave.num_samples() / (float)wave.sample_rate();
00137
00138 __speechsynth_if->set_text(text);
00139 __speechsynth_if->set_final(false);
00140 __speechsynth_if->set_duration(duration);
00141 __speechsynth_if->write();
00142
00143 Time start;
00144 clock->get_systime(start);
00145
00146 EST_Option al;
00147 play_wave(wave, al);
00148
00149
00150
00151 Time now;
00152 clock->get_systime(now);
00153 float remaining = duration - (now - &start);
00154 if (remaining > 0) {
00155 Time waittime(remaining);
00156 waittime.wait_systime();
00157 }
00158
00159 __speechsynth_if->set_final(true);
00160 __speechsynth_if->write();
00161 }