From: Torsten Dreyer Date: Wed, 7 May 2014 20:12:23 +0000 (+0200) Subject: Use FLITE voices in FGVoiceMgr X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=b80b010ef146b3d5914ea8e608eeb53aef28798e;p=flightgear.git Use FLITE voices in FGVoiceMgr This patch enables spoken words without the need for external festival using the existing FGVoiceMgr subsystem and the properties under /sim/sound/voices To hear the generated voices, set /sim/sound/voices/enabled=true at startup - use FLITEVoiceSynthesizer if a voice has false - use FLITEVoiceSynthesizer if the festival server is unreachable - decouple FGFLITEVoice from FGVoiceThread --- diff --git a/src/Sound/flitevoice.cxx b/src/Sound/flitevoice.cxx index bc70b5f2e..1c357d445 100644 --- a/src/Sound/flitevoice.cxx +++ b/src/Sound/flitevoice.cxx @@ -32,45 +32,50 @@ using std::string; #include "VoiceSynthesizer.hxx" -FGFLITEVoice::FGFLITEVoice(FGVoiceMgr * mgr, const SGPropertyNode_ptr node) - : FGVoice(mgr), _synthesizer( NULL ) +FGFLITEVoice::FGFLITEVoice(FGVoiceMgr * mgr, const SGPropertyNode_ptr node, const char * sampleGroupRefName) + : FGVoice(mgr), _synthesizer( NULL) { - string voice = globals->get_fg_root() + "/ATC/cmu_us_arctic_slt.htsvoice"; - _synthesizer = new FLITEVoiceSynthesizer( voice.c_str() ); + + _sampleName = node->getStringValue("desc", node->getPath().c_str()); + + string voice = globals->get_fg_root() + "/ATC/" + + node->getStringValue("htsvoice", "cmu_us_arctic_slt.htsvoice"); + + _synthesizer = new FLITEVoiceSynthesizer(voice.c_str()); SGSoundMgr *smgr = globals->get_soundmgr(); - _sgr = smgr->find("atc", true); + _sgr = smgr->find(sampleGroupRefName, true); _sgr->tie_to_listener(); node->getNode("text", true)->addChangeListener(this); - SG_LOG(SG_ALL, SG_ALERT, "FLITEVoice initialized"); + SG_LOG(SG_ALL, SG_INFO, "FLITEVoice initialized for sample-group '" << sampleGroupRefName + << "'. Samples will be named '" << _sampleName << "' " + << "voice is '" << voice << "'"); } FGFLITEVoice::~FGFLITEVoice() { delete _synthesizer; - SG_LOG(SG_ALL, SG_ALERT, "FLITEVoice dtor()"); } void FGFLITEVoice::speak(const string & msg) { - SG_LOG(SG_ALL, SG_ALERT, "FLITEVoice speak(" << msg << ")"); - - _sgr->remove("flite"); - - string s = simgear::strutils::strip( msg ); - if( false == s.empty() ) { - SGSoundSample * sample = _synthesizer->synthesize( msg, 1.0, 0.5, 0.5 ); - _sgr->add(sample, "flite"); - _sgr->set_volume(1.0); - _sgr->resume(); - _sgr->play("flite", true); + // this is called from voice.cxx:FGVoiceMgr::FGVoiceThread::run + string s = simgear::strutils::strip(msg); + if (false == s.empty()) { + _sampleQueue.push(_synthesizer->synthesize(msg, 1.0, 0.5, 0.5)); } } void FGFLITEVoice::update() { - + SGSharedPtr sample = _sampleQueue.pop(); + if (sample.valid()) { + _sgr->remove(_sampleName); + _sgr->add(sample, _sampleName); + _sgr->resume(); + _sgr->play(_sampleName, false); + } } diff --git a/src/Sound/flitevoice.hxx b/src/Sound/flitevoice.hxx index 4322b9d18..f1315276b 100644 --- a/src/Sound/flitevoice.hxx +++ b/src/Sound/flitevoice.hxx @@ -25,21 +25,25 @@ #include "voice.hxx" #include +#include class VoiceSynthesizer; class FGFLITEVoice: public FGVoiceMgr::FGVoice { public: - FGFLITEVoice(FGVoiceMgr *, const SGPropertyNode_ptr); + FGFLITEVoice(FGVoiceMgr *, const SGPropertyNode_ptr, const char * sampleGroupRefName = "flite-voice"); virtual ~FGFLITEVoice(); virtual void speak(const std::string & msg); virtual void update(); + private: FGFLITEVoice(const FGFLITEVoice & other); FGFLITEVoice & operator =(const FGFLITEVoice & other); SGSharedPtr _sgr; VoiceSynthesizer * _synthesizer; + SGLockedQueue > _sampleQueue; + std::string _sampleName; }; #endif // _FLITEVOICE_HXX diff --git a/src/Sound/voice.cxx b/src/Sound/voice.cxx index eec16ba53..25355a949 100644 --- a/src/Sound/voice.cxx +++ b/src/Sound/voice.cxx @@ -93,19 +93,18 @@ void FGVoiceMgr::init() 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)); + continue; } catch (const std::string& s) { - SG_LOG(SG_SOUND, SG_ALERT, "VOICE: " << s); + SG_LOG(SG_SOUND, SG_WARN, "failed to create festival voice, falling back to flite voice" ); } - } else { + } #if defined(ENABLE_FLITE) - SG_LOG(SG_ALL,SG_ALERT,"creating flite voice" ); - _voices.push_back(new FGFLITEVoice(this, voice)); + SG_LOG(SG_ALL,SG_INFO,"creating flite voice" ); + _voices.push_back(new FGFLITEVoice(this, voice)); #else - SG_LOG(SG_ALL,SG_ALERT,"non festival voice not supported." ); + SG_LOG(SG_ALL,SG_ALERT,"non festival voice not supported." ); #endif - } } #if defined(ENABLE_THREADS)