// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#include <simgear/sound/soundmgr.hxx>
+
#include <Main/fgfs.hxx>
#include <Main/fg_props.hxx>
-#include <Sound/soundmgr.hxx>
#include "ATC.hxx"
#include "ATCdisplay.hxx"
int len;
unsigned char* buf = vPtr->WriteMessage((char*)msg.c_str(), len, 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
// and can't be changed after the transmission has started.
simple->set_volume(5.0 * fgGetDouble("/radios/comm[0]/volume"));
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Main/viewmgr.hxx>
-#include <Sound/fg_fx.hxx>
-#include <Sound/soundmgr.hxx>
#include <Cockpit/panel.hxx>
#include <Cockpit/hud.hxx>
#include <Cockpit/panel_io.hxx>
// play station ident via audio system if on + ant mode,
// otherwise turn it off
if ( vol_btn >= 0.01 && audio_btn ) {
- FGSimpleSound *sound;
+ SimpleSound *sound;
sound = globals->get_soundmgr()->find( "adf-ident" );
if ( sound != NULL ) {
if ( !adf_btn ) {
if ( globals->get_soundmgr()->exists( "adf-ident" ) ) {
globals->get_soundmgr()->remove( "adf-ident" );
}
- FGSimpleSound *sound;
+ SimpleSound *sound;
sound = morse.make_ident( trans_ident, LO_FREQUENCY );
sound->set_volume( 0.3 );
globals->get_soundmgr()->add( sound, "adf-ident" );
// cout << "OUTER MARKER" << endl;
if ( last_beacon != FGMkrBeacon::OUTER ) {
if ( ! globals->get_soundmgr()->exists( "outer-marker" ) ) {
- FGSimpleSound *sound = beacon.get_outer();
+ SimpleSound *sound = beacon.get_outer();
sound->set_volume( 0.3 );
globals->get_soundmgr()->add( sound, "outer-marker" );
}
// cout << "MIDDLE MARKER" << endl;
if ( last_beacon != FGMkrBeacon::MIDDLE ) {
if ( ! globals->get_soundmgr()->exists( "middle-marker" ) ) {
- FGSimpleSound *sound = beacon.get_middle();
+ SimpleSound *sound = beacon.get_middle();
sound->set_volume( 0.3 );
globals->get_soundmgr()->add( sound, "middle-marker" );
}
// cout << "INNER MARKER" << endl;
if ( last_beacon != FGMkrBeacon::INNER ) {
if ( ! globals->get_soundmgr()->exists( "inner-marker" ) ) {
- FGSimpleSound *sound = beacon.get_inner();
+ SimpleSound *sound = beacon.get_inner();
sound->set_volume( 0.3 );
globals->get_soundmgr()->add( sound, "inner-marker" );
}
if ( power_btn && (bus_power->getDoubleValue() > 1.0)
&& nav_ident_btn && audio_btn )
{
- FGSimpleSound *sound;
+ SimpleSound *sound;
sound = globals->get_soundmgr()->find( nav_fx_name );
if ( sound != NULL ) {
sound->set_volume( nav_vol_btn );
if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
globals->get_soundmgr()->remove( nav_fx_name );
}
- FGSimpleSound *sound;
+ SimpleSound *sound;
sound = morse.make_ident( nav_trans_ident, LO_FREQUENCY );
sound->set_volume( 0.3 );
globals->get_soundmgr()->add( sound, nav_fx_name );
if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
globals->get_soundmgr()->remove( nav_fx_name );
}
- FGSimpleSound *sound;
+ SimpleSound *sound;
sound = morse.make_ident( nav_trans_ident, LO_FREQUENCY );
sound->set_volume( 0.3 );
if ( globals->get_soundmgr()->add( sound, nav_fx_name ) ) {
$(WEATHER_LIBS) \
-lsgroute -lsgsky -lsgephem -lsgmodel -lsgtiming -lsgio -lsgscreen \
-lsgmath -lsgbucket -lsgprops -lsgdebug -lsgmagvar -lsgmisc -lsgxml \
- -lsgserial \
+ -lsgsound -lsgserial \
$(THREAD_LIBS) \
-lplibpu -lplibfnt -lplibjs -lplibnet -lplibssg -lplibsg -lplibul \
$(PSL_LIBS) \
#include <Scripting/scriptmgr.hxx>
#endif
#include <Sound/fg_fx.hxx>
-#include <Sound/soundmgr.hxx>
#include <Systems/system_mgr.hxx>
#include <Time/FGEventMgr.hxx>
#include <Time/light.hxx>
SG_USING_STD(string);
+
+class Sound;
+
extern const char *default_root;
#ifdef FG_USE_CLOUDS_3D
// Initialize the sound subsystem.
////////////////////////////////////////////////////////////////////
- globals->set_soundmgr(new FGSoundMgr);
+ globals->set_soundmgr(new SoundMgr);
globals->get_soundmgr()->init();
globals->get_soundmgr()->bind();
#include <simgear/magvar/magvar.hxx>
#include <simgear/timing/sg_time.hxx>
#include <simgear/misc/sg_path.hxx>
+#include <simgear/sound/soundmgr.hxx>
#include STL_IOSTREAM
#include <Objects/matlib.hxx>
#include <GUI/gui.h>
-#include <Sound/soundmgr.hxx>
#include "globals.hxx"
#include "fgfs.hxx"
frozen = f;
// Stop sound on a pause
- FGSoundMgr *s = globals->get_soundmgr();
+ SoundMgr *s = globals->get_soundmgr();
if ( s != NULL ) {
if ( f ) {
s->pause();
class SGPropertyNode;
class SGRoute;
class SGTime;
+class SoundMgr;
class FGAIMgr;
class FGATCMgr;
class FGMultiplayTxMgr;
#endif
class FGPanel;
-class FGSoundMgr;
class FGTileMgr;
class FGViewMgr;
class FGViewer;
FGPanel *current_panel;
// sound manager
- FGSoundMgr *soundmgr;
+ SoundMgr *soundmgr;
// environment information
FGEnvironmentMgr * environment_mgr;
inline FGPanel *get_current_panel() const { return current_panel; }
inline void set_current_panel( FGPanel *cp ) { current_panel = cp; }
- inline FGSoundMgr *get_soundmgr() const { return soundmgr; }
- inline void set_soundmgr( FGSoundMgr *sm ) { soundmgr = sm; }
+ inline SoundMgr *get_soundmgr() const { return soundmgr; }
+ inline void set_soundmgr( SoundMgr *sm ) { soundmgr = sm; }
inline FGControls *get_controls() const { return controls; }
inline void set_controls( FGControls *c ) { controls = c; }
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
#ifdef ENABLE_AUDIO_SUPPORT
-# include <Sound/soundmgr.hxx>
# include <Sound/fg_fx.hxx>
# include <Sound/morse.hxx>
#endif
libSound_a_SOURCES = \
beacon.cxx beacon.hxx \
- fg_sound.cxx fg_sound.hxx \
fg_fx.cxx fg_fx.hxx \
- morse.cxx morse.hxx \
- soundmgr.cxx soundmgr.hxx
+ morse.cxx morse.hxx
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
ptr += INNER_DIT_LEN;
}
- inner = new FGSimpleSound( inner_buf, INNER_SIZE );
+ inner = new SimpleSound( inner_buf, INNER_SIZE );
// Make middle marker beacon sound
len= (int)(MIDDLE_DIT_LEN / 2.0 );
ptr += MIDDLE_DIT_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
len= (int)(OUTER_DAH_LEN * 3.0 / 4.0 );
ptr += 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;
}
#endif
#include <simgear/compiler.h>
+#include <simgear/sound/soundmgr.hxx>
#include <plib/sl.h>
#include <plib/sm.h>
#include "morse.hxx"
-#include "soundmgr.hxx"
// Quoting from http://www.smartregs.com/data/sa326.htm
unsigned char middle_buf[ MIDDLE_SIZE ] ;
unsigned char outer_buf[ OUTER_SIZE ] ;
- FGSimpleSound *inner;
- FGSimpleSound *middle;
- FGSimpleSound *outer;
+ SimpleSound *inner;
+ SimpleSound *middle;
+ SimpleSound *outer;
public:
// allocate and initialize sound samples
bool init();
- FGSimpleSound *get_inner() { return inner; }
- FGSimpleSound *get_middle() { return middle; }
- FGSimpleSound *get_outer() { return outer; }
+ SimpleSound *get_inner() { return inner; }
+ SimpleSound *get_middle() { return middle; }
+ SimpleSound *get_outer() { return outer; }
};
#endif
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
+#include <simgear/sound/sound.hxx>
#include <Main/fg_props.hxx>
#include "fg_fx.hxx"
-#include "fg_sound.hxx"
FGFX::FGFX ()
}
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());
SGPropertyNode root;
node = root.getNode("fx");
for (i = 0; i < node->nChildren(); i++) {
- FGSound *sound = new FGSound();
- sound->init(node->getChild(i));
+ Sound *sound = new Sound();
+
+ sound->init(globals->get_props(), node->getChild(i),
+ globals->get_soundmgr(), globals->get_fg_root());
_sound.push_back(sound);
}
#include <Main/fgfs.hxx>
-class FGSound;
+class Sound;
/**
* Generator for FlightGear sound effects.
private:
- vector<FGSound *> _sound;
+ vector<Sound *> _sound;
};
+++ /dev/null
-// 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;
- }
-}
+++ /dev/null
-// 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
}
-// make a FGSimpleSound morse code transmission for the specified string
-FGSimpleSound *FGMorse::make_ident( const string& id, const int freq ) {
+// make a SimpleSound morse code transmission for the specified string
+SimpleSound *FGMorse::make_ident( const string& id, const int freq ) {
char *idptr = (char *)id.c_str();
int length = 0;
buf_ptr += SPACE_SIZE;
// 4. create the simple sound and return
- FGSimpleSound *sample = new FGSimpleSound( buffer, length );
+ SimpleSound *sample = new SimpleSound( buffer, length );
return sample;
}
#endif
#include <simgear/compiler.h>
+#include <simgear/sound/soundmgr.hxx>
#include <plib/sl.h>
#include <plib/sm.h>
-#include "soundmgr.hxx"
-
// Quoting from http://www.kluft.com/~ikluft/ham/morse-intro.html by
// Ian Kluft KO6YQ <ikluft@kluft.com>
// allocate and initialize sound samples
bool init();
- // make a FGSimpleSound morse code transmission for the specified string
- FGSimpleSound *make_ident( const string& id,
+ // make a SimpleSound morse code transmission for the specified string
+ SimpleSound *make_ident( const string& id,
const int freq = LO_FREQUENCY );
};
+++ /dev/null
-// 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;
-}
+++ /dev/null
-// 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
-
-