]> git.mxchange.org Git - flightgear.git/commitdiff
voice system: all doors in FLITE
authorTorsten Dreyer <torsten@t3r.de>
Wed, 23 Apr 2014 15:09:00 +0000 (17:09 +0200)
committerTorsten Dreyer <torsten@t3r.de>
Wed, 23 Apr 2014 15:09:00 +0000 (17:09 +0200)
Prepare for festival lite generated voices

src/Sound/voice.cxx
src/Sound/voice.hxx

index 2143ba78f77ad42abc7de4a5cf03ac8b18a546df..04f8c4ef7956c82c4e56502f6e04b016a38d76f8 100644 (file)
 #include <Main/fg_props.hxx>
 #include "voice.hxx"
 
+#if defined(ENABLE_FLITE)
+#include "flitevoice.hxx"
+#endif
+
 #define VOICE "/sim/sound/voices"
 
 using std::string;
 
+class FGFestivalVoice : public FGVoiceMgr::FGVoice {
+public:
+  FGFestivalVoice(FGVoiceMgr *, const SGPropertyNode_ptr);
+  virtual ~FGFestivalVoice();
+  virtual void speak( const string & msg );
+  virtual void update();
+  void setVolume(double);
+  void setPitch(double);
+  void setSpeed(double);
+
+private:
+  SGSocket *_sock;
+  double _volume;
+  double _pitch;
+  double _speed;
+  SGPropertyNode_ptr _volumeNode;
+  SGPropertyNode_ptr _pitchNode;
+  SGPropertyNode_ptr _speedNode;
+};
+
 /// MANAGER ///
 
 FGVoiceMgr::FGVoiceMgr() :
+#if defined(ENABLE_THREADS)
+  _thread(NULL),
+#endif
        _host(fgGetString(VOICE "/host", "localhost")),
        _port(fgGetString(VOICE "/port", "1314")),
        _enabled(fgGetBool(VOICE "/enabled", false)),
-       _pausedNode(fgGetNode("/sim/sound/working", true))
+       _pausedNode(fgGetNode("/sim/sound/working", true)),
+       _paused(false)
 {
-#if defined(ENABLE_THREADS)
-       if (!_enabled)
-               return;
-       _thread = new FGVoiceThread(this);
-#endif
 }
 
 
 FGVoiceMgr::~FGVoiceMgr()
 {
-#if defined(ENABLE_THREADS)
-       if (!_enabled)
-               return;
-       _thread->cancel();
-       _thread->join();
-       delete _thread;
-#endif
 }
 
 
@@ -67,14 +83,30 @@ void FGVoiceMgr::init()
        if (!_enabled)
                return;
 
+#if defined(ENABLE_THREADS)
+  _thread = new FGVoiceThread(this);
+#endif
+
        SGPropertyNode *base = fgGetNode(VOICE, true);
        vector<SGPropertyNode_ptr> voices = base->getChildren("voice");
-       try {
-               for (unsigned int i = 0; i < voices.size(); i++)
-                       _voices.push_back(new FGVoice(this, voices[i]));
-       } catch (const std::string& s) {
-               SG_LOG(SG_SOUND, SG_ALERT, "VOICE: " << s);
-       }
+  for (unsigned int i = 0; i < voices.size(); i++) {
+    SGPropertyNode_ptr voice = voices[i];
+    if( voice->getBoolValue("festival", false ) ) {
+      try {
+        SG_LOG(SG_ALL,SG_ALERT,"creating festival voice" );
+        _voices.push_back(new FGFestivalVoice(this, voice));
+      } catch (const std::string& s) {
+        SG_LOG(SG_SOUND, SG_ALERT, "VOICE: " << s);
+      }
+    } else {
+#if defined(ENABLE_FLITE)
+      SG_LOG(SG_ALL,SG_ALERT,"creating flite voice" );
+      _voices.push_back(new FGFLITEVoice(this, voice));
+#else
+      SG_LOG(SG_ALL,SG_ALERT,"non festival voice not supported." );
+#endif
+    }
+  }
 
 #if defined(ENABLE_THREADS)
        _thread->setProcessorAffinity(1);
@@ -82,6 +114,19 @@ void FGVoiceMgr::init()
 #endif
 }
 
