14#include <simgear/compiler.h>
19#define VOICE "/sim/sound/voices"
27 virtual void speak(
const string & msg );
28 virtual void update(
double);
38 SGPropertyNode_ptr _volumeNode;
39 SGPropertyNode_ptr _pitchNode;
40 SGPropertyNode_ptr _speedNode;
46#if defined(ENABLE_THREADS)
68#if defined(ENABLE_THREADS)
69 _thread =
new FGVoiceThread(
this);
73 std::vector<SGPropertyNode_ptr> voices = base->getChildren(
"voice");
74 for (
unsigned int i = 0;
i < voices.size();
i++) {
75 SGPropertyNode_ptr voice = voices[
i];
76 if( voice->getBoolValue(
"festival",
false ) ) {
80 }
catch (
const std::string& ) {
81 SG_LOG(SG_SOUND, SG_WARN,
"failed to create festival voice, falling back to flite voice" );
88#if defined(ENABLE_THREADS)
89 _thread->setProcessorAffinity(1);
96#if defined(ENABLE_THREADS)
105 for( std::vector<FGVoice*>::iterator it =
_voices.begin(); it !=
_voices.end(); ++it )
116 for (
unsigned int i = 0;
i <
_voices.size();
i++) {
118#if !defined(ENABLE_THREADS)
127 SGSubsystemMgr::DISPLAY);
134 _volumeNode(node->getNode(
"volume", true)),
135 _pitchNode(node->getNode(
"pitch", true)),
136 _speedNode(node->getNode(
"speed", true))
138 SG_LOG(SG_SOUND, SG_INFO,
"VOICE: adding `" << node->getStringValue(
"desc",
"<unnamed>")
140 const string &host =
_mgr->_host;
141 const string &port =
_mgr->_port;
143 _sock =
new SGSocket(host, port,
"tcp");
144 _sock->set_timeout(6000);
145 if (!_sock->open(SG_IO_OUT))
146 throw string(
"no connection to `") + host +
':' + port +
'\'';
149 _sock->writestring(
"(+ 1 2)\015\012");
151 int len = _sock->read(buf, 3);
152 if (len != 3 || buf[0] !=
'L' || buf[1] !=
'P')
153 throw string(
"unexpected or no response from `") + host +
':' + port
154 +
"'. Either it's not\n Festival listening,"
155 " or Festival couldn't open a sound device.";
157 SG_LOG(SG_SOUND, SG_INFO,
"VOICE: connection to Festival server on `"
158 << host <<
':' << port <<
"' established");
161 const string preamble = node->getStringValue(
"preamble",
"");
162 if (!preamble.empty()) {
167 setVolume(_volume = _volumeNode->getDoubleValue());
168 setPitch(_pitch = _pitchNode->getDoubleValue());
169 setSpeed(_speed = _speedNode->getDoubleValue());
171 node->getNode(
"text",
true)->addChangeListener(
this);
185#if defined(ENABLE_THREADS)
186 _mgr->_thread->wake_up();
195 const string s =
_msg.front();
200 return !
_msg.empty();
210 if( msg[0] ==
'(' ) {
213 s.append(
"(SayText \"");
214 s.append(msg).append(
"\")");
217 s.append(
"\015\012");
218 _sock->writestring(s.c_str());
225 d = _volumeNode->getDoubleValue();
228 d = _pitchNode->getDoubleValue();
231 d = _speedNode->getDoubleValue();
239 std::ostringstream s;
240 s <<
"(set! default_after_synth_hooks (list (lambda (utt)"
241 "(utt.wave.rescale utt " << d <<
" t))))";
248 std::ostringstream s;
249 s <<
"(set! int_lr_params '((target_f0_mean " << d <<
250 ")(target_f0_std 14)(model_f0_mean 170)"
251 "(model_f0_std 34)))";
258 std::ostringstream s;
259 s <<
"(Parameter.set 'Duration_Stretch " << d <<
')';
265#if defined(ENABLE_THREADS)
266void FGVoiceMgr::FGVoiceThread::run(
void)
270 for (
unsigned int i = 0;
i < _mgr->_voices.size();
i++)
271 busy |= _mgr->_voices[
i]->speak();
289 const string s = node->getStringValue();
293 for (
unsigned int i = 0;
i < s.size();
i++) {
295 if (c ==
'\n' || c ==
'\r' || c ==
'\t')
297 else if (!isprint(c))
299 else if (c ==
'\\' || c ==
'"')
301 else if (c ==
'|' || c ==
'_')
305 else if (c ==
'>' || c ==
'<')
FGFestivalVoice(FGVoiceMgr *, const SGPropertyNode_ptr)
VOICE ///.
virtual void update(double)
virtual ~FGFestivalVoice()
std::queue< std::string > _msg
void pushMessage(const std::string &m)
virtual void speak(const std::string &msg)=0
void valueChanged(SGPropertyNode *node)
THREAD ///.
friend class FGFestivalVoice
void update(double dt) override
std::vector< FGVoice * > _voices
SGPropertyNode_ptr _pausedNode
std::string fgGetString(const char *name, const char *defaultValue)
Get a string value for a property.
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
SGSubsystemMgr::Registrant< FGVoiceMgr > registrantFGVoiceMgr(SGSubsystemMgr::DISPLAY)