From d8b6786d20a6762b31ccdfded78b1b5da9ac56e3 Mon Sep 17 00:00:00 2001 From: curt Date: Mon, 4 Mar 2002 16:03:11 +0000 Subject: [PATCH] This patch creates a sample manager next to the sound manager. The difference between the two is this: A sample is file related and sound is a authonomus entity. This means you can have several sounds pointing to a single sample. In that case, just one sample is loaded into memory. The advantage is you can play the same sample with different pitch or volume, but with just one sample loaded into memory. To fully support this there is a new fucntion call: FGSimpleSound *sample = new FGSimpleSound("filename"); mgr->add(sample, "name"); should be replaced by: FGSimpleSound *sample = mgr->add("name", "filename"); But the old behaviour is still supported with one minor change, sounds with the same name aren't supported anymore. Erik --- src/Sound/fg_sound.cxx | 39 +++++++++------- src/Sound/soundmgr.cxx | 100 ++++++++++++++++++++++++++++++++++++----- src/Sound/soundmgr.hxx | 17 ++++++- 3 files changed, 127 insertions(+), 29 deletions(-) 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 );