From: curt Date: Wed, 27 Mar 2002 18:47:31 +0000 (+0000) Subject: Changes corresponding to recent property manager changes X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=2e0b32dab8e63f7fca8abd5b7a003b382e51b9a8;p=flightgear.git Changes corresponding to recent property manager changes Remove bogus warning messages Documentation changes Minor speedups --- diff --git a/docs-mini/README.xmlsound b/docs-mini/README.xmlsound index f01f19a43..b63899951 100644 --- a/docs-mini/README.xmlsound +++ b/docs-mini/README.xmlsound @@ -20,10 +20,6 @@ A rewrite of the sound code was done around v0.7.10 by Erik Hofman allowing for configuration of the sounds via XML to address this limitation. -About The Property Manager: --------------------------- -The - Sound Architecture: ------------------ All of the sound configuration files are XML-encoded* property lists. @@ -85,18 +81,35 @@ Configuration description: < ... > This is the event seperator. The text inside the brackets can be anything. Bit it is adviced to give it a meaningfull name - like: - crank, engine, rumble, gear, squeal, flap, wind, stall or click. + like: crank, engine, rumble, gear, squeal, flap, wind or stall The value can be defined multiple times, thus anything which is - related may have the same name. + related may have the same name (grouping them together). This defines the name of the event. This name is used internally and, although it can me defined multiple times in the same file, - should have a unique value unless you realy know what you're doing. + should normally have an unique value. - Defining it multiple times could lead to unexpected behaviour. + Multiple definitions of the same name will allow multiple sections + to interfere in the starting and stopping of the sample. + + This method can't be used to controll the pitch or volume of the + sample, but instead multiple volume or pitch section should be + included inside the same event. + + The types "raise" and "fall" will stop the playback of the sample + regardless of any other event. This means that when the type "raise" + is supplied, sample playback will stop when the event turns false. + Using the type "fall" will stop playback when the event turns true. + + IMPORTANT: + If the trigger is used for anything else but stopping the sound + at a certain event, all sections with the same name *should* have + exactly the same sections for everything but property and type. + + In the case of just stopping the sample at a certain event, the + sections for path, volume and pitch may be omitted. This defined th path to the sound file. The path is relative to the @@ -113,7 +126,15 @@ Configuration description: The triger depends on the value of . - This specifies how the event is triggered. + This specifies how the event is triggered. When an event is triggered + the sample will start playing. Since the effects scheduler can have + multiple events controll a single sound event, it depends on the + situation if an event actually stops playing the sound. + + Basically the following is true: + The first event requesting to start playback, triggers playback. + The last event requesting to stop playback, will stop playback. + There are multiple options: level: events are active if the value is true. @@ -124,6 +145,12 @@ Configuration description: flipflop: events are triggered on state changes. this is only usefull for samples which are played once. + + raise: start playing at the raise of the event. + explicitly stop playing when the event turns false. + + fall: start playing at the fall of the event. + explicitly stop playing when the event turns true. This defines how the sample should be played: @@ -138,9 +165,9 @@ Configuration description: / Volume or Pitch definition. Currently there may be up to 5 volume and up to 5 pitch definitions defined within one sound - event. Normally all values are added together and the + event. Normally all offset values are added together and the results after property calculations will be miltplied. - A special condition occurs when the value is negative, + A special condition occurs when the value of factor is negative, in which case the offset doesn't get added to the other offset values but instead will be used in the multiplication section. @@ -149,6 +176,9 @@ Configuration description: The value is treatened as a floating point number. + Defines the function that should be used upon the property + before it is used for calculating the net result: + lin: lineair handling of the property value. this is the default. @@ -157,6 +187,13 @@ Configuration description: log: convert the property value to a true logarithmic value before scaling it. + + inv: inverse lineair handling (1/x). + + abs: absolute handling of the value (always positive). + + sqrt: calculate the square root of the absolute value + before scaling it. Defines the multiplication factor for the property value. @@ -171,28 +208,47 @@ Configuration description: Minimum allowed value. This is usefull if sounds start to sound funny. Anything lower - will be converted to 0. + will be truncated to this value. Maximum allowed value. This is usefull if sounds gets to loud. Anything higher will be truncated to this value. + +Creating a configrationfile: +--------------------------- + +To make things easy, there is a default falue for most entries to allow a +sane configuration when a certain entry is omitted. + +Default values are: + +type: lin +factor: 1.0 +offset: 0.0 for volume, 1.0 for pitch +min: 0.0 (don't check) +max: 0.0 (don't check) + - Calculations are made the following way - (function can be one of: none, ln or log ): - - if (scale < 0) { - value[i] = offset[n] - abs(scale[n]) * function(property[n]) - offset[i] = 0; - } else - value[i] = scale[n] * function(property[n]) +Calculations are made the following way (for both pitch and volume): - And the end result will be: - - result = offset[0..max] + value[0..max]; - + value = 0; + offs = 0; + for (n = 0; n < max; n++) { + if (factor < 0) + { + value += offset[n] - abs(factor[n]) * function(property[n]); + } + else + { + value += factor[n] * function(property[n]); + offs += offset[n]; + } + } + volume = offs + value; +where function can be one of: lin, ln, log, inv, abs or sqrt diff --git a/src/Autopilot/newauto.cxx b/src/Autopilot/newauto.cxx index 9c89c4cbf..8d13af2a9 100644 --- a/src/Autopilot/newauto.cxx +++ b/src/Autopilot/newauto.cxx @@ -596,8 +596,10 @@ FGAutopilot::update (int dt) // figure out how far off we are from desired heading // Now it is time to deterime how far we should be rolled. - SG_LOG( SG_AUTOPILOT, SG_DEBUG, "RelHeading: " << RelHeading ); - + SG_LOG( SG_AUTOPILOT, SG_DEBUG, + "Heading = " << heading_node->getDoubleValue() << + " TargetHeading = " << TargetHeading << + " RelHeading = " << RelHeading ); // Check if we are further from heading than the roll out point if ( fabs( RelHeading ) > RollOut ) { diff --git a/src/Sound/fg_sound.cxx b/src/Sound/fg_sound.cxx index f61becd6b..34d8f4874 100644 --- a/src/Sound/fg_sound.cxx +++ b/src/Sound/fg_sound.cxx @@ -28,7 +28,7 @@ #else # include #endif -#include STL_STRING +#include #include @@ -36,8 +36,6 @@ #include "fg_sound.hxx" -SG_USING_STD(string); - // static double _fg_lin(double v) { return v; }; static double _fg_inv(double v) { return (v == 0) ? 1e99 : 1/v; }; @@ -93,33 +91,39 @@ FGSound::init() if ((_factor = _node->getDoubleValue("factor")) == 0.0) _factor = 1.0; - if ((_offset = _node->getDoubleValue("offset")) == 0.0) - _offset = 0.0; + _offset = _node->getDoubleValue("offset"); SG_LOG(SG_GENERAL, SG_INFO, "Loading sound information for: " << _name ); - string mode_str = _node->getStringValue("mode"); - if (mode_str == "looped") { + const char *mode_str = _node->getStringValue("mode"); + if ( !strcmp(mode_str,"looped") ) { _mode = FGSound::LOOPED; + } else { _mode = FGSound::ONCE; - if (mode_str != (string)"once") - SG_LOG( SG_GENERAL, SG_INFO, "Unknown sound mode, default to 'once'"); + + if ( strcmp(mode_str, "") ) + SG_LOG(SG_GENERAL,SG_INFO, " Unknown sound mode, default to 'once'"); } - string type_str = _node->getStringValue("type"); - if (type_str == "flipflop") { + const char *type_str = _node->getStringValue("type"); + if ( !strcmp(type_str, "flipflop") ) { _type = FGSound::FLIPFLOP; - } else if (type_str== "inverted") { + + } else if ( !strcmp(type_str, "inverted") ) { _type = FGSound::INVERTED; - } else if (type_str == "raise") { + + } else if ( !strcmp(type_str, "raise") ) { _type = FGSound::RAISE; - } else if (type_str == "fall") { + + } else if ( !strcmp(type_str, "fall") ) { _type = FGSound::FALL; + } else { _type = FGSound::LEVEL; - if (type_str != (string)"level") - SG_LOG( SG_GENERAL, SG_INFO, "Unknown sound type, default to 'level'"); + + if ( strcmp(type_str, "") ) + SG_LOG(SG_GENERAL,SG_INFO, " Unknown sound type, default to 'level'"); } #if 0 @@ -140,42 +144,49 @@ FGSound::init() for (i = 0; (i < kids.size()) && (i < FGSound::MAXPROP); i++) { _snd_prop volume; - if ((volume.prop=fgGetNode(kids[i]->getStringValue("property"), true)) - == 0) - volume.prop = fgGetNode("/null", true); + volume.prop = fgGetNode(kids[i]->getStringValue("property"), true); if ((volume.factor = kids[i]->getDoubleValue("factor")) == 0.0) volume.factor = 1.0; + else if (volume.factor < 0.0) { volume.factor = -volume.factor; volume.subtract = true; + } else volume.subtract = false; volume.fn = NULL; - for (int j=0; __fg_snd_fn[j].fn; j++) - if (__fg_snd_fn[j].name == kids[i]->getStringValue("type")) { - volume.fn = __fg_snd_fn[j].fn; - break; + 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'"); } - if (!volume.fn) - SG_LOG( SG_GENERAL, SG_INFO, "Unknown volume type, default to 'lin'"); - - if ((volume.offset = kids[i]->getDoubleValue("offset")) == 0.0) - volume.offset = 0.0; + volume.offset = kids[i]->getDoubleValue("offset"); if ((volume.min = kids[i]->getDoubleValue("min")) < 0.0) { SG_LOG( SG_GENERAL, SG_WARN, "Volume minimum value below 0. Forced to 0."); + volume.min = 0.0; } - if ((volume.max = kids[i]->getDoubleValue("max")) < volume.min) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Volume maximum value below minimum value. Forced above minimum."); - volume.max = volume.min + 5.0; + volume.max = kids[i]->getDoubleValue("max"); + 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); @@ -192,36 +203,50 @@ FGSound::init() for (i = 0; (i < kids.size()) && (i < FGSound::MAXPROP); i++) { _snd_prop pitch; - if ((pitch.prop = fgGetNode(kids[i]->getStringValue("property"), true)) - == 0) - pitch.prop = fgGetNode("/null", true); + pitch.prop = fgGetNode(kids[i]->getStringValue("property"), true); if ((pitch.factor = kids[i]->getDoubleValue("factor")) == 0.0) pitch.factor = 1.0; + else + if (pitch.factor < 0.0) { + pitch.factor = -pitch.factor; + pitch.subtract = true; + + } else + pitch.subtract = false; + pitch.fn = NULL; - for (int j=0; __fg_snd_fn[j].fn; j++) - if (__fg_snd_fn[j].name == kids[i]->getStringValue("type")) { - pitch.fn = __fg_snd_fn[j].fn; - break; + 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'"); } - - if (!pitch.fn) - SG_LOG( SG_GENERAL, SG_INFO, "Unknown pitch type, default to 'lin'"); if ((pitch.offset = kids[i]->getDoubleValue("offset")) == 0.0) pitch.offset = 1.0; if ((pitch.min = kids[i]->getDoubleValue("min")) < 0.0) { - SG_LOG( SG_GENERAL, SG_WARN, - "Pitch minimum value below 0. Forced to 0."); + SG_LOG(SG_GENERAL,SG_WARN, + " Pitch minimum value below 0. Forced to 0."); + pitch.min = 0.0; } - if ((pitch.max = kids[i]->getDoubleValue("max")) < pitch.min) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Pitch maximum value below minimum value. Forced above minimum."); - pitch.max = pitch.min + 5.0; + pitch.max = kids[i]->getDoubleValue("max"); + 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); @@ -310,13 +335,16 @@ FGSound::update (int dt) } + { + int i, max; + // // Update the volume // - int max = _volume.size(); + max = _volume.size(); + double volume = 1.0; + double volume_offset = 0.0; - int i; - double volume = 1.0, volume_offset = 0.0; for(i = 0; i < max; i++) { double v = _volume[i].prop->getDoubleValue(); @@ -325,11 +353,11 @@ FGSound::update (int dt) v *= _volume[i].factor; - if (v > _volume[i].max) + if (!_volume[i].max && (v > _volume[i].max)) v = _volume[i].max; - else - if (v < _volume[i].min) - v = 0; // v = _volume[i].min; + + else if (!_volume[i].min && (v < _volume[i].min)) + v = _volume[i].min; if (_volume[i].subtract) // Hack! volume = _volume[i].offset - v; @@ -343,7 +371,9 @@ FGSound::update (int dt) // Update the pitch // max = _pitch.size(); - double pitch = 1.0, pitch_offset = 0.0; + double pitch = 1.0; + double pitch_offset = 0.0; + for(i = 0; i < max; i++) { double p = _pitch[i].prop->getDoubleValue(); @@ -352,11 +382,11 @@ FGSound::update (int dt) p *= _pitch[i].factor; - if (p > _pitch[i].max) + if (!_pitch[i].max && (p > _pitch[i].max)) p = _pitch[i].max; - else - if (p < _pitch[i].min) - p = _pitch[i].min; + + else if (!_pitch[i].min && (p < _pitch[i].min)) + p = _pitch[i].min; if (_pitch[i].subtract) // Hack! pitch = _pitch[i].offset - p; @@ -371,6 +401,7 @@ FGSound::update (int dt) // _sample->set_pitch( pitch_offset + pitch ); _sample->set_volume( volume_offset + volume ); + } // // Do we need to start playing the sample?