+void FGVoiceMgr::shutdown()
+{
+#if defined(ENABLE_THREADS)
+  _thread->cancel();
+  _thread->join();
+  delete _thread;
+  _thread = NULL;
+#endif
+
+  for( std::vector<FGVoice*>::iterator it = _voices.begin(); it != _voices.end(); ++it )
+    delete *it;
+}
+
 
 void FGVoiceMgr::update(double)
 {
@@ -95,7 +140,6 @@ void FGVoiceMgr::update(double)
                _voices[i]->speak();
 #endif
        }
-
 }
 
 
@@ -103,12 +147,11 @@ void FGVoiceMgr::update(double)
 
 /// VOICE ///
 
-FGVoiceMgr::FGVoice::FGVoice(FGVoiceMgr *mgr, const SGPropertyNode_ptr node) :
+FGFestivalVoice::FGFestivalVoice(FGVoiceMgr *mgr, const SGPropertyNode_ptr node) :
+  FGVoice(mgr),
        _volumeNode(node->getNode("volume", true)),
        _pitchNode(node->getNode("pitch", true)),
-       _speedNode(node->getNode("speed", true)),
-       _festival(node->getBoolValue("festival", true)),
-       _mgr(mgr)
+       _speedNode(node->getNode("speed", true))
 {
        SG_LOG(SG_SOUND, SG_INFO, "VOICE: adding `" << node->getStringValue("desc", "<unnamed>")
                        << "' voice");
@@ -120,7 +163,7 @@ FGVoiceMgr::FGVoice::FGVoice(FGVoiceMgr *mgr, const SGPropertyNode_ptr node) :
        if (!_sock->open(SG_IO_OUT))
                throw string("no connection to `") + host + ':' + port + '\'';
 
-       if (_festival) {
+       {
                _sock->writestring("(SayText \"\")\015\012");
                char buf[4];
                int len = _sock->read(buf, 3);
@@ -140,42 +183,59 @@ FGVoiceMgr::FGVoice::FGVoice(FGVoiceMgr *mgr, const SGPropertyNode_ptr node) :
        string preamble = node->getStringValue("preamble", "");
        if (!preamble.empty())
                pushMessage(preamble);
-
-       node->getNode("text", true)->addChangeListener(new FGVoiceListener(this));
+  node->getNode("text", true)->addChangeListener(this);
 }
 
 
-FGVoiceMgr::FGVoice::~FGVoice()
+FGFestivalVoice::~FGFestivalVoice()
 {
        _sock->close();
        delete _sock;
 }
 
 
-void FGVoiceMgr::FGVoice::pushMessage(string m)
+void FGVoiceMgr::FGVoice::pushMessage( const string & m)
 {
-       _msg.push(m + "\015\012");
+       _msg.push(m);
 #if defined(ENABLE_THREADS)
        _mgr->_thread->wake_up();
 #endif
 }
 
-
 bool FGVoiceMgr::FGVoice::speak(void)
 {
-       if (_msg.empty())
-               return false;
+  if (_msg.empty())
+    return false;
+
+  const string s = _msg.front();
+  _msg.pop();
 
-       const string s = _msg.front();
-       _msg.pop();
+  speak(s);
+
+  return !_msg.empty();
+}
+
+void FGFestivalVoice::speak( const string & msg )
+{
+  if( msg.empty() )
+    return;
+
+  string s;
+
+  if( msg[0] == '(' ) {
+    s = msg;
+  } else {
+    s.append("(SayText \"");
+    s.append(msg).append("\")");
+  }
+
+  s.append("\015\012");
        _sock->writestring(s.c_str());
-       return !_msg.empty();
 }
 
 
-void FGVoiceMgr::FGVoice::update(void)
+void FGFestivalVoice::update(void)
 {
-       if (_festival) {
                double d;
                d = _volumeNode->getDoubleValue();
                if (d != _volume)
@@ -186,11 +246,10 @@ void FGVoiceMgr::FGVoice::update(void)
                d = _speedNode->getDoubleValue();
                if (d != _speed)
                        setSpeed(_speed = d);
-       }
 }
 
 
-void FGVoiceMgr::FGVoice::setVolume(double d)
+void FGFestivalVoice::setVolume(double d)
 {
        std::ostringstream s;
        s << "(set! default_after_synth_hooks (list (lambda (utt)"
@@ -199,7 +258,7 @@ void FGVoiceMgr::FGVoice::setVolume(double d)
 }
 
 
-void FGVoiceMgr::FGVoice::setPitch(double d)
+void FGFestivalVoice::setPitch(double d)
 {
        std::ostringstream s;
        s << "(set! int_lr_params '((target_f0_mean " << d <<
@@ -209,16 +268,13 @@ void FGVoiceMgr::FGVoice::setPitch(double d)
 }
 
 
-void FGVoiceMgr::FGVoice::setSpeed(double d)
+void FGFestivalVoice::setSpeed(double d)
 {
        std::ostringstream s;
        s << "(Parameter.set 'Duration_Stretch " << d << ')';
        pushMessage(s.str());
 }
 
-
-
-
 /// THREAD ///
 
 #if defined(ENABLE_THREADS)
@@ -240,9 +296,9 @@ void FGVoiceMgr::FGVoiceThread::run(void)
 
 /// LISTENER ///
 
-void FGVoiceMgr::FGVoice::FGVoiceListener::valueChanged(SGPropertyNode *node)
+void FGVoiceMgr::FGVoice::valueChanged(SGPropertyNode *node)
 {
-       if (_voice->_mgr->_paused)
+       if (_mgr->_paused)
                return;
 
        const string s = node->getStringValue();
@@ -273,10 +329,8 @@ void FGVoiceMgr::FGVoice::FGVoiceListener::valueChanged(SGPropertyNode *node)
                        m += c;
        }
        //cerr << "\033[31;1mAFTER [" << m << "]\033[m" << endl;
-       if (_voice->_festival)
-               m = string("(SayText \"") + m + "\")";
 
-       _voice->pushMessage(m);
+       pushMessage(m);
 }
 
 
index 4bde11d1e931507ec43705dd60c2c3ee1d9ac052..eabd00a40da43d41dd9bc1d98c41c3265013873a 100644 (file)
@@ -55,11 +55,13 @@ public:
        FGVoiceMgr();
        ~FGVoiceMgr();
        void init(void);
+       void shutdown();
        void update(double dt);
 
-private:
-       class FGVoice;
 
+  class FGVoice;
+protected:
+  friend class FGFestivalVoice;
 #if defined(ENABLE_THREADS)
        class FGVoiceThread;
        FGVoiceThread *_thread;
@@ -86,53 +88,33 @@ private:
        void wait_for_jobs() { OpenThreads::ScopedLock<OpenThreads::Mutex> g(_mutex); _jobs.wait(&_mutex); }
        OpenThreads::Condition _jobs;
        OpenThreads::Mutex _mutex;
+protected:
        FGVoiceMgr *_mgr;
 };
 #endif
 
 
