X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FSound%2Ffg_sound.cxx;h=5af54d59f78d1ffa1160f4b6288c4a88316cf75f;hb=0cbe8a597d877594623417bd30b1d5c4e131b023;hp=3701766c1997b3a24f8873795a936dca25bea8f3;hpb=1c513868b77b38bf90f83d4473f0a436da97fbb8;p=flightgear.git diff --git a/src/Sound/fg_sound.cxx b/src/Sound/fg_sound.cxx index 3701766c1..5af54d59f 100644 --- a/src/Sound/fg_sound.cxx +++ b/src/Sound/fg_sound.cxx @@ -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) @@ -31,20 +31,21 @@ #include #include +#include #include
#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 +63,26 @@ static const struct { }; FGSound::FGSound() - : _condition(NULL), + : _sample(NULL), + _active(false), + _condition(NULL), _property(NULL), - _sample(NULL), - _mode(FGSound::ONCE), + _dt_play(0.0), + _dt_stop(0.0), _prev_value(0), - _name("") + _name(""), + _mode(FGSound::ONCE) { } FGSound::~FGSound() { - delete _condition; + if (_property) + delete _property; + + if (_condition) + delete _condition; + delete _sample; } @@ -85,10 +94,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 +111,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); @@ -116,25 +125,28 @@ FGSound::init(SGPropertyNode *node) // unsigned int i; float v = 0.0; - vector kids = node->getChildren("volume"); + vector 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 (!strcmp(intern_str, "random")) + volume.intern = &_random; - 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 +160,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 +183,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 +214,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 +234,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 +251,7 @@ FGSound::unbind () } void -FGSound::update (int dt) +FGSound::update (double dt) { double curr_value = 0.0; @@ -263,7 +263,7 @@ FGSound::update (int dt) if ( // Lisp, anyone? (_condition && !_condition->test()) || - (_property && + (!_condition && _property && ( !curr_value || ( (_mode == FGSound::IN_TRANSIT) && (curr_value == _prev_value) ) @@ -273,8 +273,12 @@ FGSound::update (int dt) { _active = false; + _dt_stop += dt; + _dt_play = 0.0; + 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() ); } @@ -286,13 +290,24 @@ 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 playtime, cache the current value and feed the random number // + _dt_play += dt; _prev_value = curr_value; + _random = sg_random(); // // Update the volume @@ -303,7 +318,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 +354,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 +394,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; } }