Extract the sound code from FlightGear and move it to SimGear
This commit is contained in:
parent
228d6b2f29
commit
5ecfcca7e4
21 changed files with 47 additions and 1175 deletions
|
@ -18,9 +18,10 @@
|
||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
#include <simgear/sound/soundmgr.hxx>
|
||||||
|
|
||||||
#include <Main/fgfs.hxx>
|
#include <Main/fgfs.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include <Sound/soundmgr.hxx>
|
|
||||||
|
|
||||||
#include "ATC.hxx"
|
#include "ATC.hxx"
|
||||||
#include "ATCdisplay.hxx"
|
#include "ATCdisplay.hxx"
|
||||||
|
@ -73,7 +74,7 @@ void FGATC::Render(string msg, string refname, bool repeating) {
|
||||||
int len;
|
int len;
|
||||||
unsigned char* buf = vPtr->WriteMessage((char*)msg.c_str(), len, voice);
|
unsigned char* buf = vPtr->WriteMessage((char*)msg.c_str(), len, voice);
|
||||||
if(voice) {
|
if(voice) {
|
||||||
FGSimpleSound* simple = new FGSimpleSound(buf, len);
|
SimpleSound* simple = new SimpleSound(buf, len);
|
||||||
// TODO - at the moment the volume is always set off comm1
|
// TODO - at the moment the volume is always set off comm1
|
||||||
// and can't be changed after the transmission has started.
|
// and can't be changed after the transmission has started.
|
||||||
simple->set_volume(5.0 * fgGetDouble("/radios/comm[0]/volume"));
|
simple->set_volume(5.0 * fgGetDouble("/radios/comm[0]/volume"));
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include <Main/viewmgr.hxx>
|
#include <Main/viewmgr.hxx>
|
||||||
#include <Sound/fg_fx.hxx>
|
|
||||||
#include <Sound/soundmgr.hxx>
|
|
||||||
#include <Cockpit/panel.hxx>
|
#include <Cockpit/panel.hxx>
|
||||||
#include <Cockpit/hud.hxx>
|
#include <Cockpit/hud.hxx>
|
||||||
#include <Cockpit/panel_io.hxx>
|
#include <Cockpit/panel_io.hxx>
|
||||||
|
|
|
@ -445,7 +445,7 @@ void FGKR_87::update( double dt ) {
|
||||||
// play station ident via audio system if on + ant mode,
|
// play station ident via audio system if on + ant mode,
|
||||||
// otherwise turn it off
|
// otherwise turn it off
|
||||||
if ( vol_btn >= 0.01 && audio_btn ) {
|
if ( vol_btn >= 0.01 && audio_btn ) {
|
||||||
FGSimpleSound *sound;
|
SimpleSound *sound;
|
||||||
sound = globals->get_soundmgr()->find( "adf-ident" );
|
sound = globals->get_soundmgr()->find( "adf-ident" );
|
||||||
if ( sound != NULL ) {
|
if ( sound != NULL ) {
|
||||||
if ( !adf_btn ) {
|
if ( !adf_btn ) {
|
||||||
|
@ -514,7 +514,7 @@ void FGKR_87::search() {
|
||||||
if ( globals->get_soundmgr()->exists( "adf-ident" ) ) {
|
if ( globals->get_soundmgr()->exists( "adf-ident" ) ) {
|
||||||
globals->get_soundmgr()->remove( "adf-ident" );
|
globals->get_soundmgr()->remove( "adf-ident" );
|
||||||
}
|
}
|
||||||
FGSimpleSound *sound;
|
SimpleSound *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" );
|
globals->get_soundmgr()->add( sound, "adf-ident" );
|
||||||
|
|
|
@ -193,7 +193,7 @@ void FGMarkerBeacon::search()
|
||||||
// cout << "OUTER MARKER" << endl;
|
// cout << "OUTER MARKER" << endl;
|
||||||
if ( last_beacon != FGMkrBeacon::OUTER ) {
|
if ( last_beacon != FGMkrBeacon::OUTER ) {
|
||||||
if ( ! globals->get_soundmgr()->exists( "outer-marker" ) ) {
|
if ( ! globals->get_soundmgr()->exists( "outer-marker" ) ) {
|
||||||
FGSimpleSound *sound = beacon.get_outer();
|
SimpleSound *sound = beacon.get_outer();
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
globals->get_soundmgr()->add( sound, "outer-marker" );
|
globals->get_soundmgr()->add( sound, "outer-marker" );
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ void FGMarkerBeacon::search()
|
||||||
// cout << "MIDDLE MARKER" << endl;
|
// cout << "MIDDLE MARKER" << endl;
|
||||||
if ( last_beacon != FGMkrBeacon::MIDDLE ) {
|
if ( last_beacon != FGMkrBeacon::MIDDLE ) {
|
||||||
if ( ! globals->get_soundmgr()->exists( "middle-marker" ) ) {
|
if ( ! globals->get_soundmgr()->exists( "middle-marker" ) ) {
|
||||||
FGSimpleSound *sound = beacon.get_middle();
|
SimpleSound *sound = beacon.get_middle();
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
globals->get_soundmgr()->add( sound, "middle-marker" );
|
globals->get_soundmgr()->add( sound, "middle-marker" );
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ void FGMarkerBeacon::search()
|
||||||
// cout << "INNER MARKER" << endl;
|
// cout << "INNER MARKER" << endl;
|
||||||
if ( last_beacon != FGMkrBeacon::INNER ) {
|
if ( last_beacon != FGMkrBeacon::INNER ) {
|
||||||
if ( ! globals->get_soundmgr()->exists( "inner-marker" ) ) {
|
if ( ! globals->get_soundmgr()->exists( "inner-marker" ) ) {
|
||||||
FGSimpleSound *sound = beacon.get_inner();
|
SimpleSound *sound = beacon.get_inner();
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
globals->get_soundmgr()->add( sound, "inner-marker" );
|
globals->get_soundmgr()->add( sound, "inner-marker" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -410,7 +410,7 @@ FGNavCom::update(double dt)
|
||||||
if ( power_btn && (bus_power->getDoubleValue() > 1.0)
|
if ( power_btn && (bus_power->getDoubleValue() > 1.0)
|
||||||
&& nav_ident_btn && audio_btn )
|
&& nav_ident_btn && audio_btn )
|
||||||
{
|
{
|
||||||
FGSimpleSound *sound;
|
SimpleSound *sound;
|
||||||
sound = globals->get_soundmgr()->find( nav_fx_name );
|
sound = globals->get_soundmgr()->find( nav_fx_name );
|
||||||
if ( sound != NULL ) {
|
if ( sound != NULL ) {
|
||||||
sound->set_volume( nav_vol_btn );
|
sound->set_volume( nav_vol_btn );
|
||||||
|
@ -522,7 +522,7 @@ void FGNavCom::search()
|
||||||
if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
|
if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
|
||||||
globals->get_soundmgr()->remove( nav_fx_name );
|
globals->get_soundmgr()->remove( nav_fx_name );
|
||||||
}
|
}
|
||||||
FGSimpleSound *sound;
|
SimpleSound *sound;
|
||||||
sound = morse.make_ident( nav_trans_ident, LO_FREQUENCY );
|
sound = morse.make_ident( nav_trans_ident, LO_FREQUENCY );
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
globals->get_soundmgr()->add( sound, nav_fx_name );
|
globals->get_soundmgr()->add( sound, nav_fx_name );
|
||||||
|
@ -572,7 +572,7 @@ void FGNavCom::search()
|
||||||
if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
|
if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
|
||||||
globals->get_soundmgr()->remove( nav_fx_name );
|
globals->get_soundmgr()->remove( nav_fx_name );
|
||||||
}
|
}
|
||||||
FGSimpleSound *sound;
|
SimpleSound *sound;
|
||||||
sound = morse.make_ident( nav_trans_ident, LO_FREQUENCY );
|
sound = morse.make_ident( nav_trans_ident, LO_FREQUENCY );
|
||||||
sound->set_volume( 0.3 );
|
sound->set_volume( 0.3 );
|
||||||
if ( globals->get_soundmgr()->add( sound, nav_fx_name ) ) {
|
if ( globals->get_soundmgr()->add( sound, nav_fx_name ) ) {
|
||||||
|
|
|
@ -90,7 +90,7 @@ fgfs_LDADD = \
|
||||||
$(WEATHER_LIBS) \
|
$(WEATHER_LIBS) \
|
||||||
-lsgroute -lsgsky -lsgephem -lsgmodel -lsgtiming -lsgio -lsgscreen \
|
-lsgroute -lsgsky -lsgephem -lsgmodel -lsgtiming -lsgio -lsgscreen \
|
||||||
-lsgmath -lsgbucket -lsgprops -lsgdebug -lsgmagvar -lsgmisc -lsgxml \
|
-lsgmath -lsgbucket -lsgprops -lsgdebug -lsgmagvar -lsgmisc -lsgxml \
|
||||||
-lsgserial \
|
-lsgsound -lsgserial \
|
||||||
$(THREAD_LIBS) \
|
$(THREAD_LIBS) \
|
||||||
-lplibpu -lplibfnt -lplibjs -lplibnet -lplibssg -lplibsg -lplibul \
|
-lplibpu -lplibfnt -lplibjs -lplibnet -lplibssg -lplibsg -lplibul \
|
||||||
$(PSL_LIBS) \
|
$(PSL_LIBS) \
|
||||||
|
|
|
@ -110,7 +110,6 @@
|
||||||
#include <Scripting/scriptmgr.hxx>
|
#include <Scripting/scriptmgr.hxx>
|
||||||
#endif
|
#endif
|
||||||
#include <Sound/fg_fx.hxx>
|
#include <Sound/fg_fx.hxx>
|
||||||
#include <Sound/soundmgr.hxx>
|
|
||||||
#include <Systems/system_mgr.hxx>
|
#include <Systems/system_mgr.hxx>
|
||||||
#include <Time/FGEventMgr.hxx>
|
#include <Time/FGEventMgr.hxx>
|
||||||
#include <Time/light.hxx>
|
#include <Time/light.hxx>
|
||||||
|
@ -144,6 +143,9 @@
|
||||||
|
|
||||||
SG_USING_STD(string);
|
SG_USING_STD(string);
|
||||||
|
|
||||||
|
|
||||||
|
class Sound;
|
||||||
|
|
||||||
extern const char *default_root;
|
extern const char *default_root;
|
||||||
|
|
||||||
#ifdef FG_USE_CLOUDS_3D
|
#ifdef FG_USE_CLOUDS_3D
|
||||||
|
@ -1537,7 +1539,7 @@ bool fgInitSubsystems() {
|
||||||
// Initialize the sound subsystem.
|
// Initialize the sound subsystem.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
globals->set_soundmgr(new FGSoundMgr);
|
globals->set_soundmgr(new SoundMgr);
|
||||||
globals->get_soundmgr()->init();
|
globals->get_soundmgr()->init();
|
||||||
globals->get_soundmgr()->bind();
|
globals->get_soundmgr()->bind();
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <simgear/magvar/magvar.hxx>
|
#include <simgear/magvar/magvar.hxx>
|
||||||
#include <simgear/timing/sg_time.hxx>
|
#include <simgear/timing/sg_time.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
#include <simgear/sound/soundmgr.hxx>
|
||||||
|
|
||||||
#include STL_IOSTREAM
|
#include STL_IOSTREAM
|
||||||
|
|
||||||
|
@ -43,7 +44,6 @@
|
||||||
#include <Objects/matlib.hxx>
|
#include <Objects/matlib.hxx>
|
||||||
|
|
||||||
#include <GUI/gui.h>
|
#include <GUI/gui.h>
|
||||||
#include <Sound/soundmgr.hxx>
|
|
||||||
|
|
||||||
#include "globals.hxx"
|
#include "globals.hxx"
|
||||||
#include "fgfs.hxx"
|
#include "fgfs.hxx"
|
||||||
|
@ -234,7 +234,7 @@ setFreeze (bool f)
|
||||||
frozen = f;
|
frozen = f;
|
||||||
|
|
||||||
// Stop sound on a pause
|
// Stop sound on a pause
|
||||||
FGSoundMgr *s = globals->get_soundmgr();
|
SoundMgr *s = globals->get_soundmgr();
|
||||||
if ( s != NULL ) {
|
if ( s != NULL ) {
|
||||||
if ( f ) {
|
if ( f ) {
|
||||||
s->pause();
|
s->pause();
|
||||||
|
|
|
@ -55,6 +55,7 @@ class SGMagVar;
|
||||||
class SGPropertyNode;
|
class SGPropertyNode;
|
||||||
class SGRoute;
|
class SGRoute;
|
||||||
class SGTime;
|
class SGTime;
|
||||||
|
class SoundMgr;
|
||||||
|
|
||||||
class FGAIMgr;
|
class FGAIMgr;
|
||||||
class FGATCMgr;
|
class FGATCMgr;
|
||||||
|
@ -73,7 +74,6 @@ class FGMultiplayRxMgr;
|
||||||
class FGMultiplayTxMgr;
|
class FGMultiplayTxMgr;
|
||||||
#endif
|
#endif
|
||||||
class FGPanel;
|
class FGPanel;
|
||||||
class FGSoundMgr;
|
|
||||||
class FGTileMgr;
|
class FGTileMgr;
|
||||||
class FGViewMgr;
|
class FGViewMgr;
|
||||||
class FGViewer;
|
class FGViewer;
|
||||||
|
@ -130,7 +130,7 @@ private:
|
||||||
FGPanel *current_panel;
|
FGPanel *current_panel;
|
||||||
|
|
||||||
// sound manager
|
// sound manager
|
||||||
FGSoundMgr *soundmgr;
|
SoundMgr *soundmgr;
|
||||||
|
|
||||||
// environment information
|
// environment information
|
||||||
FGEnvironmentMgr * environment_mgr;
|
FGEnvironmentMgr * environment_mgr;
|
||||||
|
@ -257,8 +257,8 @@ 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 FGSoundMgr *get_soundmgr() const { return soundmgr; }
|
inline SoundMgr *get_soundmgr() const { return soundmgr; }
|
||||||
inline void set_soundmgr( FGSoundMgr *sm ) { soundmgr = sm; }
|
inline void set_soundmgr( SoundMgr *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; }
|
||||||
|
|
|
@ -121,7 +121,6 @@ SG_USING_STD(endl);
|
||||||
#include <Scenery/scenery.hxx>
|
#include <Scenery/scenery.hxx>
|
||||||
#include <Scenery/tilemgr.hxx>
|
#include <Scenery/tilemgr.hxx>
|
||||||
#ifdef ENABLE_AUDIO_SUPPORT
|
#ifdef ENABLE_AUDIO_SUPPORT
|
||||||
# include <Sound/soundmgr.hxx>
|
|
||||||
# include <Sound/fg_fx.hxx>
|
# include <Sound/fg_fx.hxx>
|
||||||
# include <Sound/morse.hxx>
|
# include <Sound/morse.hxx>
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,9 +2,7 @@ noinst_LIBRARIES = libSound.a
|
||||||
|
|
||||||
libSound_a_SOURCES = \
|
libSound_a_SOURCES = \
|
||||||
beacon.cxx beacon.hxx \
|
beacon.cxx beacon.hxx \
|
||||||
fg_sound.cxx fg_sound.hxx \
|
|
||||||
fg_fx.cxx fg_fx.hxx \
|
fg_fx.cxx fg_fx.hxx \
|
||||||
morse.cxx morse.hxx \
|
morse.cxx morse.hxx
|
||||||
soundmgr.cxx soundmgr.hxx
|
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
||||||
|
|
|
@ -51,7 +51,7 @@ bool FGBeacon::init() {
|
||||||
ptr += INNER_DIT_LEN;
|
ptr += INNER_DIT_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
inner = new FGSimpleSound( inner_buf, INNER_SIZE );
|
inner = new SimpleSound( inner_buf, INNER_SIZE );
|
||||||
|
|
||||||
// Make middle marker beacon sound
|
// Make middle marker beacon sound
|
||||||
len= (int)(MIDDLE_DIT_LEN / 2.0 );
|
len= (int)(MIDDLE_DIT_LEN / 2.0 );
|
||||||
|
@ -69,7 +69,7 @@ bool FGBeacon::init() {
|
||||||
ptr += MIDDLE_DIT_LEN;
|
ptr += MIDDLE_DIT_LEN;
|
||||||
memcpy( ptr, middle_dah, MIDDLE_DAH_LEN );
|
memcpy( ptr, middle_dah, MIDDLE_DAH_LEN );
|
||||||
|
|
||||||
middle = new FGSimpleSound( middle_buf, MIDDLE_SIZE );
|
middle = new SimpleSound( middle_buf, MIDDLE_SIZE );
|
||||||
|
|
||||||
// Make outer marker beacon sound
|
// Make outer marker beacon sound
|
||||||
len= (int)(OUTER_DAH_LEN * 3.0 / 4.0 );
|
len= (int)(OUTER_DAH_LEN * 3.0 / 4.0 );
|
||||||
|
@ -82,7 +82,7 @@ bool FGBeacon::init() {
|
||||||
ptr += OUTER_DAH_LEN;
|
ptr += OUTER_DAH_LEN;
|
||||||
memcpy( ptr, outer_dah, OUTER_DAH_LEN );
|
memcpy( ptr, outer_dah, OUTER_DAH_LEN );
|
||||||
|
|
||||||
outer = new FGSimpleSound( outer_buf, OUTER_SIZE );
|
outer = new SimpleSound( outer_buf, OUTER_SIZE );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/sound/soundmgr.hxx>
|
||||||
|
|
||||||
#include <plib/sl.h>
|
#include <plib/sl.h>
|
||||||
#include <plib/sm.h>
|
#include <plib/sm.h>
|
||||||
|
|
||||||
#include "morse.hxx"
|
#include "morse.hxx"
|
||||||
#include "soundmgr.hxx"
|
|
||||||
|
|
||||||
|
|
||||||
// Quoting from http://www.smartregs.com/data/sa326.htm
|
// Quoting from http://www.smartregs.com/data/sa326.htm
|
||||||
|
@ -100,9 +100,9 @@ private:
|
||||||
unsigned char middle_buf[ MIDDLE_SIZE ] ;
|
unsigned char middle_buf[ MIDDLE_SIZE ] ;
|
||||||
unsigned char outer_buf[ OUTER_SIZE ] ;
|
unsigned char outer_buf[ OUTER_SIZE ] ;
|
||||||
|
|
||||||
FGSimpleSound *inner;
|
SimpleSound *inner;
|
||||||
FGSimpleSound *middle;
|
SimpleSound *middle;
|
||||||
FGSimpleSound *outer;
|
SimpleSound *outer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -112,9 +112,9 @@ public:
|
||||||
// allocate and initialize sound samples
|
// allocate and initialize sound samples
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
FGSimpleSound *get_inner() { return inner; }
|
SimpleSound *get_inner() { return inner; }
|
||||||
FGSimpleSound *get_middle() { return middle; }
|
SimpleSound *get_middle() { return middle; }
|
||||||
FGSimpleSound *get_outer() { return outer; }
|
SimpleSound *get_outer() { return outer; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,11 @@
|
||||||
#endif
|
#endif
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
|
#include <simgear/sound/sound.hxx>
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
|
|
||||||
#include "fg_fx.hxx"
|
#include "fg_fx.hxx"
|
||||||
#include "fg_sound.hxx"
|
|
||||||
|
|
||||||
|
|
||||||
FGFX::FGFX ()
|
FGFX::FGFX ()
|
||||||
|
@ -62,7 +62,7 @@ FGFX::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
path.append(path_str.c_str());
|
path.append(path_str.c_str());
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "Reading Instrument " << node->getName()
|
SG_LOG(SG_GENERAL, SG_INFO, "Reading sound " << node->getName()
|
||||||
<< " from " << path.str());
|
<< " from " << path.str());
|
||||||
|
|
||||||
SGPropertyNode root;
|
SGPropertyNode root;
|
||||||
|
@ -76,8 +76,10 @@ FGFX::init()
|
||||||
|
|
||||||
node = root.getNode("fx");
|
node = root.getNode("fx");
|
||||||
for (i = 0; i < node->nChildren(); i++) {
|
for (i = 0; i < node->nChildren(); i++) {
|
||||||
FGSound *sound = new FGSound();
|
Sound *sound = new Sound();
|
||||||
sound->init(node->getChild(i));
|
|
||||||
|
sound->init(globals->get_props(), node->getChild(i),
|
||||||
|
globals->get_soundmgr(), globals->get_fg_root());
|
||||||
|
|
||||||
_sound.push_back(sound);
|
_sound.push_back(sound);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include <Main/fgfs.hxx>
|
#include <Main/fgfs.hxx>
|
||||||
|
|
||||||
class FGSound;
|
class Sound;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generator for FlightGear sound effects.
|
* Generator for FlightGear sound effects.
|
||||||
|
@ -51,7 +51,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
vector<FGSound *> _sound;
|
vector<Sound *> _sound;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,418 +0,0 @@
|
||||||
// fg_sound.cxx -- Sound class implementation
|
|
||||||
//
|
|
||||||
// Started by Erik Hofman, February 2002
|
|
||||||
// (Reuses some code from fg_fx.cxx created by David Megginson)
|
|
||||||
//
|
|
||||||
// Copyright (C) 2002 Curtis L. Olson - curt@flightgear.org
|
|
||||||
//
|
|
||||||
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
|
||||||
|
|
||||||
#ifdef SG_HAVE_STD_INCLUDES
|
|
||||||
# include <cmath>
|
|
||||||
#else
|
|
||||||
# include <math.h>
|
|
||||||
#endif
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
|
||||||
#include <simgear/props/condition.hxx>
|
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
|
||||||
|
|
||||||
#include "fg_sound.hxx"
|
|
||||||
|
|
||||||
|
|
||||||
// static double _fg_lin(double v) { return v; }
|
|
||||||
static double _fg_inv(double v) { return (v == 0) ? 1e99 : 1/v; }
|
|
||||||
static double _fg_abs(double v) { return (v >= 0) ? v : -v; }
|
|
||||||
static double _fg_sqrt(double v) { return (v < 0) ? sqrt(-v) : sqrt(v); }
|
|
||||||
static double _fg_log10(double v) { return (v < 1) ? 0 : log10(v); }
|
|
||||||
static double _fg_log(double v) { return (v < 1) ? 0 : log(v); }
|
|
||||||
// static double _fg_sqr(double v) { return pow(v, 2); }
|
|
||||||
// static double _fg_pow3(double v) { return pow(v, 3); }
|
|
||||||
|
|
||||||
static const struct {
|
|
||||||
char *name;
|
|
||||||
double (*fn)(double);
|
|
||||||
} __fg_snd_fn[] = {
|
|
||||||
// {"lin", _fg_lin},
|
|
||||||
{"inv", _fg_inv},
|
|
||||||
{"abs", _fg_abs},
|
|
||||||
{"sqrt", _fg_sqrt},
|
|
||||||
{"log", _fg_log10},
|
|
||||||
{"ln", _fg_log},
|
|
||||||
// {"sqr", _fg_sqr},
|
|
||||||
// {"pow3", _fg_pow3},
|
|
||||||
{"", NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
FGSound::FGSound()
|
|
||||||
: _sample(NULL),
|
|
||||||
_condition(NULL),
|
|
||||||
_property(NULL),
|
|
||||||
_active(false),
|
|
||||||
_name(""),
|
|
||||||
_mode(FGSound::ONCE),
|
|
||||||
_prev_value(0),
|
|
||||||
_dt_play(0.0),
|
|
||||||
_dt_stop(0.0),
|
|
||||||
_stopping(0.0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FGSound::~FGSound()
|
|
||||||
{
|
|
||||||
_mgr->get_scheduler()->stopSample(_sample->get_sample());
|
|
||||||
|
|
||||||
if (_property)
|
|
||||||
delete _property;
|
|
||||||
|
|
||||||
if (_condition)
|
|
||||||
delete _condition;
|
|
||||||
|
|
||||||
_volume.clear();
|
|
||||||
_pitch.clear();
|
|
||||||
delete _sample;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FGSound::init(SGPropertyNode *node)
|
|
||||||
{
|
|
||||||
|
|
||||||
//
|
|
||||||
// set global sound properties
|
|
||||||
//
|
|
||||||
|
|
||||||
_name = node->getStringValue("name", "");
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "Loading sound information for: " << _name );
|
|
||||||
|
|
||||||
const char *mode_str = node->getStringValue("mode", "");
|
|
||||||
if ( !strcmp(mode_str, "looped") ) {
|
|
||||||
_mode = FGSound::LOOPED;
|
|
||||||
|
|
||||||
} else if ( !strcmp(mode_str, "in-transit") ) {
|
|
||||||
_mode = FGSound::IN_TRANSIT;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
_mode = FGSound::ONCE;
|
|
||||||
|
|
||||||
if ( strcmp(mode_str, "") )
|
|
||||||
SG_LOG(SG_GENERAL,SG_INFO, " Unknown sound mode, default to 'once'");
|
|
||||||
}
|
|
||||||
|
|
||||||
_property = fgGetNode(node->getStringValue("property", ""), true);
|
|
||||||
SGPropertyNode *condition = node->getChild("condition");
|
|
||||||
if (condition != NULL)
|
|
||||||
_condition = fgReadCondition(globals->get_props(), condition);
|
|
||||||
|
|
||||||
if (!_property && !_condition)
|
|
||||||
SG_LOG(SG_GENERAL, SG_WARN,
|
|
||||||
" Neither a condition nor a property specified");
|
|
||||||
|
|
||||||
//
|
|
||||||
// set volume properties
|
|
||||||
//
|
|
||||||
unsigned int i;
|
|
||||||
float v = 0.0;
|
|
||||||
vector<SGPropertyNode_ptr> kids = node->getChildren("volume");
|
|
||||||
for (i = 0; (i < kids.size()) && (i < FGSound::MAXPROP); i++) {
|
|
||||||
_snd_prop volume = {NULL, NULL, NULL, 1.0, 0.0, 0.0, 0.0, false};
|
|
||||||
|
|
||||||
if (strcmp(kids[i]->getStringValue("property"), ""))
|
|
||||||
volume.prop = fgGetNode(kids[i]->getStringValue("property", ""), true);
|
|
||||||
|
|
||||||
const char *intern_str = kids[i]->getStringValue("internal", "");
|
|
||||||
if (!strcmp(intern_str, "dt_play"))
|
|
||||||
volume.intern = &_dt_play;
|
|
||||||
else if (!strcmp(intern_str, "dt_stop"))
|
|
||||||
volume.intern = &_dt_stop;
|
|
||||||
|
|
||||||
if ((volume.factor = kids[i]->getDoubleValue("factor", 1.0)) != 0.0)
|
|
||||||
if (volume.factor < 0.0) {
|
|
||||||
volume.factor = -volume.factor;
|
|
||||||
volume.subtract = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *type_str = kids[i]->getStringValue("type", "");
|
|
||||||
if ( strcmp(type_str, "") ) {
|
|
||||||
|
|
||||||
for (int j=0; __fg_snd_fn[j].fn; j++)
|
|
||||||
if ( !strcmp(type_str, __fg_snd_fn[j].name) ) {
|
|
||||||
volume.fn = __fg_snd_fn[j].fn;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!volume.fn)
|
|
||||||
SG_LOG(SG_GENERAL,SG_INFO,
|
|
||||||
" Unknown volume type, default to 'lin'");
|
|
||||||
}
|
|
||||||
|
|
||||||
volume.offset = kids[i]->getDoubleValue("offset", 0.0);
|
|
||||||
|
|
||||||
if ((volume.min = kids[i]->getDoubleValue("min", 0.0)) < 0.0)
|
|
||||||
SG_LOG( SG_GENERAL, SG_WARN,
|
|
||||||
"Volume minimum value below 0. Forced to 0.");
|
|
||||||
|
|
||||||
volume.max = kids[i]->getDoubleValue("max", 0.0);
|
|
||||||
if (volume.max && (volume.max < volume.min) )
|
|
||||||
SG_LOG(SG_GENERAL,SG_ALERT,
|
|
||||||
" Volume maximum below minimum. Neglected.");
|
|
||||||
|
|
||||||
_volume.push_back(volume);
|
|
||||||
v += volume.offset;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// set pitch properties
|
|
||||||
//
|
|
||||||
float p = 0.0;
|
|
||||||
kids = node->getChildren("pitch");
|
|
||||||
for (i = 0; (i < kids.size()) && (i < FGSound::MAXPROP); i++) {
|
|
||||||
_snd_prop pitch = {NULL, NULL, NULL, 1.0, 1.0, 0.0, 0.0, false};
|
|
||||||
|
|
||||||
if (strcmp(kids[i]->getStringValue("property", ""), ""))
|
|
||||||
pitch.prop = fgGetNode(kids[i]->getStringValue("property", ""), true);
|
|
||||||
|
|
||||||
const char *intern_str = kids[i]->getStringValue("internal", "");
|
|
||||||
if (!strcmp(intern_str, "dt_play"))
|
|
||||||
pitch.intern = &_dt_play;
|
|
||||||
else if (!strcmp(intern_str, "dt_stop"))
|
|
||||||
pitch.intern = &_dt_stop;
|
|
||||||
|
|
||||||
if ((pitch.factor = kids[i]->getDoubleValue("factor", 1.0)) != 0.0)
|
|
||||||
if (pitch.factor < 0.0) {
|
|
||||||
pitch.factor = -pitch.factor;
|
|
||||||
pitch.subtract = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *type_str = kids[i]->getStringValue("type", "");
|
|
||||||
if ( strcmp(type_str, "") ) {
|
|
||||||
|
|
||||||
for (int j=0; __fg_snd_fn[j].fn; j++)
|
|
||||||
if ( !strcmp(type_str, __fg_snd_fn[j].name) ) {
|
|
||||||
pitch.fn = __fg_snd_fn[j].fn;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pitch.fn)
|
|
||||||
SG_LOG(SG_GENERAL,SG_INFO,
|
|
||||||
" Unknown pitch type, default to 'lin'");
|
|
||||||
}
|
|
||||||
|
|
||||||
pitch.offset = kids[i]->getDoubleValue("offset", 1.0);
|
|
||||||
|
|
||||||
if ((pitch.min = kids[i]->getDoubleValue("min", 0.0)) < 0.0)
|
|
||||||
SG_LOG(SG_GENERAL,SG_WARN,
|
|
||||||
" Pitch minimum value below 0. Forced to 0.");
|
|
||||||
|
|
||||||
pitch.max = kids[i]->getDoubleValue("max", 0.0);
|
|
||||||
if (pitch.max && (pitch.max < pitch.min) )
|
|
||||||
SG_LOG(SG_GENERAL,SG_ALERT,
|
|
||||||
" Pitch maximum below minimum. Neglected");
|
|
||||||
|
|
||||||
_pitch.push_back(pitch);
|
|
||||||
p += pitch.offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize the sample
|
|
||||||
//
|
|
||||||
_mgr = globals->get_soundmgr();
|
|
||||||
if ((_sample = _mgr->find(_name)) == NULL)
|
|
||||||
_sample = _mgr->add(_name, node->getStringValue("path", ""));
|
|
||||||
|
|
||||||
_sample->set_volume(v);
|
|
||||||
_sample->set_pitch(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FGSound::bind ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FGSound::unbind ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FGSound::update (double dt)
|
|
||||||
{
|
|
||||||
double curr_value = 0.0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// If the state changes to false, stop playing.
|
|
||||||
//
|
|
||||||
if (_property)
|
|
||||||
curr_value = _property->getDoubleValue();
|
|
||||||
|
|
||||||
if ( // Lisp, anyone?
|
|
||||||
(_condition && !_condition->test()) ||
|
|
||||||
(!_condition && _property &&
|
|
||||||
(
|
|
||||||
!curr_value ||
|
|
||||||
( (_mode == FGSound::IN_TRANSIT) && (curr_value == _prev_value) )
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if ((_mode != FGSound::IN_TRANSIT) || (_stopping > MAX_TRANSIT_TIME)) {
|
|
||||||
if (_sample->is_playing()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "Stopping audio after " << _dt_play
|
|
||||||
<< " sec: " << _name );
|
|
||||||
|
|
||||||
_sample->stop( _mgr->get_scheduler() );
|
|
||||||
}
|
|
||||||
|
|
||||||
_active = false;
|
|
||||||
_dt_stop += dt;
|
|
||||||
_dt_play = 0.0;
|
|
||||||
} else {
|
|
||||||
_stopping += dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// If the mode is ONCE and the sound is still playing,
|
|
||||||
// we have nothing to do anymore.
|
|
||||||
//
|
|
||||||
if (_active && (_mode == FGSound::ONCE)) {
|
|
||||||
|
|
||||||
if (!_sample->is_playing()) {
|
|
||||||
_dt_stop += dt;
|
|
||||||
_dt_play = 0.0;
|
|
||||||
} else {
|
|
||||||
_dt_play += dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Update the playing time, cache the current value and
|
|
||||||
// clear the delay timer.
|
|
||||||
//
|
|
||||||
_dt_play += dt;
|
|
||||||
_prev_value = curr_value;
|
|
||||||
_stopping = 0.0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Update the volume
|
|
||||||
//
|
|
||||||
int i;
|
|
||||||
int max = _volume.size();
|
|
||||||
double volume = 1.0;
|
|
||||||
double volume_offset = 0.0;
|
|
||||||
|
|
||||||
for(i = 0; i < max; i++) {
|
|
||||||
double v = 1.0;
|
|
||||||
|
|
||||||
if (_volume[i].prop)
|
|
||||||
v = _volume[i].prop->getDoubleValue();
|
|
||||||
|
|
||||||
else if (_volume[i].intern)
|
|
||||||
v = *_volume[i].intern;
|
|
||||||
|
|
||||||
if (_volume[i].fn)
|
|
||||||
v = _volume[i].fn(v);
|
|
||||||
|
|
||||||
v *= _volume[i].factor;
|
|
||||||
|
|
||||||
if (_volume[i].max && (v > _volume[i].max))
|
|
||||||
v = _volume[i].max;
|
|
||||||
|
|
||||||
else if (v < _volume[i].min)
|
|
||||||
v = _volume[i].min;
|
|
||||||
|
|
||||||
if (_volume[i].subtract) // Hack!
|
|
||||||
volume = _volume[i].offset - v;
|
|
||||||
|
|
||||||
else {
|
|
||||||
volume_offset += _volume[i].offset;
|
|
||||||
volume *= v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Update the pitch
|
|
||||||
//
|
|
||||||
max = _pitch.size();
|
|
||||||
double pitch = 1.0;
|
|
||||||
double pitch_offset = 0.0;
|
|
||||||
|
|
||||||
for(i = 0; i < max; i++) {
|
|
||||||
double p = 1.0;
|
|
||||||
|
|
||||||
if (_pitch[i].prop)
|
|
||||||
p = _pitch[i].prop->getDoubleValue();
|
|
||||||
|
|
||||||
else if (_pitch[i].intern)
|
|
||||||
p = *_pitch[i].intern;
|
|
||||||
|
|
||||||
if (_pitch[i].fn)
|
|
||||||
p = _pitch[i].fn(p);
|
|
||||||
|
|
||||||
p *= _pitch[i].factor;
|
|
||||||
|
|
||||||
if (_pitch[i].max && (p > _pitch[i].max))
|
|
||||||
p = _pitch[i].max;
|
|
||||||
|
|
||||||
else if (p < _pitch[i].min)
|
|
||||||
p = _pitch[i].min;
|
|
||||||
|
|
||||||
if (_pitch[i].subtract) // Hack!
|
|
||||||
pitch = _pitch[i].offset - p;
|
|
||||||
|
|
||||||
else {
|
|
||||||
pitch_offset += _pitch[i].offset;
|
|
||||||
pitch *= p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Change sample state
|
|
||||||
//
|
|
||||||
_sample->set_pitch( pitch_offset + pitch );
|
|
||||||
_sample->set_volume( volume_offset + volume );
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do we need to start playing the sample?
|
|
||||||
//
|
|
||||||
if (!_active) {
|
|
||||||
|
|
||||||
if (_mode == FGSound::ONCE)
|
|
||||||
_sample->play(_mgr->get_scheduler(), false);
|
|
||||||
|
|
||||||
else
|
|
||||||
_sample->play(_mgr->get_scheduler(), true);
|
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "Playing audio after " << _dt_stop
|
|
||||||
<< " sec: " << _name);
|
|
||||||
SG_LOG(SG_GENERAL, SG_BULK,
|
|
||||||
"Playing " << ((_mode == ONCE) ? "once" : "looped"));
|
|
||||||
|
|
||||||
_active = true;
|
|
||||||
_dt_stop = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
// fg_sound.hxx -- Sound class implementation
|
|
||||||
//
|
|
||||||
// Started by Erik Hofman, February 2002
|
|
||||||
//
|
|
||||||
// Copyright (C) 2002 Erik Hofman - erik@ehofman.com
|
|
||||||
//
|
|
||||||
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
#ifndef __FGSOUND_HXX
|
|
||||||
#define __FGSOUND_HXX 1
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
|
||||||
#include <simgear/props/condition.hxx>
|
|
||||||
|
|
||||||
#include <Main/fgfs.hxx>
|
|
||||||
#include <Main/globals.hxx>
|
|
||||||
|
|
||||||
#include "soundmgr.hxx"
|
|
||||||
|
|
||||||
static const double MAX_TRANSIT_TIME = 0.1; // 100 ms.
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for handling one sound event.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class FGSound
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FGSound();
|
|
||||||
virtual ~FGSound();
|
|
||||||
|
|
||||||
virtual void init (SGPropertyNode *);
|
|
||||||
virtual void bind ();
|
|
||||||
virtual void unbind ();
|
|
||||||
virtual void update (double dt);
|
|
||||||
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
enum { MAXPROP=5 };
|
|
||||||
enum { ONCE=0, LOOPED, IN_TRANSIT };
|
|
||||||
enum { LEVEL=0, INVERTED, FLIPFLOP };
|
|
||||||
|
|
||||||
// Sound properties
|
|
||||||
typedef struct {
|
|
||||||
SGPropertyNode * prop;
|
|
||||||
double (*fn)(double);
|
|
||||||
double *intern;
|
|
||||||
double factor;
|
|
||||||
double offset;
|
|
||||||
double min;
|
|
||||||
double max;
|
|
||||||
bool subtract;
|
|
||||||
} _snd_prop;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
FGSoundMgr * _mgr;
|
|
||||||
FGSimpleSound * _sample;
|
|
||||||
|
|
||||||
FGCondition * _condition;
|
|
||||||
SGPropertyNode * _property;
|
|
||||||
|
|
||||||
bool _active;
|
|
||||||
string _name;
|
|
||||||
int _mode;
|
|
||||||
double _prev_value;
|
|
||||||
double _dt_play;
|
|
||||||
double _dt_stop;
|
|
||||||
double _stopping; // time after the sound should have stopped.
|
|
||||||
// This is usefull for lost packets in in-trasit mode.
|
|
||||||
|
|
||||||
vector<_snd_prop> _volume;
|
|
||||||
vector<_snd_prop> _pitch;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -165,8 +165,8 @@ bool FGMorse::cust_init(const int freq ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// make a FGSimpleSound morse code transmission for the specified string
|
// make a SimpleSound morse code transmission for the specified string
|
||||||
FGSimpleSound *FGMorse::make_ident( const string& id, const int freq ) {
|
SimpleSound *FGMorse::make_ident( const string& id, const int freq ) {
|
||||||
char *idptr = (char *)id.c_str();
|
char *idptr = (char *)id.c_str();
|
||||||
|
|
||||||
int length = 0;
|
int length = 0;
|
||||||
|
@ -260,7 +260,7 @@ FGSimpleSound *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
|
||||||
FGSimpleSound *sample = new FGSimpleSound( buffer, length );
|
SimpleSound *sample = new SimpleSound( buffer, length );
|
||||||
|
|
||||||
return sample;
|
return sample;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,11 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/sound/soundmgr.hxx>
|
||||||
|
|
||||||
#include <plib/sl.h>
|
#include <plib/sl.h>
|
||||||
#include <plib/sm.h>
|
#include <plib/sm.h>
|
||||||
|
|
||||||
#include "soundmgr.hxx"
|
|
||||||
|
|
||||||
|
|
||||||
// Quoting from http://www.kluft.com/~ikluft/ham/morse-intro.html by
|
// Quoting from http://www.kluft.com/~ikluft/ham/morse-intro.html by
|
||||||
// Ian Kluft KO6YQ <ikluft@kluft.com>
|
// Ian Kluft KO6YQ <ikluft@kluft.com>
|
||||||
|
@ -124,8 +123,8 @@ public:
|
||||||
// allocate and initialize sound samples
|
// allocate and initialize sound samples
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
// make a FGSimpleSound morse code transmission for the specified string
|
// make a SimpleSound morse code transmission for the specified string
|
||||||
FGSimpleSound *make_ident( const string& id,
|
SimpleSound *make_ident( const string& id,
|
||||||
const int freq = LO_FREQUENCY );
|
const int freq = LO_FREQUENCY );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,406 +0,0 @@
|
||||||
// soundmgr.cxx -- Sound effect management class
|
|
||||||
//
|
|
||||||
// Sound manager initially written by David Findlay
|
|
||||||
// <david_j_findlay@yahoo.com.au> 2001
|
|
||||||
//
|
|
||||||
// C++-ified by Curtis Olson, started March 2001.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org
|
|
||||||
//
|
|
||||||
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
|
||||||
|
|
||||||
#include <Main/globals.hxx>
|
|
||||||
|
|
||||||
#include "soundmgr.hxx"
|
|
||||||
|
|
||||||
#define FG_SOUND_SAFETY_MULT 3
|
|
||||||
#define FG_MAX_SOUND_SAFETY ( 1.0 / FG_SOUND_SAFETY_MULT )
|
|
||||||
|
|
||||||
//
|
|
||||||
// SimpleSound
|
|
||||||
//
|
|
||||||
|
|
||||||
// constructor
|
|
||||||
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() );
|
|
||||||
pitch_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
|
|
||||||
volume_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
|
|
||||||
pitch_envelope->setStep ( 0, 0.01, 1.0 );
|
|
||||||
volume_envelope->setStep ( 0, 0.01, 1.0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
|
||||||
pitch_envelope->setStep ( 0, 0.01, 1.0 );
|
|
||||||
volume_envelope->setStep ( 0, 0.01, 1.0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// destructor
|
|
||||||
FGSimpleSound::~FGSimpleSound() {
|
|
||||||
delete pitch_envelope;
|
|
||||||
delete volume_envelope;
|
|
||||||
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 );
|
|
||||||
if ( audio_sched->notWorking() ) {
|
|
||||||
SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
|
|
||||||
} else {
|
|
||||||
audio_sched -> setMaxConcurrent ( 6 );
|
|
||||||
|
|
||||||
audio_mixer = new smMixer;
|
|
||||||
|
|
||||||
SG_LOG( SG_GENERAL, SG_INFO,
|
|
||||||
"Rate = " << audio_sched->getRate()
|
|
||||||
<< " Bps = " << audio_sched->getBps()
|
|
||||||
<< " Stereo = " << audio_sched->getStereo() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// destructor
|
|
||||||
|
|
||||||
FGSoundMgr::~FGSoundMgr() {
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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;
|
|
||||||
delete audio_mixer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// initialize the sound manager
|
|
||||||
void FGSoundMgr::init() {
|
|
||||||
safety = FG_MAX_SOUND_SAFETY;
|
|
||||||
|
|
||||||
// audio_mixer -> setMasterVolume ( 80 ) ; /* 80% of max volume. */
|
|
||||||
audio_sched -> setSafetyMargin ( FG_SOUND_SAFETY_MULT * safety ) ;
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FGSoundMgr::bind ()
|
|
||||||
{
|
|
||||||
// no properties yet
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 + dt * 0.01;
|
|
||||||
}
|
|
||||||
if ( safety > FG_MAX_SOUND_SAFETY ) {
|
|
||||||
safety = FG_MAX_SOUND_SAFETY;
|
|
||||||
}
|
|
||||||
// cout << "safety = " << safety << endl;
|
|
||||||
audio_sched -> setSafetyMargin ( FG_SOUND_SAFETY_MULT * safety ) ;
|
|
||||||
|
|
||||||
if ( !audio_sched->not_working() )
|
|
||||||
audio_sched -> update();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 ) {
|
|
||||||
|
|
||||||
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 ) {
|
|
||||||
|
|
||||||
sound_map_iterator it = sounds.find( refname );
|
|
||||||
if ( it != sounds.end() ) {
|
|
||||||
// first stop the sound from playing (so we don't bomb the
|
|
||||||
// audio scheduler)
|
|
||||||
FGSimpleSound *sample = it->second;
|
|
||||||
|
|
||||||
// cout << "Playing " << sample->get_sample()->getPlayCount()
|
|
||||||
// << " instances!" << endl;
|
|
||||||
|
|
||||||
audio_sched->stopSample( sample->get_sample() );
|
|
||||||
audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0,
|
|
||||||
NULL,
|
|
||||||
SL_PITCH_ENVELOPE );
|
|
||||||
audio_sched->addSampleEnvelope( sample->get_sample(), 0, 1,
|
|
||||||
NULL,
|
|
||||||
SL_VOLUME_ENVELOPE );
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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;
|
|
||||||
} else {
|
|
||||||
// cout << "sndmgr: failed remove -> " << refname << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return true of the specified sound exists in the sound manager system
|
|
||||||
bool FGSoundMgr::exists( const string& refname ) {
|
|
||||||
sound_map_iterator it = sounds.find( refname );
|
|
||||||
if ( it != sounds.end() ) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return a pointer to the FGSimpleSound if the specified sound exists
|
|
||||||
// in the sound manager system, otherwise return NULL
|
|
||||||
FGSimpleSound *FGSoundMgr::find( const string& refname ) {
|
|
||||||
sound_map_iterator it = sounds.find( refname );
|
|
||||||
if ( it != sounds.end() ) {
|
|
||||||
return it->second;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// tell the scheduler to play the indexed sample in a continuous
|
|
||||||
// loop
|
|
||||||
bool FGSoundMgr::play_looped( const string& refname ) {
|
|
||||||
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 ) {
|
|
||||||
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 ) {
|
|
||||||
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 ) {
|
|
||||||
FGSimpleSound *sample;
|
|
||||||
|
|
||||||
if ((sample = find( refname )) == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
audio_sched->stopSample( sample->get_sample() );
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,203 +0,0 @@
|
||||||
// soundmgr.hxx -- Sound effect management class
|
|
||||||
//
|
|
||||||
// Sound manager initially written by David Findlay
|
|
||||||
// <david_j_findlay@yahoo.com.au> 2001
|
|
||||||
//
|
|
||||||
// C++-ified by Curtis Olson, started March 2001.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org
|
|
||||||
//
|
|
||||||
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _SOUNDMGR_HXX
|
|
||||||
#define _SOUNDMGR_HXX
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
|
||||||
|
|
||||||
#include STL_STRING
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include <plib/sl.h>
|
|
||||||
#include <plib/sm.h>
|
|
||||||
|
|
||||||
#include <simgear/timing/timestamp.hxx>
|
|
||||||
|
|
||||||
#include <Main/fgfs.hxx>
|
|
||||||
|
|
||||||
SG_USING_STD(map);
|
|
||||||
SG_USING_STD(string);
|
|
||||||
|
|
||||||
|
|
||||||
// manages everything we need to know for an individual sound sample
|
|
||||||
class FGSimpleSound {
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
slSample *sample;
|
|
||||||
slEnvelope *pitch_envelope;
|
|
||||||
slEnvelope *volume_envelope;
|
|
||||||
double pitch;
|
|
||||||
double volume;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FGSimpleSound( string file );
|
|
||||||
FGSimpleSound( unsigned char *buffer, int len );
|
|
||||||
~FGSimpleSound();
|
|
||||||
|
|
||||||
void play( slScheduler *sched, bool looped );
|
|
||||||
void stop( slScheduler *sched, bool quick = true );
|
|
||||||
|
|
||||||
inline void play_once( slScheduler *sched ) { play( sched, false); }
|
|
||||||
inline void play_looped( slScheduler *sched ) { play( sched, true); }
|
|
||||||
inline bool is_playing( ) {
|
|
||||||
return ( sample->getPlayCount() > 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline double get_pitch() const { return pitch; }
|
|
||||||
inline void set_pitch( double p ) {
|
|
||||||
pitch = p;
|
|
||||||
pitch_envelope->setStep( 0, 0.01, pitch );
|
|
||||||
}
|
|
||||||
inline double get_volume() const { return volume; }
|
|
||||||
inline void set_volume( double v ) {
|
|
||||||
volume = v;
|
|
||||||
volume_envelope->setStep( 0, 0.01, volume );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline slSample *get_sample() { return sample; }
|
|
||||||
inline slEnvelope *get_pitch_envelope() { return pitch_envelope; }
|
|
||||||
inline slEnvelope *get_volume_envelope() { return volume_envelope; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
class FGSoundMgr : public FGSubsystem
|
|
||||||
{
|
|
||||||
|
|
||||||
slScheduler *audio_sched;
|
|
||||||
smMixer *audio_mixer;
|
|
||||||
|
|
||||||
sound_map sounds;
|
|
||||||
sample_map samples;
|
|
||||||
|
|
||||||
double safety;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FGSoundMgr();
|
|
||||||
~FGSoundMgr();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (re) initialize the sound manager.
|
|
||||||
*/
|
|
||||||
void init();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind properties for the sound manager.
|
|
||||||
*/
|
|
||||||
void bind ();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unbind properties for the sound manager.
|
|
||||||
*/
|
|
||||||
void unbind ();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the audio scheduler.
|
|
||||||
*/
|
|
||||||
void update(double dt);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pause all sounds.
|
|
||||||
*/
|
|
||||||
void pause ();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resume all sounds.
|
|
||||||
*/
|
|
||||||
void resume ();
|
|
||||||
|
|
||||||
|
|
||||||
// is audio working?
|
|
||||||
inline bool is_working() const { return !audio_sched->notWorking(); }
|
|
||||||
|
|
||||||
// reinitialize the sound manager
|
|
||||||
inline void reinit() { init(); }
|
|
||||||
|
|
||||||
// add a sound effect, return true if successful
|
|
||||||
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 );
|
|
||||||
|
|
||||||
// return true of the specified sound exists in the sound manager system
|
|
||||||
bool exists( const string& refname );
|
|
||||||
|
|
||||||
// return a pointer to the FGSimpleSound if the specified sound
|
|
||||||
// exists in the sound manager system, otherwise return NULL
|
|
||||||
FGSimpleSound *find( const string& refname );
|
|
||||||
|
|
||||||
// tell the scheduler to play the indexed sample in a continuous
|
|
||||||
// loop
|
|
||||||
bool play_looped( const string& refname );
|
|
||||||
|
|
||||||
// tell the scheduler to play the indexed sample once
|
|
||||||
bool play_once( const string& refname );
|
|
||||||
|
|
||||||
// return true of the specified sound is currently being played
|
|
||||||
bool is_playing( const string& refname );
|
|
||||||
|
|
||||||
// immediate stop playing the sound
|
|
||||||
bool stop( const string& refname );
|
|
||||||
|
|
||||||
// return the audio scheduler
|
|
||||||
inline slScheduler *get_scheduler( ) { return audio_sched; };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _SOUNDMGR_HXX
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue