Be able to control atis speech pitch, volume and speed.
Uses these properties: /sim/atis/speed /sim/atis/volume /sim/atis/pitch Values 1.0 behave as default. Other values are used to multiply default settings. Changes don't take affect immediately. But changing com frequency seems to often cause an update which will then pick up the new values.
This commit is contained in:
parent
1a4d3785c4
commit
3591bd8631
2 changed files with 42 additions and 10 deletions
|
@ -81,6 +81,9 @@ private:
|
||||||
AtisSpeaker::AtisSpeaker()
|
AtisSpeaker::AtisSpeaker()
|
||||||
{
|
{
|
||||||
_synthesizeRequest.listener = this;
|
_synthesizeRequest.listener = this;
|
||||||
|
if (!fgHasNode("/sim/atis/speed")) fgSetDouble("/sim/atis/speed", 1);
|
||||||
|
if (!fgHasNode("/sim/atis/pitch")) fgSetDouble("/sim/atis/pitch", 1);
|
||||||
|
if (!fgHasNode("/sim/atis/enabled")) fgSetBool("/sim/atis/enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
AtisSpeaker::~AtisSpeaker()
|
AtisSpeaker::~AtisSpeaker()
|
||||||
|
@ -115,9 +118,9 @@ void AtisSpeaker::valueChanged(SGPropertyNode * node)
|
||||||
hash += *i;
|
hash += *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
_synthesizeRequest.speed = (hash % 16) / 16.0;
|
_synthesizeRequest.speed = (hash % 16) / 16.0 * fgGetDouble("/sim/atis/speed", 1);
|
||||||
_synthesizeRequest.pitch = (hash % 16) / 16.0;
|
_synthesizeRequest.pitch = (hash % 16) / 16.0 * fgGetDouble("/sim/atis/pitch", 1);
|
||||||
|
|
||||||
if( starts_with( _stationId, "K" ) || starts_with( _stationId, "C" ) ||
|
if( starts_with( _stationId, "K" ) || starts_with( _stationId, "C" ) ||
|
||||||
starts_with( _stationId, "P" ) ) {
|
starts_with( _stationId, "P" ) ) {
|
||||||
voice = FLITEVoiceSynthesizer::getVoicePath("cmu_us_arctic_slt");
|
voice = FLITEVoiceSynthesizer::getVoicePath("cmu_us_arctic_slt");
|
||||||
|
@ -133,7 +136,7 @@ void AtisSpeaker::valueChanged(SGPropertyNode * node)
|
||||||
FGSoundManager * smgr = globals->get_subsystem<FGSoundManager>();
|
FGSoundManager * smgr = globals->get_subsystem<FGSoundManager>();
|
||||||
assert(smgr != NULL);
|
assert(smgr != NULL);
|
||||||
|
|
||||||
SG_LOG(SG_INSTR, SG_DEBUG,"AtisSpeaker voice is " << voice );
|
SG_LOG(SG_INSTR, SG_DEBUG,"node->getPath()=" << node->getPath() << " AtisSpeaker voice is " << voice );
|
||||||
FLITEVoiceSynthesizer * synthesizer = dynamic_cast<FLITEVoiceSynthesizer*>(smgr->getSynthesizer(voice));
|
FLITEVoiceSynthesizer * synthesizer = dynamic_cast<FLITEVoiceSynthesizer*>(smgr->getSynthesizer(voice));
|
||||||
|
|
||||||
synthesizer->synthesize(_synthesizeRequest);
|
synthesizer->synthesize(_synthesizeRequest);
|
||||||
|
@ -484,6 +487,10 @@ private:
|
||||||
PropertyObject<bool> _addNoise;
|
PropertyObject<bool> _addNoise;
|
||||||
PropertyObject<double> _cutoffSignalQuality;
|
PropertyObject<double> _cutoffSignalQuality;
|
||||||
|
|
||||||
|
SGPropertyNode_ptr _atis_enabled_node;
|
||||||
|
bool _atis_enabled_prev;
|
||||||
|
SGSharedPtr<SGSoundSample> _atis_sample;
|
||||||
|
|
||||||
std::string _soundPrefix;
|
std::string _soundPrefix;
|
||||||
void stopAudio();
|
void stopAudio();
|
||||||
void updateAudio();
|
void updateAudio();
|
||||||
|
@ -514,6 +521,8 @@ void CommRadioImpl::bind()
|
||||||
|
|
||||||
_volume_norm = PropertyObject<double>(_rootNode->getNode("volume", true));
|
_volume_norm = PropertyObject<double>(_rootNode->getNode("volume", true));
|
||||||
_atis = PropertyObject<string>(_rootNode->getNode("atis", true));
|
_atis = PropertyObject<string>(_rootNode->getNode("atis", true));
|
||||||
|
if (!fgHasNode("/sim/atis/enabled")) fgSetBool("/sim/atis/enabled", true);
|
||||||
|
_atis_enabled_node = fgGetNode("/sim/atis/enabled");
|
||||||
_addNoise = PropertyObject<bool>(_rootNode->getNode("add-noise", true));
|
_addNoise = PropertyObject<bool>(_rootNode->getNode("add-noise", true));
|
||||||
_cutoffSignalQuality = PropertyObject<double>(_rootNode->getNode("cutoff-signal-quality", true));
|
_cutoffSignalQuality = PropertyObject<double>(_rootNode->getNode("cutoff-signal-quality", true));
|
||||||
|
|
||||||
|
@ -682,15 +691,38 @@ void CommRadioImpl::updateAudio()
|
||||||
noiseSample = noise;
|
noiseSample = noise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool atis_enabled = _atis_enabled_node->getBoolValue();
|
||||||
|
int atis_delta = 0;
|
||||||
|
if (atis_enabled and !_atis_enabled_prev) atis_delta = 1;
|
||||||
|
if (!atis_enabled and _atis_enabled_prev) atis_delta = -1;
|
||||||
|
|
||||||
if (_atisSpeaker.hasSpokenAtis()) {
|
if (_atisSpeaker.hasSpokenAtis()) {
|
||||||
// the speaker has created a new atis sample
|
// the speaker has created a new atis sample
|
||||||
// remove previous atis sample
|
// remove previous atis sample
|
||||||
_sampleGroup->remove(atisRef);
|
_sampleGroup->remove(atisRef);
|
||||||
|
if (!atis_delta and atis_enabled) atis_delta = 1;
|
||||||
SGSharedPtr<SGSoundSample> sample = _atisSpeaker.getSpokenAtis();
|
|
||||||
_sampleGroup->add(sample, atisRef);
|
|
||||||
_sampleGroup->play_looped(atisRef);
|
|
||||||
}
|
}
|
||||||
|
if (atis_delta == 1) {
|
||||||
|
// Start play of atis text. We store the most recent sample in _atis_sample
|
||||||
|
// so that we can resume if /sim/atis/enabled is changed from false to
|
||||||
|
// true.
|
||||||
|
SGSharedPtr<SGSoundSample> sample = _atisSpeaker.getSpokenAtis();
|
||||||
|
if (sample) _atis_sample = sample;
|
||||||
|
else sample = _atis_sample;
|
||||||
|
if (sample) {
|
||||||
|
SG_LOG(SG_INSTR, SG_DEBUG, "starting looped play of atis sample.");
|
||||||
|
_sampleGroup->add(sample, atisRef);
|
||||||
|
_sampleGroup->play_looped(atisRef);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SG_LOG(SG_INSTR, SG_DEBUG, "no atis sample available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (atis_delta == -1) {
|
||||||
|
// Stop play of atis text.
|
||||||
|
_sampleGroup->remove(atisRef);
|
||||||
|
}
|
||||||
|
_atis_enabled_prev = atis_enabled;
|
||||||
|
|
||||||
// adjust volumes
|
// adjust volumes
|
||||||
const bool doSquelch = (_signalQuality_norm < _cutoffSignalQuality);
|
const bool doSquelch = (_signalQuality_norm < _cutoffSignalQuality);
|
||||||
|
|
|
@ -112,8 +112,8 @@ FLITEVoiceSynthesizer::~FLITEVoiceSynthesizer()
|
||||||
SGSoundSample * FLITEVoiceSynthesizer::synthesize(const std::string & text, double volume, double speed, double pitch )
|
SGSoundSample * FLITEVoiceSynthesizer::synthesize(const std::string & text, double volume, double speed, double pitch )
|
||||||
{
|
{
|
||||||
SG_CLAMP_RANGE( volume, 0.0, 1.0 );
|
SG_CLAMP_RANGE( volume, 0.0, 1.0 );
|
||||||
SG_CLAMP_RANGE( speed, 0.0, 1.0 );
|
SG_CLAMP_RANGE( speed, 0.0, 10.0 );
|
||||||
SG_CLAMP_RANGE( pitch, 0.0, 1.0 );
|
SG_CLAMP_RANGE( pitch, 0.0, 10.0 );
|
||||||
HTS_Engine_set_volume( &_engine->engine, _volume );
|
HTS_Engine_set_volume( &_engine->engine, _volume );
|
||||||
HTS_Engine_set_speed( &_engine->engine, 0.8 + 0.4 * speed );
|
HTS_Engine_set_speed( &_engine->engine, 0.8 + 0.4 * speed );
|
||||||
HTS_Engine_add_half_tone(&_engine->engine, -4.0 + 8.0 * pitch );
|
HTS_Engine_add_half_tone(&_engine->engine, -4.0 + 8.0 * pitch );
|
||||||
|
|
Loading…
Reference in a new issue