_trackSet = false;
_tgtRoll = 0.0;
_rollSuspended = false;
+ _sgr = 0;
}
FGAIPlane::~FGAIPlane() {
}
void FGAIPlane::Update(double dt) {
+ if (!_sgr) {
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ if (smgr) _sgr = smgr->find("atc", true);
+ }
+
if(_pending) {
if(tuned_station) {
if(tuned_station->GetFreqClear()) {
// For now assume in range !!!
// TODO - implement range checking
// 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);
}
}
}
void FGAIPlane::ImmediateTransmit(int callback_code) {
- // TODO - at the moment the volume is always set off comm1
- double volume = fgGetDouble("/instrumentation/comm[0]/volume");
+ // TODO - at the moment the volume is always set off comm1
+ float volume = fgGetFloat("/instrumentation/comm[0]/volume");
+
Render(plane.callsign, volume, false);
if(callback_code) {
ProcessCallback(callback_code);
// 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 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());
#ifdef ENABLE_AUDIO_SUPPORT
voice = (voiceOK && fgGetBool("/sim/sound/voice"));
if(voice) {
string buf = vPtr->WriteMessage((char*)pending_transmission.c_str(), voice);
- if(voice) {
+ if(voice && (volume > 0.05)) {
SGSoundSample* simple =
- new SGSoundSample((unsigned char*)buf.c_str(), buf.length(), 8000, AL_FORMAT_MONO8 );
+ new SGSoundSample((unsigned char*)buf.c_str(), buf.length(), 8000 );
// TODO - at the moment the volume can't be changed
// after the transmission has started.
simple->set_volume(volume);
- globals->get_soundmgr()->add(simple, refname);
- if(repeating) {
- globals->get_soundmgr()->play_looped(refname);
- } else {
- globals->get_soundmgr()->play_once(refname);
- }
+ _sgr->add(simple, refname);
+ _sgr->play(refname, repeating);
}
}
#endif // ENABLE_AUDIO_SUPPORT
if(playing) {
if(voice) {
#ifdef ENABLE_AUDIO_SUPPORT
- globals->get_soundmgr()->stop(refname);
- globals->get_soundmgr()->remove(refname);
+ _sgr->stop(refname);
+ _sgr->remove(refname);
#endif
}
playing = false;
#include "AIEntity.hxx"
#include "ATC.hxx"
+class SGSampleGroup;
+
enum PatternLeg {
TAKEOFF_ROLL,
CLIMBOUT,
// 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 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.
// Requires the sound manager refname if audio, else "".
bool _trackSet; // Set true if tgtTrack is to be followed
double _tgtRoll;
bool _rollSuspended; // Set true when a derived class has suspended AIPlane's roll control
+
+ SGSampleGroup *_sgr;
};
#endif // _FG_AI_PLANE_HXX
FGATC::FGATC() :
- _voiceOK(false),
+ _voiceOK(false),
+ _sgr(NULL),
freqClear(true),
receiving(false),
respond(false),
}
void FGATC::SetData(ATCData* d) {
- _type = d->type;
+ _type = d->type;
_geod = d->geod;
_cart = d->cart;
range = d->range;
// 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 repeating flag indicates whether the message should be repeated continuously or played once.
-void FGATC::Render(string& msg, const double volume,
- const string& refname, const bool repeating) {
+void FGATC::Render(string& msg, const float volume,
+ const string& refname, const bool repeating) {
if (repeating)
fgSetString("/sim/messages/atis", msg.c_str());
else
fgSetString("/sim/messages/atc", msg.c_str());
- #ifdef ENABLE_AUDIO_SUPPORT
+#ifdef ENABLE_AUDIO_SUPPORT
_voice = (_voiceOK && fgGetBool("/sim/sound/voice"));
if(_voice) {
- string buf = _vPtr->WriteMessage((char*)msg.c_str(), _voice);
- if(_voice) {
- NoRender(refname);
- try {
+ string buf = _vPtr->WriteMessage((char*)msg.c_str(), _voice);
+ if(_voice && (volume > 0.05)) {
+ NoRender(refname);
+ try {
// >>> Beware: must pass a (new) object to the (add) method,
// >>> because the (remove) method is going to do a (delete)
// >>> whether that's what you want or not.
- SGSoundSample *simple =
- new SGSoundSample((unsigned char*) buf.c_str(),
- buf.length(), 8000, AL_FORMAT_MONO8);
- // TODO - at the moment the volume can't be changed
- // after the transmission has started.
- simple->set_volume(volume);
- 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());
+ SGSoundSample *simple =
+ new SGSoundSample((unsigned char*) buf.c_str(), buf.length(), 8000);
+ // TODO - at the moment the volume can't be changed
+ // after the transmission has started.
+ if (!_sgr) {
+ SGSoundMgr *smgr;
+ smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ _sgr = smgr->find("atc", true);
+ }
+ simple->set_volume(volume);
+ _sgr->add(simple, refname);
+ _sgr->play(refname, repeating);
+ } catch ( sg_io_exception &e ) {
+ SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage());
+ }
}
- }
}
- #endif // ENABLE_AUDIO_SUPPORT
+#endif // ENABLE_AUDIO_SUPPORT
if(!_voice) {
// 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) {
if(_playing) {
if(_voice) {
#ifdef ENABLE_AUDIO_SUPPORT
- globals->get_soundmgr()->stop(refname);
- globals->get_soundmgr()->remove(refname);
+ _sgr->stop(refname);
+ _sgr->remove(refname);
#endif
}
_playing = false;
ostream& operator << (ostream& os, atc_type atc) {
switch(atc) {
- case(AWOS): return(os << "AWOS");
- case(ATIS): return(os << "ATIS");
- case(GROUND): return(os << "GROUND");
- case(TOWER): return(os << "TOWER");
+ case(AWOS): return(os << "AWOS");
+ case(ATIS): return(os << "ATIS");
+ case(GROUND): return(os << "GROUND");
+ case(TOWER): return(os << "TOWER");
case(APPROACH): return(os << "APPROACH");
case(DEPARTURE): return(os << "DEPARTURE");
- case(ENROUTE): return(os << "ENROUTE");
- case(INVALID): return(os << "INVALID");
+ case(ENROUTE): return(os << "ENROUTE");
+ case(INVALID): return(os << "INVALID");
}
return(os << "ERROR - Unknown switch in atc_type operator << ");
}
return fin >> skipeol;
}
- double lat, lon, elev;
+ double lat, lon, elev;
fin >> lat >> lon >> elev >> f >> a.range >> a.ident;
a.geod = SGGeod::fromDegM(lon, lat, elev);
// cout << a.ident << endl;
// generate cartesian coordinates
- a.cart = SGVec3d::fromGeod(a.geod);
+ a.cart = SGVec3d::fromGeod(a.geod);
return fin >> skipeol;
}
#include "ATCVoice.hxx"
+class SGSampleGroup;
+
// Convert a frequency in MHz to tens of kHz
// so we can use it e.g. as an index into commlist_freq
//
APPROACH,
DEPARTURE,
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;
// DCL - new experimental ATC data store
struct ATCData {
atc_type type;
- SGGeod geod;
- SGVec3d cart;
+ SGGeod geod;
+ SGVec3d cart;
unsigned short int freq;
unsigned short int range;
std::string ident;
FGATC();
virtual ~FGATC();
- virtual void Init()=0;
+ virtual void Init()=0;
// Run the internal calculations
// Derived classes should call this method from their own Update methods if they
// 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 repeating flag indicates whether the message should be repeated continuously or played once.
- void Render(std::string& msg, const double volume = 1.0,
- const std::string& refname = "", bool repeating = false);
+ void Render(std::string& msg, const float volume = 1.0,
+ const std::string& refname = "", bool repeating = false);
// Cease rendering all transmission from this station.
// Requires the sound manager refname if audio, else "".
void NoRender(const std::string& refname);
// 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
void ConditionalTransmit(double timeout, int callback_code = 0);
SGGeod _geod;
SGVec3d _cart;
int freq;
- std::map<std::string,int> active_on;
+ std::map<std::string,int> active_on;
int range;
- std::string ident; // Code of the airport its at.
- std::string name; // Name transmitted in the broadcast.
+ std::string ident; // Code of the airport its at.
+ std::string name; // Name transmitted in the broadcast.
// Rendering related stuff
- bool _voice; // Flag - true if we are using voice
- bool _playing; // Indicates a message in progress
- bool _voiceOK; // Flag - true if at least one voice has loaded OK
+ bool _voice; // Flag - true if we are using voice
+ bool _playing; // Indicates a message in progress
+ bool _voiceOK; // Flag - true if at least one voice has loaded OK
FGATCVoice* _vPtr;
+ SGSampleGroup *_sgr; // default sample group;
+
- bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog
- bool receiving; // Flag to indicate we are receiving a transmission
+ bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog
+ bool receiving; // Flag to indicate we are receiving a transmission
- double responseTime; // Time to take from end of request transmission to beginning of response
- // The idea is that this will be slightly random.
+ double responseTime; // Time to take from end of request transmission to beginning of response
+ // 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
- bool runResponseCounter; // Flag to indicate the response counter should be run
- double responseCounter; // counter to implement the above
+ bool runResponseCounter; // Flag to indicate the response counter should be run
+ 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(...)
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 _releaseCounter;
atc_type _type;
- 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(...)
+ 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(...)
private:
// Transmission timing stuff.
double _timeout;
- bool _pending;
+ bool _pending;
int _callback_code; // A callback code to be notified and processed by the derived classes
// A value of zero indicates no callback required
#include <boost/shared_array.hpp>
+#include <simgear/sound/soundmgr_openal.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/math/sg_random.h>
-#include <simgear/sound/sample_openal.hxx>
#include <Main/globals.hxx>
FGATCVoice::~FGATCVoice() {
if (rawSoundData)
- free( rawSoundData );
+ free( rawSoundData );
delete SoundData;
}
// Load the two voice files - one containing the raw sound data (.wav) and one containing the word positions (.vce).
// Return true if successful.
bool FGATCVoice::LoadVoice(const string& voice) {
- // FIXME CLO: disabled to try to see if this is causing problemcs
- // return false;
-
std::ifstream fin;
SGPath path = globals->get_fg_root();
+ string file = voice + ".wav";
path.append( "ATC" );
-
- string file = voice + ".wav";
+ path.append( file );
- SGSoundSample SoundData;
- rawSoundData = (char *)SoundData.load_file(path.c_str(), file.c_str());
- rawDataSize = SoundData.get_size();
+ string full_path = path.str();
+ int format, freq;
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ void *data;
+ smgr->load(full_path, &data, &format, &rawDataSize, &freq);
+ rawSoundData = (char*)data;
#ifdef VOICE_TEST
- ALenum fmt = SoundData.get_format();
- cout << "ATCVoice: format: " << fmt
+ cout << "ATCVoice: format: " << format
<< " size: " << rawDataSize << endl;
#endif
path = globals->get_fg_root();
wd.offset = wrdOffset;
wd.length = wrdLength;
wordMap[wrdstr] = wd;
- string ws2 = wrdstr;
- for(string::iterator p = ws2.begin(); p != ws2.end(); p++){
- *p = tolower(*p);
- if (*p == '-') *p = '_';
- }
- if (wrdstr != ws2) wordMap[ws2] = wd;
+ string ws2 = wrdstr;
+ for(string::iterator p = ws2.begin(); p != ws2.end(); p++){
+ *p = tolower(*p);
+ if (*p == '-') *p = '_';
+ }
+ if (wrdstr != ws2) wordMap[ws2] = wd;
//cout << wrd << "\t\t" << wrdOffset << "\t\t" << wrdLength << '\n';
//cout << i << '\n';
// TODO - at the moment we're effectively taking 3 passes through the data.
// 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]);
+ boost::shared_array<char> msg(new char[n1]);
strncpy(msg.get(), message, n1); // strtok requires a non-const char*
char* token;
int numWords = 0;
char* context;
token = strtok_r(msg.get(), delimiters, &context);
while(token != NULL) {
- for (char *t = token; *t; t++) {
- *t = tolower(*t); // canonicalize the case, to
- if (*t == '-') *t = '_'; // match what's in the index
- }
+ for (char *t = token; *t; t++) {
+ *t = tolower(*t); // canonicalize the case, to
+ if (*t == '-') *t = '_'; // match what's in the index
+ }
tokenList.push_back(token);
++numWords;
SG_LOG(SG_ATC, SG_DEBUG, "voice synth: token: '"
- << token << "'");
+ << token << "'");
token = strtok_r(NULL, delimiters, &context);
}
vector<WordData> wdptr;
- wdptr.reserve(numWords);
+ wdptr.reserve(numWords);
unsigned int cumLength = 0;
tokenListItr = tokenList.begin();
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");
+ << *tokenListItr << "' not found");
} else {
- wdptr.push_back(wordMap[*tokenListItr]);
- cumLength += wdptr.back().length;
+ wdptr.push_back(wordMap[*tokenListItr]);
+ cumLength += wdptr.back().length;
}
++tokenListItr;
}
const size_t word = wdptr.size();
-
+
// Check for no tokens found else slScheduler can be crashed
if(!word) {
dataOK = false;
return "";
}
- boost::shared_array<char> tmpbuf(new char[cumLength]);
+ boost::shared_array<char> tmpbuf(new char[cumLength]);
unsigned int bufpos = 0;
for(int i=0; i<word; ++i) {
/*
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/commands.hxx>
#include <simgear/structure/exception.hxx>
+#include <simgear/sound/soundmgr_openal.hxx>
#include <Main/globals.hxx>
#include <Main/fg_init.hxx>
t = fgInitTime();
globals->set_time_params( t );
- // Reinitialize some subsystems
- //
globals->get_viewmgr()->reinit();
globals->get_controls()->reset_all();
globals->get_aircraft_model()->reinit();
- globals->get_subsystem("fx")->reinit();
globals->get_subsystem("xml-autopilot")->reinit();
fgReInitSubsystems();
// forward decls
class SGPropertyNode;
+class SGSampleGroup;
class FGMetar;
/**
snd_lightning = new SGSoundSample(globals->get_fg_root().c_str(), "Sounds/thunder.wav");
snd_lightning->set_max_dist(7000.0f);
snd_lightning->set_reference_dist(3000.0f);
- SGSoundMgr *soundMgr = globals->get_soundmgr();
- soundMgr->add( snd_lightning, "thunder" );
- sgEnviro.set_soundMgr( soundMgr );
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ SGSampleGroup *sgr = smgr->find("weather", true);
+ sgr->add( snd_lightning, "thunder" );
+ sgEnviro.set_sampleGroup( sgr );
}
}
using std::string;
-class SGNewCloud;
+class SGSampleGroup;
class SGCloudField;
+class SGNewCloud;
class FGMetar;
-class FGEnvironmentCtrl;
+//class FGEnvironmentCtrl;
class FGClouds {
_transmitter_range_nm(0),
_ident_count(0),
_last_ident_time(0),
- _last_volume(-1)
+ _last_volume(-1),
+ _sgr(0)
{
}
_ident_node = node->getChild("ident", 0, true);
_ident_audible_node = node->getChild("ident-audible", 0, true);
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ _sgr = smgr->find("avionics", true);
+
morse.init();
std::ostringstream temp;
double range_nm = adjust_range(_transmitter_pos.getElevationFt(),
altitude_m * SG_METER_TO_FEET,
_transmitter_range_nm);
+
if (distance_nm <= range_nm) {
double bearing, az2, s;
set_bearing(delta_time_sec, bearing);
// adf ident sound
- double volume;
+ float volume;
if ( _ident_audible_node->getBoolValue() )
- volume = _volume_node->getDoubleValue();
+ volume = _volume_node->getFloatValue();
else
volume = 0.0;
_last_volume = volume;
SGSoundSample *sound;
- sound = globals->get_soundmgr()->find( _adf_ident );
+ sound = _sgr->find( _adf_ident );
if ( sound != NULL )
sound->set_volume( volume );
else
}
if ( _ident_count < 4 ) {
- if ( !globals->get_soundmgr()->is_playing(_adf_ident) ) {
- globals->get_soundmgr()->play_once( _adf_ident );
+ if ( !_sgr->is_playing(_adf_ident) && (volume > 0.05) ) {
+ _sgr->play_once( _adf_ident );
++_ident_count;
}
}
_in_range_node->setBoolValue(false);
set_bearing(delta_time_sec, 90);
_ident_node->setStringValue("");
- globals->get_soundmgr()->stop( _adf_ident );
+ _sgr->stop( _adf_ident );
}
}
_last_ident = ident;
_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
- globals->get_soundmgr()->stop( _adf_ident );
- globals->get_soundmgr()->remove( _adf_ident );
+ _sgr->stop( _adf_ident );
+ _sgr->remove( _adf_ident );
}
SGSoundSample *sound;
sound = morse.make_ident( ident, LO_FREQUENCY );
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);
_ident_count = offset / 4;
using std::string;
+class SGSampleGroup;
+
/**
* Model an ADF radio.
*
FGMorse morse;
int _ident_count;
time_t _last_ident_time;
- double _last_volume;
+ float _last_volume;
string _adf_ident;
+
+ SGSampleGroup *_sgr;
};
flight_timer(0.0),
elapsed_timer(0.0),
tmp_timer(0.0),
- _time_before_search_sec(0)
+ _time_before_search_sec(0),
+ _sgr(NULL)
{
}
void FGKR_87::init () {
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ _sgr = smgr->find("avionics", true);
morse.init();
}
// otherwise turn it off
if ( vol_btn >= 0.01 && audio_btn ) {
SGSoundSample *sound;
- sound = globals->get_soundmgr()->find( "adf-ident" );
+ sound = _sgr->find( "adf-ident" );
if ( sound != NULL ) {
if ( !adf_btn ) {
sound->set_volume( vol_btn );
}
if ( play_count < 4 ) {
// play ADF ident
- if ( !globals->get_soundmgr()->is_playing("adf-ident") ) {
- globals->get_soundmgr()->play_once( "adf-ident" );
+ if ( !_sgr->is_playing("adf-ident") && (vol_btn > 0.05) ) {
+ _sgr->play_once( "adf-ident" );
++play_count;
}
}
} else {
- globals->get_soundmgr()->stop( "adf-ident" );
+ _sgr->stop( "adf-ident" );
}
}
}
effective_range = kludgeRange(stn_elev, pos.getElevationM(), range);
xyz = adf->cart();
- if ( globals->get_soundmgr()->exists( "adf-ident" ) ) {
- globals->get_soundmgr()->remove( "adf-ident" );
+ if ( _sgr->exists( "adf-ident" ) ) {
+ _sgr->remove( "adf-ident" );
}
SGSoundSample *sound;
sound = morse.make_ident( trans_ident, LO_FREQUENCY );
sound->set_volume( 0.3 );
- globals->get_soundmgr()->add( sound, "adf-ident" );
+ _sgr->add( sound, "adf-ident" );
int offset = (int)(sg_random() * 30.0);
play_count = offset / 4;
valid = false;
ident = "";
trans_ident = "";
- globals->get_soundmgr()->remove( "adf-ident" );
+ _sgr->remove( "adf-ident" );
last_ident = "";
// cout << "not picking up adf. :-(" << endl;
}
#include <Navaids/navlist.hxx>
#include <Sound/morse.hxx>
+class SGSampleGroup;
class FGKR_87 : public SGSubsystem
{
// internal periodic station search timer
double _time_before_search_sec;
+ SGSampleGroup *_sgr;
+
public:
FGKR_87( SGPropertyNode *node );
inner_blink(false),
name("marker-beacon"),
num(0),
- _time_before_search_sec(0.0)
+ _time_before_search_sec(0.0),
+ _sgr(NULL)
{
SGPath path( globals->get_fg_root() );
SGPath term = path;
if (serviceable->getType() == simgear::props::NONE)
serviceable->setBoolValue( true );
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ _sgr = smgr->find("avionics", true);
+
morse.init();
beacon.init();
blink.stamp();
if ( b == NULL || !inrange || !has_power() || !serviceable->getBoolValue() )
{
// cout << "no marker" << endl;
- globals->get_soundmgr()->stop( "outer-marker" );
- globals->get_soundmgr()->stop( "middle-marker" );
- globals->get_soundmgr()->stop( "inner-marker" );
+ _sgr->stop( "outer-marker" );
+ _sgr->stop( "middle-marker" );
+ _sgr->stop( "inner-marker" );
} else {
string current_sound_name;
current_sound_name = "outer-marker";
// cout << "OUTER MARKER" << endl;
if ( last_beacon != OUTER ) {
- if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) {
+ if ( ! _sgr->exists( current_sound_name ) ) {
SGSoundSample *sound = beacon.get_outer();
if ( sound ) {
- globals->get_soundmgr()->add( sound, current_sound_name );
+ _sgr->add( sound, current_sound_name );
}
}
}
if ( audio_btn->getBoolValue() ) {
- if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) {
- globals->get_soundmgr()->play_looped( current_sound_name );
+ if ( !_sgr->is_playing(current_sound_name) ) {
+ _sgr->play_looped( current_sound_name );
}
} else {
- globals->get_soundmgr()->stop( current_sound_name );
+ _sgr->stop( current_sound_name );
}
} else if ( beacon_type == MIDDLE ) {
middle_marker = true;
current_sound_name = "middle-marker";
// cout << "MIDDLE MARKER" << endl;
if ( last_beacon != MIDDLE ) {
- if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) {
+ if ( ! _sgr->exists( current_sound_name ) ) {
SGSoundSample *sound = beacon.get_middle();
if ( sound ) {
- globals->get_soundmgr()->add( sound, current_sound_name );
+ _sgr->add( sound, current_sound_name );
}
}
}
if ( audio_btn->getBoolValue() ) {
- if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) {
- globals->get_soundmgr()->play_looped( current_sound_name );
+ if ( !_sgr->is_playing(current_sound_name) ) {
+ _sgr->play_looped( current_sound_name );
}
} else {
- globals->get_soundmgr()->stop( current_sound_name );
+ _sgr->stop( current_sound_name );
}
} else if ( beacon_type == INNER ) {
inner_marker = true;
current_sound_name = "inner-marker";
// cout << "INNER MARKER" << endl;
if ( last_beacon != INNER ) {
- if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) {
+ if ( ! _sgr->exists( current_sound_name ) ) {
SGSoundSample *sound = beacon.get_inner();
if ( sound ) {
- globals->get_soundmgr()->add( sound, current_sound_name );
+ _sgr->add( sound, current_sound_name );
}
}
}
if ( audio_btn->getBoolValue() ) {
- if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) {
- globals->get_soundmgr()->play_looped( current_sound_name );
+ if ( !_sgr->is_playing(current_sound_name) ) {
+ _sgr->play_looped( current_sound_name );
}
} else {
- globals->get_soundmgr()->stop( current_sound_name );
+ _sgr->stop( current_sound_name );
}
}
// cout << "VOLUME " << audio_vol->getDoubleValue() << endl;
- SGSoundSample * mkr = globals->get_soundmgr()->find( current_sound_name );
+ SGSoundSample * mkr = _sgr->find( current_sound_name );
if (mkr)
- mkr->set_volume( audio_vol->getDoubleValue() );
+ mkr->set_volume( audio_vol->getFloatValue() );
}
if ( inrange ) {
#include <Sound/beacon.hxx>
#include <Sound/morse.hxx>
+class SGSampleGroup;
class FGMarkerBeacon : public SGSubsystem
{
// internal periodic station search timer
double _time_before_search_sec;
+ SGSampleGroup *_sgr;
+
public:
enum fgMkrBeacType {
SGSoundSample *sample = (*iter).second;
sample->set_pitch(pitch);
- sample->set_offset_pos(position);
- sample->set_orientation(orientation,
- inner_cone,
- outer_cone,
- outer_gain);
+ sample->set_base_position(position); // TODO: tie to listener pos
+ sample->set_orientation(orientation);
+ sample->set_audio_cone(inner_cone, outer_cone, outer_gain);
sample->set_reference_dist(reference_dist);
sample->set_max_dist(max_dist);
}
}
void
-MK_VIII::VoicePlayer::Voice::set_volume (double _volume)
+MK_VIII::VoicePlayer::Voice::set_volume (float _volume)
{
volume = _volume;
volume_changed();
for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++)
delete *iter1;
_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();
}
{
#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay"
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ _sgr = smgr->find("avionics", true);
+
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, "bank-angle", "bank-angle");
std::ostringstream refname;
refname << mk->name << "[" << mk->num << "]" << "/" << name;
- SGSoundMgr *soundmgr = globals->get_soundmgr();
- if (soundmgr->is_working() == false)
- {
- return NULL;
- }
-
- SGSoundSample *sample = soundmgr->find(refname.str());
+ SGSoundSample *sample = _sgr->find(refname.str());
if (! sample)
{
SGPath sample_path(globals->get_fg_root());
exit(1);
}
- soundmgr->add(sample, refname.str());
+ _sgr->add(sample, refname.str());
samples[refname.str()] = sample;
}
}
void
-MK_VIII::VoicePlayer::set_volume (double _volume)
+MK_VIII::VoicePlayer::set_volume (float _volume)
{
volume = _volume;
if (voice)
}
void
-MK_VIII::Mode6Handler::set_volume (double volume)
+MK_VIII::Mode6Handler::set_volume (float volume)
{
mk_voice(minimums_minimums)->set_volume(volume);
mk_voice(five_hundred_above)->set_volume(volume);
using std::deque;
using std::map;
+class SGSampleGroup;
+
#include <Airports/runways.hxx>
#include <Airports/simple.hxx>
#include <Main/globals.hxx>
public:
bool silence;
- virtual inline void play (double volume) {}
+ virtual inline void play (float volume) {}
virtual inline void stop () {}
virtual bool is_playing () = 0;
- virtual inline void set_volume (double volume) {}
+ virtual inline void set_volume (float volume) {}
};
/////////////////////////////////////////////////////////////////////////
class SampleElement : public Element
{
SGSoundSample *_sample;
- double _volume;
+ float _volume;
public:
- inline SampleElement (SGSoundSample *sample, double volume = 1.0)
+ inline SampleElement (SGSoundSample *sample, float volume = 1.0)
: _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 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); }
};
/////////////////////////////////////////////////////////////////////////
inline SilenceElement (double duration)
: _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; }
};
void play ();
void stop (bool now);
- void set_volume (double _volume);
+ void set_volume (float _volume);
void volume_changed ();
void update ();
private:
VoicePlayer *player;
- double volume;
+ float volume;
vector<Element *> elements;
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; }
};
///////////////////////////////////////////////////////////////////////////
struct
{
- double volume;
+ float volume;
} conf;
- double volume;
+ float volume;
Voice *voice;
Voice *next_voice;
};
void stop (unsigned int flags = 0);
- void set_volume (double _volume);
+ void set_volume (float _volume);
void update ();
inline void bind (SGPropertyNode *node) { speaker.bind(node); }
VoicePlayer *player;
double pitch;
- float position[3];
- float orientation[3];
+ SGVec3d position;
+ SGVec3f orientation;
float inner_cone;
float outer_cone;
float outer_gain;
template <class T>
inline T get_property (T *ptr) const { return *ptr; }
- double volume;
+ float volume;
inline Speaker (VoicePlayer *_player)
: player(_player),
MK_VIII *mk;
+ SGSampleGroup *_sgr;
Speaker speaker;
map<string, SGSoundSample *> samples;
void power_off ();
void enter_takeoff ();
void leave_takeoff ();
- void set_volume (double volume);
+ void set_volume (float volume);
bool altitude_callouts_enabled ();
void update ();
_name(node->getStringValue("name", "nav")),
_num(node->getIntValue("number", 0)),
_time_before_search_sec(-1.0),
- _falseCoursesEnabled(true)
+ _falseCoursesEnabled(true),
+ _sgr(NULL)
{
SGPath path( globals->get_fg_root() );
SGPath term = path;
void
FGNavRadio::init ()
{
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ _sgr = smgr->find("avionics", true);
+
morse.init();
string branch;
// play station ident via audio system if on + ident,
// otherwise turn it off
- if (!power_btn_node->getBoolValue()
+ if (!power_btn_node->getBoolValue()
|| !(bus_power_node->getDoubleValue() > 1.0)
|| !ident_btn_node->getBoolValue()
|| !audio_btn_node->getBoolValue() ) {
- globals->get_soundmgr()->stop( nav_fx_name );
- globals->get_soundmgr()->stop( dme_fx_name );
+ _sgr->stop( nav_fx_name );
+ _sgr->stop( dme_fx_name );
return;
}
- SGSoundSample *sound = globals->get_soundmgr()->find( nav_fx_name );
- double vol = vol_btn_node->getDoubleValue();
+ SGSoundSample *sound = _sgr->find( nav_fx_name );
+ double vol = vol_btn_node->getFloatValue();
SG_CLAMP_RANGE(vol, 0.0, 1.0);
if ( sound != NULL ) {
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 ) {
sound->set_volume( vol );
} else {
play_count = ++play_count % NUM_IDENT_SLOTS;
// Previous ident is out of time; if still playing, cut it off:
- globals->get_soundmgr()->stop( nav_fx_name );
- globals->get_soundmgr()->stop( dme_fx_name );
+ _sgr->stop( nav_fx_name );
+ _sgr->stop( dme_fx_name );
if (play_count == 0) { // the DME slot
if (_dmeInRange && dme_serviceable_node->getBoolValue()) {
// play DME ident
- globals->get_soundmgr()->play_once( dme_fx_name );
+ if (vol > 0.05) _sgr->play_once( dme_fx_name );
}
} else { // NAV slot
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);
}
}
}
_gs = NULL;
_dme = NULL;
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);
void FGNavRadio::audioNavidChanged()
{
- if ( globals->get_soundmgr()->exists(nav_fx_name)) {
- globals->get_soundmgr()->remove(nav_fx_name);
+ if (_sgr->exists(nav_fx_name)) {
+ _sgr->remove(nav_fx_name);
}
try {
string trans_ident(_navaid->get_trans_ident());
SGSoundSample* sound = morse.make_ident(trans_ident, LO_FREQUENCY);
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");
}
- if ( globals->get_soundmgr()->exists( dme_fx_name ) ) {
- globals->get_soundmgr()->remove( dme_fx_name );
+ if ( _sgr->exists( dme_fx_name ) ) {
+ _sgr->remove( dme_fx_name );
}
sound = morse.make_ident( trans_ident, HI_FREQUENCY );
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);
play_count = offset / 4;
// forward decls
class SGInterpTable;
+class SGSampleGroup;
class FGNavRecord;
typedef SGSharedPtr<FGNavRecord> FGNavRecordPtr;
// realism setting, are false courses and GS lobes enabled?
bool _falseCoursesEnabled;
+
+ SGSampleGroup *_sgr;
bool updateWithPower(double aDt);
#include <simgear/structure/commands.hxx>
#include <simgear/props/props.hxx>
#include <simgear/structure/event_mgr.hxx>
+#include <simgear/sound/soundmgr_openal.hxx>
#include <Cockpit/panel.hxx>
#include <Cockpit/panel_io.hxx>
static bool
do_play_audio_sample (const SGPropertyNode * arg)
{
- FGFX *fx = (FGFX *)globals->get_subsystem("fx");
string path = arg->getStringValue("path");
string file = arg->getStringValue("file");
double volume = arg->getDoubleValue("volume");
// cout << "playing " << path << " / " << file << endl;
try {
- fx->play_message( path, file, volume );
+ static FGFX *fx = 0;
+ if ( !fx ) {
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ fx = (FGFX *)smgr->find("fx");
+ }
+ if (fx) fx->play_message( path, file, volume );
return true;
} catch (const sg_io_exception&) {
using std::string;
class Sound;
+class SGSoundMgr;
extern const char *default_root;
float init_volume;
// Initialize the ridgelift subsystem
globals->add_subsystem("ridgelift", new FGRidgeLift);
-
////////////////////////////////////////////////////////////////////
// Initialize the aircraft systems and instrumentation (before the
// autopilot.)
fgGetBool("/sim/rendering/bump-mapping", false);
#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.
////////////////////////////////////////////////////////////////////
-
- globals->add_subsystem("fx", new FGFX);
globals->add_subsystem("voice", new FGVoiceMgr);
#endif
////////////////////////////////////////////////////////////////////
globals->add_subsystem("replay", new FGReplay);
+
+ ////////////////////////////////////////////////////////////////////
+ // Add Sound Manager.
+ // Put 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
+ init_volume = fgGetFloat("/sim/sound/volume");
+ fgSetFloat("/sim/sound/volume", 0.0f);
+
+ globals->add_subsystem("soundmgr", new SGSoundMgr);
+#endif
+
////////////////////////////////////////////////////////////////////
// Bind and initialize subsystems.
////////////////////////////////////////////////////////////////////
{
frozen = f;
+#if 0
// Stop sound on a pause
- SGSoundMgr *s = globals->get_soundmgr();
- if ( s != NULL ) {
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ if ( smgr != NULL ) {
if ( f ) {
- s->pause();
+ smgr->suspend();
} else if (!fgGetBool("/sim/sound/pause")) {
- s->resume();
+ smgr->resume();
}
}
+#endif
}
# include <config.h>
#endif
-#include <simgear/sound/soundmgr_openal.hxx>
#include <simgear/structure/commands.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/timing/sg_time.hxx>
matlib( NULL ),
route_mgr( NULL ),
current_panel( NULL ),
- soundmgr( NULL ),
ATC_mgr( NULL ),
AI_mgr( NULL ),
controls( NULL ),
delete matlib;
delete route_mgr;
delete current_panel;
- delete soundmgr;
delete ATC_mgr;
delete AI_mgr;
class SGMaterialLib;
class SGPropertyNode;
class SGTime;
-class SGSoundMgr;
class SGEventMgr;
class SGSubsystemMgr;
class SGSubsystem;
// 2D panel
FGPanel *current_panel;
- // sound manager
- SGSoundMgr *soundmgr;
-
// ATC manager
FGATCMgr *ATC_mgr;
inline FGPanel *get_current_panel() const { return current_panel; }
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 void set_controls( FGControls *c ) { controls = c; }
inline void set_tile_mgr ( FGTileMgr *t ) { tile_mgr = t; }
inline FGFontCache *get_fontcache() const { return fontcache; }
-
+
inline FGNavList *get_navlist() const { return navlist; }
inline void set_navlist( FGNavList *n ) { navlist = n; }
inline FGNavList *get_loclist() const { return loclist; }
#include <Model/acmodel.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
+#include <Sound/fg_fx.hxx>
#include <Sound/beacon.hxx>
#include <Sound/morse.hxx>
#include <Sound/fg_fx.hxx>
// update the view angle as late as possible, but before sound calculations
globals->get_viewmgr()->update(real_delta_time_sec);
- // Run audio scheduler
-#ifdef ENABLE_AUDIO_SUPPORT
- FGFX* fx = (FGFX*) globals->get_subsystem("fx");
- fx->update_fx_late(delta_time_sec);
-#endif
-
// END Tile Manager udpates
if (!scenery_loaded && globals->get_tile_mgr()->isSceneryLoaded()
&& cur_fdm_state->get_inited()) {
fgSetBool("sim/sceneryloaded",true);
fgSetFloat("/sim/sound/volume", init_volume);
- globals->get_soundmgr()->set_volume(init_volume);
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ smgr->set_volume(init_volume);
}
fgRequestRedraw();
SG_LOG( SG_GENERAL, SG_INFO,
"Starting intro music: " << mp3file.str() );
-#if defined( __CYGWIN__ )
+# if defined( __CYGWIN__ )
string command = "start /m `cygpath -w " + mp3file.str() + "`";
-#elif defined( WIN32 )
+# elif defined( WIN32 )
string command = "start /m " + mp3file.str();
-#else
+# else
string command = "mpg123 " + mp3file.str() + "> /dev/null 2>&1";
-#endif
+# endif
system ( command.c_str() );
}
#include <string.h> // strcmp
#include <simgear/compiler.h>
+#include <simgear/sound/soundmgr_openal.hxx>
#include <Model/acmodel.hxx>
#include <Main/viewer.hxx>
#include <Main/fg_props.hxx>
do_axes();
view->update(dt);
abs_viewer_position = loop_view->getViewPosition();
+
+ // update audio listener values
+ static SGSoundMgr *smgr = 0;
+ if (!smgr) smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ if (smgr) {
+ // set the viewer posotion in Cartesian coordinates in meters
+ smgr->set_position(abs_viewer_position);
+ smgr->set_orientation(loop_view->getViewOrientation());
+//TODO: should be in meters per second
+// smr->set_veloicty(SGVec3f(0,0,0));
+ }
}
void
#include <Main/viewmgr.hxx>
#include <Main/viewer.hxx>
#include <Scenery/scenery.hxx>
+#include <Sound/fg_fx.hxx>
#include "model_panel.hxx"
#include "acmodel.hxx"
+
\f
////////////////////////////////////////////////////////////////////////
// Implementation of FGAircraftModel
////////////////////////////////////////////////////////////////////////
FGAircraftModel::FGAircraftModel ()
- : _aircraft(0)
+ : _aircraft(0),
+ _fx(0),
+ _lon(0),
+ _lat(0),
+ _alt(0),
+ _pitch(0),
+ _roll(0),
+ _heading(0),
+ _speed_north(0),
+ _speed_east(0),
+ _speed_up(0)
{
}
void
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_north = fgGetNode("/velocities/speed-north-fps", true);
+ _speed_east = fgGetNode("/velocities/speed-east-fps", true);
+ _speed_up = fgGetNode("/velocities/vertical-speed-fps", true);
}
void
_aircraft->setVisible(true);
}
- _aircraft->setPosition(fgGetDouble("/position/longitude-deg"),
- fgGetDouble("/position/latitude-deg"),
- fgGetDouble("/position/altitude-ft"));
- _aircraft->setOrientation(fgGetDouble("/orientation/roll-deg"),
- fgGetDouble("/orientation/pitch-deg"),
- fgGetDouble("/orientation/heading-deg"));
+ _aircraft->setPosition(_lon->getDoubleValue(),
+ _lat->getDoubleValue(),
+ _alt->getDoubleValue());
+ _aircraft->setOrientation(_roll->getDoubleValue(),
+ _pitch->getDoubleValue(),
+ _heading->getDoubleValue());
_aircraft->update();
+
+ if ( !_fx) {
+ SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr");
+ if (smgr) {
+ _fx = new FGFX(smgr, "fx");
+ _fx->init();
+ }
+ }
+
+ if (_fx) {
+ // Get the Cartesian coordinates in meters
+ SGVec3d pos = SGVec3d::fromGeod(_aircraft->getPosition());
+ _fx->set_position( pos );
+
+ SGQuatd orient_m = SGQuatd::fromLonLat(_aircraft->getPosition());
+ orient_m *= SGQuatd::fromYawPitchRollDeg(_heading->getDoubleValue(),
+ _pitch->getDoubleValue(),
+ _roll->getDoubleValue());
+ SGVec3d orient = orient_m.rotateBack(SGVec3d::e1());
+ _fx->set_orientation( toVec3f(orient) );
+
+ SGVec3f vel = SGVec3f( _speed_north->getFloatValue(),
+ _speed_east->getFloatValue(),
+ _speed_up->getFloatValue());
+// TODO: rotate to properly align with the model orientation
+
+ _fx->set_velocity( vel*SG_FEET_TO_METER );
+ }
}
// Don't pull in the headers, since we don't need them here.
class SGModelPlacement;
-
+class FGFX;
class FGAircraftModel : public SGSubsystem
{
private:
SGModelPlacement * _aircraft;
+ FGFX * _fx;
+
+ SGPropertyNode * _lon;
+ SGPropertyNode * _lat;
+ SGPropertyNode * _alt;
+ SGPropertyNode * _pitch;
+ SGPropertyNode * _roll;
+ SGPropertyNode * _heading;
+ SGPropertyNode * _speed_north;
+ SGPropertyNode * _speed_east;
+ SGPropertyNode * _speed_up;
+
};
#endif // __ACMODEL_HXX
#include "beacon.hxx"
#include <simgear/structure/exception.hxx>
-#include <Main/fg_props.hxx>
-#include <Main/globals.hxx>
// constructor
FGBeacon::FGBeacon()
int len;
unsigned char *ptr;
- if (globals->get_soundmgr()->is_working() == false) {
- return false;
- }
-
- unsigned char inner_buf[ INNER_SIZE ] ;
- unsigned char middle_buf[ MIDDLE_SIZE ] ;
- unsigned char outer_buf[ OUTER_SIZE ] ;
+ unsigned char *inner_buf = new unsigned char[ INNER_SIZE ] ;
+ unsigned char *middle_buf = new unsigned char[ MIDDLE_SIZE ] ;
+ unsigned char *outer_buf = new unsigned char[ OUTER_SIZE ] ;
// Make inner marker beacon sound
len= (int)(INNER_DIT_LEN / 2.0 );
ptr += 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_max_dist( 20.0 );
} catch ( sg_io_exception &e ) {
#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 <simgear/sound/xmlsound.hxx>
#include <Main/fg_props.hxx>
#include <Model/acmodel.hxx>
#include <Main/viewer.hxx>
-FGFX::FGFX () :
+FGFX::FGFX ( SGSoundMgr *smgr, const string &refname ) :
last_visitor_pos(SGVec3d::zeros()),
last_model_pos(SGVec3d::zeros()),
last_pause( true ),
_pause( fgGetNode("/sim/sound/pause") ),
_volume( fgGetNode("/sim/sound/volume") )
{
+ SGSampleGroup::_smgr = smgr;
+ SGSampleGroup::_smgr->add(this, refname);
+ SGSampleGroup::_active = _smgr->is_working();
}
+
FGFX::~FGFX ()
{
unsigned int i;
}
}
+
void
FGFX::init()
{
SGXmlSound *sound = new SGXmlSound();
try {
- sound->init(globals->get_props(), node->getChild(i),
- globals->get_soundmgr(), globals->get_fg_root());
+ sound->init(globals->get_props(), node->getChild(i), this,
+ globals->get_fg_root());
_sound.push_back(sound);
} catch ( sg_exception &e ) {
}
}
+
void
FGFX::reinit()
{
- _sound.clear();
- init();
+ _sound.clear();
+ init();
};
-void
-FGFX::bind ()
-{
-}
-
-void
-FGFX::unbind ()
-{
-}
void
FGFX::update (double dt)
{
- SGSoundMgr *smgr = globals->get_soundmgr();
-
- if (smgr->is_working() == false) {
- return;
- }
-
// command sound manger
- bool pause = _pause->getBoolValue();
- if ( pause != last_pause ) {
- if ( pause ) {
- smgr->pause();
+ bool new_pause = _pause->getBoolValue();
+ if ( new_pause != last_pause ) {
+ if ( new_pause ) {
+ suspend();
} else {
- smgr->resume();
+ resume();
}
- last_pause = pause;
+ last_pause = new_pause;
}
// process mesage queue
const string msgid = "Sequential Audio Message";
- bool is_playing = false;
- if ( smgr->exists( msgid ) ) {
- if ( smgr->is_playing( msgid ) ) {
+ bool now_playing = false;
+ if ( exists( msgid ) ) {
+ if ( is_playing( msgid ) ) {
// still playing, do nothing
- is_playing = true;
+ now_playing = true;
} else {
// current message finished, stop and remove
- smgr->stop( msgid ); // removes source
- smgr->remove( msgid ); // removes buffer
+ stop( msgid ); // removes source
+ remove( msgid ); // removes buffer
}
}
- if ( !is_playing ) {
+ if ( !now_playing ) {
// message queue idle, add next sound if we have one
if ( _samplequeue.size() > 0 ) {
- smgr->add( _samplequeue.front(), msgid );
+ add( _samplequeue.front(), msgid );
_samplequeue.pop();
- smgr->play_once( msgid );
+ play_once( msgid );
}
}
double volume = _volume->getDoubleValue();
if ( volume != last_volume ) {
- smgr->set_volume( volume );
+ set_volume( volume );
last_volume = volume;
}
- if ( !pause ) {
+ if ( !new_pause ) {
// update sound effects if not paused
for ( unsigned int i = 0; i < _sound.size(); i++ ) {
_sound[i]->update(dt);
}
}
-}
-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);
+ SGSampleGroup::update(dt);
}
/**
void
FGFX::play_message( SGSoundSample *_sample )
{
- _samplequeue.push( _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() );
+ SGSoundSample *sample = new SGSoundSample( path.c_str(), fname.c_str() );
+ sample->set_volume( volume );
+ play_message( sample );
}
// end of fg_fx.cxx
#include <vector>
#include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/sound/sample_group.hxx>
#include <simgear/math/SGMath.hxx>
class SGXmlSound;
-class SGSoundSample;
-class SGSoundMgr;
/**
* 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
* before this object is.
*
* This second mechanims is useful for things like tutorial messages or
* background atc chatter.
*/
-class FGFX : public SGSubsystem
+class FGFX : public SGSampleGroup
{
public:
- FGFX ();
+ FGFX ( SGSoundMgr *smgr, const string &refname );
virtual ~FGFX ();
virtual void init ();
virtual void reinit ();
- virtual void bind ();
- virtual void unbind ();
virtual void update (double dt);
/**
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:
- void update_pos_and_orientation(SGSoundMgr *smgr, double dt);
+ void update_pos_and_orientation(double dt);
+
SGVec3d last_visitor_pos;
SGVec3d last_model_pos;
#include <simgear/constants.h>
-#include <Main/fg_props.hxx>
-#include <Main/globals.hxx>
-
#include "morse.hxx"
// make a SGSoundSample morse code transmission for the specified string
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();
int length = 0;
SGSoundSample *sample = new SGSoundSample( buffer, length,
BYTES_PER_SECOND );
- // clean up the buffer
- delete [] buffer;
-
sample->set_reference_dist( 10.0 );
sample->set_max_dist( 20.0 );