-
-class FGVoiceMgr::FGVoice {
+class FGVoiceMgr::FGVoice : public SGPropertyChangeListener {
 public:
-       FGVoice(FGVoiceMgr *, const SGPropertyNode_ptr);
-       ~FGVoice();
-       bool speak();
-       void update();
-       void setVolume(double);
-       void setPitch(double);
-       void setSpeed(double);
-       void pushMessage(std::string);
+  FGVoice(FGVoiceMgr * mgr ) : _mgr(mgr) {}
+  virtual ~FGVoice() {}
+  virtual void speak( const std::string & msg ) = 0;
+  virtual void update() = 0;
+  void pushMessage( const std::string & m);
+  bool speak();
 
-private:
-       class FGVoiceListener;
-       SGSocket *_sock;
-       double _volume;
-       double _pitch;
-       double _speed;
-       SGPropertyNode_ptr _volumeNode;
-       SGPropertyNode_ptr _pitchNode;
-       SGPropertyNode_ptr _speedNode;
-       bool _festival;
-       FGVoiceMgr *_mgr;
+protected:
+  void valueChanged(SGPropertyNode *node);
 
-#if defined(ENABLE_THREADS)
-       SGLockedQueue<std::string> _msg;
+  FGVoiceMgr *_mgr;
+
+  #if defined(ENABLE_THREADS)
+  SGLockedQueue<std::string> _msg;
 #else
   std::queue<std::string> _msg;
 #endif
 
-};
 
-
-
-class FGVoiceMgr::FGVoice::FGVoiceListener : public SGPropertyChangeListener {
-public:
-       FGVoiceListener(FGVoice *voice) : _voice(voice) {}
-       void valueChanged(SGPropertyNode *node);
-
-private:
-       FGVoice *_voice;
 };
 
-
 #endif // _VOICE_HXX