diff --git a/src/Sound/fg_sound.cxx b/src/Sound/fg_sound.cxx index c8bb87eed..1cbbd242d 100644 --- a/src/Sound/fg_sound.cxx +++ b/src/Sound/fg_sound.cxx @@ -37,12 +37,13 @@ FGSound::FGSound(const SGPropertyNode * node) : _name(""), + _sample(0), _factor(1.0), _active(false), _mode(FGSound::ONCE), - _type(FGSound::LEVEL) + _type(FGSound::LEVEL), + _node(node) { - _node = node; } FGSound::~FGSound() @@ -53,7 +54,6 @@ FGSound::~FGSound() void FGSound::init() { - FGSoundMgr * mgr = globals->get_soundmgr(); vector kids; float p = 0.0; float v = 0.0; @@ -204,12 +204,10 @@ FGSound::init() // // Initialize the sample // - _sample = new FGSimpleSound(_node->getStringValue("path")); + FGSoundMgr * mgr = globals->get_soundmgr(); + _sample = mgr->add(_name, _node->getStringValue("path")); _sample->set_volume(v); _sample->set_pitch(p); - - if (!mgr->exists(_name)) - mgr->add(_sample, _name); } void @@ -235,12 +233,22 @@ FGSound::update (int dt) // if (!_property) // return; - i = _property->getFloatValue() * _factor; - if (_type == FGSound::INVERTED) - i = !i; - if ((_type == FGSound::LEVEL) || (_type == FGSound::INVERTED)) { - if (i == 0) { + + // + // If the sound is already playing we have nothing to do. + // + if (_active && (_mode == FGSound::ONCE)) + return; + + int check = _property->getFloatValue() * _factor; + if (_type == FGSound::INVERTED) + check = !check; + + // + // If the state changes to false, stop playing. + // + if (check == 0) { _active = false; if (mgr->is_playing(_name)) { SG_LOG(SG_GENERAL, SG_INFO, "Stopping sound: " << _name); @@ -250,12 +258,10 @@ FGSound::update (int dt) return; } - if (_active && (_mode == FGSound::ONCE)) - return; - } else { // FGSound::FLIPFLOP - if ((bool)i == _active) + bool check = _property->getFloatValue() * _factor; + if (check == _active) return; // @@ -272,6 +278,7 @@ FGSound::update (int dt) // Update the volume // int max = _volume.size(); + double volume = 1.0, volume_offset = 0.0; for(i = 0; i < max; i++) { double v = _volume[i].prop->getDoubleValue(); diff --git a/src/Sound/soundmgr.cxx b/src/Sound/soundmgr.cxx index 834632fba..aa4b6f4f0 100644 --- a/src/Sound/soundmgr.cxx +++ b/src/Sound/soundmgr.cxx @@ -81,12 +81,26 @@ FGSoundMgr::FGSoundMgr() { // destructor FGSoundMgr::~FGSoundMgr() { - sound_map_iterator current = sounds.begin(); - sound_map_iterator end = sounds.end(); - for ( ; current != end; ++current ) { - FGSimpleSound *s = current->second; - delete s->get_sample(); - delete s; + + // + // Remove the samples from the sample manager. + // + sample_map_iterator sample_current = samples.begin(); + sample_map_iterator sample_end = samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + sample_ref *sr = sample_current->second; + delete sr->sample; + delete sr; + } + + // + // Remove the sounds from the sound manager. + // + sound_map_iterator sound_current = sounds.begin(); + sound_map_iterator sound_end = sounds.end(); + for ( ; sound_current != sound_end; ++sound_current ) { + FGSimpleSound *s = sound_current->second; + delete s; } delete audio_sched; @@ -102,10 +116,26 @@ void FGSoundMgr::init() { // audio_mixer -> setMasterVolume ( 80 ) ; /* 80% of max volume. */ audio_sched -> setSafetyMargin ( FG_SOUND_SAFETY_MULT * safety ) ; - sound_map_iterator current = sounds.begin(); - sound_map_iterator end = sounds.end(); - for ( ; current != end; ++current ) { - FGSimpleSound *s = current->second; + + // + // Remove the samples from the sample manager. + // + sample_map_iterator sample_current = samples.begin(); + sample_map_iterator sample_end = samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + sample_ref *sr = sample_current->second; + delete sr->sample; + delete sr; + } + samples.clear(); + + // + // Remove the sounds from the sound manager. + // + sound_map_iterator sound_current = sounds.begin(); + sound_map_iterator sound_end = sounds.end(); + for ( ; sound_current != sound_end; ++sound_current ) { + FGSimpleSound *s = sound_current->second; delete s->get_sample(); delete s; } @@ -149,12 +179,53 @@ void FGSoundMgr::update(int dt) { // add a sound effect, return true if successful -bool FGSoundMgr::add( FGSimpleSound *sound, const string& refname ) { +bool FGSoundMgr::add( FGSimpleSound *sound, const string& refname ) { + + sample_map_iterator it = samples.find(refname); + if (it != samples.end()) + return false; + + sample_ref *sr = new sample_ref; + + sr->n=1; + sr->sample = sound->get_sample(); + samples[refname] = sr; + sounds[refname] = sound; return true; } +// add a sound from a file, return the sample if successful, else return NULL +FGSimpleSound *FGSoundMgr::add( const string& refname, const string &file ) { + FGSimpleSound *sound; + + if (file == (string)"") + return NULL; + + sample_map_iterator it = samples.find(file); + if (it == samples.end()) { + sound = new FGSimpleSound(file); + sounds[refname] = sound; + + sample_ref *sr = new sample_ref; + + sr->n=1; + sr->sample = sound->get_sample(); + samples[file] = sr; + + } else { + sample_ref *sr = it->second; + + sr->n++; + sound = + new FGSimpleSound(sr->sample->getBuffer(), sr->sample->getLength()); + sounds[refname] = sound; + + } + + return sound; +} // remove a sound effect, return true if successful bool FGSoundMgr::remove( const string& refname ) { @@ -182,7 +253,12 @@ bool FGSoundMgr::remove( const string& refname ) { // cout << "Still playing " << sample->get_sample()->getPlayCount() // << " instances!" << endl; - delete sample; + // + // FIXME: + // Due to the change in the sound manager, samples live + // until the sound manager gets removed. + // + // delete sample; sounds.erase( it ); return true; diff --git a/src/Sound/soundmgr.hxx b/src/Sound/soundmgr.hxx index c8809d002..2c7563905 100644 --- a/src/Sound/soundmgr.hxx +++ b/src/Sound/soundmgr.hxx @@ -79,6 +79,16 @@ public: }; +typedef struct { + int n; + slSample *sample; +} sample_ref; + +typedef map < string, sample_ref * > sample_map; +typedef sample_map::iterator sample_map_iterator; +typedef sample_map::const_iterator const_sample_map_iterator; + + typedef map < string, FGSimpleSound * > sound_map; typedef sound_map::iterator sound_map_iterator; typedef sound_map::const_iterator const_sound_map_iterator; @@ -89,7 +99,9 @@ class FGSoundMgr : public FGSubsystem slScheduler *audio_sched; smMixer *audio_mixer; + sound_map sounds; + sample_map samples; SGTimeStamp last; double safety; @@ -128,7 +140,10 @@ public: inline bool is_working() const { return !audio_sched->notWorking(); } // add a sound effect, return true if successful - bool add( FGSimpleSound *sound, const string& refname ); + bool add( FGSimpleSound *sound, const string& refname); + + // add a sound file, return the sample if successful, else return NULL + FGSimpleSound *add( const string& refname, const string& file = "" ); // remove a sound effect, return true if successful bool remove( const string& refname );