_stationId = stationId;
}
- void setVoice(const string & voice)
- {
- _voice = voice;
- }
-
- const string & getVoice() const
- {
- return _voice;
- }
private:
SynthesizeRequest _synthesizeRequest;
SGLockedQueue<SGSharedPtr<SGSoundSample> > _spokenAtis;
string _stationId;
- string _voice;
};
AtisSpeaker::AtisSpeaker()
- :
- _voice("/ATC/cmu_us_arctic_slt.htsvoice")
-// _voice("/ATC/cstr_uk_female-1.0.htsvoice")
{
_synthesizeRequest.listener = this;
}
void AtisSpeaker::valueChanged(SGPropertyNode * node)
{
if (!fgGetBool("/sim/sound/working", false))
- return;
+ return;
string newText = node->getStringValue();
if (_synthesizeRequest.text == newText) return;
_synthesizeRequest.text = newText;
+ string voice = "cmu_us_arctic_slt";
+
if (!_stationId.empty()) {
// lets play a bit with the voice so not every airports atis sounds alike
// but every atis of an airport has the same voice
+ // create a simple hash from the last two letters of the airport's id
+ unsigned char hash = 0;
string::iterator i = _stationId.end() - 1;
- if( i != _stationId.begin() )
+ hash += *i;
+
+ if( i != _stationId.begin() ) {
--i;
+ hash += *i;
+ }
- _synthesizeRequest.speed = ((*i) % 16) / 16.0;
- _synthesizeRequest.pitch = ((*i) % 16) / 16.0;
+ _synthesizeRequest.speed = (hash % 16) / 16.0;
+ _synthesizeRequest.pitch = (hash % 16) / 16.0;
+
+ // pick a voice
+ voice = FLITEVoiceSynthesizer::getVoicePath(
+ static_cast<FLITEVoiceSynthesizer::voice_t>(hash % FLITEVoiceSynthesizer::VOICE_UNKNOWN) );
}
+
FGSoundManager * smgr = dynamic_cast<FGSoundManager*>(globals->get_soundmgr());
assert(smgr != NULL);
- string voice = globals->get_fg_root() + _voice;
+ SG_LOG(SG_INSTR,SG_INFO,"AtisSpeaker voice is " << voice );
FLITEVoiceSynthesizer * synthesizer = dynamic_cast<FLITEVoiceSynthesizer*>(smgr->getSynthesizer(voice));
synthesizer->synthesize(_synthesizeRequest);
#include <OpenThreads/Thread>
#include <flite_hts_engine.h>
+using std::string;
+
+static const char * VOICE_FILES[] = {
+ "cmu_us_arctic_slt.htsvoice",
+ "cstr_uk_female-1.0.htsvoice"
+};
+
class FLITEVoiceSynthesizer::WorkerThread: public OpenThreads::Thread {
public:
WorkerThread(FLITEVoiceSynthesizer * synthesizer)
}
}
+string FLITEVoiceSynthesizer::getVoicePath( voice_t voice )
+{
+ if( voice < 0 || voice >= VOICE_UNKNOWN ) return string("");
+ string voicePath = globals->get_fg_root() + "/ATC/" + VOICE_FILES[voice];
+ return voicePath;
+}
+
+string FLITEVoiceSynthesizer::getVoicePath( const string & voice )
+{
+ if( voice == "cmu_us_arctic_slt" ) return getVoicePath(CMU_US_ARCTIC_SLT);
+ if( voice == "cstr_uk_female" ) return getVoicePath(CSTR_UK_FEMALE);
+ return getVoicePath(VOICE_UNKNOWN);
+}
+
+
void FLITEVoiceSynthesizer::synthesize( SynthesizeRequest & request)
{
_requests.push(request);
*/
class FLITEVoiceSynthesizer : public VoiceSynthesizer {
public:
+
+ typedef enum {
+ CMU_US_ARCTIC_SLT = 0,
+ CSTR_UK_FEMALE,
+
+ VOICE_UNKNOWN // keep this at the end
+ } voice_t;
+
+ static std::string getVoicePath( voice_t voice );
+ static std::string getVoicePath( const std::string & voice );
+
FLITEVoiceSynthesizer( const std::string & voice );
~FLITEVoiceSynthesizer();
virtual SGSoundSample * synthesize( const std::string & text, double volume, double speed, double pitch );