#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<SGSoundSample> sample = _sampleQueue.pop();
+ if (sample.valid()) {
+ _sgr->remove(_sampleName);
+ _sgr->add(sample, _sampleName);
+ _sgr->resume();
+ _sgr->play(_sampleName, false);
+ }
}
#include "voice.hxx"
#include <simgear/sound/soundmgr_openal.hxx>
+#include <simgear/threads/SGQueue.hxx>
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<SGSampleGroup> _sgr;
VoiceSynthesizer * _synthesizer;
+ SGLockedQueue<SGSharedPtr<SGSoundSample> > _sampleQueue;
+ std::string _sampleName;
};
#endif // _FLITEVOICE_HXX
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)