X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FSound%2Fsoundmgr.cxx;h=b303a11cdcfe8acf06b38fd16d24df29969c31d7;hb=198b88ca9b4a4b123b2e9ccdc85ea17eeaea70c6;hp=76f041bec9209d0336742e020476b22f93b726a2;hpb=1de5373ed91e657bf3723619ec3ce8b036831f14;p=flightgear.git diff --git a/src/Sound/soundmgr.cxx b/src/Sound/soundmgr.cxx index 76f041bec..b303a11cd 100644 --- a/src/Sound/soundmgr.cxx +++ b/src/Sound/soundmgr.cxx @@ -34,8 +34,15 @@ #define FG_SOUND_SAFETY_MULT 3 #define FG_MAX_SOUND_SAFETY ( 1.0 / FG_SOUND_SAFETY_MULT ) +// +// SimpleSound +// + // constructor -FGSimpleSound::FGSimpleSound( string file ) { +FGSimpleSound::FGSimpleSound( string file ) + : pitch(1.0), + volume(1.0) +{ SGPath slfile( globals->get_fg_root() ); slfile.append( file ); sample = new slSample ( (char *)slfile.c_str() ); @@ -45,7 +52,10 @@ FGSimpleSound::FGSimpleSound( string file ) { volume_envelope->setStep ( 0, 0.01, 1.0 ); } -FGSimpleSound::FGSimpleSound( unsigned char *buffer, int len ) { +FGSimpleSound::FGSimpleSound( unsigned char *buffer, int len ) + : pitch(1.0), + volume(1.0) +{ sample = new slSample ( buffer, len ); pitch_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT ); volume_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT ); @@ -60,28 +70,78 @@ FGSimpleSound::~FGSimpleSound() { delete sample; } +void FGSimpleSound::play( slScheduler *sched, bool looped ) { + + // make sure sound isn't already playing + if ( sample->getPlayCount() > 0 ) { + sched->stopSample(sample); + // return; + } + + if ( looped ) { + sched->loopSample(sample); + } else { + sched->playSample(sample); + } + + sched->addSampleEnvelope(sample, 0, 0, pitch_envelope, SL_PITCH_ENVELOPE); + sched->addSampleEnvelope(sample, 0, 1, volume_envelope, SL_VOLUME_ENVELOPE); +} + +void FGSimpleSound::stop( slScheduler *sched, bool quick ) { + + sched->stopSample( sample ); +} + +// +// Sound Manager +// // constructor FGSoundMgr::FGSoundMgr() { audio_sched = new slScheduler( 8000 ); - audio_sched -> setMaxConcurrent ( 6 ); + if ( audio_sched->notWorking() ) { + SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" ); + } else { + audio_sched -> setMaxConcurrent ( 6 ); - audio_mixer = new smMixer; + audio_mixer = new smMixer; - SG_LOG( SG_GENERAL, SG_INFO, - "Rate = " << audio_sched->getRate() - << " Bps = " << audio_sched->getBps() - << " Stereo = " << audio_sched->getStereo() ); + SG_LOG( SG_GENERAL, SG_INFO, + "Rate = " << audio_sched->getRate() + << " Bps = " << audio_sched->getBps() + << " Stereo = " << audio_sched->getStereo() ); + } } // 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; + + audio_sched->stopSample(sr->sample); + 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; + + audio_sched->stopSample(s->get_sample()); + delete s->get_sample(); + delete s; } delete audio_sched; @@ -90,42 +150,62 @@ FGSoundMgr::~FGSoundMgr() { // initialize the sound manager -bool FGSoundMgr::init() { - last.stamp(); +void FGSoundMgr::init() { safety = FG_MAX_SOUND_SAFETY; // 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; + + audio_sched->stopSample(sr->sample); + 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; + + audio_sched->stopSample(s->get_sample()); delete s->get_sample(); delete s; } sounds.clear(); - if ( audio_sched->not_working() ) { - return false; - } else { - return true; - } } -// run the audio scheduler -bool FGSoundMgr::update() { - SGTimeStamp current; - current.stamp(); +void FGSoundMgr::bind () +{ + // no properties yet +} - double elapsed = (double)(current - last) / 1000000.0; - last = current; - if ( elapsed > safety ) { - safety = elapsed; +void FGSoundMgr::unbind () +{ + // no properties yet +} + + +// run the audio scheduler +void FGSoundMgr::update( double dt ) { + if ( dt > safety ) { + safety = dt; } else { - safety = safety * 0.99 + elapsed * 0.01; + safety = safety * 0.99 + dt * 0.01; } if ( safety > FG_MAX_SOUND_SAFETY ) { safety = FG_MAX_SOUND_SAFETY; @@ -133,23 +213,85 @@ bool FGSoundMgr::update() { // cout << "safety = " << safety << endl; audio_sched -> setSafetyMargin ( FG_SOUND_SAFETY_MULT * safety ) ; - if ( !audio_sched->not_working() ) { + if ( !audio_sched->not_working() ) audio_sched -> update(); - return true; - } else { - return false; - } +} + + +void +FGSoundMgr::pause () +{ + audio_sched->pauseSample(0, 0); +} + + +void +FGSoundMgr::resume () +{ + audio_sched->resumeSample(0, 0); } // add a sound effect, return true if successful -bool FGSoundMgr::add( FGSimpleSound *sound, const string& refname ) { +bool FGSoundMgr::add( FGSimpleSound *sound, const string& refname ) { + + sound_map_iterator sound_it = sounds.find( refname ); + if ( sound_it != sounds.end() ) { + // sound already exists + return false; + } + + sample_map_iterator sample_it = samples.find( refname ); + if ( sample_it != samples.end() ) { + // this sound has existed in the past and it's sample is still + // here, delete the sample so we can replace it. + samples.erase( sample_it ); + } + + 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.empty()) + 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 ) { @@ -170,35 +312,25 @@ bool FGSoundMgr::remove( const string& refname ) { NULL, SL_VOLUME_ENVELOPE ); -#if defined ( PLIB_1_2_X ) - // if PLIB_1_2_X, we can't reliably remove sounds - // that are currently being played. :-( So, let's just not - // remove them and return false. The effects of this are that - // the sound sample will continue to finish playing (or - // continue to loop forever.) And the sound sample will - // remain registered in the plib audio system. This is a - // memory leak, and eventually this could cause us to max out - // the total number of allowed sound samples in plib, but what - // are you going to do? Hopefully the plib team will do a new - // stable relase with these problems fixed. - - // cout << "plib broken audio, skipping actual remove" << endl; - - return false; -#else // must call audio_sched->update() after stopping the sound // but before deleting it. audio_sched -> update(); // 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 ); + // cout << "sndmgr: removed -> " << refname << endl; return true; -#endif - } else { - return false; + } else { + // cout << "sndmgr: failed remove -> " << refname << endl; + return false; } } @@ -220,7 +352,7 @@ FGSimpleSound *FGSoundMgr::find( const string& refname ) { sound_map_iterator it = sounds.find( refname ); if ( it != sounds.end() ) { return it->second; - } else { + } else { return NULL; } } @@ -229,66 +361,46 @@ FGSimpleSound *FGSoundMgr::find( const string& refname ) { // tell the scheduler to play the indexed sample in a continuous // loop bool FGSoundMgr::play_looped( const string& refname ) { - sound_map_iterator it = sounds.find( refname ); - if ( it != sounds.end() ) { - FGSimpleSound *sample = it->second; - audio_sched->loopSample( sample->get_sample() ); - audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0, - sample->get_pitch_envelope(), - SL_PITCH_ENVELOPE ); - audio_sched->addSampleEnvelope( sample->get_sample(), 0, 1, - sample->get_volume_envelope(), - SL_VOLUME_ENVELOPE ); - - return true; - } else { - return false; - } + FGSimpleSound *sample; + + if ((sample = find( refname )) == NULL) + return false; + + sample->play(audio_sched, true); + return true; } // tell the scheduler to play the indexed sample once bool FGSoundMgr::play_once( const string& refname ) { - sound_map_iterator it = sounds.find( refname ); - if ( it != sounds.end() ) { - FGSimpleSound *sample = it->second; - audio_sched->stopSample( sample->get_sample() ); - audio_sched->playSample( sample->get_sample() ); - audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0, - sample->get_pitch_envelope(), - SL_PITCH_ENVELOPE ); - audio_sched->addSampleEnvelope( sample->get_sample(), 0, 1, - sample->get_volume_envelope(), - SL_VOLUME_ENVELOPE ); - - return true; - } else { - return false; - } + FGSimpleSound *sample; + + if ((sample = find( refname )) == NULL) + return false; + + sample->play(audio_sched, false); + return true; } // return true of the specified sound is currently being played bool FGSoundMgr::is_playing( const string& refname ) { - sound_map_iterator it = sounds.find( refname ); - if ( it != sounds.end() ) { - FGSimpleSound *sample = it->second; - return (sample->get_sample()->getPlayCount() > 0 ); - return true; - } else { - return false; - } + FGSimpleSound *sample; + + if ((sample = find( refname )) == NULL) + return false; + + return (sample->get_sample()->getPlayCount() > 0 ); } // immediate stop playing the sound bool FGSoundMgr::stop( const string& refname ) { - sound_map_iterator it = sounds.find( refname ); - if ( it != sounds.end() ) { - FGSimpleSound *sample = it->second; - audio_sched->stopSample( sample->get_sample() ); - return true; - } else { - return false; - } + FGSimpleSound *sample; + + if ((sample = find( refname )) == NULL) + return false; + + audio_sched->stopSample( sample->get_sample() ); + return true; }