Merge branch 'ehofman/sound'
This commit is contained in:
commit
b5c46a8d59
46 changed files with 1338 additions and 796 deletions
|
@ -128,6 +128,17 @@ Configuration description:
|
||||||
|
|
||||||
in-transit: the sample plays continuously,
|
in-transit: the sample plays continuously,
|
||||||
while the property is changing its value.
|
while the property is changing its value.
|
||||||
|
|
||||||
|
<type>
|
||||||
|
This defines the type os this sample:
|
||||||
|
|
||||||
|
fx: this is the default type and doesn't need to be defined.
|
||||||
|
|
||||||
|
avionics: sounds set to this type don't have a position and
|
||||||
|
orientation but are treated as if it's mounted to
|
||||||
|
the aircraft panel. it's up to the user to define
|
||||||
|
if it can always be heard or only when in cockpit
|
||||||
|
view.
|
||||||
|
|
||||||
<volume> / <pitch>
|
<volume> / <pitch>
|
||||||
Volume or Pitch definition. Currently there may be up to 5
|
Volume or Pitch definition. Currently there may be up to 5
|
||||||
|
|
|
@ -841,7 +841,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
// TODO - At hot 'n high airports this may be 500ft AGL though - need to make this a variable.
|
// TODO - At hot 'n high airports this may be 500ft AGL though - need to make this a variable.
|
||||||
if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 700) {
|
if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 700) {
|
||||||
double cc = 0.0;
|
double cc = 0.0;
|
||||||
if(tower->GetCrosswindConstraint(cc)) {
|
if(tower && tower->GetCrosswindConstraint(cc)) {
|
||||||
if(orthopos.y() > cc) {
|
if(orthopos.y() > cc) {
|
||||||
//cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n';
|
//cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n';
|
||||||
leg = TURN1;
|
leg = TURN1;
|
||||||
|
@ -884,7 +884,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
// turn 1000m out for now, taking other traffic into accout
|
// turn 1000m out for now, taking other traffic into accout
|
||||||
if(fabs(orthopos.x()) > 900) {
|
if(fabs(orthopos.x()) > 900) {
|
||||||
double dd = 0.0;
|
double dd = 0.0;
|
||||||
if(tower->GetDownwindConstraint(dd)) {
|
if(tower && tower->GetDownwindConstraint(dd)) {
|
||||||
if(fabs(orthopos.x()) > fabs(dd)) {
|
if(fabs(orthopos.x()) > fabs(dd)) {
|
||||||
//cout << "Turning to downwind, distance from centerline = " << fabs(orthopos.x()) << '\n';
|
//cout << "Turning to downwind, distance from centerline = " << fabs(orthopos.x()) << '\n';
|
||||||
leg = TURN2;
|
leg = TURN2;
|
||||||
|
@ -930,7 +930,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
// For now we're assuming that we aim to follow the same glidepath regardless of wind.
|
// For now we're assuming that we aim to follow the same glidepath regardless of wind.
|
||||||
double d1;
|
double d1;
|
||||||
double d2;
|
double d2;
|
||||||
CalculateSoD((tower->GetBaseConstraint(d1) ? d1 : -1000.0), (tower->GetDownwindConstraint(d2) ? d2 : 1000.0 * patternDirection), (patternDirection ? true : false));
|
CalculateSoD(((tower && tower->GetBaseConstraint(d1)) ? d1 : -1000.0), ((tower && tower->GetDownwindConstraint(d2)) ? d2 : 1000.0 * patternDirection), (patternDirection ? true : false));
|
||||||
if(SoD.leg == DOWNWIND) {
|
if(SoD.leg == DOWNWIND) {
|
||||||
descending = (orthopos.y() < SoD.y ? true : false);
|
descending = (orthopos.y() < SoD.y ? true : false);
|
||||||
}
|
}
|
||||||
|
@ -950,7 +950,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
if(orthopos.y() < -1000.0 + turn_radius) {
|
if(orthopos.y() < -1000.0 + turn_radius) {
|
||||||
//if(orthopos.y() < -980) {
|
//if(orthopos.y() < -980) {
|
||||||
double bb = 0.0;
|
double bb = 0.0;
|
||||||
if(tower->GetBaseConstraint(bb)) {
|
if(tower && tower->GetBaseConstraint(bb)) {
|
||||||
if(fabs(orthopos.y()) > fabs(bb)) {
|
if(fabs(orthopos.y()) > fabs(bb)) {
|
||||||
//cout << "Turning to base, distance from threshold = " << fabs(orthopos.y()) << '\n';
|
//cout << "Turning to base, distance from threshold = " << fabs(orthopos.y()) << '\n';
|
||||||
leg = TURN3;
|
leg = TURN3;
|
||||||
|
@ -982,7 +982,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
double d1;
|
double d1;
|
||||||
// Make downwind leg position artifically large to avoid any chance of SoD being returned as
|
// Make downwind leg position artifically large to avoid any chance of SoD being returned as
|
||||||
// on downwind when we are already on base.
|
// on downwind when we are already on base.
|
||||||
CalculateSoD((tower->GetBaseConstraint(d1) ? d1 : -1000.0), (10000.0 * patternDirection), (patternDirection ? true : false));
|
CalculateSoD(((tower && tower->GetBaseConstraint(d1)) ? d1 : -1000.0), (10000.0 * patternDirection), (patternDirection ? true : false));
|
||||||
if(SoD.leg == BASE) {
|
if(SoD.leg == BASE) {
|
||||||
descending = (fabs(orthopos.y()) < fabs(SoD.y) ? true : false);
|
descending = (fabs(orthopos.y()) < fabs(SoD.y) ? true : false);
|
||||||
}
|
}
|
||||||
|
@ -1207,10 +1207,11 @@ void FGAILocalTraffic::CalculateSoD(double base_leg_pos, double downwind_leg_pos
|
||||||
|
|
||||||
void FGAILocalTraffic::TransmitPatternPositionReport(void) {
|
void FGAILocalTraffic::TransmitPatternPositionReport(void) {
|
||||||
// airport name + "traffic" + airplane callsign + pattern direction + pattern leg + rwy + ?
|
// airport name + "traffic" + airplane callsign + pattern direction + pattern leg + rwy + ?
|
||||||
string trns = "";
|
string trns;
|
||||||
int code = 0;
|
int code = 0;
|
||||||
|
const string& apt_name = tower ? tower->get_name() : airportID;
|
||||||
trns += tower->get_name();
|
|
||||||
|
trns += apt_name;
|
||||||
trns += " Traffic ";
|
trns += " Traffic ";
|
||||||
trns += plane.callsign;
|
trns += plane.callsign;
|
||||||
if(patternDirection == 1) {
|
if(patternDirection == 1) {
|
||||||
|
@ -1249,10 +1250,10 @@ void FGAILocalTraffic::TransmitPatternPositionReport(void) {
|
||||||
}
|
}
|
||||||
trns += ConvertRwyNumToSpokenString(rwy.rwyID);
|
trns += ConvertRwyNumToSpokenString(rwy.rwyID);
|
||||||
|
|
||||||
trns += " ";
|
trns += ' ';
|
||||||
|
|
||||||
// And add the airport name again
|
// And add the airport name again
|
||||||
trns += tower->get_name();
|
trns += apt_name;
|
||||||
|
|
||||||
pending_transmission = trns;
|
pending_transmission = trns;
|
||||||
ConditionalTransmit(60.0, code); // Assume a report of this leg will be invalid if we can't transmit within a minute.
|
ConditionalTransmit(60.0, code); // Assume a report of this leg will be invalid if we can't transmit within a minute.
|
||||||
|
|
|
@ -47,6 +47,12 @@ FGAIPlane::FGAIPlane() {
|
||||||
_trackSet = false;
|
_trackSet = false;
|
||||||
_tgtRoll = 0.0;
|
_tgtRoll = 0.0;
|
||||||
_rollSuspended = false;
|
_rollSuspended = false;
|
||||||
|
|
||||||
|
if ( !_sgr ) {
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
_sgr = smgr->find("atc", true);
|
||||||
|
_sgr->tie_to_listener();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FGAIPlane::~FGAIPlane() {
|
FGAIPlane::~FGAIPlane() {
|
||||||
|
@ -106,7 +112,7 @@ void FGAIPlane::Update(double dt) {
|
||||||
// For now assume in range !!!
|
// For now assume in range !!!
|
||||||
// TODO - implement range checking
|
// TODO - implement range checking
|
||||||
// TODO - at the moment the volume is always set off comm1
|
// TODO - at the moment the volume is always set off comm1
|
||||||
double volume = fgGetDouble("/instrumentation/comm[0]/volume");
|
float volume = fgGetFloat("/instrumentation/comm[0]/volume");
|
||||||
Render(plane.callsign, volume, false);
|
Render(plane.callsign, volume, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,8 +173,9 @@ void FGAIPlane::ConditionalTransmit(double timeout, int callback_code) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIPlane::ImmediateTransmit(int callback_code) {
|
void FGAIPlane::ImmediateTransmit(int callback_code) {
|
||||||
// TODO - at the moment the volume is always set off comm1
|
// TODO - at the moment the volume is always set off comm1
|
||||||
double volume = fgGetDouble("/instrumentation/comm[0]/volume");
|
float volume = fgGetFloat("/instrumentation/comm[0]/volume");
|
||||||
|
|
||||||
Render(plane.callsign, volume, false);
|
Render(plane.callsign, volume, false);
|
||||||
if(callback_code) {
|
if(callback_code) {
|
||||||
ProcessCallback(callback_code);
|
ProcessCallback(callback_code);
|
||||||
|
@ -183,24 +190,18 @@ void FGAIPlane::ProcessCallback(int code) {
|
||||||
// Outputs the transmission either on screen or as audio depending on user preference
|
// Outputs the transmission either on screen or as audio depending on user preference
|
||||||
// The refname is a string to identify this sample to the sound manager
|
// The refname is a string to identify this sample to the sound manager
|
||||||
// The repeating flag indicates whether the message should be repeated continuously or played once.
|
// The repeating flag indicates whether the message should be repeated continuously or played once.
|
||||||
void FGAIPlane::Render(const string& refname, const double volume, bool repeating) {
|
void FGAIPlane::Render(const string& refname, const float volume, bool repeating) {
|
||||||
fgSetString("/sim/messages/ai-plane", pending_transmission.c_str());
|
fgSetString("/sim/messages/ai-plane", pending_transmission.c_str());
|
||||||
#ifdef ENABLE_AUDIO_SUPPORT
|
#ifdef ENABLE_AUDIO_SUPPORT
|
||||||
voice = (voiceOK && fgGetBool("/sim/sound/voice"));
|
voice = (voiceOK && fgGetBool("/sim/sound/voice"));
|
||||||
if(voice) {
|
if(voice) {
|
||||||
string buf = vPtr->WriteMessage((char*)pending_transmission.c_str(), voice);
|
size_t len;
|
||||||
if(voice) {
|
void* buf = vPtr->WriteMessage(pending_transmission, &len);
|
||||||
SGSoundSample* simple =
|
if(voice && (volume > 0.05)) {
|
||||||
new SGSoundSample((unsigned char*)buf.c_str(), buf.length(), 8000, AL_FORMAT_MONO8 );
|
SGSoundSample* simple = new SGSoundSample(&buf, len, 8000 );
|
||||||
// TODO - at the moment the volume can't be changed
|
|
||||||
// after the transmission has started.
|
|
||||||
simple->set_volume(volume);
|
simple->set_volume(volume);
|
||||||
globals->get_soundmgr()->add(simple, refname);
|
_sgr->add(simple, refname);
|
||||||
if(repeating) {
|
_sgr->play(refname, repeating);
|
||||||
globals->get_soundmgr()->play_looped(refname);
|
|
||||||
} else {
|
|
||||||
globals->get_soundmgr()->play_once(refname);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // ENABLE_AUDIO_SUPPORT
|
#endif // ENABLE_AUDIO_SUPPORT
|
||||||
|
@ -221,8 +222,8 @@ void FGAIPlane::NoRender(const string& refname) {
|
||||||
if(playing) {
|
if(playing) {
|
||||||
if(voice) {
|
if(voice) {
|
||||||
#ifdef ENABLE_AUDIO_SUPPORT
|
#ifdef ENABLE_AUDIO_SUPPORT
|
||||||
globals->get_soundmgr()->stop(refname);
|
_sgr->stop(refname);
|
||||||
globals->get_soundmgr()->remove(refname);
|
_sgr->remove(refname);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
playing = false;
|
playing = false;
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "AIEntity.hxx"
|
#include "AIEntity.hxx"
|
||||||
#include "ATC.hxx"
|
#include "ATC.hxx"
|
||||||
|
|
||||||
|
class SGSampleGroup;
|
||||||
|
|
||||||
enum PatternLeg {
|
enum PatternLeg {
|
||||||
TAKEOFF_ROLL,
|
TAKEOFF_ROLL,
|
||||||
CLIMBOUT,
|
CLIMBOUT,
|
||||||
|
@ -140,7 +142,7 @@ private:
|
||||||
// Outputs the transmission either on screen or as audio depending on user preference
|
// Outputs the transmission either on screen or as audio depending on user preference
|
||||||
// The refname is a string to identify this sample to the sound manager
|
// The refname is a string to identify this sample to the sound manager
|
||||||
// The repeating flag indicates whether the message should be repeated continuously or played once.
|
// The repeating flag indicates whether the message should be repeated continuously or played once.
|
||||||
void Render(const string& refname, const double volume, bool repeating);
|
void Render(const string& refname, const float volume, bool repeating);
|
||||||
|
|
||||||
// Cease rendering a transmission.
|
// Cease rendering a transmission.
|
||||||
// Requires the sound manager refname if audio, else "".
|
// Requires the sound manager refname if audio, else "".
|
||||||
|
@ -157,6 +159,8 @@ private:
|
||||||
bool _trackSet; // Set true if tgtTrack is to be followed
|
bool _trackSet; // Set true if tgtTrack is to be followed
|
||||||
double _tgtRoll;
|
double _tgtRoll;
|
||||||
bool _rollSuspended; // Set true when a derived class has suspended AIPlane's roll control
|
bool _rollSuspended; // Set true when a derived class has suspended AIPlane's roll control
|
||||||
|
|
||||||
|
SGSharedPtr<SGSampleGroup> _sgr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _FG_AI_PLANE_HXX
|
#endif // _FG_AI_PLANE_HXX
|
||||||
|
|
|
@ -35,7 +35,9 @@
|
||||||
|
|
||||||
|
|
||||||
FGATC::FGATC() :
|
FGATC::FGATC() :
|
||||||
_voiceOK(false),
|
_voiceOK(false),
|
||||||
|
_playing(false),
|
||||||
|
_sgr(NULL),
|
||||||
freqClear(true),
|
freqClear(true),
|
||||||
receiving(false),
|
receiving(false),
|
||||||
respond(false),
|
respond(false),
|
||||||
|
@ -55,6 +57,13 @@ FGATC::FGATC() :
|
||||||
_counter(0.0),
|
_counter(0.0),
|
||||||
_max_count(5.0)
|
_max_count(5.0)
|
||||||
{
|
{
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
_sgr = smgr->find("atc", true);
|
||||||
|
|
||||||
|
_volume = fgGetNode("/sim/sound/atc/volume", true);
|
||||||
|
_enabled = fgGetNode("/sim/sound/atc/enabled", true);
|
||||||
|
_atc_external = fgGetNode("/sim/sound/atc/external-view", true);
|
||||||
|
_internal = fgGetNode("/sim/current-view/internal", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
FGATC::~FGATC() {
|
FGATC::~FGATC() {
|
||||||
|
@ -103,6 +112,18 @@ void FGATC::Update(double dt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_AUDIO_SUPPORT
|
||||||
|
bool active = _atc_external->getBoolValue() ||
|
||||||
|
_internal->getBoolValue();
|
||||||
|
|
||||||
|
if ( active && _enabled->getBoolValue() ) {
|
||||||
|
_sgr->set_volume( _volume->getFloatValue() );
|
||||||
|
_sgr->resume(); // no-op if already in resumed state
|
||||||
|
} else {
|
||||||
|
_sgr->suspend();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(_transmit) {
|
if(_transmit) {
|
||||||
_counter = 0.0;
|
_counter = 0.0;
|
||||||
_max_count = 5.0; // FIXME - hardwired length of message - need to calculate it!
|
_max_count = 5.0; // FIXME - hardwired length of message - need to calculate it!
|
||||||
|
@ -203,7 +224,7 @@ int FGATC::RemovePlane() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGATC::SetData(ATCData* d) {
|
void FGATC::SetData(ATCData* d) {
|
||||||
_type = d->type;
|
_type = d->type;
|
||||||
_geod = d->geod;
|
_geod = d->geod;
|
||||||
_cart = d->cart;
|
_cart = d->cart;
|
||||||
range = d->range;
|
range = d->range;
|
||||||
|
@ -216,41 +237,36 @@ void FGATC::SetData(ATCData* d) {
|
||||||
// Outputs the transmission either on screen or as audio depending on user preference
|
// Outputs the transmission either on screen or as audio depending on user preference
|
||||||
// The refname is a string to identify this sample to the sound manager
|
// The refname is a string to identify this sample to the sound manager
|
||||||
// The repeating flag indicates whether the message should be repeated continuously or played once.
|
// The repeating flag indicates whether the message should be repeated continuously or played once.
|
||||||
void FGATC::Render(string& msg, const double volume,
|
void FGATC::Render(string& msg, const float volume,
|
||||||
const string& refname, const bool repeating) {
|
const string& refname, const bool repeating) {
|
||||||
|
if (volume < 0.05) return;
|
||||||
|
|
||||||
if (repeating)
|
if (repeating)
|
||||||
fgSetString("/sim/messages/atis", msg.c_str());
|
fgSetString("/sim/messages/atis", msg.c_str());
|
||||||
else
|
else
|
||||||
fgSetString("/sim/messages/atc", msg.c_str());
|
fgSetString("/sim/messages/atc", msg.c_str());
|
||||||
|
|
||||||
#ifdef ENABLE_AUDIO_SUPPORT
|
#ifdef ENABLE_AUDIO_SUPPORT
|
||||||
_voice = (_voiceOK && fgGetBool("/sim/sound/voice"));
|
_voice = (_voiceOK && fgGetBool("/sim/sound/voice"));
|
||||||
if(_voice) {
|
if(_voice) {
|
||||||
string buf = _vPtr->WriteMessage((char*)msg.c_str(), _voice);
|
size_t len;
|
||||||
if(_voice) {
|
void* buf = _vPtr->WriteMessage((char*)msg.c_str(), &len);
|
||||||
NoRender(refname);
|
if(buf) {
|
||||||
try {
|
NoRender(refname);
|
||||||
|
try {
|
||||||
// >>> Beware: must pass a (new) object to the (add) method,
|
// >>> Beware: must pass a (new) object to the (add) method,
|
||||||
// >>> because the (remove) method is going to do a (delete)
|
// >>> because the (remove) method is going to do a (delete)
|
||||||
// >>> whether that's what you want or not.
|
// >>> whether that's what you want or not.
|
||||||
SGSoundSample *simple =
|
SGSoundSample *simple = new SGSoundSample(&buf, len, 8000);
|
||||||
new SGSoundSample((unsigned char*) buf.c_str(),
|
simple->set_volume(volume);
|
||||||
buf.length(), 8000, AL_FORMAT_MONO8);
|
_sgr->add(simple, refname);
|
||||||
// TODO - at the moment the volume can't be changed
|
_sgr->play(refname, repeating);
|
||||||
// after the transmission has started.
|
} catch ( sg_io_exception &e ) {
|
||||||
simple->set_volume(volume);
|
SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage());
|
||||||
globals->get_soundmgr()->add(simple, refname);
|
}
|
||||||
if(repeating) {
|
|
||||||
globals->get_soundmgr()->play_looped(refname);
|
|
||||||
} else {
|
|
||||||
globals->get_soundmgr()->play_once(refname);
|
|
||||||
}
|
|
||||||
} catch ( sg_io_exception &e ) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif // ENABLE_AUDIO_SUPPORT
|
#endif // ENABLE_AUDIO_SUPPORT
|
||||||
if(!_voice) {
|
if(!_voice) {
|
||||||
// first rip the underscores and the pause hints out of the string - these are for the convienience of the voice parser
|
// first rip the underscores and the pause hints out of the string - these are for the convienience of the voice parser
|
||||||
for(unsigned int i = 0; i < msg.length(); ++i) {
|
for(unsigned int i = 0; i < msg.length(); ++i) {
|
||||||
|
@ -268,8 +284,8 @@ void FGATC::NoRender(const string& refname) {
|
||||||
if(_playing) {
|
if(_playing) {
|
||||||
if(_voice) {
|
if(_voice) {
|
||||||
#ifdef ENABLE_AUDIO_SUPPORT
|
#ifdef ENABLE_AUDIO_SUPPORT
|
||||||
globals->get_soundmgr()->stop(refname);
|
_sgr->stop(refname);
|
||||||
globals->get_soundmgr()->remove(refname);
|
_sgr->remove(refname);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
_playing = false;
|
_playing = false;
|
||||||
|
@ -283,14 +299,14 @@ string FGATC::GenText(const string& m, int c) {
|
||||||
|
|
||||||
ostream& operator << (ostream& os, atc_type atc) {
|
ostream& operator << (ostream& os, atc_type atc) {
|
||||||
switch(atc) {
|
switch(atc) {
|
||||||
case(AWOS): return(os << "AWOS");
|
case(AWOS): return(os << "AWOS");
|
||||||
case(ATIS): return(os << "ATIS");
|
case(ATIS): return(os << "ATIS");
|
||||||
case(GROUND): return(os << "GROUND");
|
case(GROUND): return(os << "GROUND");
|
||||||
case(TOWER): return(os << "TOWER");
|
case(TOWER): return(os << "TOWER");
|
||||||
case(APPROACH): return(os << "APPROACH");
|
case(APPROACH): return(os << "APPROACH");
|
||||||
case(DEPARTURE): return(os << "DEPARTURE");
|
case(DEPARTURE): return(os << "DEPARTURE");
|
||||||
case(ENROUTE): return(os << "ENROUTE");
|
case(ENROUTE): return(os << "ENROUTE");
|
||||||
case(INVALID): return(os << "INVALID");
|
case(INVALID): return(os << "INVALID");
|
||||||
}
|
}
|
||||||
return(os << "ERROR - Unknown switch in atc_type operator << ");
|
return(os << "ERROR - Unknown switch in atc_type operator << ");
|
||||||
}
|
}
|
||||||
|
@ -325,8 +341,8 @@ std::istream& operator >> ( std::istream& fin, ATCData& a )
|
||||||
return fin >> skipeol;
|
return fin >> skipeol;
|
||||||
}
|
}
|
||||||
|
|
||||||
double lat, lon, elev;
|
double lat, lon, elev;
|
||||||
|
|
||||||
fin >> lat >> lon >> elev >> f >> a.range >> a.ident;
|
fin >> lat >> lon >> elev >> f >> a.range >> a.ident;
|
||||||
a.geod = SGGeod::fromDegM(lon, lat, elev);
|
a.geod = SGGeod::fromDegM(lon, lat, elev);
|
||||||
a.name = "";
|
a.name = "";
|
||||||
|
@ -349,7 +365,7 @@ std::istream& operator >> ( std::istream& fin, ATCData& a )
|
||||||
// cout << a.ident << endl;
|
// cout << a.ident << endl;
|
||||||
|
|
||||||
// generate cartesian coordinates
|
// generate cartesian coordinates
|
||||||
a.cart = SGVec3d::fromGeod(a.geod);
|
a.cart = SGVec3d::fromGeod(a.geod);
|
||||||
return fin >> skipeol;
|
return fin >> skipeol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,15 +24,19 @@
|
||||||
|
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/props/props.hxx>
|
||||||
#include <simgear/misc/sgstream.hxx>
|
#include <simgear/misc/sgstream.hxx>
|
||||||
#include <simgear/math/sg_geodesy.hxx>
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "ATCVoice.hxx"
|
#include "ATCVoice.hxx"
|
||||||
|
|
||||||
|
class SGSampleGroup;
|
||||||
|
|
||||||
// Convert a frequency in MHz to tens of kHz
|
// Convert a frequency in MHz to tens of kHz
|
||||||
// so we can use it e.g. as an index into commlist_freq
|
// so we can use it e.g. as an index into commlist_freq
|
||||||
//
|
//
|
||||||
|
@ -76,7 +80,7 @@ enum atc_type {
|
||||||
APPROACH,
|
APPROACH,
|
||||||
DEPARTURE,
|
DEPARTURE,
|
||||||
ENROUTE,
|
ENROUTE,
|
||||||
INVALID /* must be last element; see ATC_NUM_TYPES */
|
INVALID /* must be last element; see ATC_NUM_TYPES */
|
||||||
};
|
};
|
||||||
|
|
||||||
const int ATC_NUM_TYPES = 1 + INVALID;
|
const int ATC_NUM_TYPES = 1 + INVALID;
|
||||||
|
@ -84,8 +88,8 @@ const int ATC_NUM_TYPES = 1 + INVALID;
|
||||||
// DCL - new experimental ATC data store
|
// DCL - new experimental ATC data store
|
||||||
struct ATCData {
|
struct ATCData {
|
||||||
atc_type type;
|
atc_type type;
|
||||||
SGGeod geod;
|
SGGeod geod;
|
||||||
SGVec3d cart;
|
SGVec3d cart;
|
||||||
unsigned short int freq;
|
unsigned short int freq;
|
||||||
unsigned short int range;
|
unsigned short int range;
|
||||||
std::string ident;
|
std::string ident;
|
||||||
|
@ -114,7 +118,7 @@ public:
|
||||||
FGATC();
|
FGATC();
|
||||||
virtual ~FGATC();
|
virtual ~FGATC();
|
||||||
|
|
||||||
virtual void Init()=0;
|
virtual void Init()=0;
|
||||||
|
|
||||||
// Run the internal calculations
|
// Run the internal calculations
|
||||||
// Derived classes should call this method from their own Update methods if they
|
// Derived classes should call this method from their own Update methods if they
|
||||||
|
@ -176,15 +180,15 @@ protected:
|
||||||
// Outputs the transmission either on screen or as audio depending on user preference
|
// Outputs the transmission either on screen or as audio depending on user preference
|
||||||
// The refname is a string to identify this sample to the sound manager
|
// The refname is a string to identify this sample to the sound manager
|
||||||
// The repeating flag indicates whether the message should be repeated continuously or played once.
|
// The repeating flag indicates whether the message should be repeated continuously or played once.
|
||||||
void Render(std::string& msg, const double volume = 1.0,
|
void Render(std::string& msg, const float volume = 1.0,
|
||||||
const std::string& refname = "", bool repeating = false);
|
const std::string& refname = "", bool repeating = false);
|
||||||
|
|
||||||
// Cease rendering all transmission from this station.
|
// Cease rendering all transmission from this station.
|
||||||
// Requires the sound manager refname if audio, else "".
|
// Requires the sound manager refname if audio, else "".
|
||||||
void NoRender(const std::string& refname);
|
void NoRender(const std::string& refname);
|
||||||
|
|
||||||
// Transmit a message when channel becomes free of other dialog
|
// Transmit a message when channel becomes free of other dialog
|
||||||
void Transmit(int callback_code = 0);
|
void Transmit(int callback_code = 0);
|
||||||
|
|
||||||
// Transmit a message if channel becomes free within timeout (seconds). timeout of zero implies no limit
|
// Transmit a message if channel becomes free within timeout (seconds). timeout of zero implies no limit
|
||||||
void ConditionalTransmit(double timeout, int callback_code = 0);
|
void ConditionalTransmit(double timeout, int callback_code = 0);
|
||||||
|
@ -197,44 +201,46 @@ protected:
|
||||||
SGGeod _geod;
|
SGGeod _geod;
|
||||||
SGVec3d _cart;
|
SGVec3d _cart;
|
||||||
int freq;
|
int freq;
|
||||||
std::map<std::string,int> active_on;
|
std::map<std::string,int> active_on;
|
||||||
|
|
||||||
int range;
|
int range;
|
||||||
std::string ident; // Code of the airport its at.
|
std::string ident; // Code of the airport its at.
|
||||||
std::string name; // Name transmitted in the broadcast.
|
std::string name; // Name transmitted in the broadcast.
|
||||||
|
|
||||||
|
|
||||||
// Rendering related stuff
|
// Rendering related stuff
|
||||||
bool _voice; // Flag - true if we are using voice
|
bool _voice; // Flag - true if we are using voice
|
||||||
bool _playing; // Indicates a message in progress
|
bool _playing; // Indicates a message in progress
|
||||||
bool _voiceOK; // Flag - true if at least one voice has loaded OK
|
bool _voiceOK; // Flag - true if at least one voice has loaded OK
|
||||||
FGATCVoice* _vPtr;
|
FGATCVoice* _vPtr;
|
||||||
|
|
||||||
|
SGSharedPtr<SGSampleGroup> _sgr; // default sample group;
|
||||||
|
|
||||||
|
|
||||||
bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog
|
bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog
|
||||||
bool receiving; // Flag to indicate we are receiving a transmission
|
bool receiving; // Flag to indicate we are receiving a transmission
|
||||||
|
|
||||||
|
|
||||||
double responseTime; // Time to take from end of request transmission to beginning of response
|
double responseTime; // Time to take from end of request transmission to beginning of response
|
||||||
// The idea is that this will be slightly random.
|
// The idea is that this will be slightly random.
|
||||||
|
|
||||||
bool respond; // Flag to indicate now is the time to respond - ie set following the count down of the response timer.
|
bool respond; // Flag to indicate now is the time to respond - ie set following the count down of the response timer.
|
||||||
std::string responseID; // ID of the plane to respond to
|
std::string responseID; // ID of the plane to respond to
|
||||||
bool runResponseCounter; // Flag to indicate the response counter should be run
|
bool runResponseCounter; // Flag to indicate the response counter should be run
|
||||||
double responseCounter; // counter to implement the above
|
double responseCounter; // counter to implement the above
|
||||||
// Derived classes only need monitor this flag, and use the response ID, as long as they call FGATC::Update(...)
|
// Derived classes only need monitor this flag, and use the response ID, as long as they call FGATC::Update(...)
|
||||||
bool _runReleaseCounter; // A timer for releasing the frequency after giving the message enough time to display
|
bool _runReleaseCounter; // A timer for releasing the frequency after giving the message enough time to display
|
||||||
bool responseReqd; // Flag to indicate we should be responding to a request/report
|
bool responseReqd; // Flag to indicate we should be responding to a request/report
|
||||||
double _releaseTime;
|
double _releaseTime;
|
||||||
double _releaseCounter;
|
double _releaseCounter;
|
||||||
atc_type _type;
|
atc_type _type;
|
||||||
bool _display; // Flag to indicate whether we should be outputting to the ATC display.
|
bool _display; // Flag to indicate whether we should be outputting to the ATC display.
|
||||||
std::string pending_transmission; // derived classes set this string before calling Transmit(...)
|
std::string pending_transmission; // derived classes set this string before calling Transmit(...)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Transmission timing stuff.
|
// Transmission timing stuff.
|
||||||
double _timeout;
|
double _timeout;
|
||||||
bool _pending;
|
bool _pending;
|
||||||
|
|
||||||
int _callback_code; // A callback code to be notified and processed by the derived classes
|
int _callback_code; // A callback code to be notified and processed by the derived classes
|
||||||
// A value of zero indicates no callback required
|
// A value of zero indicates no callback required
|
||||||
|
@ -242,6 +248,11 @@ private:
|
||||||
bool _transmitting; // we are transmitting
|
bool _transmitting; // we are transmitting
|
||||||
double _counter;
|
double _counter;
|
||||||
double _max_count;
|
double _max_count;
|
||||||
|
|
||||||
|
SGPropertyNode_ptr _volume;
|
||||||
|
SGPropertyNode_ptr _enabled;
|
||||||
|
SGPropertyNode_ptr _atc_external;
|
||||||
|
SGPropertyNode_ptr _internal;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::istream& operator>> ( std::istream& fin, ATCData& a );
|
std::istream& operator>> ( std::istream& fin, ATCData& a );
|
||||||
|
|
|
@ -28,25 +28,17 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <boost/shared_array.hpp>
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/misc/sgstream.hxx>
|
#include <simgear/misc/sgstream.hxx>
|
||||||
#include <simgear/math/sg_random.h>
|
#include <simgear/math/sg_random.h>
|
||||||
#include <simgear/sound/sample_openal.hxx>
|
|
||||||
|
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define strtok_r strtok_s
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
FGATCVoice::FGATCVoice() {
|
FGATCVoice::FGATCVoice() {
|
||||||
|
@ -56,29 +48,29 @@ FGATCVoice::FGATCVoice() {
|
||||||
|
|
||||||
FGATCVoice::~FGATCVoice() {
|
FGATCVoice::~FGATCVoice() {
|
||||||
if (rawSoundData)
|
if (rawSoundData)
|
||||||
free( rawSoundData );
|
free( rawSoundData );
|
||||||
delete SoundData;
|
delete SoundData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the two voice files - one containing the raw sound data (.wav) and one containing the word positions (.vce).
|
// Load the two voice files - one containing the raw sound data (.wav) and one containing the word positions (.vce).
|
||||||
// Return true if successful.
|
// Return true if successful.
|
||||||
bool FGATCVoice::LoadVoice(const string& voice) {
|
bool FGATCVoice::LoadVoice(const string& voice) {
|
||||||
// FIXME CLO: disabled to try to see if this is causing problemcs
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
std::ifstream fin;
|
std::ifstream fin;
|
||||||
|
|
||||||
SGPath path = globals->get_fg_root();
|
SGPath path = globals->get_fg_root();
|
||||||
|
string file = voice + ".wav";
|
||||||
path.append( "ATC" );
|
path.append( "ATC" );
|
||||||
|
path.append( file );
|
||||||
string file = voice + ".wav";
|
|
||||||
|
|
||||||
SGSoundSample SoundData;
|
string full_path = path.str();
|
||||||
rawSoundData = (char *)SoundData.load_file(path.c_str(), file.c_str());
|
int format, freq;
|
||||||
rawDataSize = SoundData.get_size();
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
void *data;
|
||||||
|
if (!smgr->load(full_path, &data, &format, &rawDataSize, &freq))
|
||||||
|
return false;
|
||||||
|
rawSoundData = (char*)data;
|
||||||
#ifdef VOICE_TEST
|
#ifdef VOICE_TEST
|
||||||
ALenum fmt = SoundData.get_format();
|
cout << "ATCVoice: format: " << format
|
||||||
cout << "ATCVoice: format: " << fmt
|
|
||||||
<< " size: " << rawDataSize << endl;
|
<< " size: " << rawDataSize << endl;
|
||||||
#endif
|
#endif
|
||||||
path = globals->get_fg_root();
|
path = globals->get_fg_root();
|
||||||
|
@ -113,12 +105,12 @@ bool FGATCVoice::LoadVoice(const string& voice) {
|
||||||
wd.offset = wrdOffset;
|
wd.offset = wrdOffset;
|
||||||
wd.length = wrdLength;
|
wd.length = wrdLength;
|
||||||
wordMap[wrdstr] = wd;
|
wordMap[wrdstr] = wd;
|
||||||
string ws2 = wrdstr;
|
string ws2 = wrdstr;
|
||||||
for(string::iterator p = ws2.begin(); p != ws2.end(); p++){
|
for(string::iterator p = ws2.begin(); p != ws2.end(); p++){
|
||||||
*p = tolower(*p);
|
*p = tolower(*p);
|
||||||
if (*p == '-') *p = '_';
|
if (*p == '-') *p = '_';
|
||||||
}
|
}
|
||||||
if (wrdstr != ws2) wordMap[ws2] = wd;
|
if (wrdstr != ws2) wordMap[ws2] = wd;
|
||||||
|
|
||||||
//cout << wrd << "\t\t" << wrdOffset << "\t\t" << wrdLength << '\n';
|
//cout << wrd << "\t\t" << wrdOffset << "\t\t" << wrdLength << '\n';
|
||||||
//cout << i << '\n';
|
//cout << i << '\n';
|
||||||
|
@ -129,93 +121,82 @@ bool FGATCVoice::LoadVoice(const string& voice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef list < string > tokenList_type;
|
|
||||||
typedef tokenList_type::iterator tokenList_iterator;
|
|
||||||
|
|
||||||
// Given a desired message, return a string containing the
|
// Given a desired message, return a string containing the
|
||||||
// sound-sample data
|
// sound-sample data
|
||||||
string FGATCVoice::WriteMessage(const char* message, bool& dataOK) {
|
void* FGATCVoice::WriteMessage(const string& message, size_t* len) {
|
||||||
|
|
||||||
// What should we do here?
|
// What should we do here?
|
||||||
// First - parse the message into a list of tokens.
|
// First - parse the message into a list of tokens.
|
||||||
// Sort the tokens into those we understand and those we don't.
|
// Sort the tokens into those we understand and those we don't.
|
||||||
// Add all the raw lengths of the token sound data, allocate enough space, and fill it with the rqd data.
|
// Add all the raw lengths of the token sound data, allocate enough space, and fill it with the rqd data.
|
||||||
tokenList_type tokenList;
|
|
||||||
tokenList_iterator tokenListItr;
|
|
||||||
|
|
||||||
// TODO - at the moment we're effectively taking 3 passes through the data.
|
vector<char> sound;
|
||||||
// There is no need for this - 2 should be sufficient - we can probably ditch the tokenList.
|
|
||||||
size_t n1 = 1+strlen(message);
|
|
||||||
boost::shared_array<char> msg(new char[n1]);
|
|
||||||
strncpy(msg.get(), message, n1); // strtok requires a non-const char*
|
|
||||||
char* token;
|
|
||||||
int numWords = 0;
|
|
||||||
const char delimiters[] = " \t.,;:\"\n";
|
const char delimiters[] = " \t.,;:\"\n";
|
||||||
char* context;
|
string::size_type token_start = message.find_first_not_of(delimiters);
|
||||||
token = strtok_r(msg.get(), delimiters, &context);
|
while(token_start != string::npos) {
|
||||||
while(token != NULL) {
|
string::size_type token_end = message.find_first_of(delimiters, token_start);
|
||||||
for (char *t = token; *t; t++) {
|
string token;
|
||||||
*t = tolower(*t); // canonicalize the case, to
|
if (token_end == string::npos) {
|
||||||
if (*t == '-') *t = '_'; // match what's in the index
|
token = message.substr(token_start);
|
||||||
}
|
token_start = string::npos;
|
||||||
tokenList.push_back(token);
|
|
||||||
++numWords;
|
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "voice synth: token: '"
|
|
||||||
<< token << "'");
|
|
||||||
token = strtok_r(NULL, delimiters, &context);
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<WordData> wdptr;
|
|
||||||
wdptr.reserve(numWords);
|
|
||||||
unsigned int cumLength = 0;
|
|
||||||
|
|
||||||
tokenListItr = tokenList.begin();
|
|
||||||
while(tokenListItr != tokenList.end()) {
|
|
||||||
if(wordMap.find(*tokenListItr) == wordMap.end()) {
|
|
||||||
// Oh dear - the token isn't in the sound file
|
|
||||||
SG_LOG(SG_ATC, SG_ALERT, "voice synth: word '"
|
|
||||||
<< *tokenListItr << "' not found");
|
|
||||||
} else {
|
} else {
|
||||||
wdptr.push_back(wordMap[*tokenListItr]);
|
token = message.substr(token_start, token_end - token_start);
|
||||||
cumLength += wdptr.back().length;
|
token_start = message.find_first_not_of(delimiters, token_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(string::iterator t = token.begin(); t != token.end(); t++) {
|
||||||
|
// canonicalize the token, to match what's in the index
|
||||||
|
*t = (*t == '-') ? '_' : tolower(*t);
|
||||||
|
}
|
||||||
|
SG_LOG(SG_ATC, SG_DEBUG, "voice synth: token: '"
|
||||||
|
<< token << "'");
|
||||||
|
|
||||||
|
atc_word_map_const_iterator wordIt = wordMap.find(token);
|
||||||
|
if(wordIt == wordMap.end()) {
|
||||||
|
// Oh dear - the token isn't in the sound file
|
||||||
|
SG_LOG(SG_ATC, SG_ALERT, "voice synth: word '"
|
||||||
|
<< token << "' not found");
|
||||||
|
} else {
|
||||||
|
const WordData& word = wordIt->second;
|
||||||
|
/*
|
||||||
|
* Sanity check for corrupt/mismatched sound data input - avoids a seg fault
|
||||||
|
* (As long as the calling function checks the return value!!)
|
||||||
|
* This check should be left in even when the default Flightgear files are known
|
||||||
|
* to be OK since it checks for mis-indexing of voice files by 3rd party developers.
|
||||||
|
*/
|
||||||
|
if((word.offset + word.length) > rawDataSize) {
|
||||||
|
SG_LOG(SG_ATC, SG_ALERT, "ERROR - mismatch between ATC .wav and .vce file in ATCVoice.cxx\n");
|
||||||
|
SG_LOG(SG_ATC, SG_ALERT, "Offset + length: " << word.offset + word.length
|
||||||
|
<< " exceeds rawdata size: " << rawDataSize << endl);
|
||||||
|
|
||||||
|
*len = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sound.insert(sound.end(), rawSoundData + word.offset, rawSoundData + word.offset + word.length);
|
||||||
}
|
}
|
||||||
++tokenListItr;
|
|
||||||
}
|
}
|
||||||
const size_t word = wdptr.size();
|
|
||||||
|
|
||||||
// Check for no tokens found else slScheduler can be crashed
|
// Check for no tokens found else slScheduler can be crashed
|
||||||
if(!word) {
|
*len = sound.size();
|
||||||
dataOK = false;
|
if (*len == 0) {
|
||||||
return "";
|
return 0;
|
||||||
}
|
}
|
||||||
boost::shared_array<char> tmpbuf(new char[cumLength]);
|
|
||||||
unsigned int bufpos = 0;
|
|
||||||
for(int i=0; i<word; ++i) {
|
|
||||||
/*
|
|
||||||
* Sanity check for corrupt/mismatched sound data input - avoids a seg fault
|
|
||||||
* (As long as the calling function checks the return value!!)
|
|
||||||
* This check should be left in even when the default Flightgear files are known
|
|
||||||
* to be OK since it checks for mis-indexing of voice files by 3rd party developers.
|
|
||||||
*/
|
|
||||||
if((wdptr[i].offset + wdptr[i].length) > rawDataSize) {
|
|
||||||
SG_LOG(SG_ATC, SG_ALERT, "ERROR - mismatch between ATC .wav and .vce file in ATCVoice.cxx\n");
|
|
||||||
SG_LOG(SG_ATC, SG_ALERT, "Offset + length: " << wdptr[i].offset + wdptr[i].length
|
|
||||||
<< " exceeds rawdata size: " << rawDataSize << endl);
|
|
||||||
|
|
||||||
dataOK = false;
|
char* data = (char*)malloc(*len);
|
||||||
return "";
|
if (data == 0) {
|
||||||
}
|
SG_LOG(SG_ATC, SG_ALERT, "ERROR - could not allocate " << *len << " bytes of memory for ATIS sound\n");
|
||||||
memcpy(tmpbuf.get() + bufpos, rawSoundData + wdptr[i].offset, wdptr[i].length);
|
*len = 0;
|
||||||
bufpos += wdptr[i].length;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// tmpbuf now contains the message starting at the beginning - but we want it to start at a random position.
|
|
||||||
unsigned int offsetIn = (int)(cumLength * sg_random());
|
|
||||||
if(offsetIn > cumLength) offsetIn = cumLength;
|
|
||||||
|
|
||||||
string front(tmpbuf.get(), offsetIn);
|
// randomize start position
|
||||||
string back(tmpbuf.get() + offsetIn, cumLength - offsetIn);
|
unsigned int offsetIn = (unsigned int)(*len * sg_random());
|
||||||
|
if (offsetIn > 0 && offsetIn < *len) {
|
||||||
|
copy(sound.begin() + offsetIn, sound.end(), data);
|
||||||
|
copy(sound.begin(), sound.begin() + offsetIn, data + *len - offsetIn);
|
||||||
|
} else {
|
||||||
|
copy(sound.begin(), sound.end(), data);
|
||||||
|
}
|
||||||
|
|
||||||
dataOK = true;
|
return data;
|
||||||
return back + front;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define _FG_ATC_VOICE
|
#define _FG_ATC_VOICE
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -49,15 +50,15 @@ public:
|
||||||
bool LoadVoice(const std::string& voice);
|
bool LoadVoice(const std::string& voice);
|
||||||
|
|
||||||
// Given a desired message, return a pointer to the data buffer and write the buffer length into len.
|
// Given a desired message, return a pointer to the data buffer and write the buffer length into len.
|
||||||
// Sets dataOK = true if the returned buffer is valid.
|
// Sets len to something other than 0 if the returned buffer is valid.
|
||||||
std::string WriteMessage(const char* message, bool& dataOK);
|
void* WriteMessage(const std::string& message, size_t *len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// the sound and word position data
|
// the sound and word position data
|
||||||
char* rawSoundData;
|
char* rawSoundData;
|
||||||
unsigned int rawDataSize;
|
size_t rawDataSize;
|
||||||
SGSoundSample *SoundData;
|
SGSharedPtr<SGSoundSample> SoundData;
|
||||||
|
|
||||||
// A map of words vs. byte position and length in rawSoundData
|
// A map of words vs. byte position and length in rawSoundData
|
||||||
atc_word_map_type wordMap;
|
atc_word_map_type wordMap;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/structure/commands.hxx>
|
#include <simgear/structure/commands.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
|
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
#include <Main/fg_init.hxx>
|
#include <Main/fg_init.hxx>
|
||||||
|
@ -226,12 +227,9 @@ fgLoadAircraft (const SGPropertyNode * arg)
|
||||||
t = fgInitTime();
|
t = fgInitTime();
|
||||||
globals->set_time_params( t );
|
globals->set_time_params( t );
|
||||||
|
|
||||||
// Reinitialize some subsystems
|
|
||||||
//
|
|
||||||
globals->get_viewmgr()->reinit();
|
globals->get_viewmgr()->reinit();
|
||||||
globals->get_controls()->reset_all();
|
globals->get_controls()->reset_all();
|
||||||
globals->get_aircraft_model()->reinit();
|
globals->get_aircraft_model()->reinit();
|
||||||
globals->get_subsystem("fx")->reinit();
|
|
||||||
globals->get_subsystem("xml-autopilot")->reinit();
|
globals->get_subsystem("xml-autopilot")->reinit();
|
||||||
|
|
||||||
fgReInitSubsystems();
|
fgReInitSubsystems();
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
// forward decls
|
// forward decls
|
||||||
class SGPropertyNode;
|
class SGPropertyNode;
|
||||||
|
class SGSampleGroup;
|
||||||
class FGMetar;
|
class FGMetar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -68,9 +68,10 @@ void FGClouds::init(void) {
|
||||||
snd_lightning = new SGSoundSample(globals->get_fg_root().c_str(), "Sounds/thunder.wav");
|
snd_lightning = new SGSoundSample(globals->get_fg_root().c_str(), "Sounds/thunder.wav");
|
||||||
snd_lightning->set_max_dist(7000.0f);
|
snd_lightning->set_max_dist(7000.0f);
|
||||||
snd_lightning->set_reference_dist(3000.0f);
|
snd_lightning->set_reference_dist(3000.0f);
|
||||||
SGSoundMgr *soundMgr = globals->get_soundmgr();
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
soundMgr->add( snd_lightning, "thunder" );
|
SGSampleGroup *sgr = smgr->find("weather", true);
|
||||||
sgEnviro.set_soundMgr( soundMgr );
|
sgr->add( snd_lightning, "thunder" );
|
||||||
|
sgEnviro.set_sampleGroup( sgr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,11 @@
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
class SGNewCloud;
|
class SGSampleGroup;
|
||||||
class SGCloudField;
|
class SGCloudField;
|
||||||
|
class SGNewCloud;
|
||||||
class FGMetar;
|
class FGMetar;
|
||||||
class FGEnvironmentCtrl;
|
//class FGEnvironmentCtrl;
|
||||||
|
|
||||||
class FGClouds {
|
class FGClouds {
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,8 @@ ADF::ADF (SGPropertyNode *node )
|
||||||
_transmitter_range_nm(0),
|
_transmitter_range_nm(0),
|
||||||
_ident_count(0),
|
_ident_count(0),
|
||||||
_last_ident_time(0),
|
_last_ident_time(0),
|
||||||
_last_volume(-1)
|
_last_volume(-1),
|
||||||
|
_sgr(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +102,10 @@ ADF::init ()
|
||||||
_ident_node = node->getChild("ident", 0, true);
|
_ident_node = node->getChild("ident", 0, true);
|
||||||
_ident_audible_node = node->getChild("ident-audible", 0, true);
|
_ident_audible_node = node->getChild("ident-audible", 0, true);
|
||||||
|
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
_sgr = smgr->find("avionics", true);
|
||||||
|
_sgr->tie_to_listener();
|
||||||
|
|
||||||
morse.init();
|
morse.init();
|
||||||
|
|
||||||
std::ostringstream temp;
|
std::ostringstream temp;
|
||||||
|
@ -156,6 +161,7 @@ ADF::update (double delta_time_sec)
|
||||||
double range_nm = adjust_range(_transmitter_pos.getElevationFt(),
|
double range_nm = adjust_range(_transmitter_pos.getElevationFt(),
|
||||||
altitude_m * SG_METER_TO_FEET,
|
altitude_m * SG_METER_TO_FEET,
|
||||||
_transmitter_range_nm);
|
_transmitter_range_nm);
|
||||||
|
|
||||||
if (distance_nm <= range_nm) {
|
if (distance_nm <= range_nm) {
|
||||||
|
|
||||||
double bearing, az2, s;
|
double bearing, az2, s;
|
||||||
|
@ -171,9 +177,9 @@ ADF::update (double delta_time_sec)
|
||||||
set_bearing(delta_time_sec, bearing);
|
set_bearing(delta_time_sec, bearing);
|
||||||
|
|
||||||
// adf ident sound
|
// adf ident sound
|
||||||
double volume;
|
float volume;
|
||||||
if ( _ident_audible_node->getBoolValue() )
|
if ( _ident_audible_node->getBoolValue() )
|
||||||
volume = _volume_node->getDoubleValue();
|
volume = _volume_node->getFloatValue();
|
||||||
else
|
else
|
||||||
volume = 0.0;
|
volume = 0.0;
|
||||||
|
|
||||||
|
@ -181,7 +187,7 @@ ADF::update (double delta_time_sec)
|
||||||
_last_volume = volume;
|
_last_volume = volume;
|
||||||
|
|
||||||
SGSoundSample *sound;
|
SGSoundSample *sound;
|
||||||
sound = globals->get_soundmgr()->find( _adf_ident );
|
sound = _sgr->find( _adf_ident );
|
||||||
if ( sound != NULL )
|
if ( sound != NULL )
|
||||||
sound->set_volume( volume );
|
sound->set_volume( volume );
|
||||||
else
|
else
|
||||||
|
@ -195,8 +201,8 @@ ADF::update (double delta_time_sec)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _ident_count < 4 ) {
|
if ( _ident_count < 4 ) {
|
||||||
if ( !globals->get_soundmgr()->is_playing(_adf_ident) ) {
|
if ( !_sgr->is_playing(_adf_ident) && (volume > 0.05) ) {
|
||||||
globals->get_soundmgr()->play_once( _adf_ident );
|
_sgr->play_once( _adf_ident );
|
||||||
++_ident_count;
|
++_ident_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +210,7 @@ ADF::update (double delta_time_sec)
|
||||||
_in_range_node->setBoolValue(false);
|
_in_range_node->setBoolValue(false);
|
||||||
set_bearing(delta_time_sec, 90);
|
set_bearing(delta_time_sec, 90);
|
||||||
_ident_node->setStringValue("");
|
_ident_node->setStringValue("");
|
||||||
globals->get_soundmgr()->stop( _adf_ident );
|
_sgr->stop( _adf_ident );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,16 +240,16 @@ ADF::search (double frequency_khz, double longitude_rad,
|
||||||
_last_ident = ident;
|
_last_ident = ident;
|
||||||
_ident_node->setStringValue(ident.c_str());
|
_ident_node->setStringValue(ident.c_str());
|
||||||
|
|
||||||
if ( globals->get_soundmgr()->exists( _adf_ident ) ) {
|
if ( _sgr->exists( _adf_ident ) ) {
|
||||||
// stop is required! -- remove alone wouldn't stop immediately
|
// stop is required! -- remove alone wouldn't stop immediately
|
||||||
globals->get_soundmgr()->stop( _adf_ident );
|
_sgr->stop( _adf_ident );
|
||||||
globals->get_soundmgr()->remove( _adf_ident );
|
_sgr->remove( _adf_ident );
|
||||||
}
|
}
|
||||||
|
|
||||||
SGSoundSample *sound;
|
SGSoundSample *sound;
|
||||||
sound = morse.make_ident( ident, LO_FREQUENCY );
|
sound = morse.make_ident( ident, LO_FREQUENCY );
|
||||||
sound->set_volume(_last_volume = 0);
|
sound->set_volume(_last_volume = 0);
|
||||||
globals->get_soundmgr()->add( sound, _adf_ident );
|
_sgr->add( sound, _adf_ident );
|
||||||
|
|
||||||
int offset = (int)(sg_random() * 30.0);
|
int offset = (int)(sg_random() * 30.0);
|
||||||
_ident_count = offset / 4;
|
_ident_count = offset / 4;
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
|
||||||
|
class SGSampleGroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model an ADF radio.
|
* Model an ADF radio.
|
||||||
*
|
*
|
||||||
|
@ -93,8 +95,10 @@ private:
|
||||||
FGMorse morse;
|
FGMorse morse;
|
||||||
int _ident_count;
|
int _ident_count;
|
||||||
time_t _last_ident_time;
|
time_t _last_ident_time;
|
||||||
double _last_volume;
|
float _last_volume;
|
||||||
string _adf_ident;
|
string _adf_ident;
|
||||||
|
|
||||||
|
SGSharedPtr<SGSampleGroup> _sgr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,8 @@ FGKR_87::FGKR_87( SGPropertyNode *node ) :
|
||||||
flight_timer(0.0),
|
flight_timer(0.0),
|
||||||
elapsed_timer(0.0),
|
elapsed_timer(0.0),
|
||||||
tmp_timer(0.0),
|
tmp_timer(0.0),
|
||||||
_time_before_search_sec(0)
|
_time_before_search_sec(0),
|
||||||
|
_sgr(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +117,9 @@ FGKR_87::~FGKR_87() {
|
||||||
|
|
||||||
|
|
||||||
void FGKR_87::init () {
|
void FGKR_87::init () {
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
_sgr = smgr->find("avionics", true);
|
||||||
|
_sgr->tie_to_listener();
|
||||||
morse.init();
|
morse.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +467,7 @@ void FGKR_87::update( double dt_sec ) {
|
||||||
// otherwise turn it off
|
// otherwise turn it off
|
||||||
if ( vol_btn >= 0.01 && audio_btn ) {
|
if ( vol_btn >= 0.01 && audio_btn ) {
|
||||||
SGSoundSample *sound;
|
SGSoundSample *sound;
|
||||||
sound = globals->get_soundmgr()->find( "adf-ident" );
|
sound = _sgr->find( "adf-ident" );
|
||||||
if ( sound != NULL ) {
|
if ( sound != NULL ) {
|
||||||
if ( !adf_btn ) {
|
if ( !adf_btn ) {
|
||||||
sound->set_volume( vol_btn );
|
sound->set_volume( vol_btn );
|
||||||
|
@ -480,13 +484,13 @@ void FGKR_87::update( double dt_sec ) {
|
||||||
}
|
}
|
||||||
if ( play_count < 4 ) {
|
if ( play_count < 4 ) {
|
||||||
// play ADF ident
|
// play ADF ident
|
||||||
if ( !globals->get_soundmgr()->is_playing("adf-ident") ) {
|
if ( !_sgr->is_playing("adf-ident") && (vol_btn > 0.05) ) {
|
||||||
globals->get_soundmgr()->play_once( "adf-ident" );
|
_sgr->play_once( "adf-ident" );
|
||||||
++play_count;
|
++play_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
globals->get_soundmgr()->stop( "adf-ident" );
|
_sgr->stop( "adf-ident" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,13 +531,13 @@ void FGKR_87::search() {
|
||||||
effective_range = kludgeRange(stn_elev, pos.getElevationM(), range);
|
effective_range = kludgeRange(stn_elev, pos.getElevationM(), range);
|
||||||
xyz = adf->cart();
|
xyz = adf->cart();
|
||||||
|
|
||||||
if ( globals->get_soundmgr()->exists( "adf-ident" ) ) {
|
if ( _sgr->exists( "adf-ident" ) ) {
|
||||||
globals->get_soundmgr()->remove( "adf-ident" );
|
_sgr->remove( "adf-ident" );
|
||||||
}
|
}
|
||||||
SGSoundSample *sound;
|
SGSoundSample *sound;
|
||||||
sound = morse.make_ident( trans_ident, LO_FREQUENCY );
|
sound = morse.make_ident( trans_ident, LO_FREQUENCY );
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
globals->get_soundmgr()->add( sound, "adf-ident" );
|
_sgr->add( sound, "adf-ident" );
|
||||||
|
|
||||||
int offset = (int)(sg_random() * 30.0);
|
int offset = (int)(sg_random() * 30.0);
|
||||||
play_count = offset / 4;
|
play_count = offset / 4;
|
||||||
|
@ -551,7 +555,7 @@ void FGKR_87::search() {
|
||||||
valid = false;
|
valid = false;
|
||||||
ident = "";
|
ident = "";
|
||||||
trans_ident = "";
|
trans_ident = "";
|
||||||
globals->get_soundmgr()->remove( "adf-ident" );
|
_sgr->remove( "adf-ident" );
|
||||||
last_ident = "";
|
last_ident = "";
|
||||||
// cout << "not picking up adf. :-(" << endl;
|
// cout << "not picking up adf. :-(" << endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <Navaids/navlist.hxx>
|
#include <Navaids/navlist.hxx>
|
||||||
#include <Sound/morse.hxx>
|
#include <Sound/morse.hxx>
|
||||||
|
|
||||||
|
class SGSampleGroup;
|
||||||
|
|
||||||
class FGKR_87 : public SGSubsystem
|
class FGKR_87 : public SGSubsystem
|
||||||
{
|
{
|
||||||
|
@ -104,6 +105,8 @@ class FGKR_87 : public SGSubsystem
|
||||||
// internal periodic station search timer
|
// internal periodic station search timer
|
||||||
double _time_before_search_sec;
|
double _time_before_search_sec;
|
||||||
|
|
||||||
|
SGSharedPtr<SGSampleGroup> _sgr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FGKR_87( SGPropertyNode *node );
|
FGKR_87( SGPropertyNode *node );
|
||||||
|
|
|
@ -49,7 +49,8 @@ FGMarkerBeacon::FGMarkerBeacon(SGPropertyNode *node) :
|
||||||
inner_blink(false),
|
inner_blink(false),
|
||||||
name("marker-beacon"),
|
name("marker-beacon"),
|
||||||
num(0),
|
num(0),
|
||||||
_time_before_search_sec(0.0)
|
_time_before_search_sec(0.0),
|
||||||
|
_sgr(NULL)
|
||||||
{
|
{
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
SGPath term = path;
|
SGPath term = path;
|
||||||
|
@ -99,7 +100,7 @@ FGMarkerBeacon::init ()
|
||||||
|
|
||||||
SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
|
SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
|
||||||
// Inputs
|
// Inputs
|
||||||
sound_pause = fgGetNode("/sim/sound/pause", false);
|
sound_working = fgGetNode("/sim/sound/working", true);
|
||||||
lon_node = fgGetNode("/position/longitude-deg", true);
|
lon_node = fgGetNode("/position/longitude-deg", true);
|
||||||
lat_node = fgGetNode("/position/latitude-deg", true);
|
lat_node = fgGetNode("/position/latitude-deg", true);
|
||||||
alt_node = fgGetNode("/position/altitude-ft", true);
|
alt_node = fgGetNode("/position/altitude-ft", true);
|
||||||
|
@ -116,6 +117,10 @@ FGMarkerBeacon::init ()
|
||||||
if (serviceable->getType() == simgear::props::NONE)
|
if (serviceable->getType() == simgear::props::NONE)
|
||||||
serviceable->setBoolValue( true );
|
serviceable->setBoolValue( true );
|
||||||
|
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
_sgr = smgr->find("avionics", true);
|
||||||
|
_sgr->tie_to_listener();
|
||||||
|
|
||||||
morse.init();
|
morse.init();
|
||||||
beacon.init();
|
beacon.init();
|
||||||
blink.stamp();
|
blink.stamp();
|
||||||
|
@ -171,7 +176,7 @@ FGMarkerBeacon::update(double dt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( has_power() && serviceable->getBoolValue()
|
if ( has_power() && serviceable->getBoolValue()
|
||||||
&& !sound_pause->getBoolValue()) {
|
&& sound_working->getBoolValue()) {
|
||||||
|
|
||||||
// marker beacon blinking
|
// marker beacon blinking
|
||||||
bool light_on = ( outer_blink || middle_blink || inner_blink );
|
bool light_on = ( outer_blink || middle_blink || inner_blink );
|
||||||
|
@ -300,9 +305,9 @@ void FGMarkerBeacon::search()
|
||||||
if ( b == NULL || !inrange || !has_power() || !serviceable->getBoolValue() )
|
if ( b == NULL || !inrange || !has_power() || !serviceable->getBoolValue() )
|
||||||
{
|
{
|
||||||
// cout << "no marker" << endl;
|
// cout << "no marker" << endl;
|
||||||
globals->get_soundmgr()->stop( "outer-marker" );
|
_sgr->stop( "outer-marker" );
|
||||||
globals->get_soundmgr()->stop( "middle-marker" );
|
_sgr->stop( "middle-marker" );
|
||||||
globals->get_soundmgr()->stop( "inner-marker" );
|
_sgr->stop( "inner-marker" );
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
string current_sound_name;
|
string current_sound_name;
|
||||||
|
@ -312,63 +317,63 @@ void FGMarkerBeacon::search()
|
||||||
current_sound_name = "outer-marker";
|
current_sound_name = "outer-marker";
|
||||||
// cout << "OUTER MARKER" << endl;
|
// cout << "OUTER MARKER" << endl;
|
||||||
if ( last_beacon != OUTER ) {
|
if ( last_beacon != OUTER ) {
|
||||||
if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) {
|
if ( ! _sgr->exists( current_sound_name ) ) {
|
||||||
SGSoundSample *sound = beacon.get_outer();
|
SGSoundSample *sound = beacon.get_outer();
|
||||||
if ( sound ) {
|
if ( sound ) {
|
||||||
globals->get_soundmgr()->add( sound, current_sound_name );
|
_sgr->add( sound, current_sound_name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( audio_btn->getBoolValue() ) {
|
if ( audio_btn->getBoolValue() ) {
|
||||||
if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) {
|
if ( !_sgr->is_playing(current_sound_name) ) {
|
||||||
globals->get_soundmgr()->play_looped( current_sound_name );
|
_sgr->play_looped( current_sound_name );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
globals->get_soundmgr()->stop( current_sound_name );
|
_sgr->stop( current_sound_name );
|
||||||
}
|
}
|
||||||
} else if ( beacon_type == MIDDLE ) {
|
} else if ( beacon_type == MIDDLE ) {
|
||||||
middle_marker = true;
|
middle_marker = true;
|
||||||
current_sound_name = "middle-marker";
|
current_sound_name = "middle-marker";
|
||||||
// cout << "MIDDLE MARKER" << endl;
|
// cout << "MIDDLE MARKER" << endl;
|
||||||
if ( last_beacon != MIDDLE ) {
|
if ( last_beacon != MIDDLE ) {
|
||||||
if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) {
|
if ( ! _sgr->exists( current_sound_name ) ) {
|
||||||
SGSoundSample *sound = beacon.get_middle();
|
SGSoundSample *sound = beacon.get_middle();
|
||||||
if ( sound ) {
|
if ( sound ) {
|
||||||
globals->get_soundmgr()->add( sound, current_sound_name );
|
_sgr->add( sound, current_sound_name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( audio_btn->getBoolValue() ) {
|
if ( audio_btn->getBoolValue() ) {
|
||||||
if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) {
|
if ( !_sgr->is_playing(current_sound_name) ) {
|
||||||
globals->get_soundmgr()->play_looped( current_sound_name );
|
_sgr->play_looped( current_sound_name );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
globals->get_soundmgr()->stop( current_sound_name );
|
_sgr->stop( current_sound_name );
|
||||||
}
|
}
|
||||||
} else if ( beacon_type == INNER ) {
|
} else if ( beacon_type == INNER ) {
|
||||||
inner_marker = true;
|
inner_marker = true;
|
||||||
current_sound_name = "inner-marker";
|
current_sound_name = "inner-marker";
|
||||||
// cout << "INNER MARKER" << endl;
|
// cout << "INNER MARKER" << endl;
|
||||||
if ( last_beacon != INNER ) {
|
if ( last_beacon != INNER ) {
|
||||||
if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) {
|
if ( ! _sgr->exists( current_sound_name ) ) {
|
||||||
SGSoundSample *sound = beacon.get_inner();
|
SGSoundSample *sound = beacon.get_inner();
|
||||||
if ( sound ) {
|
if ( sound ) {
|
||||||
globals->get_soundmgr()->add( sound, current_sound_name );
|
_sgr->add( sound, current_sound_name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( audio_btn->getBoolValue() ) {
|
if ( audio_btn->getBoolValue() ) {
|
||||||
if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) {
|
if ( !_sgr->is_playing(current_sound_name) ) {
|
||||||
globals->get_soundmgr()->play_looped( current_sound_name );
|
_sgr->play_looped( current_sound_name );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
globals->get_soundmgr()->stop( current_sound_name );
|
_sgr->stop( current_sound_name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// cout << "VOLUME " << audio_vol->getDoubleValue() << endl;
|
// cout << "VOLUME " << audio_vol->getDoubleValue() << endl;
|
||||||
SGSoundSample * mkr = globals->get_soundmgr()->find( current_sound_name );
|
SGSoundSample * mkr = _sgr->find( current_sound_name );
|
||||||
if (mkr)
|
if (mkr)
|
||||||
mkr->set_volume( audio_vol->getDoubleValue() );
|
mkr->set_volume( audio_vol->getFloatValue() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( inrange ) {
|
if ( inrange ) {
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <Sound/beacon.hxx>
|
#include <Sound/beacon.hxx>
|
||||||
#include <Sound/morse.hxx>
|
#include <Sound/morse.hxx>
|
||||||
|
|
||||||
|
class SGSampleGroup;
|
||||||
|
|
||||||
class FGMarkerBeacon : public SGSubsystem
|
class FGMarkerBeacon : public SGSubsystem
|
||||||
{
|
{
|
||||||
|
@ -54,7 +55,7 @@ class FGMarkerBeacon : public SGSubsystem
|
||||||
SGPropertyNode_ptr audio_btn;
|
SGPropertyNode_ptr audio_btn;
|
||||||
SGPropertyNode_ptr audio_vol;
|
SGPropertyNode_ptr audio_vol;
|
||||||
SGPropertyNode_ptr serviceable;
|
SGPropertyNode_ptr serviceable;
|
||||||
SGPropertyNode_ptr sound_pause;
|
SGPropertyNode_ptr sound_working;
|
||||||
|
|
||||||
bool need_update;
|
bool need_update;
|
||||||
|
|
||||||
|
@ -73,6 +74,8 @@ class FGMarkerBeacon : public SGSubsystem
|
||||||
// internal periodic station search timer
|
// internal periodic station search timer
|
||||||
double _time_before_search_sec;
|
double _time_before_search_sec;
|
||||||
|
|
||||||
|
SGSharedPtr<SGSampleGroup> _sgr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum fgMkrBeacType {
|
enum fgMkrBeacType {
|
||||||
|
|
|
@ -2106,34 +2106,17 @@ MK_VIII::VoicePlayer::Speaker::bind (SGPropertyNode *node)
|
||||||
// uses xmlsound property names
|
// uses xmlsound property names
|
||||||
tie(node, "volume", &volume);
|
tie(node, "volume", &volume);
|
||||||
tie(node, "pitch", &pitch);
|
tie(node, "pitch", &pitch);
|
||||||
tie(node, "position/x", &position[0]);
|
|
||||||
tie(node, "position/y", &position[1]);
|
|
||||||
tie(node, "position/z", &position[2]);
|
|
||||||
tie(node, "orientation/x", &orientation[0]);
|
|
||||||
tie(node, "orientation/y", &orientation[1]);
|
|
||||||
tie(node, "orientation/z", &orientation[2]);
|
|
||||||
tie(node, "orientation/inner-cone", &inner_cone);
|
|
||||||
tie(node, "orientation/outer-cone", &outer_cone);
|
|
||||||
tie(node, "reference-dist", &reference_dist);
|
|
||||||
tie(node, "max-dist", &max_dist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MK_VIII::VoicePlayer::Speaker::update_configuration ()
|
MK_VIII::VoicePlayer::Speaker::update_configuration ()
|
||||||
{
|
{
|
||||||
map<string, SGSoundSample *>::iterator iter;
|
map< string, SGSharedPtr<SGSoundSample> >::iterator iter;
|
||||||
for (iter = player->samples.begin(); iter != player->samples.end(); iter++)
|
for (iter = player->samples.begin(); iter != player->samples.end(); iter++)
|
||||||
{
|
{
|
||||||
SGSoundSample *sample = (*iter).second;
|
SGSoundSample *sample = (*iter).second;
|
||||||
|
|
||||||
sample->set_pitch(pitch);
|
sample->set_pitch(pitch);
|
||||||
sample->set_offset_pos(position);
|
|
||||||
sample->set_orientation(orientation,
|
|
||||||
inner_cone,
|
|
||||||
outer_cone,
|
|
||||||
outer_gain);
|
|
||||||
sample->set_reference_dist(reference_dist);
|
|
||||||
sample->set_max_dist(max_dist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->voice)
|
if (player->voice)
|
||||||
|
@ -2172,7 +2155,7 @@ MK_VIII::VoicePlayer::Voice::stop (bool now)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MK_VIII::VoicePlayer::Voice::set_volume (double _volume)
|
MK_VIII::VoicePlayer::Voice::set_volume (float _volume)
|
||||||
{
|
{
|
||||||
volume = _volume;
|
volume = _volume;
|
||||||
volume_changed();
|
volume_changed();
|
||||||
|
@ -2209,15 +2192,6 @@ MK_VIII::VoicePlayer::~VoicePlayer ()
|
||||||
for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++)
|
for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++)
|
||||||
delete *iter1;
|
delete *iter1;
|
||||||
_voices.clear();
|
_voices.clear();
|
||||||
|
|
||||||
/* sound mgr already destroyed - samples already deleted
|
|
||||||
map<string, SGSoundSample *>::iterator iter2;
|
|
||||||
for (iter2 = samples.begin(); iter2 != samples.end(); iter2++)
|
|
||||||
{
|
|
||||||
bool status = globals->get_soundmgr()->remove((*iter2).first);
|
|
||||||
assert(status);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
samples.clear();
|
samples.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2226,6 +2200,10 @@ MK_VIII::VoicePlayer::init ()
|
||||||
{
|
{
|
||||||
#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay"
|
#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay"
|
||||||
|
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
_sgr = smgr->find("avionics", true);
|
||||||
|
_sgr->tie_to_listener();
|
||||||
|
|
||||||
make_voice(&voices.application_data_base_failed, "application-data-base-failed");
|
make_voice(&voices.application_data_base_failed, "application-data-base-failed");
|
||||||
make_voice(&voices.bank_angle, "bank-angle");
|
make_voice(&voices.bank_angle, "bank-angle");
|
||||||
make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle");
|
make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle");
|
||||||
|
@ -2270,13 +2248,7 @@ MK_VIII::VoicePlayer::get_sample (const char *name)
|
||||||
std::ostringstream refname;
|
std::ostringstream refname;
|
||||||
refname << mk->name << "[" << mk->num << "]" << "/" << name;
|
refname << mk->name << "[" << mk->num << "]" << "/" << name;
|
||||||
|
|
||||||
SGSoundMgr *soundmgr = globals->get_soundmgr();
|
SGSoundSample *sample = _sgr->find(refname.str());
|
||||||
if (soundmgr->is_working() == false)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGSoundSample *sample = soundmgr->find(refname.str());
|
|
||||||
if (! sample)
|
if (! sample)
|
||||||
{
|
{
|
||||||
SGPath sample_path(globals->get_fg_root());
|
SGPath sample_path(globals->get_fg_root());
|
||||||
|
@ -2293,7 +2265,7 @@ MK_VIII::VoicePlayer::get_sample (const char *name)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
soundmgr->add(sample, refname.str());
|
_sgr->add(sample, refname.str());
|
||||||
samples[refname.str()] = sample;
|
samples[refname.str()] = sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2338,7 +2310,7 @@ MK_VIII::VoicePlayer::stop (unsigned int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MK_VIII::VoicePlayer::set_volume (double _volume)
|
MK_VIII::VoicePlayer::set_volume (float _volume)
|
||||||
{
|
{
|
||||||
volume = _volume;
|
volume = _volume;
|
||||||
if (voice)
|
if (voice)
|
||||||
|
@ -4130,7 +4102,7 @@ MK_VIII::Mode6Handler::leave_takeoff ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MK_VIII::Mode6Handler::set_volume (double volume)
|
MK_VIII::Mode6Handler::set_volume (float volume)
|
||||||
{
|
{
|
||||||
mk_voice(minimums_minimums)->set_volume(volume);
|
mk_voice(minimums_minimums)->set_volume(volume);
|
||||||
mk_voice(five_hundred_above)->set_volume(volume);
|
mk_voice(five_hundred_above)->set_volume(volume);
|
||||||
|
|
|
@ -36,6 +36,8 @@ using std::vector;
|
||||||
using std::deque;
|
using std::deque;
|
||||||
using std::map;
|
using std::map;
|
||||||
|
|
||||||
|
class SGSampleGroup;
|
||||||
|
|
||||||
#include <Airports/runways.hxx>
|
#include <Airports/runways.hxx>
|
||||||
#include <Airports/simple.hxx>
|
#include <Airports/simple.hxx>
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
|
@ -733,10 +735,10 @@ public:
|
||||||
public:
|
public:
|
||||||
bool silence;
|
bool silence;
|
||||||
|
|
||||||
virtual inline void play (double volume) {}
|
virtual inline void play (float volume) {}
|
||||||
virtual inline void stop () {}
|
virtual inline void stop () {}
|
||||||
virtual bool is_playing () = 0;
|
virtual bool is_playing () = 0;
|
||||||
virtual inline void set_volume (double volume) {}
|
virtual inline void set_volume (float volume) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -745,17 +747,17 @@ public:
|
||||||
|
|
||||||
class SampleElement : public Element
|
class SampleElement : public Element
|
||||||
{
|
{
|
||||||
SGSoundSample *_sample;
|
SGSharedPtr<SGSoundSample> _sample;
|
||||||
double _volume;
|
float _volume;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline SampleElement (SGSoundSample *sample, double volume = 1.0)
|
inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
|
||||||
: _sample(sample), _volume(volume) { silence = false; }
|
: _sample(sample), _volume(volume) { silence = false; }
|
||||||
|
|
||||||
virtual inline void play (double volume) { if (_sample) { set_volume(volume); _sample->play_once(); } }
|
virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
|
||||||
virtual inline void stop () { if (_sample) _sample->stop(); }
|
virtual inline void stop () { if (_sample) _sample->stop(); }
|
||||||
virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
|
virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
|
||||||
virtual inline void set_volume (double volume) { if (_sample) _sample->set_volume(volume * _volume); }
|
virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -771,7 +773,7 @@ public:
|
||||||
inline SilenceElement (double duration)
|
inline SilenceElement (double duration)
|
||||||
: _duration(duration) { silence = true; }
|
: _duration(duration) { silence = true; }
|
||||||
|
|
||||||
virtual inline void play (double volume) { start_time = globals->get_sim_time_sec(); }
|
virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
|
||||||
virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
|
virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -790,19 +792,19 @@ public:
|
||||||
|
|
||||||
void play ();
|
void play ();
|
||||||
void stop (bool now);
|
void stop (bool now);
|
||||||
void set_volume (double _volume);
|
void set_volume (float _volume);
|
||||||
void volume_changed ();
|
void volume_changed ();
|
||||||
void update ();
|
void update ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VoicePlayer *player;
|
VoicePlayer *player;
|
||||||
|
|
||||||
double volume;
|
float volume;
|
||||||
|
|
||||||
vector<Element *> elements;
|
vector<Element *> elements;
|
||||||
vector<Element *>::iterator iter;
|
vector<Element *>::iterator iter;
|
||||||
|
|
||||||
inline double get_volume () const { return player->volume * player->speaker.volume * volume; }
|
inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -811,10 +813,10 @@ public:
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
double volume;
|
float volume;
|
||||||
} conf;
|
} conf;
|
||||||
|
|
||||||
double volume;
|
float volume;
|
||||||
|
|
||||||
Voice *voice;
|
Voice *voice;
|
||||||
Voice *next_voice;
|
Voice *next_voice;
|
||||||
|
@ -871,7 +873,7 @@ public:
|
||||||
};
|
};
|
||||||
void stop (unsigned int flags = 0);
|
void stop (unsigned int flags = 0);
|
||||||
|
|
||||||
void set_volume (double _volume);
|
void set_volume (float _volume);
|
||||||
void update ();
|
void update ();
|
||||||
|
|
||||||
inline void bind (SGPropertyNode *node) { speaker.bind(node); }
|
inline void bind (SGPropertyNode *node) { speaker.bind(node); }
|
||||||
|
@ -887,13 +889,6 @@ public:
|
||||||
VoicePlayer *player;
|
VoicePlayer *player;
|
||||||
|
|
||||||
double pitch;
|
double pitch;
|
||||||
float position[3];
|
|
||||||
float orientation[3];
|
|
||||||
float inner_cone;
|
|
||||||
float outer_cone;
|
|
||||||
float outer_gain;
|
|
||||||
float reference_dist;
|
|
||||||
float max_dist;
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void tie (SGPropertyNode *node, const char *name, T *ptr)
|
inline void tie (SGPropertyNode *node, const char *name, T *ptr)
|
||||||
|
@ -913,20 +908,13 @@ public:
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T get_property (T *ptr) const { return *ptr; }
|
inline T get_property (T *ptr) const { return *ptr; }
|
||||||
|
|
||||||
double volume;
|
float volume;
|
||||||
|
|
||||||
inline Speaker (VoicePlayer *_player)
|
inline Speaker (VoicePlayer *_player)
|
||||||
: player(_player),
|
: player(_player),
|
||||||
pitch(1),
|
pitch(1),
|
||||||
inner_cone(360),
|
|
||||||
outer_cone(360),
|
|
||||||
outer_gain(0),
|
|
||||||
reference_dist(3),
|
|
||||||
max_dist(10),
|
|
||||||
volume(1)
|
volume(1)
|
||||||
{
|
{
|
||||||
position[0] = 0; position[1] = 0; position[2] = 0;
|
|
||||||
orientation[0] = 0; orientation[1] = 0; orientation[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind (SGPropertyNode *node);
|
void bind (SGPropertyNode *node);
|
||||||
|
@ -940,9 +928,10 @@ public:
|
||||||
|
|
||||||
MK_VIII *mk;
|
MK_VIII *mk;
|
||||||
|
|
||||||
|
SGSharedPtr<SGSampleGroup> _sgr;
|
||||||
Speaker speaker;
|
Speaker speaker;
|
||||||
|
|
||||||
map<string, SGSoundSample *> samples;
|
map< string, SGSharedPtr<SGSoundSample> > samples;
|
||||||
vector<Voice *> _voices;
|
vector<Voice *> _voices;
|
||||||
|
|
||||||
bool looped;
|
bool looped;
|
||||||
|
@ -1465,7 +1454,7 @@ private:
|
||||||
void power_off ();
|
void power_off ();
|
||||||
void enter_takeoff ();
|
void enter_takeoff ();
|
||||||
void leave_takeoff ();
|
void leave_takeoff ();
|
||||||
void set_volume (double volume);
|
void set_volume (float volume);
|
||||||
bool altitude_callouts_enabled ();
|
bool altitude_callouts_enabled ();
|
||||||
void update ();
|
void update ();
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,8 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
||||||
_name(node->getStringValue("name", "nav")),
|
_name(node->getStringValue("name", "nav")),
|
||||||
_num(node->getIntValue("number", 0)),
|
_num(node->getIntValue("number", 0)),
|
||||||
_time_before_search_sec(-1.0),
|
_time_before_search_sec(-1.0),
|
||||||
_falseCoursesEnabled(true)
|
_falseCoursesEnabled(true),
|
||||||
|
_sgr(NULL)
|
||||||
{
|
{
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
SGPath term = path;
|
SGPath term = path;
|
||||||
|
@ -184,6 +185,10 @@ FGNavRadio::~FGNavRadio()
|
||||||
void
|
void
|
||||||
FGNavRadio::init ()
|
FGNavRadio::init ()
|
||||||
{
|
{
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
_sgr = smgr->find("avionics", true);
|
||||||
|
_sgr->tie_to_listener();
|
||||||
|
|
||||||
morse.init();
|
morse.init();
|
||||||
|
|
||||||
string branch;
|
string branch;
|
||||||
|
@ -575,6 +580,8 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig
|
||||||
if (!_gs || !inrange_node->getBoolValue()) {
|
if (!_gs || !inrange_node->getBoolValue()) {
|
||||||
gs_dist_node->setDoubleValue( 0.0 );
|
gs_dist_node->setDoubleValue( 0.0 );
|
||||||
gs_inrange_node->setBoolValue(false);
|
gs_inrange_node->setBoolValue(false);
|
||||||
|
_gsNeedleDeflection = 0.0;
|
||||||
|
_gsNeedleDeflectionNorm = 0.0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,6 +591,8 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig
|
||||||
gs_inrange_node->setBoolValue(gsInRange);
|
gs_inrange_node->setBoolValue(gsInRange);
|
||||||
|
|
||||||
if (!gsInRange) {
|
if (!gsInRange) {
|
||||||
|
_gsNeedleDeflection = 0.0;
|
||||||
|
_gsNeedleDeflectionNorm = 0.0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,17 +799,17 @@ void FGNavRadio::updateAudio()
|
||||||
|
|
||||||
// play station ident via audio system if on + ident,
|
// play station ident via audio system if on + ident,
|
||||||
// otherwise turn it off
|
// otherwise turn it off
|
||||||
if (!power_btn_node->getBoolValue()
|
if (!power_btn_node->getBoolValue()
|
||||||
|| !(bus_power_node->getDoubleValue() > 1.0)
|
|| !(bus_power_node->getDoubleValue() > 1.0)
|
||||||
|| !ident_btn_node->getBoolValue()
|
|| !ident_btn_node->getBoolValue()
|
||||||
|| !audio_btn_node->getBoolValue() ) {
|
|| !audio_btn_node->getBoolValue() ) {
|
||||||
globals->get_soundmgr()->stop( nav_fx_name );
|
_sgr->stop( nav_fx_name );
|
||||||
globals->get_soundmgr()->stop( dme_fx_name );
|
_sgr->stop( dme_fx_name );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGSoundSample *sound = globals->get_soundmgr()->find( nav_fx_name );
|
SGSoundSample *sound = _sgr->find( nav_fx_name );
|
||||||
double vol = vol_btn_node->getDoubleValue();
|
double vol = vol_btn_node->getFloatValue();
|
||||||
SG_CLAMP_RANGE(vol, 0.0, 1.0);
|
SG_CLAMP_RANGE(vol, 0.0, 1.0);
|
||||||
|
|
||||||
if ( sound != NULL ) {
|
if ( sound != NULL ) {
|
||||||
|
@ -809,7 +818,7 @@ void FGNavRadio::updateAudio()
|
||||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-vor-ident sound" );
|
SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-vor-ident sound" );
|
||||||
}
|
}
|
||||||
|
|
||||||
sound = globals->get_soundmgr()->find( dme_fx_name );
|
sound = _sgr->find( dme_fx_name );
|
||||||
if ( sound != NULL ) {
|
if ( sound != NULL ) {
|
||||||
sound->set_volume( vol );
|
sound->set_volume( vol );
|
||||||
} else {
|
} else {
|
||||||
|
@ -832,16 +841,16 @@ void FGNavRadio::updateAudio()
|
||||||
play_count = ++play_count % NUM_IDENT_SLOTS;
|
play_count = ++play_count % NUM_IDENT_SLOTS;
|
||||||
|
|
||||||
// Previous ident is out of time; if still playing, cut it off:
|
// Previous ident is out of time; if still playing, cut it off:
|
||||||
globals->get_soundmgr()->stop( nav_fx_name );
|
_sgr->stop( nav_fx_name );
|
||||||
globals->get_soundmgr()->stop( dme_fx_name );
|
_sgr->stop( dme_fx_name );
|
||||||
if (play_count == 0) { // the DME slot
|
if (play_count == 0) { // the DME slot
|
||||||
if (_dmeInRange && dme_serviceable_node->getBoolValue()) {
|
if (_dmeInRange && dme_serviceable_node->getBoolValue()) {
|
||||||
// play DME ident
|
// play DME ident
|
||||||
globals->get_soundmgr()->play_once( dme_fx_name );
|
if (vol > 0.05) _sgr->play_once( dme_fx_name );
|
||||||
}
|
}
|
||||||
} else { // NAV slot
|
} else { // NAV slot
|
||||||
if (inrange_node->getBoolValue() && nav_serviceable_node->getBoolValue()) {
|
if (inrange_node->getBoolValue() && nav_serviceable_node->getBoolValue()) {
|
||||||
globals->get_soundmgr()->play_once(nav_fx_name);
|
if (vol > 0.05) _sgr->play_once(nav_fx_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -924,8 +933,9 @@ void FGNavRadio::search()
|
||||||
_gs = NULL;
|
_gs = NULL;
|
||||||
_dme = NULL;
|
_dme = NULL;
|
||||||
nav_id_node->setStringValue("");
|
nav_id_node->setStringValue("");
|
||||||
globals->get_soundmgr()->remove( nav_fx_name );
|
|
||||||
globals->get_soundmgr()->remove( dme_fx_name );
|
_sgr->remove( nav_fx_name );
|
||||||
|
_sgr->remove( dme_fx_name );
|
||||||
}
|
}
|
||||||
|
|
||||||
is_valid_node->setBoolValue(nav != NULL);
|
is_valid_node->setBoolValue(nav != NULL);
|
||||||
|
@ -967,25 +977,25 @@ double FGNavRadio::localizerWidth(FGNavRecord* aLOC)
|
||||||
|
|
||||||
void FGNavRadio::audioNavidChanged()
|
void FGNavRadio::audioNavidChanged()
|
||||||
{
|
{
|
||||||
if ( globals->get_soundmgr()->exists(nav_fx_name)) {
|
if (_sgr->exists(nav_fx_name)) {
|
||||||
globals->get_soundmgr()->remove(nav_fx_name);
|
_sgr->remove(nav_fx_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
string trans_ident(_navaid->get_trans_ident());
|
string trans_ident(_navaid->get_trans_ident());
|
||||||
SGSoundSample* sound = morse.make_ident(trans_ident, LO_FREQUENCY);
|
SGSoundSample* sound = morse.make_ident(trans_ident, LO_FREQUENCY);
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
if (!globals->get_soundmgr()->add( sound, nav_fx_name )) {
|
if (!_sgr->add( sound, nav_fx_name )) {
|
||||||
SG_LOG(SG_COCKPIT, SG_WARN, "Failed to add v1-vor-ident sound");
|
SG_LOG(SG_COCKPIT, SG_WARN, "Failed to add v1-vor-ident sound");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( globals->get_soundmgr()->exists( dme_fx_name ) ) {
|
if ( _sgr->exists( dme_fx_name ) ) {
|
||||||
globals->get_soundmgr()->remove( dme_fx_name );
|
_sgr->remove( dme_fx_name );
|
||||||
}
|
}
|
||||||
|
|
||||||
sound = morse.make_ident( trans_ident, HI_FREQUENCY );
|
sound = morse.make_ident( trans_ident, HI_FREQUENCY );
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
globals->get_soundmgr()->add( sound, dme_fx_name );
|
_sgr->add( sound, dme_fx_name );
|
||||||
|
|
||||||
int offset = (int)(sg_random() * 30.0);
|
int offset = (int)(sg_random() * 30.0);
|
||||||
play_count = offset / 4;
|
play_count = offset / 4;
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
// forward decls
|
// forward decls
|
||||||
class SGInterpTable;
|
class SGInterpTable;
|
||||||
|
|
||||||
|
class SGSampleGroup;
|
||||||
class FGNavRecord;
|
class FGNavRecord;
|
||||||
typedef SGSharedPtr<FGNavRecord> FGNavRecordPtr;
|
typedef SGSharedPtr<FGNavRecord> FGNavRecordPtr;
|
||||||
|
|
||||||
|
@ -162,6 +163,8 @@ class FGNavRadio : public SGSubsystem
|
||||||
|
|
||||||
// realism setting, are false courses and GS lobes enabled?
|
// realism setting, are false courses and GS lobes enabled?
|
||||||
bool _falseCoursesEnabled;
|
bool _falseCoursesEnabled;
|
||||||
|
|
||||||
|
SGSharedPtr<SGSampleGroup> _sgr;
|
||||||
|
|
||||||
bool updateWithPower(double aDt);
|
bool updateWithPower(double aDt);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <simgear/structure/commands.hxx>
|
#include <simgear/structure/commands.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
#include <simgear/structure/event_mgr.hxx>
|
#include <simgear/structure/event_mgr.hxx>
|
||||||
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
|
|
||||||
#include <Cockpit/panel.hxx>
|
#include <Cockpit/panel.hxx>
|
||||||
#include <Cockpit/panel_io.hxx>
|
#include <Cockpit/panel_io.hxx>
|
||||||
|
@ -33,7 +34,7 @@
|
||||||
#include <Scenery/tilemgr.hxx>
|
#include <Scenery/tilemgr.hxx>
|
||||||
#include <Scenery/scenery.hxx>
|
#include <Scenery/scenery.hxx>
|
||||||
#include <Scripting/NasalSys.hxx>
|
#include <Scripting/NasalSys.hxx>
|
||||||
#include <Sound/fg_fx.hxx>
|
#include <Sound/sample_queue.hxx>
|
||||||
#include <Time/sunsolver.hxx>
|
#include <Time/sunsolver.hxx>
|
||||||
#include <Time/tmp.hxx>
|
#include <Time/tmp.hxx>
|
||||||
|
|
||||||
|
@ -1251,13 +1252,22 @@ do_set_cursor (const SGPropertyNode * arg)
|
||||||
static bool
|
static bool
|
||||||
do_play_audio_sample (const SGPropertyNode * arg)
|
do_play_audio_sample (const SGPropertyNode * arg)
|
||||||
{
|
{
|
||||||
FGFX *fx = (FGFX *)globals->get_subsystem("fx");
|
|
||||||
string path = arg->getStringValue("path");
|
string path = arg->getStringValue("path");
|
||||||
string file = arg->getStringValue("file");
|
string file = arg->getStringValue("file");
|
||||||
double volume = arg->getDoubleValue("volume");
|
float volume = arg->getFloatValue("volume");
|
||||||
// cout << "playing " << path << " / " << file << endl;
|
// cout << "playing " << path << " / " << file << endl;
|
||||||
try {
|
try {
|
||||||
fx->play_message( path, file, volume );
|
static FGSampleQueue *queue = 0;
|
||||||
|
if ( !queue ) {
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
queue = new FGSampleQueue(smgr, "chatter");
|
||||||
|
queue->tie_to_listener();
|
||||||
|
}
|
||||||
|
|
||||||
|
SGSoundSample *msg = new SGSoundSample(path.c_str(), file.c_str());
|
||||||
|
msg->set_volume( volume );
|
||||||
|
queue->add( msg );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} catch (const sg_io_exception&) {
|
} catch (const sg_io_exception&) {
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
#include <simgear/misc/interpolator.hxx>
|
#include <simgear/misc/interpolator.hxx>
|
||||||
#include <simgear/scene/material/matlib.hxx>
|
#include <simgear/scene/material/matlib.hxx>
|
||||||
#include <simgear/scene/model/particles.hxx>
|
#include <simgear/scene/model/particles.hxx>
|
||||||
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
#include <simgear/timing/sg_time.hxx>
|
#include <simgear/timing/sg_time.hxx>
|
||||||
#include <simgear/timing/lowleveltime.h>
|
#include <simgear/timing/lowleveltime.h>
|
||||||
|
|
||||||
|
@ -106,9 +107,6 @@
|
||||||
#include <Scenery/scenery.hxx>
|
#include <Scenery/scenery.hxx>
|
||||||
#include <Scenery/tilemgr.hxx>
|
#include <Scenery/tilemgr.hxx>
|
||||||
#include <Scripting/NasalSys.hxx>
|
#include <Scripting/NasalSys.hxx>
|
||||||
#include <Sound/fg_fx.hxx>
|
|
||||||
#include <Sound/beacon.hxx>
|
|
||||||
#include <Sound/morse.hxx>
|
|
||||||
#include <Sound/voice.hxx>
|
#include <Sound/voice.hxx>
|
||||||
#include <Systems/system_mgr.hxx>
|
#include <Systems/system_mgr.hxx>
|
||||||
#include <Time/light.hxx>
|
#include <Time/light.hxx>
|
||||||
|
@ -138,9 +136,7 @@
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
class Sound;
|
|
||||||
extern const char *default_root;
|
extern const char *default_root;
|
||||||
float init_volume;
|
|
||||||
|
|
||||||
|
|
||||||
// Scan the command line options for the specified option and return
|
// Scan the command line options for the specified option and return
|
||||||
|
@ -1456,6 +1452,21 @@ bool fgInitSubsystems() {
|
||||||
globals->get_event_mgr()->init();
|
globals->get_event_mgr()->init();
|
||||||
globals->get_event_mgr()->setRealtimeProperty(fgGetNode("/sim/time/delta-realtime-sec", true));
|
globals->get_event_mgr()->setRealtimeProperty(fgGetNode("/sim/time/delta-realtime-sec", true));
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Initialize the sound manager subsystem.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
globals->get_soundmgr()->bind();
|
||||||
|
globals->get_soundmgr()->init(fgGetString("/sim/sound/device-name", NULL));
|
||||||
|
|
||||||
|
vector <const char*>devices =
|
||||||
|
globals->get_soundmgr()->get_available_devices();
|
||||||
|
for (unsigned int i=0; i<devices.size(); i++) {
|
||||||
|
SGPropertyNode *p = fgGetNode("/sim/sound/devices/device", i, true);
|
||||||
|
p->setStringValue(devices[i]);
|
||||||
|
}
|
||||||
|
devices.clear();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Initialize the property interpolator subsystem. Put into the INIT
|
// Initialize the property interpolator subsystem. Put into the INIT
|
||||||
// group because the "nasal" subsystem may need it at GENERAL take-down.
|
// group because the "nasal" subsystem may need it at GENERAL take-down.
|
||||||
|
@ -1524,7 +1535,6 @@ bool fgInitSubsystems() {
|
||||||
// Initialize the ridgelift subsystem
|
// Initialize the ridgelift subsystem
|
||||||
globals->add_subsystem("ridgelift", new FGRidgeLift);
|
globals->add_subsystem("ridgelift", new FGRidgeLift);
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Initialize the aircraft systems and instrumentation (before the
|
// Initialize the aircraft systems and instrumentation (before the
|
||||||
// autopilot.)
|
// autopilot.)
|
||||||
|
@ -1587,22 +1597,9 @@ bool fgInitSubsystems() {
|
||||||
fgGetBool("/sim/rendering/bump-mapping", false);
|
fgGetBool("/sim/rendering/bump-mapping", false);
|
||||||
|
|
||||||
#ifdef ENABLE_AUDIO_SUPPORT
|
#ifdef ENABLE_AUDIO_SUPPORT
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Initialize the sound subsystem.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
init_volume = fgGetFloat("/sim/sound/volume");
|
|
||||||
fgSetFloat("/sim/sound/volume", 0.0f);
|
|
||||||
globals->set_soundmgr(new SGSoundMgr);
|
|
||||||
globals->get_soundmgr()->init();
|
|
||||||
globals->get_soundmgr()->bind();
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Initialize the sound-effects subsystem.
|
// Initialize the sound-effects subsystem.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
globals->add_subsystem("fx", new FGFX);
|
|
||||||
globals->add_subsystem("voice", new FGVoiceMgr);
|
globals->add_subsystem("voice", new FGVoiceMgr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1685,6 +1682,7 @@ bool fgInitSubsystems() {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
globals->add_subsystem("replay", new FGReplay);
|
globals->add_subsystem("replay", new FGReplay);
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Bind and initialize subsystems.
|
// Bind and initialize subsystems.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -222,12 +222,12 @@ setFreeze (bool f)
|
||||||
frozen = f;
|
frozen = f;
|
||||||
|
|
||||||
// Stop sound on a pause
|
// Stop sound on a pause
|
||||||
SGSoundMgr *s = globals->get_soundmgr();
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
if ( s != NULL ) {
|
if ( smgr != NULL ) {
|
||||||
if ( f ) {
|
if ( f ) {
|
||||||
s->pause();
|
smgr->suspend();
|
||||||
} else if (!fgGetBool("/sim/sound/pause")) {
|
} else if (fgGetBool("/sim/sound/working")) {
|
||||||
s->resume();
|
smgr->resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
// General Public License for more details.
|
// General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
//
|
//
|
||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <simgear/sound/soundmgr_openal.hxx>
|
|
||||||
#include <simgear/structure/commands.hxx>
|
#include <simgear/structure/commands.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/timing/sg_time.hxx>
|
#include <simgear/timing/sg_time.hxx>
|
||||||
|
@ -33,6 +32,7 @@
|
||||||
#include <simgear/scene/material/matlib.hxx>
|
#include <simgear/scene/material/matlib.hxx>
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/structure/event_mgr.hxx>
|
#include <simgear/structure/event_mgr.hxx>
|
||||||
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
|
|
||||||
#include <Aircraft/controls.hxx>
|
#include <Aircraft/controls.hxx>
|
||||||
#include <Airports/runways.hxx>
|
#include <Airports/runways.hxx>
|
||||||
|
@ -73,6 +73,7 @@ FGGlobals::FGGlobals() :
|
||||||
renderer( new FGRenderer ),
|
renderer( new FGRenderer ),
|
||||||
subsystem_mgr( new SGSubsystemMgr ),
|
subsystem_mgr( new SGSubsystemMgr ),
|
||||||
event_mgr( new SGEventMgr ),
|
event_mgr( new SGEventMgr ),
|
||||||
|
soundmgr( new SGSoundMgr ),
|
||||||
sim_time_sec( 0.0 ),
|
sim_time_sec( 0.0 ),
|
||||||
fg_root( "" ),
|
fg_root( "" ),
|
||||||
warp( 0 ),
|
warp( 0 ),
|
||||||
|
@ -83,7 +84,6 @@ FGGlobals::FGGlobals() :
|
||||||
matlib( NULL ),
|
matlib( NULL ),
|
||||||
route_mgr( NULL ),
|
route_mgr( NULL ),
|
||||||
current_panel( NULL ),
|
current_panel( NULL ),
|
||||||
soundmgr( NULL ),
|
|
||||||
ATC_mgr( NULL ),
|
ATC_mgr( NULL ),
|
||||||
AI_mgr( NULL ),
|
AI_mgr( NULL ),
|
||||||
controls( NULL ),
|
controls( NULL ),
|
||||||
|
@ -127,6 +127,7 @@ FGGlobals::~FGGlobals()
|
||||||
// deleted subsystems.
|
// deleted subsystems.
|
||||||
subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("input");
|
subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("input");
|
||||||
subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("gui");
|
subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("gui");
|
||||||
|
subsystem_mgr->unbind();
|
||||||
delete subsystem_mgr;
|
delete subsystem_mgr;
|
||||||
delete event_mgr;
|
delete event_mgr;
|
||||||
delete time_params;
|
delete time_params;
|
||||||
|
@ -135,7 +136,6 @@ FGGlobals::~FGGlobals()
|
||||||
delete matlib;
|
delete matlib;
|
||||||
delete route_mgr;
|
delete route_mgr;
|
||||||
delete current_panel;
|
delete current_panel;
|
||||||
delete soundmgr;
|
|
||||||
|
|
||||||
delete ATC_mgr;
|
delete ATC_mgr;
|
||||||
delete AI_mgr;
|
delete AI_mgr;
|
||||||
|
@ -160,6 +160,9 @@ FGGlobals::~FGGlobals()
|
||||||
delete channellist;
|
delete channellist;
|
||||||
delete airwaynet;
|
delete airwaynet;
|
||||||
delete multiplayer_mgr;
|
delete multiplayer_mgr;
|
||||||
|
|
||||||
|
soundmgr->unbind();
|
||||||
|
delete soundmgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -261,6 +264,11 @@ FGGlobals::add_subsystem (const char * name,
|
||||||
subsystem_mgr->add(name, subsystem, type, min_time_sec);
|
subsystem_mgr->add(name, subsystem, type, min_time_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SGSoundMgr *
|
||||||
|
FGGlobals::get_soundmgr () const
|
||||||
|
{
|
||||||
|
return soundmgr;
|
||||||
|
}
|
||||||
|
|
||||||
SGEventMgr *
|
SGEventMgr *
|
||||||
FGGlobals::get_event_mgr () const
|
FGGlobals::get_event_mgr () const
|
||||||
|
|
|
@ -49,10 +49,10 @@ class SGMagVar;
|
||||||
class SGMaterialLib;
|
class SGMaterialLib;
|
||||||
class SGPropertyNode;
|
class SGPropertyNode;
|
||||||
class SGTime;
|
class SGTime;
|
||||||
class SGSoundMgr;
|
|
||||||
class SGEventMgr;
|
class SGEventMgr;
|
||||||
class SGSubsystemMgr;
|
class SGSubsystemMgr;
|
||||||
class SGSubsystem;
|
class SGSubsystem;
|
||||||
|
class SGSoundMgr;
|
||||||
|
|
||||||
class FGAIMgr;
|
class FGAIMgr;
|
||||||
class FGATCMgr;
|
class FGATCMgr;
|
||||||
|
@ -94,6 +94,7 @@ private:
|
||||||
FGRenderer *renderer;
|
FGRenderer *renderer;
|
||||||
SGSubsystemMgr *subsystem_mgr;
|
SGSubsystemMgr *subsystem_mgr;
|
||||||
SGEventMgr *event_mgr;
|
SGEventMgr *event_mgr;
|
||||||
|
SGSoundMgr *soundmgr;
|
||||||
|
|
||||||
// Number of milliseconds elapsed since the start of the program.
|
// Number of milliseconds elapsed since the start of the program.
|
||||||
double sim_time_sec;
|
double sim_time_sec;
|
||||||
|
@ -132,9 +133,6 @@ private:
|
||||||
// 2D panel
|
// 2D panel
|
||||||
FGPanel *current_panel;
|
FGPanel *current_panel;
|
||||||
|
|
||||||
// sound manager
|
|
||||||
SGSoundMgr *soundmgr;
|
|
||||||
|
|
||||||
// ATC manager
|
// ATC manager
|
||||||
FGATCMgr *ATC_mgr;
|
FGATCMgr *ATC_mgr;
|
||||||
|
|
||||||
|
@ -202,6 +200,8 @@ public:
|
||||||
|
|
||||||
virtual SGEventMgr *get_event_mgr () const;
|
virtual SGEventMgr *get_event_mgr () const;
|
||||||
|
|
||||||
|
virtual SGSoundMgr *get_soundmgr () const;
|
||||||
|
|
||||||
inline double get_sim_time_sec () const { return sim_time_sec; }
|
inline double get_sim_time_sec () const { return sim_time_sec; }
|
||||||
inline void inc_sim_time_sec (double dt) { sim_time_sec += dt; }
|
inline void inc_sim_time_sec (double dt) { sim_time_sec += dt; }
|
||||||
inline void set_sim_time_sec (double t) { sim_time_sec = t; }
|
inline void set_sim_time_sec (double t) { sim_time_sec = t; }
|
||||||
|
@ -244,9 +244,6 @@ public:
|
||||||
inline FGPanel *get_current_panel() const { return current_panel; }
|
inline FGPanel *get_current_panel() const { return current_panel; }
|
||||||
inline void set_current_panel( FGPanel *cp ) { current_panel = cp; }
|
inline void set_current_panel( FGPanel *cp ) { current_panel = cp; }
|
||||||
|
|
||||||
inline SGSoundMgr *get_soundmgr() const { return soundmgr; }
|
|
||||||
inline void set_soundmgr( SGSoundMgr *sm ) { soundmgr = sm; }
|
|
||||||
|
|
||||||
inline FGControls *get_controls() const { return controls; }
|
inline FGControls *get_controls() const { return controls; }
|
||||||
inline void set_controls( FGControls *c ) { controls = c; }
|
inline void set_controls( FGControls *c ) { controls = c; }
|
||||||
|
|
||||||
|
@ -305,7 +302,7 @@ public:
|
||||||
inline void set_tile_mgr ( FGTileMgr *t ) { tile_mgr = t; }
|
inline void set_tile_mgr ( FGTileMgr *t ) { tile_mgr = t; }
|
||||||
|
|
||||||
inline FGFontCache *get_fontcache() const { return fontcache; }
|
inline FGFontCache *get_fontcache() const { return fontcache; }
|
||||||
|
|
||||||
inline FGNavList *get_navlist() const { return navlist; }
|
inline FGNavList *get_navlist() const { return navlist; }
|
||||||
inline void set_navlist( FGNavList *n ) { navlist = n; }
|
inline void set_navlist( FGNavList *n ) { navlist = n; }
|
||||||
inline FGNavList *get_loclist() const { return loclist; }
|
inline FGNavList *get_loclist() const { return loclist; }
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include <Model/acmodel.hxx>
|
#include <Model/acmodel.hxx>
|
||||||
#include <Scenery/scenery.hxx>
|
#include <Scenery/scenery.hxx>
|
||||||
#include <Scenery/tilemgr.hxx>
|
#include <Scenery/tilemgr.hxx>
|
||||||
|
#include <Sound/fg_fx.hxx>
|
||||||
#include <Sound/beacon.hxx>
|
#include <Sound/beacon.hxx>
|
||||||
#include <Sound/morse.hxx>
|
#include <Sound/morse.hxx>
|
||||||
#include <Sound/fg_fx.hxx>
|
#include <Sound/fg_fx.hxx>
|
||||||
|
@ -86,7 +87,6 @@
|
||||||
|
|
||||||
static double real_delta_time_sec = 0.0;
|
static double real_delta_time_sec = 0.0;
|
||||||
double delta_time_sec = 0.0;
|
double delta_time_sec = 0.0;
|
||||||
extern float init_volume;
|
|
||||||
|
|
||||||
using namespace flightgear;
|
using namespace flightgear;
|
||||||
|
|
||||||
|
@ -104,6 +104,8 @@ long global_multi_loop;
|
||||||
SGTimeStamp last_time_stamp;
|
SGTimeStamp last_time_stamp;
|
||||||
SGTimeStamp current_time_stamp;
|
SGTimeStamp current_time_stamp;
|
||||||
|
|
||||||
|
void fgSetNewSoundDevice(const char *);
|
||||||
|
|
||||||
// The atexit() function handler should know when the graphical subsystem
|
// The atexit() function handler should know when the graphical subsystem
|
||||||
// is initialized.
|
// is initialized.
|
||||||
extern int _bootstrap_OSInit;
|
extern int _bootstrap_OSInit;
|
||||||
|
@ -460,8 +462,8 @@ static void fgMainLoop( void ) {
|
||||||
// we may want to move this to its own class at some point
|
// we may want to move this to its own class at some point
|
||||||
//
|
//
|
||||||
double visibility_meters = fgGetDouble("/environment/visibility-m");
|
double visibility_meters = fgGetDouble("/environment/visibility-m");
|
||||||
|
|
||||||
globals->get_tile_mgr()->prep_ssg_nodes( visibility_meters );
|
globals->get_tile_mgr()->prep_ssg_nodes( visibility_meters );
|
||||||
|
|
||||||
// update tile manager for view...
|
// update tile manager for view...
|
||||||
SGVec3d viewPos = globals->get_current_view()->get_view_pos();
|
SGVec3d viewPos = globals->get_current_view()->get_view_pos();
|
||||||
SGGeod geodViewPos = SGGeod::fromCart(viewPos);
|
SGGeod geodViewPos = SGGeod::fromCart(viewPos);
|
||||||
|
@ -477,10 +479,26 @@ static void fgMainLoop( void ) {
|
||||||
// update the view angle as late as possible, but before sound calculations
|
// update the view angle as late as possible, but before sound calculations
|
||||||
globals->get_viewmgr()->update(real_delta_time_sec);
|
globals->get_viewmgr()->update(real_delta_time_sec);
|
||||||
|
|
||||||
// Run audio scheduler
|
// Update the sound manager last so it can use the CPU while the GPU
|
||||||
|
// is processing the scenery (doubled the frame-rate for me) -EMH-
|
||||||
#ifdef ENABLE_AUDIO_SUPPORT
|
#ifdef ENABLE_AUDIO_SUPPORT
|
||||||
FGFX* fx = (FGFX*) globals->get_subsystem("fx");
|
static SGPropertyNode *sound_enabled = fgGetNode("/sim/sound/enabled");
|
||||||
fx->update_fx_late(delta_time_sec);
|
static SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
static bool smgr_enabled = true;
|
||||||
|
if (smgr_enabled != sound_enabled->getBoolValue()) {
|
||||||
|
if (smgr_enabled == true) { // request to suspend
|
||||||
|
smgr->suspend();
|
||||||
|
} else {
|
||||||
|
smgr->resume();
|
||||||
|
}
|
||||||
|
smgr_enabled = sound_enabled->getBoolValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smgr_enabled == true) {
|
||||||
|
static SGPropertyNode *volume = fgGetNode("/sim/sound/volume");
|
||||||
|
smgr->set_volume(volume->getFloatValue());
|
||||||
|
smgr->update(delta_time_sec);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// END Tile Manager udpates
|
// END Tile Manager udpates
|
||||||
|
@ -488,8 +506,13 @@ static void fgMainLoop( void ) {
|
||||||
if (!scenery_loaded && globals->get_tile_mgr()->isSceneryLoaded()
|
if (!scenery_loaded && globals->get_tile_mgr()->isSceneryLoaded()
|
||||||
&& cur_fdm_state->get_inited()) {
|
&& cur_fdm_state->get_inited()) {
|
||||||
fgSetBool("sim/sceneryloaded",true);
|
fgSetBool("sim/sceneryloaded",true);
|
||||||
fgSetFloat("/sim/sound/volume", init_volume);
|
if (fgGetBool("/sim/sound/working")) {
|
||||||
globals->get_soundmgr()->set_volume(init_volume);
|
smgr->activate();
|
||||||
|
} else {
|
||||||
|
smgr->stop();
|
||||||
|
}
|
||||||
|
globals->get_props()->tie("/sim/sound/devices/name",
|
||||||
|
SGRawValueFunctions<const char *>(0, fgSetNewSoundDevice), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fgRequestRedraw();
|
fgRequestRedraw();
|
||||||
|
@ -497,6 +520,14 @@ static void fgMainLoop( void ) {
|
||||||
SG_LOG( SG_ALL, SG_DEBUG, "" );
|
SG_LOG( SG_ALL, SG_DEBUG, "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fgSetNewSoundDevice(const char *device)
|
||||||
|
{
|
||||||
|
globals->get_soundmgr()->suspend();
|
||||||
|
globals->get_soundmgr()->stop();
|
||||||
|
globals->get_soundmgr()->init(device);
|
||||||
|
globals->get_soundmgr()->resume();
|
||||||
|
}
|
||||||
|
|
||||||
// Operation for querying OpenGL parameters. This must be done in a
|
// Operation for querying OpenGL parameters. This must be done in a
|
||||||
// valid OpenGL context, potentially in another thread.
|
// valid OpenGL context, potentially in another thread.
|
||||||
namespace
|
namespace
|
||||||
|
@ -627,6 +658,7 @@ static void fgIdleFunction ( void ) {
|
||||||
|
|
||||||
} else if ( idle_state == 5 ) {
|
} else if ( idle_state == 5 ) {
|
||||||
idle_state++;
|
idle_state++;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Initialize the 3D aircraft model subsystem (has a dependency on
|
// Initialize the 3D aircraft model subsystem (has a dependency on
|
||||||
// the scenery subsystem.)
|
// the scenery subsystem.)
|
||||||
|
@ -723,13 +755,13 @@ static void fgIdleFunction ( void ) {
|
||||||
SG_LOG( SG_GENERAL, SG_INFO,
|
SG_LOG( SG_GENERAL, SG_INFO,
|
||||||
"Starting intro music: " << mp3file.str() );
|
"Starting intro music: " << mp3file.str() );
|
||||||
|
|
||||||
#if defined( __CYGWIN__ )
|
# if defined( __CYGWIN__ )
|
||||||
string command = "start /m `cygpath -w " + mp3file.str() + "`";
|
string command = "start /m `cygpath -w " + mp3file.str() + "`";
|
||||||
#elif defined( WIN32 )
|
# elif defined( WIN32 )
|
||||||
string command = "start /m " + mp3file.str();
|
string command = "start /m " + mp3file.str();
|
||||||
#else
|
# else
|
||||||
string command = "mpg123 " + mp3file.str() + "> /dev/null 2>&1";
|
string command = "mpg123 " + mp3file.str() + "> /dev/null 2>&1";
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
system ( command.c_str() );
|
system ( command.c_str() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include <simgear/misc/sgstream.hxx>
|
#include <simgear/misc/sgstream.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/scene/material/mat.hxx>
|
#include <simgear/scene/material/mat.hxx>
|
||||||
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
|
|
||||||
// #include <Include/general.hxx>
|
// #include <Include/general.hxx>
|
||||||
// #include <Airports/simple.hxx>
|
// #include <Airports/simple.hxx>
|
||||||
|
@ -81,7 +82,8 @@ enum
|
||||||
FG_OPTIONS_ERROR = 2,
|
FG_OPTIONS_ERROR = 2,
|
||||||
FG_OPTIONS_EXIT = 3,
|
FG_OPTIONS_EXIT = 3,
|
||||||
FG_OPTIONS_VERBOSE_HELP = 4,
|
FG_OPTIONS_VERBOSE_HELP = 4,
|
||||||
FG_OPTIONS_SHOW_AIRCRAFT = 5
|
FG_OPTIONS_SHOW_AIRCRAFT = 5,
|
||||||
|
FG_OPTIONS_SHOW_SOUND_DEVICES = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
static double
|
static double
|
||||||
|
@ -186,7 +188,8 @@ fgSetDefaults ()
|
||||||
fgSetBool("/sim/hud/enable3d", true);
|
fgSetBool("/sim/hud/enable3d", true);
|
||||||
fgSetBool("/sim/hud/visibility", false);
|
fgSetBool("/sim/hud/visibility", false);
|
||||||
fgSetBool("/sim/panel/visibility", true);
|
fgSetBool("/sim/panel/visibility", true);
|
||||||
fgSetBool("/sim/sound/pause", false);
|
fgSetBool("/sim/sound/enabled", true);
|
||||||
|
fgSetBool("/sim/sound/working", true);
|
||||||
|
|
||||||
// Flight Model options
|
// Flight Model options
|
||||||
fgSetString("/sim/flight-model", "jsb");
|
fgSetString("/sim/flight-model", "jsb");
|
||||||
|
@ -201,7 +204,7 @@ fgSetDefaults ()
|
||||||
fgSetBool("/sim/rendering/shading", true);
|
fgSetBool("/sim/rendering/shading", true);
|
||||||
fgSetBool("/sim/rendering/skyblend", true);
|
fgSetBool("/sim/rendering/skyblend", true);
|
||||||
fgSetBool("/sim/rendering/textures", true);
|
fgSetBool("/sim/rendering/textures", true);
|
||||||
fgTie( "/sim/rendering/filtering", SGGetTextureFilter, SGSetTextureFilter, false);
|
fgTie( "/sim/rendering/filtering", SGGetTextureFilter, SGSetTextureFilter, false);
|
||||||
fgSetInt("/sim/rendering/filtering", 1);
|
fgSetInt("/sim/rendering/filtering", 1);
|
||||||
fgSetBool("/sim/rendering/wireframe", false);
|
fgSetBool("/sim/rendering/wireframe", false);
|
||||||
fgSetBool("/sim/rendering/horizon-effect", false);
|
fgSetBool("/sim/rendering/horizon-effect", false);
|
||||||
|
@ -1290,8 +1293,9 @@ struct OptionDesc {
|
||||||
{"enable-hud", false, OPTION_BOOL, "/sim/hud/visibility", true, "", 0 },
|
{"enable-hud", false, OPTION_BOOL, "/sim/hud/visibility", true, "", 0 },
|
||||||
{"disable-panel", false, OPTION_BOOL, "/sim/panel/visibility", false, "", 0 },
|
{"disable-panel", false, OPTION_BOOL, "/sim/panel/visibility", false, "", 0 },
|
||||||
{"enable-panel", false, OPTION_BOOL, "/sim/panel/visibility", true, "", 0 },
|
{"enable-panel", false, OPTION_BOOL, "/sim/panel/visibility", true, "", 0 },
|
||||||
{"disable-sound", false, OPTION_BOOL, "/sim/sound/pause", true, "", 0 },
|
{"disable-sound", false, OPTION_BOOL, "/sim/sound/working", false, "", 0 },
|
||||||
{"enable-sound", false, OPTION_BOOL, "/sim/sound/pause", false, "", 0 },
|
{"enable-sound", false, OPTION_BOOL, "/sim/sound/working", true, "", 0 },
|
||||||
|
{"sound-device", true, OPTION_STRING, "/sim/sound/device-name", false, "", 0 },
|
||||||
{"airport", true, OPTION_STRING, "/sim/presets/airport-id", false, "", 0 },
|
{"airport", true, OPTION_STRING, "/sim/presets/airport-id", false, "", 0 },
|
||||||
{"runway", true, OPTION_FUNC, "", false, "", fgOptRunway },
|
{"runway", true, OPTION_FUNC, "", false, "", fgOptRunway },
|
||||||
{"vor", true, OPTION_FUNC, "", false, "", fgOptVOR },
|
{"vor", true, OPTION_FUNC, "", false, "", fgOptVOR },
|
||||||
|
@ -1501,6 +1505,8 @@ parse_option (const string& arg)
|
||||||
return(FG_OPTIONS_VERBOSE_HELP);
|
return(FG_OPTIONS_VERBOSE_HELP);
|
||||||
} else if ( arg.find( "--show-aircraft") == 0) {
|
} else if ( arg.find( "--show-aircraft") == 0) {
|
||||||
return(FG_OPTIONS_SHOW_AIRCRAFT);
|
return(FG_OPTIONS_SHOW_AIRCRAFT);
|
||||||
|
} else if ( arg.find( "--show-sound-devices") == 0) {
|
||||||
|
return(FG_OPTIONS_SHOW_SOUND_DEVICES);
|
||||||
} else if ( arg.find( "--prop:" ) == 0 ) {
|
} else if ( arg.find( "--prop:" ) == 0 ) {
|
||||||
if (!set_property(arg.substr(7))) {
|
if (!set_property(arg.substr(7))) {
|
||||||
SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
|
SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
|
||||||
|
@ -1616,11 +1622,20 @@ fgParseArgs (int argc, char **argv)
|
||||||
verbose = true;
|
verbose = true;
|
||||||
|
|
||||||
else if (result == FG_OPTIONS_SHOW_AIRCRAFT) {
|
else if (result == FG_OPTIONS_SHOW_AIRCRAFT) {
|
||||||
fgOptLogLevel( "alert" );
|
fgOptLogLevel( "alert" );
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
path.append("Aircraft");
|
path.append("Aircraft");
|
||||||
fgShowAircraft(path, true);
|
fgShowAircraft(path, true);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
|
} else if (result == FG_OPTIONS_SHOW_SOUND_DEVICES) {
|
||||||
|
SGSoundMgr smgr;
|
||||||
|
vector <const char*>devices = smgr.get_available_devices();
|
||||||
|
for (int i=0; i<devices.size(); i++) {
|
||||||
|
printf("%i. \"%s\"\n", i, devices[i]);
|
||||||
|
}
|
||||||
|
devices.clear();
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (result == FG_OPTIONS_EXIT)
|
else if (result == FG_OPTIONS_EXIT)
|
||||||
|
|
|
@ -380,7 +380,7 @@ FGViewer::recalcLookFrom ()
|
||||||
SGQuatd hlToBody = SGQuatd::fromYawPitchRollDeg(head, pitch, roll);
|
SGQuatd hlToBody = SGQuatd::fromYawPitchRollDeg(head, pitch, roll);
|
||||||
|
|
||||||
// The rotation offset, don't know why heading is negative here ...
|
// The rotation offset, don't know why heading is negative here ...
|
||||||
SGQuatd viewOffsetOr
|
mViewOffsetOr
|
||||||
= SGQuatd::fromYawPitchRollDeg(-_heading_offset_deg, _pitch_offset_deg,
|
= SGQuatd::fromYawPitchRollDeg(-_heading_offset_deg, _pitch_offset_deg,
|
||||||
_roll_offset_deg);
|
_roll_offset_deg);
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ FGViewer::recalcLookFrom ()
|
||||||
SGQuatd q(-0.5, -0.5, 0.5, 0.5);
|
SGQuatd q(-0.5, -0.5, 0.5, 0.5);
|
||||||
|
|
||||||
_absolute_view_pos = position + (ec2body*q).backTransform(_offset_m);
|
_absolute_view_pos = position + (ec2body*q).backTransform(_offset_m);
|
||||||
mViewOrientation = ec2body*viewOffsetOr*q;
|
mViewOrientation = ec2body*mViewOffsetOr*q;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -437,7 +437,7 @@ FGViewer::recalcLookAt ()
|
||||||
SGQuatd geodEyeHlOr = SGQuatd::fromLonLat(_position);
|
SGQuatd geodEyeHlOr = SGQuatd::fromLonLat(_position);
|
||||||
|
|
||||||
// the rotation offset, don't know why heading is negative here ...
|
// the rotation offset, don't know why heading is negative here ...
|
||||||
SGQuatd eyeOffsetOr =
|
mViewOffsetOr =
|
||||||
SGQuatd::fromYawPitchRollDeg(-_heading_offset_deg + 180, _pitch_offset_deg,
|
SGQuatd::fromYawPitchRollDeg(-_heading_offset_deg + 180, _pitch_offset_deg,
|
||||||
_roll_offset_deg);
|
_roll_offset_deg);
|
||||||
|
|
||||||
|
@ -445,7 +445,7 @@ FGViewer::recalcLookAt ()
|
||||||
SGVec3d eyeOff(-_offset_m.z(), _offset_m.x(), -_offset_m.y());
|
SGVec3d eyeOff(-_offset_m.z(), _offset_m.x(), -_offset_m.y());
|
||||||
SGQuatd ec2eye = geodEyeHlOr*geodEyeOr;
|
SGQuatd ec2eye = geodEyeHlOr*geodEyeOr;
|
||||||
SGVec3d eyeCart = SGVec3d::fromGeod(_position);
|
SGVec3d eyeCart = SGVec3d::fromGeod(_position);
|
||||||
eyeCart += (ec2eye*eyeOffsetOr).backTransform(eyeOff);
|
eyeCart += (ec2eye*mViewOffsetOr).backTransform(eyeOff);
|
||||||
|
|
||||||
SGVec3d atCart = SGVec3d::fromGeod(_target);
|
SGVec3d atCart = SGVec3d::fromGeod(_target);
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,7 @@ public:
|
||||||
// orientation rotations listed below. This has the effect of the
|
// orientation rotations listed below. This has the effect of the
|
||||||
// eye moving around and "looking at" the object (model) from
|
// eye moving around and "looking at" the object (model) from
|
||||||
// different angles.
|
// different angles.
|
||||||
|
virtual SGVec3d getOffset_m () const { return _offset_m; }
|
||||||
virtual double getXOffset_m () const { return _offset_m.x(); }
|
virtual double getXOffset_m () const { return _offset_m.x(); }
|
||||||
virtual double getYOffset_m () const { return _offset_m.y(); }
|
virtual double getYOffset_m () const { return _offset_m.y(); }
|
||||||
virtual double getZOffset_m () const { return _offset_m.z(); }
|
virtual double getZOffset_m () const { return _offset_m.z(); }
|
||||||
|
@ -201,6 +202,7 @@ public:
|
||||||
const SGVec3d& get_view_pos() { if ( _dirty ) { recalc(); } return _absolute_view_pos; }
|
const SGVec3d& get_view_pos() { if ( _dirty ) { recalc(); } return _absolute_view_pos; }
|
||||||
const SGVec3d& getViewPosition() { if ( _dirty ) { recalc(); } return _absolute_view_pos; }
|
const SGVec3d& getViewPosition() { if ( _dirty ) { recalc(); } return _absolute_view_pos; }
|
||||||
const SGQuatd& getViewOrientation() { if ( _dirty ) { recalc(); } return mViewOrientation; }
|
const SGQuatd& getViewOrientation() { if ( _dirty ) { recalc(); } return mViewOrientation; }
|
||||||
|
const SGQuatd& getViewOrientationOffset() { if ( _dirty ) { recalc(); } return mViewOffsetOr; }
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Part 4: View and frustrum data setters and getters
|
// Part 4: View and frustrum data setters and getters
|
||||||
|
@ -247,6 +249,7 @@ private:
|
||||||
bool _dirty;
|
bool _dirty;
|
||||||
|
|
||||||
SGQuatd mViewOrientation;
|
SGQuatd mViewOrientation;
|
||||||
|
SGQuatd mViewOffsetOr;
|
||||||
SGVec3d _absolute_view_pos;
|
SGVec3d _absolute_view_pos;
|
||||||
|
|
||||||
SGGeod _position;
|
SGGeod _position;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <string.h> // strcmp
|
#include <string.h> // strcmp
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
#include <Model/acmodel.hxx>
|
#include <Model/acmodel.hxx>
|
||||||
#include <Main/viewer.hxx>
|
#include <Main/viewer.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
|
@ -42,6 +43,7 @@ FGViewMgr::FGViewMgr( void ) :
|
||||||
config_list(fgGetNode("/sim", true)->getChildren("view")),
|
config_list(fgGetNode("/sim", true)->getChildren("view")),
|
||||||
current(0)
|
current(0)
|
||||||
{
|
{
|
||||||
|
smgr = globals->get_soundmgr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
|
@ -214,6 +216,38 @@ FGViewMgr::bind ()
|
||||||
n->tie("viewer-x-m", SGRawValuePointer<double>(&abs_viewer_position[0]));
|
n->tie("viewer-x-m", SGRawValuePointer<double>(&abs_viewer_position[0]));
|
||||||
n->tie("viewer-y-m", SGRawValuePointer<double>(&abs_viewer_position[1]));
|
n->tie("viewer-y-m", SGRawValuePointer<double>(&abs_viewer_position[1]));
|
||||||
n->tie("viewer-z-m", SGRawValuePointer<double>(&abs_viewer_position[2]));
|
n->tie("viewer-z-m", SGRawValuePointer<double>(&abs_viewer_position[2]));
|
||||||
|
|
||||||
|
// for automatic untying:
|
||||||
|
#define x(str) ((void)tied_props.push_back(str), str)
|
||||||
|
|
||||||
|
fgTie(x("/sim/current-view/debug/orientation-w"), this,
|
||||||
|
&FGViewMgr::getCurrentViewOrientation_w);
|
||||||
|
fgTie(x("/sim/current-view/debug/orientation-x"), this,
|
||||||
|
&FGViewMgr::getCurrentViewOrientation_x);
|
||||||
|
fgTie(x("/sim/current-view/debug/orientation-y"), this,
|
||||||
|
&FGViewMgr::getCurrentViewOrientation_y);
|
||||||
|
fgTie(x("/sim/current-view/debug/orientation-z"), this,
|
||||||
|
&FGViewMgr::getCurrentViewOrientation_z);
|
||||||
|
|
||||||
|
fgTie(x("/sim/current-view/debug/orientation_offset-w"), this,
|
||||||
|
&FGViewMgr::getCurrentViewOrOffset_w);
|
||||||
|
fgTie(x("/sim/current-view/debug/orientation_offset-x"), this,
|
||||||
|
&FGViewMgr::getCurrentViewOrOffset_x);
|
||||||
|
fgTie(x("/sim/current-view/debug/orientation_offset-y"), this,
|
||||||
|
&FGViewMgr::getCurrentViewOrOffset_y);
|
||||||
|
fgTie(x("/sim/current-view/debug/orientation_offset-z"), this,
|
||||||
|
&FGViewMgr::getCurrentViewOrOffset_z);
|
||||||
|
|
||||||
|
fgTie(x("/sim/current-view/debug/frame-w"), this,
|
||||||
|
&FGViewMgr::getCurrentViewFrame_w);
|
||||||
|
fgTie(x("/sim/current-view/debug/frame-x"), this,
|
||||||
|
&FGViewMgr::getCurrentViewFrame_x);
|
||||||
|
fgTie(x("/sim/current-view/debug/frame-y"), this,
|
||||||
|
&FGViewMgr::getCurrentViewFrame_y);
|
||||||
|
fgTie(x("/sim/current-view/debug/frame-z"), this,
|
||||||
|
&FGViewMgr::getCurrentViewFrame_z);
|
||||||
|
|
||||||
|
#undef x
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -234,16 +268,21 @@ FGViewMgr::unbind ()
|
||||||
fgUntie("/sim/current-view/viewer-x-m");
|
fgUntie("/sim/current-view/viewer-x-m");
|
||||||
fgUntie("/sim/current-view/viewer-y-m");
|
fgUntie("/sim/current-view/viewer-y-m");
|
||||||
fgUntie("/sim/current-view/viewer-z-m");
|
fgUntie("/sim/current-view/viewer-z-m");
|
||||||
|
|
||||||
|
list<const char*>::const_iterator it;
|
||||||
|
for (it = tied_props.begin(); it != tied_props.end(); it++){
|
||||||
|
fgUntie(*it);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FGViewMgr::update (double dt)
|
FGViewMgr::update (double dt)
|
||||||
{
|
{
|
||||||
FGViewer * view = get_current_view();
|
|
||||||
if (view == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FGViewer *loop_view = (FGViewer *)get_view(current);
|
FGViewer *loop_view = (FGViewer *)get_current_view();
|
||||||
|
if (loop_view == 0) return;
|
||||||
|
|
||||||
SGPropertyNode *n = config_list[current];
|
SGPropertyNode *n = config_list[current];
|
||||||
double lon_deg, lat_deg, alt_ft, roll_deg, pitch_deg, heading_deg;
|
double lon_deg, lat_deg, alt_ft, roll_deg, pitch_deg, heading_deg;
|
||||||
|
|
||||||
|
@ -289,10 +328,25 @@ FGViewMgr::update (double dt)
|
||||||
setViewTargetYOffset_m(fgGetDouble("/sim/current-view/target-y-offset-m"));
|
setViewTargetYOffset_m(fgGetDouble("/sim/current-view/target-y-offset-m"));
|
||||||
setViewTargetZOffset_m(fgGetDouble("/sim/current-view/target-z-offset-m"));
|
setViewTargetZOffset_m(fgGetDouble("/sim/current-view/target-z-offset-m"));
|
||||||
|
|
||||||
|
current_view_orientation = loop_view->getViewOrientation();
|
||||||
|
current_view_or_offset = loop_view->getViewOrientationOffset();
|
||||||
|
|
||||||
// Update the current view
|
// Update the current view
|
||||||
do_axes();
|
do_axes();
|
||||||
view->update(dt);
|
loop_view->update(dt);
|
||||||
abs_viewer_position = loop_view->getViewPosition();
|
abs_viewer_position = loop_view->getViewPosition();
|
||||||
|
|
||||||
|
// update audio listener values
|
||||||
|
// set the viewer posotion in Cartesian coordinates in meters
|
||||||
|
smgr->set_position( abs_viewer_position, loop_view->getPosition() );
|
||||||
|
smgr->set_orientation( current_view_orientation );
|
||||||
|
|
||||||
|
// get the model velocity
|
||||||
|
SGVec3d velocity = SGVec3d::zeros();
|
||||||
|
if ( !stationary() ) {
|
||||||
|
velocity = globals->get_aircraft_model()->getVelocity();
|
||||||
|
}
|
||||||
|
smgr->set_velocity( velocity );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -562,6 +616,20 @@ FGViewMgr::setViewZOffset_m (double z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGViewMgr::stationary () const
|
||||||
|
{
|
||||||
|
const FGViewer * view = get_current_view();
|
||||||
|
if (view != 0) {
|
||||||
|
if (((FGViewer *)view)->getXOffset_m() == 0.0 &&
|
||||||
|
((FGViewer *)view)->getYOffset_m() == 0.0 &&
|
||||||
|
((FGViewer *)view)->getZOffset_m() == 0.0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
FGViewMgr::getViewTargetXOffset_m () const
|
FGViewMgr::getViewTargetXOffset_m () const
|
||||||
{
|
{
|
||||||
|
@ -720,6 +788,101 @@ FGViewMgr::setViewAxisLat (double axis)
|
||||||
axis_lat = axis;
|
axis_lat = axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reference frame orientation.
|
||||||
|
// This is the view orientation you get when you have no
|
||||||
|
// view offset, i.e. the offset operator is the identity.
|
||||||
|
//
|
||||||
|
// For example, in the familiar "cockpit lookfrom" view,
|
||||||
|
// the reference frame is equal to the aircraft attitude,
|
||||||
|
// i.e. it is the view looking towards 12:00 straight ahead.
|
||||||
|
//
|
||||||
|
// FIXME: Somebody needs to figure out what is the reference
|
||||||
|
// frame view for the other view modes.
|
||||||
|
//
|
||||||
|
// Conceptually, this quat represents a rotation relative
|
||||||
|
// to the ECEF reference orientation, as described at
|
||||||
|
// http://www.av8n.com/physics/coords.htm#sec-orientation
|
||||||
|
//
|
||||||
|
// See the NOTE concerning reference orientations, below.
|
||||||
|
//
|
||||||
|
// The components of this quat are expressed in
|
||||||
|
// the conventional aviation basis set,
|
||||||
|
// i.e. x=forward, y=starboard, z=bottom
|
||||||
|
double FGViewMgr::getCurrentViewFrame_w() const{
|
||||||
|
return ((current_view_orientation*conj(fsb2sta())*conj(current_view_or_offset))).w();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewFrame_x() const{
|
||||||
|
return ((current_view_orientation*conj(fsb2sta())*conj(current_view_or_offset))).x();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewFrame_y() const{
|
||||||
|
return ((current_view_orientation*conj(fsb2sta())*conj(current_view_or_offset))).y();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewFrame_z() const{
|
||||||
|
return ((current_view_orientation*conj(fsb2sta())*conj(current_view_or_offset))).z();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// view offset.
|
||||||
|
// This rotation takes you from the aforementioned
|
||||||
|
// reference frame view orientation to whatever
|
||||||
|
// actual current view orientation is.
|
||||||
|
//
|
||||||
|
// The components of this quaternion are expressed in
|
||||||
|
// the conventional aviation basis set,
|
||||||
|
// i.e. x=forward, y=starboard, z=bottom
|
||||||
|
double FGViewMgr::getCurrentViewOrOffset_w() const{
|
||||||
|
return current_view_or_offset.w();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewOrOffset_x() const{
|
||||||
|
return current_view_or_offset.x();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewOrOffset_y() const{
|
||||||
|
return current_view_or_offset.y();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewOrOffset_z() const{
|
||||||
|
return current_view_or_offset.z();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// current view orientation.
|
||||||
|
// This is a rotation relative to the earth-centered (ec)
|
||||||
|
// reference frame.
|
||||||
|
//
|
||||||
|
// NOTE: Here we remove a factor of fsb2sta so that
|
||||||
|
// the components of this quat are displayed using the
|
||||||
|
// conventional ECEF basis set. This is *not* the way
|
||||||
|
// the view orientation is stored in the views[] array,
|
||||||
|
// but is easier for non-graphics hackers to understand.
|
||||||
|
// If we did not remove this factor of fsb2sta here and
|
||||||
|
// in getCurrentViewFrame, that would be equivalent to
|
||||||
|
// the following peculiar reference orientation:
|
||||||
|
// Suppose you are over the Gulf of Guinea, at (lat,lon) = (0,0).
|
||||||
|
// Then the reference frame orientation can be achieved via:
|
||||||
|
// -- The aircraft X-axis (nose) headed south.
|
||||||
|
// -- The aircraft Y-axis (starboard wingtip) pointing up.
|
||||||
|
// -- The aircraft Z-axis (belly) pointing west.
|
||||||
|
// To say the same thing in other words, and perhaps more to the
|
||||||
|
// point: If we use the OpenGL camera orientation conventions,
|
||||||
|
// i.e. Xprime=starboard, Yprime=top, Zprime=aft, then the
|
||||||
|
// aforementioned peculiar reference orientation at (lat,lon)
|
||||||
|
// = (0,0) can be described as:
|
||||||
|
// -- aircraft Xprime axis (starboard) pointed up
|
||||||
|
// -- aircraft Yprime axis (top) pointed east
|
||||||
|
// -- aircraft Zprime axis (aft) pointed north
|
||||||
|
// meaning the OpenGL axes are aligned with the ECEF axes.
|
||||||
|
double FGViewMgr::getCurrentViewOrientation_w() const{
|
||||||
|
return (current_view_orientation * conj(fsb2sta())).w();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewOrientation_x() const{
|
||||||
|
return (current_view_orientation * conj(fsb2sta())).x();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewOrientation_y() const{
|
||||||
|
return (current_view_orientation * conj(fsb2sta())).y();
|
||||||
|
}
|
||||||
|
double FGViewMgr::getCurrentViewOrientation_z() const{
|
||||||
|
return (current_view_orientation * conj(fsb2sta())).z();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FGViewMgr::do_axes ()
|
FGViewMgr::do_axes ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define _VIEWMGR_HXX
|
#define _VIEWMGR_HXX
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
|
|
||||||
// forward decls
|
// forward decls
|
||||||
class FGViewer;
|
class FGViewer;
|
||||||
|
class SGSoundMgr;
|
||||||
typedef SGSharedPtr<FGViewer> FGViewerPtr;
|
typedef SGSharedPtr<FGViewer> FGViewerPtr;
|
||||||
|
|
||||||
// Define a structure containing view information
|
// Define a structure containing view information
|
||||||
|
@ -75,6 +77,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
list<const char*> tied_props;
|
||||||
|
|
||||||
double axis_long;
|
double axis_long;
|
||||||
double axis_lat;
|
double axis_lat;
|
||||||
|
|
||||||
|
@ -116,6 +120,22 @@ private:
|
||||||
int getView () const;
|
int getView () const;
|
||||||
void setView (int newview);
|
void setView (int newview);
|
||||||
|
|
||||||
|
// quaternion accessors, for debugging:
|
||||||
|
double getCurrentViewOrientation_w() const;
|
||||||
|
double getCurrentViewOrientation_x() const;
|
||||||
|
double getCurrentViewOrientation_y() const;
|
||||||
|
double getCurrentViewOrientation_z() const;
|
||||||
|
double getCurrentViewOrOffset_w() const;
|
||||||
|
double getCurrentViewOrOffset_x() const;
|
||||||
|
double getCurrentViewOrOffset_y() const;
|
||||||
|
double getCurrentViewOrOffset_z() const;
|
||||||
|
double getCurrentViewFrame_w() const;
|
||||||
|
double getCurrentViewFrame_x() const;
|
||||||
|
double getCurrentViewFrame_y() const;
|
||||||
|
double getCurrentViewFrame_z() const;
|
||||||
|
|
||||||
|
bool stationary () const;
|
||||||
|
|
||||||
SGPropertyNode_ptr view_number;
|
SGPropertyNode_ptr view_number;
|
||||||
vector<SGPropertyNode_ptr> config_list;
|
vector<SGPropertyNode_ptr> config_list;
|
||||||
typedef std::vector<FGViewerPtr> viewer_list;
|
typedef std::vector<FGViewerPtr> viewer_list;
|
||||||
|
@ -123,8 +143,20 @@ private:
|
||||||
SGVec3d abs_viewer_position;
|
SGVec3d abs_viewer_position;
|
||||||
|
|
||||||
int current;
|
int current;
|
||||||
|
SGQuatd current_view_orientation, current_view_or_offset;
|
||||||
|
|
||||||
|
SGSoundMgr *smgr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This takes the conventional aviation XYZ body system
|
||||||
|
// i.e. x=forward, y=starboard, z=bottom
|
||||||
|
// which is widely used in FGFS
|
||||||
|
// and rotates it into the OpenGL camera system
|
||||||
|
// i.e. Xprime=starboard, Yprime=top, Zprime=aft.
|
||||||
|
inline const SGQuatd fsb2sta()
|
||||||
|
{
|
||||||
|
return SGQuatd(-0.5, -0.5, 0.5, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _VIEWMGR_HXX
|
#endif // _VIEWMGR_HXX
|
||||||
|
|
|
@ -22,19 +22,35 @@
|
||||||
#include <Main/viewmgr.hxx>
|
#include <Main/viewmgr.hxx>
|
||||||
#include <Main/viewer.hxx>
|
#include <Main/viewer.hxx>
|
||||||
#include <Scenery/scenery.hxx>
|
#include <Scenery/scenery.hxx>
|
||||||
|
#include <Sound/fg_fx.hxx>
|
||||||
|
|
||||||
#include "model_panel.hxx"
|
#include "model_panel.hxx"
|
||||||
|
|
||||||
#include "acmodel.hxx"
|
#include "acmodel.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Implementation of FGAircraftModel
|
// Implementation of FGAircraftModel
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FGAircraftModel::FGAircraftModel ()
|
FGAircraftModel::FGAircraftModel ()
|
||||||
: _aircraft(0)
|
: _aircraft(0),
|
||||||
|
_velocity(SGVec3d::zeros()),
|
||||||
|
_fx(0),
|
||||||
|
_lon(0),
|
||||||
|
_lat(0),
|
||||||
|
_alt(0),
|
||||||
|
_pitch(0),
|
||||||
|
_roll(0),
|
||||||
|
_heading(0),
|
||||||
|
_speed_n(0),
|
||||||
|
_speed_e(0),
|
||||||
|
_speed_d(0)
|
||||||
{
|
{
|
||||||
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||||
|
_fx = new FGFX(smgr, "fx");
|
||||||
|
_fx->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
FGAircraftModel::~FGAircraftModel ()
|
FGAircraftModel::~FGAircraftModel ()
|
||||||
|
@ -70,7 +86,15 @@ FGAircraftModel::init ()
|
||||||
void
|
void
|
||||||
FGAircraftModel::bind ()
|
FGAircraftModel::bind ()
|
||||||
{
|
{
|
||||||
// No-op
|
_lon = fgGetNode("position/longitude-deg", true);
|
||||||
|
_lat = fgGetNode("position/latitude-deg", true);
|
||||||
|
_alt = fgGetNode("position/altitude-ft", true);
|
||||||
|
_pitch = fgGetNode("orientation/pitch-deg", true);
|
||||||
|
_roll = fgGetNode("orientation/roll-deg", true);
|
||||||
|
_heading = fgGetNode("orientation/heading-deg", true);
|
||||||
|
_speed_n = fgGetNode("velocities/speed-north-fps", true);
|
||||||
|
_speed_e = fgGetNode("velocities/speed-east-fps", true);
|
||||||
|
_speed_d = fgGetNode("velocities/speed-down-fps", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -91,13 +115,27 @@ FGAircraftModel::update (double dt)
|
||||||
_aircraft->setVisible(true);
|
_aircraft->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_aircraft->setPosition(fgGetDouble("/position/longitude-deg"),
|
_aircraft->setPosition(_lon->getDoubleValue(),
|
||||||
fgGetDouble("/position/latitude-deg"),
|
_lat->getDoubleValue(),
|
||||||
fgGetDouble("/position/altitude-ft"));
|
_alt->getDoubleValue());
|
||||||
_aircraft->setOrientation(fgGetDouble("/orientation/roll-deg"),
|
_aircraft->setOrientation(_roll->getDoubleValue(),
|
||||||
fgGetDouble("/orientation/pitch-deg"),
|
_pitch->getDoubleValue(),
|
||||||
fgGetDouble("/orientation/heading-deg"));
|
_heading->getDoubleValue());
|
||||||
_aircraft->update();
|
_aircraft->update();
|
||||||
|
|
||||||
|
// update model's audio sample values
|
||||||
|
SGGeod position = _aircraft->getPosition();
|
||||||
|
_fx->set_position_geod( position );
|
||||||
|
|
||||||
|
SGQuatd orient = SGQuatd::fromYawPitchRollDeg(_heading->getDoubleValue(),
|
||||||
|
_pitch->getDoubleValue(),
|
||||||
|
_roll->getDoubleValue());
|
||||||
|
_fx->set_orientation( orient );
|
||||||
|
|
||||||
|
_velocity = SGVec3d( _speed_n->getDoubleValue(),
|
||||||
|
_speed_e->getDoubleValue(),
|
||||||
|
_speed_d->getDoubleValue() );
|
||||||
|
_fx->set_velocity( _velocity );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ using std::vector;
|
||||||
|
|
||||||
// Don't pull in the headers, since we don't need them here.
|
// Don't pull in the headers, since we don't need them here.
|
||||||
class SGModelPlacement;
|
class SGModelPlacement;
|
||||||
|
class FGFX;
|
||||||
|
|
||||||
class FGAircraftModel : public SGSubsystem
|
class FGAircraftModel : public SGSubsystem
|
||||||
{
|
{
|
||||||
|
@ -39,10 +39,23 @@ public:
|
||||||
virtual void unbind ();
|
virtual void unbind ();
|
||||||
virtual void update (double dt);
|
virtual void update (double dt);
|
||||||
virtual SGModelPlacement * get3DModel() { return _aircraft; }
|
virtual SGModelPlacement * get3DModel() { return _aircraft; }
|
||||||
|
virtual SGVec3d& getVelocity() { return _velocity; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SGModelPlacement * _aircraft;
|
SGModelPlacement * _aircraft;
|
||||||
|
SGVec3d _velocity;
|
||||||
|
SGSharedPtr<FGFX> _fx;
|
||||||
|
|
||||||
|
SGPropertyNode_ptr _lon;
|
||||||
|
SGPropertyNode_ptr _lat;
|
||||||
|
SGPropertyNode_ptr _alt;
|
||||||
|
SGPropertyNode_ptr _pitch;
|
||||||
|
SGPropertyNode_ptr _roll;
|
||||||
|
SGPropertyNode_ptr _heading;
|
||||||
|
SGPropertyNode_ptr _speed_n;
|
||||||
|
SGPropertyNode_ptr _speed_e;
|
||||||
|
SGPropertyNode_ptr _speed_d;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __ACMODEL_HXX
|
#endif // __ACMODEL_HXX
|
||||||
|
|
|
@ -4,6 +4,7 @@ libSound_a_SOURCES = \
|
||||||
beacon.cxx beacon.hxx \
|
beacon.cxx beacon.hxx \
|
||||||
fg_fx.cxx fg_fx.hxx \
|
fg_fx.cxx fg_fx.hxx \
|
||||||
morse.cxx morse.hxx \
|
morse.cxx morse.hxx \
|
||||||
voice.cxx voice.hxx
|
voice.cxx voice.hxx \
|
||||||
|
sample_queue.cxx sample_queue.hxx
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
||||||
|
|
|
@ -21,11 +21,11 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "beacon.hxx"
|
#include "beacon.hxx"
|
||||||
|
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
|
||||||
#include <Main/globals.hxx>
|
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
FGBeacon::FGBeacon()
|
FGBeacon::FGBeacon()
|
||||||
|
@ -39,17 +39,12 @@ FGBeacon::~FGBeacon() {
|
||||||
|
|
||||||
// allocate and initialize sound samples
|
// allocate and initialize sound samples
|
||||||
bool FGBeacon::init() {
|
bool FGBeacon::init() {
|
||||||
int i;
|
|
||||||
int len;
|
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
|
size_t i, len;
|
||||||
|
|
||||||
if (globals->get_soundmgr()->is_working() == false) {
|
const unsigned char* inner_buf = (const unsigned char*)malloc( INNER_SIZE );
|
||||||
return false;
|
const unsigned char* middle_buf = (const unsigned char*)malloc(MIDDLE_SIZE);
|
||||||
}
|
const unsigned char* outer_buf = (const unsigned char*)malloc( OUTER_SIZE );
|
||||||
|
|
||||||
unsigned char inner_buf[ INNER_SIZE ] ;
|
|
||||||
unsigned char middle_buf[ MIDDLE_SIZE ] ;
|
|
||||||
unsigned char outer_buf[ OUTER_SIZE ] ;
|
|
||||||
|
|
||||||
// Make inner marker beacon sound
|
// Make inner marker beacon sound
|
||||||
len= (int)(INNER_DIT_LEN / 2.0 );
|
len= (int)(INNER_DIT_LEN / 2.0 );
|
||||||
|
@ -57,14 +52,14 @@ bool FGBeacon::init() {
|
||||||
make_tone( inner_dit, INNER_FREQ, len, INNER_DIT_LEN,
|
make_tone( inner_dit, INNER_FREQ, len, INNER_DIT_LEN,
|
||||||
TRANSITION_BYTES );
|
TRANSITION_BYTES );
|
||||||
|
|
||||||
ptr = inner_buf;
|
ptr = (unsigned char*)inner_buf;
|
||||||
for ( i = 0; i < 6; ++i ) {
|
for ( i = 0; i < 6; ++i ) {
|
||||||
memcpy( ptr, inner_dit, INNER_DIT_LEN );
|
memcpy( ptr, inner_dit, INNER_DIT_LEN );
|
||||||
ptr += INNER_DIT_LEN;
|
ptr += INNER_DIT_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inner = new SGSoundSample( inner_buf, INNER_SIZE, BYTES_PER_SECOND );
|
inner = new SGSoundSample( &inner_buf, INNER_SIZE, BYTES_PER_SECOND );
|
||||||
inner->set_reference_dist( 10.0 );
|
inner->set_reference_dist( 10.0 );
|
||||||
inner->set_max_dist( 20.0 );
|
inner->set_max_dist( 20.0 );
|
||||||
|
|
||||||
|
@ -79,12 +74,12 @@ bool FGBeacon::init() {
|
||||||
make_tone( middle_dah, MIDDLE_FREQ, len, MIDDLE_DAH_LEN,
|
make_tone( middle_dah, MIDDLE_FREQ, len, MIDDLE_DAH_LEN,
|
||||||
TRANSITION_BYTES );
|
TRANSITION_BYTES );
|
||||||
|
|
||||||
ptr = middle_buf;
|
ptr = (unsigned char*)middle_buf;
|
||||||
memcpy( ptr, middle_dit, MIDDLE_DIT_LEN );
|
memcpy( ptr, middle_dit, MIDDLE_DIT_LEN );
|
||||||
ptr += MIDDLE_DIT_LEN;
|
ptr += MIDDLE_DIT_LEN;
|
||||||
memcpy( ptr, middle_dah, MIDDLE_DAH_LEN );
|
memcpy( ptr, middle_dah, MIDDLE_DAH_LEN );
|
||||||
|
|
||||||
middle = new SGSoundSample( middle_buf, MIDDLE_SIZE, BYTES_PER_SECOND );
|
middle = new SGSoundSample( &middle_buf, MIDDLE_SIZE, BYTES_PER_SECOND);
|
||||||
middle->set_reference_dist( 10.0 );
|
middle->set_reference_dist( 10.0 );
|
||||||
middle->set_max_dist( 20.0 );
|
middle->set_max_dist( 20.0 );
|
||||||
|
|
||||||
|
@ -94,12 +89,12 @@ bool FGBeacon::init() {
|
||||||
make_tone( outer_dah, OUTER_FREQ, len, OUTER_DAH_LEN,
|
make_tone( outer_dah, OUTER_FREQ, len, OUTER_DAH_LEN,
|
||||||
TRANSITION_BYTES );
|
TRANSITION_BYTES );
|
||||||
|
|
||||||
ptr = outer_buf;
|
ptr = (unsigned char*)outer_buf;
|
||||||
memcpy( ptr, outer_dah, OUTER_DAH_LEN );
|
memcpy( ptr, outer_dah, OUTER_DAH_LEN );
|
||||||
ptr += OUTER_DAH_LEN;
|
ptr += OUTER_DAH_LEN;
|
||||||
memcpy( ptr, outer_dah, OUTER_DAH_LEN );
|
memcpy( ptr, outer_dah, OUTER_DAH_LEN );
|
||||||
|
|
||||||
outer = new SGSoundSample( outer_buf, OUTER_SIZE, BYTES_PER_SECOND);
|
outer = new SGSoundSample( &outer_buf, OUTER_SIZE, BYTES_PER_SECOND );
|
||||||
outer->set_reference_dist( 10.0 );
|
outer->set_reference_dist( 10.0 );
|
||||||
outer->set_max_dist( 20.0 );
|
outer->set_max_dist( 20.0 );
|
||||||
} catch ( sg_io_exception &e ) {
|
} catch ( sg_io_exception &e ) {
|
||||||
|
|
|
@ -31,43 +31,38 @@
|
||||||
|
|
||||||
#include "fg_fx.hxx"
|
#include "fg_fx.hxx"
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
|
||||||
#include <simgear/structure/exception.hxx>
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
|
||||||
#include <simgear/props/props.hxx>
|
|
||||||
#include <simgear/sound/xmlsound.hxx>
|
|
||||||
#include <simgear/sound/soundmgr_openal.hxx>
|
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
|
|
||||||
#include <simgear/scene/model/placement.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
#include <Model/acmodel.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <Main/viewer.hxx>
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
|
#include <simgear/sound/xmlsound.hxx>
|
||||||
|
|
||||||
FGFX::FGFX () :
|
FGFX::FGFX ( SGSoundMgr *smgr, const string &refname ) :
|
||||||
last_visitor_pos(SGVec3d::zeros()),
|
_enabled( fgGetNode("/sim/sound/effects/enabled", true) ),
|
||||||
last_model_pos(SGVec3d::zeros()),
|
_volume( fgGetNode("/sim/sound/effects/volume", true) ),
|
||||||
last_pause( true ),
|
_avionics_enabled( fgGetNode("/sim/sound/avionics/enabled", true) ),
|
||||||
last_volume( 0.0 ),
|
_avionics_volume( fgGetNode("/sim/sound/avionics/volume", true) ),
|
||||||
_pause( fgGetNode("/sim/sound/pause") ),
|
_avionics_external( fgGetNode("/sim/sound/avionics/external-view", true) ),
|
||||||
_volume( fgGetNode("/sim/sound/volume") )
|
_internal( fgGetNode("/sim/current-view/internal", true) )
|
||||||
{
|
{
|
||||||
|
SGSampleGroup::_smgr = smgr;
|
||||||
|
SGSampleGroup::_refname = refname;
|
||||||
|
SGSampleGroup::_smgr->add(this, refname);
|
||||||
|
_avionics = _smgr->find("avionics", true);
|
||||||
|
_avionics->tie_to_listener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FGFX::~FGFX ()
|
FGFX::~FGFX ()
|
||||||
{
|
{
|
||||||
unsigned int i;
|
for (unsigned int i = 0; i < _sound.size(); i++ ) {
|
||||||
for ( i = 0; i < _sound.size(); i++ ) {
|
|
||||||
delete _sound[i];
|
delete _sound[i];
|
||||||
}
|
}
|
||||||
_sound.clear();
|
_sound.clear();
|
||||||
|
|
||||||
while ( _samplequeue.size() > 0 ) {
|
|
||||||
delete _samplequeue.front();
|
|
||||||
_samplequeue.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGFX::init()
|
FGFX::init()
|
||||||
{
|
{
|
||||||
|
@ -99,8 +94,8 @@ FGFX::init()
|
||||||
SGXmlSound *sound = new SGXmlSound();
|
SGXmlSound *sound = new SGXmlSound();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sound->init(globals->get_props(), node->getChild(i),
|
sound->init(globals->get_props(), node->getChild(i), this,
|
||||||
globals->get_soundmgr(), globals->get_fg_root());
|
_avionics, globals->get_fg_root());
|
||||||
|
|
||||||
_sound.push_back(sound);
|
_sound.push_back(sound);
|
||||||
} catch ( sg_exception &e ) {
|
} catch ( sg_exception &e ) {
|
||||||
|
@ -111,192 +106,40 @@ FGFX::init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGFX::reinit()
|
FGFX::reinit()
|
||||||
{
|
{
|
||||||
_sound.clear();
|
_sound.clear();
|
||||||
init();
|
init();
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
|
||||||
FGFX::bind ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FGFX::unbind ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGFX::update (double dt)
|
FGFX::update (double dt)
|
||||||
{
|
{
|
||||||
SGSoundMgr *smgr = globals->get_soundmgr();
|
bool active = _avionics_external->getBoolValue() ||
|
||||||
|
_internal->getBoolValue();
|
||||||
|
|
||||||
if (smgr->is_working() == false) {
|
if ( active && _avionics_enabled->getBoolValue() )
|
||||||
return;
|
_avionics->resume(); // no-op if already in resumed state
|
||||||
}
|
else
|
||||||
|
_avionics->suspend();
|
||||||
|
_avionics->set_volume( _avionics_volume->getFloatValue() );
|
||||||
|
|
||||||
// command sound manger
|
if ( _enabled->getBoolValue() ) {
|
||||||
bool pause = _pause->getBoolValue();
|
set_volume( _volume->getDoubleValue() );
|
||||||
if ( pause != last_pause ) {
|
resume();
|
||||||
if ( pause ) {
|
|
||||||
smgr->pause();
|
|
||||||
} else {
|
|
||||||
smgr->resume();
|
|
||||||
}
|
|
||||||
last_pause = pause;
|
|
||||||
}
|
|
||||||
|
|
||||||
// process mesage queue
|
|
||||||
const string msgid = "Sequential Audio Message";
|
|
||||||
bool is_playing = false;
|
|
||||||
if ( smgr->exists( msgid ) ) {
|
|
||||||
if ( smgr->is_playing( msgid ) ) {
|
|
||||||
// still playing, do nothing
|
|
||||||
is_playing = true;
|
|
||||||
} else {
|
|
||||||
// current message finished, stop and remove
|
|
||||||
smgr->stop( msgid ); // removes source
|
|
||||||
smgr->remove( msgid ); // removes buffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !is_playing ) {
|
|
||||||
// message queue idle, add next sound if we have one
|
|
||||||
if ( _samplequeue.size() > 0 ) {
|
|
||||||
smgr->add( _samplequeue.front(), msgid );
|
|
||||||
_samplequeue.pop();
|
|
||||||
smgr->play_once( msgid );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double volume = _volume->getDoubleValue();
|
|
||||||
if ( volume != last_volume ) {
|
|
||||||
smgr->set_volume( volume );
|
|
||||||
last_volume = volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !pause ) {
|
|
||||||
// update sound effects if not paused
|
// update sound effects if not paused
|
||||||
for ( unsigned int i = 0; i < _sound.size(); i++ ) {
|
for ( unsigned int i = 0; i < _sound.size(); i++ ) {
|
||||||
_sound[i]->update(dt);
|
_sound[i]->update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SGSampleGroup::update(dt);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
suspend();
|
||||||
void
|
|
||||||
FGFX::update_fx_late(double dt)
|
|
||||||
{
|
|
||||||
SGSoundMgr *smgr = globals->get_soundmgr();
|
|
||||||
if (!smgr->is_working()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
smgr->update(dt);
|
|
||||||
update_pos_and_orientation(smgr, dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add a sound sample to the message queue which is played sequentially
|
|
||||||
* in order.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
FGFX::play_message( SGSoundSample *_sample )
|
|
||||||
{
|
|
||||||
_samplequeue.push( _sample );
|
|
||||||
}
|
|
||||||
void
|
|
||||||
FGFX::play_message( const std::string& path, const std::string& fname, double volume )
|
|
||||||
{
|
|
||||||
if (globals->get_soundmgr()->is_working() == true) {
|
|
||||||
SGSoundSample *sample;
|
|
||||||
sample = new SGSoundSample( path.c_str(), fname.c_str() );
|
|
||||||
sample->set_volume( volume );
|
|
||||||
play_message( sample );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FGFX::update_pos_and_orientation(SGSoundMgr *smgr, double dt)
|
|
||||||
{
|
|
||||||
SGModelPlacement *model = globals->get_aircraft_model()->get3DModel();
|
|
||||||
FGViewer *observer = globals->get_current_view();
|
|
||||||
|
|
||||||
// Right now we make a simplifying assumption that the primary
|
|
||||||
// aircraft is the source of all sounds and that all sounds are
|
|
||||||
// positioned in the aircraft base
|
|
||||||
// EMH: Note: this is fine, to hear multiple aircraft simulataniously
|
|
||||||
// we just have to trigger one instance of the FGFX class for every
|
|
||||||
// aircraft
|
|
||||||
|
|
||||||
// get the orientation
|
|
||||||
const SGQuatd view_or = observer->getViewOrientation();
|
|
||||||
SGQuatd surf_or = SGQuatd::fromLonLat(observer->getPosition());
|
|
||||||
|
|
||||||
SGQuatd model_or = SGQuatd::fromYawPitchRollDeg(
|
|
||||||
model->getHeadingDeg(),
|
|
||||||
model->getPitchDeg(),
|
|
||||||
model->getRollDeg());
|
|
||||||
|
|
||||||
// get the up and at vector in the aircraft base
|
|
||||||
// (ok, the up vector is a down vector, but the coordinates
|
|
||||||
// are finally calculated in a left hand system and openal
|
|
||||||
// lives in a right hand system. Therefore we need to pass
|
|
||||||
// the down vector to get correct stereo sound.)
|
|
||||||
SGVec3d sgv_up
|
|
||||||
= model_or.rotateBack(surf_or.rotateBack(view_or.rotate(SGVec3d(0,1,0))));
|
|
||||||
SGVec3d sgv_at
|
|
||||||
= model_or.rotateBack(surf_or.rotateBack(view_or.rotate(SGVec3d(0,0,1))));
|
|
||||||
|
|
||||||
// get the location data for the primary FDM (now hardcoded to ac model)...
|
|
||||||
// EMH: to add multiple sound sources this should be replaced
|
|
||||||
SGVec3d absolute_view_pos = SGVec3d::fromGeod(model->getPosition());
|
|
||||||
|
|
||||||
// calculate speed of visitor and model
|
|
||||||
SGVec3d moved = last_visitor_pos - observer->get_view_pos();
|
|
||||||
last_visitor_pos = observer->get_view_pos();
|
|
||||||
SGVec3f listener_vel(model_or.rotateBack(surf_or.rotateBack(moved)));
|
|
||||||
|
|
||||||
moved = last_model_pos - absolute_view_pos;
|
|
||||||
last_model_pos = absolute_view_pos;
|
|
||||||
SGVec3f model_vel(model_or.rotateBack(surf_or.rotateBack(moved)));
|
|
||||||
|
|
||||||
if (dt > 0) {
|
|
||||||
model_vel /= dt;
|
|
||||||
listener_vel /= dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// checking, if the listener pos has moved suddenly
|
|
||||||
if (length(listener_vel) > 1000) {
|
|
||||||
// check if the relative speed model vs listener has moved suddenly, too
|
|
||||||
SGVec3f delta_vel = listener_vel - model_vel;
|
|
||||||
if (length(delta_vel) > 1000)
|
|
||||||
// a sane value
|
|
||||||
smgr->set_listener_vel(model_vel.data());
|
|
||||||
else
|
|
||||||
smgr->set_listener_vel(listener_vel.data());
|
|
||||||
} else {
|
|
||||||
smgr->set_listener_vel( listener_vel.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
// set positional offset for sources
|
|
||||||
SGVec3d dsource_pos_offset = observer->get_view_pos() - absolute_view_pos;
|
|
||||||
dsource_pos_offset = model_or.rotateBack(surf_or.rotateBack(
|
|
||||||
dsource_pos_offset
|
|
||||||
));
|
|
||||||
|
|
||||||
smgr->set_source_pos_all( SGVec3f(dsource_pos_offset).data() );
|
|
||||||
smgr->set_source_vel_all(model_vel.data() );
|
|
||||||
|
|
||||||
float orient[6];
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
orient[i] = sgv_at[i];
|
|
||||||
orient[i + 3] = sgv_up[i];
|
|
||||||
}
|
|
||||||
smgr->set_listener_orientation( orient );
|
|
||||||
|
|
||||||
// The listener is always positioned at the origin.
|
|
||||||
smgr->set_listener_pos( SGVec3f::zeros().data() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of fg_fx.cxx
|
// end of fg_fx.cxx
|
||||||
|
|
|
@ -26,73 +26,46 @@
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/sound/sample_group.hxx>
|
||||||
|
|
||||||
class SGXmlSound;
|
class SGXmlSound;
|
||||||
class SGSoundSample;
|
|
||||||
class SGSoundMgr;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generator for FlightGear sound effects.
|
* Generator for FlightGear sound effects.
|
||||||
*
|
*
|
||||||
* This module uses FGSoundMgr to generate sound effects based
|
* This module uses a FGSampleGroup class to generate sound effects based
|
||||||
* on current flight conditions. The sound manager must be initialized
|
* on current flight conditions. The sound manager must be initialized
|
||||||
* before this object is.
|
* before this object is.
|
||||||
*
|
*
|
||||||
* Note: this module supports two separate sound mechanisms concurrently.
|
* This module will load and play a set of sound effects defined in an
|
||||||
*
|
|
||||||
* 1. This module will load and play a set of sound effects defined in an
|
|
||||||
* xml file and tie them to various property states.
|
* xml file and tie them to various property states.
|
||||||
* 2. This modules also maintains a queue of 'message' audio files. These
|
|
||||||
* are played sequentially with no overlap until the queue is finished.
|
|
||||||
* This second mechanims is useful for things like tutorial messages or
|
|
||||||
* background atc chatter.
|
|
||||||
*/
|
*/
|
||||||
class FGFX : public SGSubsystem
|
class FGFX : public SGSampleGroup
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FGFX ();
|
FGFX ( SGSoundMgr *smgr, const string &refname );
|
||||||
virtual ~FGFX ();
|
virtual ~FGFX ();
|
||||||
|
|
||||||
virtual void init ();
|
virtual void init ();
|
||||||
virtual void reinit ();
|
virtual void reinit ();
|
||||||
virtual void bind ();
|
|
||||||
virtual void unbind ();
|
|
||||||
virtual void update (double dt);
|
virtual void update (double dt);
|
||||||
|
|
||||||
/**
|
|
||||||
* add a sound sample to the message queue which is played sequentially
|
|
||||||
* in order.
|
|
||||||
*/
|
|
||||||
void play_message( SGSoundSample *_sample );
|
|
||||||
void play_message( const std::string& path, const std::string& fname, double volume );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Explicit late update hook, to avoid problems which occur if done during
|
|
||||||
* normal SGSubsytem updating.
|
|
||||||
*/
|
|
||||||
void update_fx_late(double dt);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void update_pos_and_orientation(SGSoundMgr *smgr, double dt);
|
SGSharedPtr<SGSampleGroup> _avionics;
|
||||||
SGVec3d last_visitor_pos;
|
|
||||||
SGVec3d last_model_pos;
|
|
||||||
|
|
||||||
std::vector<SGXmlSound *> _sound;
|
std::vector<SGXmlSound *> _sound;
|
||||||
std::queue<SGSoundSample *> _samplequeue;
|
|
||||||
|
|
||||||
bool last_pause;
|
SGPropertyNode_ptr _enabled;
|
||||||
double last_volume;
|
|
||||||
|
|
||||||
SGPropertyNode_ptr _pause;
|
|
||||||
SGPropertyNode_ptr _volume;
|
SGPropertyNode_ptr _volume;
|
||||||
|
SGPropertyNode_ptr _avionics_enabled;
|
||||||
|
SGPropertyNode_ptr _avionics_volume;
|
||||||
|
SGPropertyNode_ptr _avionics_external;
|
||||||
|
SGPropertyNode_ptr _internal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,6 @@
|
||||||
|
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
|
||||||
#include <Main/globals.hxx>
|
|
||||||
|
|
||||||
#include "morse.hxx"
|
#include "morse.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
@ -171,10 +168,6 @@ bool FGMorse::cust_init(const int freq ) {
|
||||||
// make a SGSoundSample morse code transmission for the specified string
|
// make a SGSoundSample morse code transmission for the specified string
|
||||||
SGSoundSample *FGMorse::make_ident( const string& id, const int freq ) {
|
SGSoundSample *FGMorse::make_ident( const string& id, const int freq ) {
|
||||||
|
|
||||||
if (globals->get_soundmgr()->is_working() == false) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *idptr = (char *)id.c_str();
|
char *idptr = (char *)id.c_str();
|
||||||
|
|
||||||
int length = 0;
|
int length = 0;
|
||||||
|
@ -226,10 +219,10 @@ SGSoundSample *FGMorse::make_ident( const string& id, const int freq ) {
|
||||||
length += 2 * SPACE_SIZE;
|
length += 2 * SPACE_SIZE;
|
||||||
|
|
||||||
// 2. Allocate space for the message
|
// 2. Allocate space for the message
|
||||||
unsigned char *buffer = new unsigned char[length];
|
const unsigned char* buffer = (const unsigned char *)malloc(length);
|
||||||
|
|
||||||
// 3. Assemble the message;
|
// 3. Assemble the message;
|
||||||
unsigned char *buf_ptr = buffer;
|
unsigned char *buf_ptr = (unsigned char*)buffer;
|
||||||
|
|
||||||
for ( i = 0; i < (int)id.length(); ++i ) {
|
for ( i = 0; i < (int)id.length(); ++i ) {
|
||||||
if ( idptr[i] >= 'A' && idptr[i] <= 'Z' ) {
|
if ( idptr[i] >= 'A' && idptr[i] <= 'Z' ) {
|
||||||
|
@ -268,12 +261,9 @@ SGSoundSample *FGMorse::make_ident( const string& id, const int freq ) {
|
||||||
buf_ptr += SPACE_SIZE;
|
buf_ptr += SPACE_SIZE;
|
||||||
|
|
||||||
// 4. create the simple sound and return
|
// 4. create the simple sound and return
|
||||||
SGSoundSample *sample = new SGSoundSample( buffer, length,
|
SGSoundSample *sample = new SGSoundSample( &buffer, length,
|
||||||
BYTES_PER_SECOND );
|
BYTES_PER_SECOND );
|
||||||
|
|
||||||
// clean up the buffer
|
|
||||||
delete [] buffer;
|
|
||||||
|
|
||||||
sample->set_reference_dist( 10.0 );
|
sample->set_reference_dist( 10.0 );
|
||||||
sample->set_max_dist( 20.0 );
|
sample->set_max_dist( 20.0 );
|
||||||
|
|
||||||
|
|
108
src/Sound/sample_queue.cxx
Normal file
108
src/Sound/sample_queue.cxx
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
// _samplequeue.cxx -- Sound effect management class implementation
|
||||||
|
//
|
||||||
|
// Started by David Megginson, October 2001
|
||||||
|
// (Reuses some code from main.cxx, probably by Curtis Olson)
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable: 4786)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "sample_queue.hxx"
|
||||||
|
|
||||||
|
#include <Main/fg_props.hxx>
|
||||||
|
|
||||||
|
#include <simgear/sound/soundmgr_openal.hxx>
|
||||||
|
#include <simgear/sound/sample_openal.hxx>
|
||||||
|
|
||||||
|
FGSampleQueue::FGSampleQueue ( SGSoundMgr *smgr, const string &refname ) :
|
||||||
|
last_enabled( true ),
|
||||||
|
last_volume( 0.0 ),
|
||||||
|
_enabled( fgGetNode("/sim/sound/chatter/enabled", true) ),
|
||||||
|
_volume( fgGetNode("/sim/sound/chatter/volume", true) )
|
||||||
|
{
|
||||||
|
SGSampleGroup::_smgr = smgr;
|
||||||
|
SGSampleGroup::_smgr->add(this, refname);
|
||||||
|
SGSampleGroup::_refname = refname;
|
||||||
|
_enabled->setBoolValue(true);
|
||||||
|
_volume->setFloatValue(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FGSampleQueue::~FGSampleQueue ()
|
||||||
|
{
|
||||||
|
while ( _messages.size() > 0 ) {
|
||||||
|
delete _messages.front();
|
||||||
|
_messages.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FGSampleQueue::update (double dt)
|
||||||
|
{
|
||||||
|
// command sound manger
|
||||||
|
bool new_enabled = _enabled->getBoolValue();
|
||||||
|
if ( new_enabled != last_enabled ) {
|
||||||
|
if ( new_enabled ) {
|
||||||
|
resume();
|
||||||
|
} else {
|
||||||
|
suspend();
|
||||||
|
}
|
||||||
|
last_enabled = new_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( new_enabled ) {
|
||||||
|
double volume = _volume->getDoubleValue();
|
||||||
|
if ( volume != last_volume ) {
|
||||||
|
set_volume( volume );
|
||||||
|
last_volume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process mesage queue
|
||||||
|
const string msgid = "Sequential Audio Message";
|
||||||
|
bool now_playing = false;
|
||||||
|
if ( exists( msgid ) ) {
|
||||||
|
now_playing = is_playing( msgid );
|
||||||
|
if ( !now_playing ) {
|
||||||
|
// current message finished, stop and remove
|
||||||
|
stop( msgid ); // removes source
|
||||||
|
remove( msgid ); // removes buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !now_playing ) {
|
||||||
|
// message queue idle, add next sound if we have one
|
||||||
|
if ( _messages.size() > 0 ) {
|
||||||
|
SGSampleGroup::add( _messages.front(), msgid );
|
||||||
|
_messages.pop();
|
||||||
|
play_once( msgid );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SGSampleGroup::update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end of _samplequeue.cxx
|
70
src/Sound/sample_queue.hxx
Normal file
70
src/Sound/sample_queue.hxx
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// sample_queue.hxx -- sample queue management class
|
||||||
|
//
|
||||||
|
// Started by David Megginson, October 2001
|
||||||
|
// (Reuses some code from main.cxx, probably by Curtis Olson)
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
|
||||||
|
#ifndef __FGSAMPLE_QUEUE_HXX
|
||||||
|
#define __FGSAMPLE_QUEUE_HXX 1
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
#include <simgear/sound/sample_group.hxx>
|
||||||
|
|
||||||
|
class SGSoundSample;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlightGear sample queue class
|
||||||
|
*
|
||||||
|
* This modules maintains a queue of 'message' audio files. These
|
||||||
|
* are played sequentially with no overlap until the queue is finished.
|
||||||
|
* This second mechanims is useful for things like tutorial messages or
|
||||||
|
* background atc chatter.
|
||||||
|
*/
|
||||||
|
class FGSampleQueue : public SGSampleGroup
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FGSampleQueue ( SGSoundMgr *smgr, const string &refname );
|
||||||
|
virtual ~FGSampleQueue ();
|
||||||
|
|
||||||
|
virtual void update (double dt);
|
||||||
|
|
||||||
|
inline void add (SGSharedPtr<SGSoundSample> msg) { _messages.push(msg); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::queue< SGSharedPtr<SGSoundSample> > _messages;
|
||||||
|
|
||||||
|
bool last_enabled;
|
||||||
|
double last_volume;
|
||||||
|
|
||||||
|
SGPropertyNode_ptr _enabled;
|
||||||
|
SGPropertyNode_ptr _volume;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// end of fg_fx.hxx
|
|
@ -35,7 +35,7 @@ FGVoiceMgr::FGVoiceMgr() :
|
||||||
_host(fgGetString(VOICE "/host", "localhost")),
|
_host(fgGetString(VOICE "/host", "localhost")),
|
||||||
_port(fgGetString(VOICE "/port", "1314")),
|
_port(fgGetString(VOICE "/port", "1314")),
|
||||||
_enabled(fgGetBool(VOICE "/enabled", false)),
|
_enabled(fgGetBool(VOICE "/enabled", false)),
|
||||||
_pausedNode(fgGetNode("/sim/sound/pause", true))
|
_pausedNode(fgGetNode("/sim/sound/working", true))
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_THREADS)
|
#if defined(ENABLE_THREADS)
|
||||||
if (!_enabled)
|
if (!_enabled)
|
||||||
|
@ -83,7 +83,7 @@ void FGVoiceMgr::update(double)
|
||||||
if (!_enabled)
|
if (!_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_paused = _pausedNode->getBoolValue();
|
_paused = !_pausedNode->getBoolValue();
|
||||||
for (unsigned int i = 0; i < _voices.size(); i++) {
|
for (unsigned int i = 0; i < _voices.size(); i++) {
|
||||||
_voices[i]->update();
|
_voices[i]->update();
|
||||||
#if !defined(ENABLE_THREADS)
|
#if !defined(ENABLE_THREADS)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
bin_PROGRAMS = est-epsilon gl-info al-info
|
bin_PROGRAMS = est-epsilon gl-info alcinfo
|
||||||
|
|
||||||
noinst_PROGRAMS = test-gethostname test-mktime test-text test-up test-env-map
|
noinst_PROGRAMS = test-gethostname test-mktime test-text test-up test-env-map
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ est_epsilon_LDADD = $(opengl_LIBS)
|
||||||
gl_info_SOURCES = gl-info.c
|
gl_info_SOURCES = gl-info.c
|
||||||
gl_info_LDADD = $(opengl_LIBS)
|
gl_info_LDADD = $(opengl_LIBS)
|
||||||
|
|
||||||
al_info_SOURCES = al-info.c
|
alcinfo_SOURCES = alcinfo.cxx
|
||||||
al_info_LDADD = $(openal_LIBS)
|
alcinfo_LDADD = $(openal_LIBS)
|
||||||
|
|
||||||
test_env_map_SOURCES = test-env-map.cxx
|
test_env_map_SOURCES = test-env-map.cxx
|
||||||
test_env_map_LDADD = $(opengl_LIBS)
|
test_env_map_LDADD = $(opengl_LIBS)
|
||||||
|
|
114
tests/al-info.c
114
tests/al-info.c
|
@ -1,114 +0,0 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
# include <OpenAL/al.h>
|
|
||||||
# include <OpenAL/alc.h>
|
|
||||||
#else
|
|
||||||
# include <AL/al.h>
|
|
||||||
# include <AL/alc.h>
|
|
||||||
# ifndef __CYGWIN__
|
|
||||||
# include <AL/alext.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_VERSION_1_1
|
|
||||||
# ifdef __APPLE__
|
|
||||||
# include <OpenAL/altypes.h>
|
|
||||||
# include <OpenAL/alctypes.h>
|
|
||||||
#else
|
|
||||||
# include <AL/altypes.h>
|
|
||||||
# include <AL/alctypes.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_DATA 16
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
ALCint data[MAX_DATA];
|
|
||||||
ALCdevice *device = NULL;
|
|
||||||
ALCcontext *context = NULL;
|
|
||||||
const ALchar *s;
|
|
||||||
ALCenum error;
|
|
||||||
|
|
||||||
device = alcOpenDevice(NULL);
|
|
||||||
if (device == NULL)
|
|
||||||
{
|
|
||||||
printf("No default audio device available.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
context = alcCreateContext(device, NULL);
|
|
||||||
if (context == NULL)
|
|
||||||
{
|
|
||||||
printf("Could not create a valid context.\n");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
alcMakeContextCurrent(context);
|
|
||||||
|
|
||||||
s = alGetString(AL_VENDOR);
|
|
||||||
printf("AL_VENDOR = \"%s\"\n", s);
|
|
||||||
|
|
||||||
s = alGetString(AL_RENDERER);
|
|
||||||
printf("AL_RENDERER = \"%s\"\n", s);
|
|
||||||
|
|
||||||
s = alGetString(AL_VERSION);
|
|
||||||
printf("AL_VERSION = \"%s\"\n", s);
|
|
||||||
|
|
||||||
s = alGetString(AL_EXTENSIONS);
|
|
||||||
printf("AL_EXTENSIONS = \"%s\"\n", s);
|
|
||||||
|
|
||||||
alcGetError(device);
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
if (alcIsExtensionPresent(NULL, (const ALchar *)"ALC_ENUMERATION_EXT") == AL_TRUE)
|
|
||||||
{
|
|
||||||
s = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
|
||||||
printf("ALC_DEVICE_SPECIFIER = \"%s\"\n", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, data);
|
|
||||||
printf("ALC_MAJOR_VERSION = %i\n", *data);
|
|
||||||
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, data);
|
|
||||||
printf("ALC_MINOR_VERSION = %i\n", *data);
|
|
||||||
|
|
||||||
s = alcGetString(device, ALC_EXTENSIONS);
|
|
||||||
printf("ALC_EXTENSIONS = \"%s\"\n", s);
|
|
||||||
|
|
||||||
if ((error = alcGetError(device)))
|
|
||||||
{
|
|
||||||
printf("Error #%i occured\n", error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = alcGetString(device, ALC_DEFAULT_DEVICE_SPECIFIER);
|
|
||||||
printf("ALC_DEFAULT_DEVICE_SPECIFIER = \"%s\"\n", s);
|
|
||||||
|
|
||||||
if ((error = alcGetError(device)))
|
|
||||||
{
|
|
||||||
printf("Error #%i occured\n", error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
alcGetIntegerv(device, ALC_ATTRIBUTES_SIZE, 1, &i);
|
|
||||||
printf("ALC attributes(%i): ", i);
|
|
||||||
|
|
||||||
alcGetIntegerv(device, ALC_ALL_ATTRIBUTES, i, data);
|
|
||||||
for (j=0; j<i; j++)
|
|
||||||
{
|
|
||||||
printf("%i ", data[j]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
if ((error = alcGetError(device)))
|
|
||||||
{
|
|
||||||
printf("Error #%i occured\n", error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
alcCloseDevice(device);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
341
tests/alcinfo.cxx
Normal file
341
tests/alcinfo.cxx
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
/* -*- mode: C; tab-width:8; c-basic-offset:8 -*-
|
||||||
|
* vi:set ts=8:
|
||||||
|
*
|
||||||
|
* alcinfo.x
|
||||||
|
*
|
||||||
|
* alcinfo display info about a ALC extension and OpenAL renderer
|
||||||
|
*
|
||||||
|
* This file is in the Public Domain and comes with no warranty.
|
||||||
|
* Erik Hofman <erik@ehofman.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
# include <OpenAL/al.h>
|
||||||
|
# include <OpenAL/alc.h>
|
||||||
|
#else
|
||||||
|
# include <AL/al.h>
|
||||||
|
# include <AL/alc.h>
|
||||||
|
# include <AL/alext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef AL_VERSION_1_1
|
||||||
|
# ifdef __APPLE__
|
||||||
|
# include <OpenAL/altypes.h>
|
||||||
|
# include <OpenAL/alctypes.h>
|
||||||
|
#else
|
||||||
|
# include <AL/altypes.h>
|
||||||
|
# include <AL/alctypes.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||||
|
# define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_DATA 16
|
||||||
|
static const int indentation = 4;
|
||||||
|
static const int maxmimumWidth = 79;
|
||||||
|
|
||||||
|
void printExtensions (const char *, char, const char *);
|
||||||
|
void displayDevices(const char *, const char *);
|
||||||
|
char *getDeviceName(int, char **);
|
||||||
|
void testForError(void *, const string&);
|
||||||
|
void testForALCError(ALCdevice *);
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
ALCint data[MAX_DATA];
|
||||||
|
ALCdevice *device = NULL;
|
||||||
|
ALCcontext *context = NULL;
|
||||||
|
ALenum error;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
if (alcIsExtensionPresent(NULL, "ALC_enumeration_EXT") == AL_TRUE)
|
||||||
|
{
|
||||||
|
if (alcIsExtensionPresent(NULL, "ALC_enumerate_all_EXT") == AL_FALSE)
|
||||||
|
s = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||||
|
else
|
||||||
|
s = (char *)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||||
|
displayDevices("output", s);
|
||||||
|
|
||||||
|
s = (char *)alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||||
|
displayDevices("input", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = getDeviceName(argc, argv);
|
||||||
|
device = alcOpenDevice(s);
|
||||||
|
testForError(device, "Audio device not available.");
|
||||||
|
|
||||||
|
context = alcCreateContext(device, NULL);
|
||||||
|
testForError(context, "Unable to create a valid context.");
|
||||||
|
|
||||||
|
alcMakeContextCurrent(context);
|
||||||
|
testForALCError(device);
|
||||||
|
|
||||||
|
s = (char *)alcGetString(device, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||||
|
printf("default output device: %s\n", s);
|
||||||
|
testForALCError(device);
|
||||||
|
|
||||||
|
error = alcIsExtensionPresent(device, "ALC_EXT_capture");
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
s = (char *)alcGetString(device, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
||||||
|
printf("default input device: %s\n", s);
|
||||||
|
testForALCError(device);
|
||||||
|
}
|
||||||
|
printf("capture support: %s\n", (error) ? "yes" : "no");
|
||||||
|
|
||||||
|
alcGetIntegerv(device, ALC_FREQUENCY, 1, data);
|
||||||
|
printf("mixer frequency: %u hz\n", data[0]);
|
||||||
|
testForALCError(device);
|
||||||
|
|
||||||
|
alcGetIntegerv(device, ALC_REFRESH, 1, data+1);
|
||||||
|
printf("refresh rate : %u hz\n", data[0]/data[1]);
|
||||||
|
testForALCError(device);
|
||||||
|
|
||||||
|
data[0] = 0;
|
||||||
|
alcGetIntegerv(device, ALC_MONO_SOURCES, 1, data);
|
||||||
|
error = alcGetError(device);
|
||||||
|
if (error == AL_NONE) {
|
||||||
|
printf("supported sources; mono: %u, ", data[0]);
|
||||||
|
|
||||||
|
data[0] = 0;
|
||||||
|
alcGetIntegerv(device, ALC_STEREO_SOURCES, 1, data);
|
||||||
|
printf("stereo: %u\n", data[0]);
|
||||||
|
testForALCError(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("ALC version: ");
|
||||||
|
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, data);
|
||||||
|
printf("%i.", *data);
|
||||||
|
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, data);
|
||||||
|
printf("%i\n", *data);
|
||||||
|
testForALCError(device);
|
||||||
|
|
||||||
|
s = (char *)alcGetString(device, ALC_EXTENSIONS);
|
||||||
|
printExtensions ("ALC extensions", ' ', s);
|
||||||
|
testForALCError(device);
|
||||||
|
|
||||||
|
s = (char *)alGetString(AL_VENDOR);
|
||||||
|
error = alGetError();
|
||||||
|
if ((error = alGetError()) != AL_NO_ERROR)
|
||||||
|
printf("Error #%x: %s\n", error, alGetString(error));
|
||||||
|
else
|
||||||
|
printf("OpenAL vendor string: %s\n", s);
|
||||||
|
|
||||||
|
s = (char *)alGetString(AL_RENDERER);
|
||||||
|
if ((error = alGetError()) != AL_NO_ERROR)
|
||||||
|
printf("Error #%x: %s\n", error, alGetString(error));
|
||||||
|
else
|
||||||
|
printf("OpenAL renderer string: %s\n", s);
|
||||||
|
|
||||||
|
s = (char *)alGetString(AL_VERSION);
|
||||||
|
if ((error = alGetError()) != AL_NO_ERROR)
|
||||||
|
printf("Error #%x: %s\n", error, alGetString(error));
|
||||||
|
else if (!s)
|
||||||
|
printf("Quering AL_VERSION returned NULL pointer!\n");
|
||||||
|
else
|
||||||
|
printf("OpenAL version string: %s\n", s);
|
||||||
|
|
||||||
|
s = (char *)alGetString(AL_EXTENSIONS);
|
||||||
|
printExtensions ("OpenAL extensions", ' ', s);
|
||||||
|
testForALCError(device);
|
||||||
|
|
||||||
|
/* alut testing mechanism */
|
||||||
|
context = alcGetCurrentContext();
|
||||||
|
if (context == NULL)
|
||||||
|
{
|
||||||
|
printf("Error: no current context\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (alGetError () != AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
printf("Alert: AL error on entry\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (alcGetError (alcGetContextsDevice (context)) != ALC_NO_ERROR)
|
||||||
|
{
|
||||||
|
printf("Alert: ALC error on entry\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* end of alut test */
|
||||||
|
|
||||||
|
|
||||||
|
if (alcMakeContextCurrent(NULL) == 0)
|
||||||
|
printf("alcMakeContextCurrent failed.\n");
|
||||||
|
|
||||||
|
device = alcGetContextsDevice(context);
|
||||||
|
alcDestroyContext(context);
|
||||||
|
testForALCError(device);
|
||||||
|
|
||||||
|
if (alcCloseDevice(device) == 0)
|
||||||
|
printf("alcCloseDevice failed.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
printChar (int c, int *width)
|
||||||
|
{
|
||||||
|
putchar (c);
|
||||||
|
*width = (c == '\n') ? 0 : (*width + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
indent (int *width)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < indentation; i++)
|
||||||
|
{
|
||||||
|
printChar (' ', width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printExtensions (const char *header, char separator, const char *extensions)
|
||||||
|
{
|
||||||
|
int width = 0, start = 0, end = 0;
|
||||||
|
|
||||||
|
printf ("%s:\n", header);
|
||||||
|
if (extensions == NULL || extensions[0] == '\0')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
indent (&width);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (extensions[end] == separator || extensions[end] == '\0')
|
||||||
|
{
|
||||||
|
if (width + end - start + 2 > maxmimumWidth)
|
||||||
|
{
|
||||||
|
printChar ('\n', &width);
|
||||||
|
indent (&width);
|
||||||
|
}
|
||||||
|
while (start < end)
|
||||||
|
{
|
||||||
|
printChar (extensions[start], &width);
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
if (extensions[end] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start++;
|
||||||
|
end++;
|
||||||
|
if (extensions[end] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printChar (',', &width);
|
||||||
|
printChar (' ', &width);
|
||||||
|
}
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
printChar ('\n', &width);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
getCommandLineOption(int argc, char **argv, const string& option)
|
||||||
|
{
|
||||||
|
int slen = option.size();
|
||||||
|
char *rv = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<argc; i++)
|
||||||
|
{
|
||||||
|
if (strncmp(argv[i], option.c_str(), slen) == 0)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if (i<argc) rv = argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
getDeviceName(int argc, char **argv)
|
||||||
|
{
|
||||||
|
static char devname[255];
|
||||||
|
int len = 255;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
s = getCommandLineOption(argc, argv, "-d");
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
strncpy((char *)&devname, s, len);
|
||||||
|
len -= strlen(s);
|
||||||
|
|
||||||
|
s = getCommandLineOption(argc, argv, "-r");
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
strncat((char *)&devname, " on ", len);
|
||||||
|
len -= 4;
|
||||||
|
|
||||||
|
strncat((char *)&devname, s, len);
|
||||||
|
}
|
||||||
|
s = (char *)&devname;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
displayDevices(const char *type, const char *list)
|
||||||
|
{
|
||||||
|
ALCchar *ptr, *nptr;
|
||||||
|
|
||||||
|
ptr = (ALCchar *)list;
|
||||||
|
printf("list of all available %s devices:\n", type);
|
||||||
|
if (!list)
|
||||||
|
{
|
||||||
|
printf("none\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nptr = ptr;
|
||||||
|
while (*(nptr += strlen(ptr)+1) != 0)
|
||||||
|
{
|
||||||
|
printf(" %s\n", ptr);
|
||||||
|
ptr = nptr;
|
||||||
|
}
|
||||||
|
printf(" %s\n", ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testForError(void *p, const string& s)
|
||||||
|
{
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
printf("\nError: %s\n\n", s.c_str());
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testForALCError(ALCdevice *device)
|
||||||
|
{
|
||||||
|
ALenum error;
|
||||||
|
error = alcGetError(device);
|
||||||
|
if (error != ALC_NO_ERROR)
|
||||||
|
printf("\nALC Error %x occurred: %s\n", error, alcGetString(device, error));
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue