]> git.mxchange.org Git - flightgear.git/blobdiff - src/Sound/fg_sound.cxx
Added static port system and a new altimeter model connected to it.
[flightgear.git] / src / Sound / fg_sound.cxx
index 51b7ecb72ee5eba4b4ae49eb8fdf189d8a745c98..28ebafb708e195814335c886d671db41d2f2d397 100644 (file)
@@ -1,4 +1,4 @@
-// fg_sound.hxx -- Sound class implementation
+// fg_sound.cxx -- Sound class implementation
 //
 // Started by Erik Hofman, February 2002
 // (Reuses some code from  fg_fx.cxx created by David Megginson)
 #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 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;
@@ -62,18 +62,26 @@ static const struct {
 };
 
 FGSound::FGSound()
-  : _condition(NULL),
+  : _sample(NULL),
+    _condition(NULL),
     _property(NULL),
-    _sample(NULL),
+    _active(false),
+    _name(""),
     _mode(FGSound::ONCE),
     _prev_value(0),
-    _name("")
+    _dt_play(0.0),
+    _dt_stop(0.0)
 {
 }
 
 FGSound::~FGSound()
 {
-   delete _condition;
+   if (_property)
+      delete _property;
+
+   if (_condition)
+      delete _condition;
+
    delete _sample;
 }
 
@@ -85,10 +93,10 @@ FGSound::init(SGPropertyNode *node)
    // set global sound properties
    //
    
-   _name = node->getStringValue("name");
+   _name = node->getStringValue("name", "");
    SG_LOG(SG_GENERAL, SG_INFO, "Loading sound information for: " << _name );
 
-   const char *mode_str = node->getStringValue("mode");
+   const char *mode_str = node->getStringValue("mode", "");
    if ( !strcmp(mode_str, "looped") ) {
        _mode = FGSound::LOOPED;
 
@@ -102,7 +110,7 @@ FGSound::init(SGPropertyNode *node)
          SG_LOG(SG_GENERAL,SG_INFO, "  Unknown sound mode, default to 'once'");
    }
 
-   _property = fgGetNode(node->getStringValue("property"), true);
+   _property = fgGetNode(node->getStringValue("property", ""), true);
    SGPropertyNode *condition = node->getChild("condition");
    if (condition != NULL)
       _condition = fgReadCondition(condition);
@@ -118,23 +126,24 @@ FGSound::init(SGPropertyNode *node)
    float v = 0.0;
    vector<SGPropertyNode_ptr> kids = node->getChildren("volume");
    for (i = 0; (i < kids.size()) && (i < FGSound::MAXPROP); i++) {
-      _snd_prop volume;
+      _snd_prop volume = {NULL, NULL, NULL, 1.0, 0.0, 0.0, 0.0, false};
 
-      volume.prop = fgGetNode(kids[i]->getStringValue("property"), true);
+      if (strcmp(kids[i]->getStringValue("property"), ""))
+         volume.prop = fgGetNode(kids[i]->getStringValue("property", ""), true);
 
-      if ((volume.factor = kids[i]->getDoubleValue("factor")) == 0.0)
-         volume.factor = 1.0;
+      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;
 
-      else 
+      if ((volume.factor = kids[i]->getDoubleValue("factor", 1.0)) != 0.0)
          if (volume.factor < 0.0) {
             volume.factor = -volume.factor;
             volume.subtract = true;
+         }
 
-         } else
-            volume.subtract = false;
-
-      volume.fn = NULL;
-      const char *type_str = kids[i]->getStringValue("type");
+      const char *type_str = kids[i]->getStringValue("type", "");
       if ( strcmp(type_str, "") ) {
 
          for (int j=0; __fg_snd_fn[j].fn; j++)
@@ -148,23 +157,17 @@ FGSound::init(SGPropertyNode *node)
                    "  Unknown volume type, default to 'lin'");
       }
 
-      volume.offset = kids[i]->getDoubleValue("offset");
+      volume.offset = kids[i]->getDoubleValue("offset", 0.0);
 
-      if ((volume.min = kids[i]->getDoubleValue("min")) < 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.min = 0.0;
-      }
-
-      volume.max = kids[i]->getDoubleValue("max");
-      if (volume.max && (volume.max < volume.min) ) {
+      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.max = 0.0;
-      }
-
       _volume.push_back(volume);
       v += volume.offset;
 
@@ -177,23 +180,24 @@ FGSound::init(SGPropertyNode *node)
    float p = 0.0;
    kids = node->getChildren("pitch");
    for (i = 0; (i < kids.size()) && (i < FGSound::MAXPROP); i++) {
-      _snd_prop pitch;
+      _snd_prop pitch = {NULL, NULL, NULL, 1.0, 1.0, 0.0, 0.0, false};
 
-      pitch.prop = fgGetNode(kids[i]->getStringValue("property"), true);
+      if (strcmp(kids[i]->getStringValue("property", ""), ""))
+         pitch.prop = fgGetNode(kids[i]->getStringValue("property", ""), true);
 
-      if ((pitch.factor = kids[i]->getDoubleValue("factor")) == 0.0)
-         pitch.factor = 1.0;
+      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;
 
-      else
+      if ((pitch.factor = kids[i]->getDoubleValue("factor", 1.0)) != 0.0)
          if (pitch.factor < 0.0) {
             pitch.factor = -pitch.factor;
             pitch.subtract = true;
+         }
 
-         } else
-            pitch.subtract = false;
-
-      pitch.fn = NULL;
-      const char *type_str = kids[i]->getStringValue("type");
+      const char *type_str = kids[i]->getStringValue("type", "");
       if ( strcmp(type_str, "") ) {
 
          for (int j=0; __fg_snd_fn[j].fn; j++) 
@@ -207,24 +211,17 @@ FGSound::init(SGPropertyNode *node)
                    "  Unknown pitch type, default to 'lin'");
       }
      
-      if ((pitch.offset = kids[i]->getDoubleValue("offset")) == 0.0)
-         pitch.offset = 1.0;
+      pitch.offset = kids[i]->getDoubleValue("offset", 1.0);
 
-      if ((pitch.min = kids[i]->getDoubleValue("min")) < 0.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.min = 0.0;
-      }
-
-      pitch.max = kids[i]->getDoubleValue("max");
-      if (pitch.max && (pitch.max < pitch.min) ) {
+      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.max = 0.0;
-      }
-
       _pitch.push_back(pitch);
       p += pitch.offset;
    }
@@ -234,7 +231,7 @@ FGSound::init(SGPropertyNode *node)
    //
    _mgr = globals->get_soundmgr();
    if ((_sample = _mgr->find(_name)) == NULL)
-      _sample = _mgr->add(_name, node->getStringValue("path"));
+      _sample = _mgr->add(_name, node->getStringValue("path", ""));
 
    _sample->set_volume(v);
    _sample->set_pitch(p);
@@ -251,7 +248,7 @@ FGSound::unbind ()
 }
 
 void
-FGSound::update (int dt)
+FGSound::update (double dt)
 {
    double curr_value = 0.0;
 
@@ -263,7 +260,7 @@ FGSound::update (int dt)
 
    if (                                                        // Lisp, anyone?
          (_condition && !_condition->test()) ||
-         (_property &&
+         (!_condition && _property &&
             (
                !curr_value ||
                ( (_mode == FGSound::IN_TRANSIT) && (curr_value == _prev_value) )
@@ -272,12 +269,16 @@ FGSound::update (int dt)
       )
    {
 
-      _active = false;
       if (_sample->is_playing()) {
-         SG_LOG(SG_GENERAL, SG_INFO, "Stopping sound: " << _name);
+         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;
+
       return;
 
    }
@@ -286,12 +287,22 @@ FGSound::update (int dt)
    // If the mode is ONCE and the sound is still playing,
    //  we have nothing to do anymore.
    //
-   if (_active && (_mode == FGSound::ONCE))
+   if (_active && (_mode == FGSound::ONCE)) {
+
+      if (!_sample->is_playing()) {
+         _dt_stop += dt;
+         _dt_play = 0.0;
+
+      } else
+         _dt_play += dt;
+
       return;
+   }
 
    //
-   // Cache current value;
+   // Update playing time and cache the current value.
    //
+    _dt_play += dt;
    _prev_value = curr_value;
 
    //
@@ -303,7 +314,13 @@ FGSound::update (int dt)
    double volume_offset = 0.0;
 
    for(i = 0; i < max; i++) {
-      double v = _volume[i].prop->getDoubleValue();
+      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);
@@ -333,7 +350,13 @@ FGSound::update (int dt)
    double pitch_offset = 0.0;
 
    for(i = 0; i < max; i++) {
-      double p = _pitch[i].prop->getDoubleValue();
+      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);
@@ -367,15 +390,18 @@ FGSound::update (int dt)
    //
    if (!_active) {
 
-      _active = true;
       if (_mode == FGSound::ONCE)
          _sample->play(_mgr->get_scheduler(), false);
 
       else
          _sample->play(_mgr->get_scheduler(), true);
 
-      SG_LOG(SG_GENERAL, SG_INFO, "Starting audio playback for: " << _name);
+      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;
    }
 }