Changes corresponding to recent property manager changes
Remove bogus warning messages Documentation changes Minor speedups
This commit is contained in:
parent
0944ab91c2
commit
2e0b32dab8
3 changed files with 177 additions and 88 deletions
|
@ -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).
|
||||
|
||||
<name>
|
||||
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.
|
||||
|
||||
<path>
|
||||
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 <type>.
|
||||
|
||||
<type>
|
||||
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.
|
||||
|
||||
<mode>
|
||||
This defines how the sample should be played:
|
||||
|
@ -138,9 +165,9 @@ Configuration description:
|
|||
<volume> / <pitch>
|
||||
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 <offset> 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 <factor> 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.
|
||||
|
||||
<type>
|
||||
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.
|
||||
|
||||
<factor>
|
||||
Defines the multiplication factor for the property value.
|
||||
|
@ -171,28 +208,47 @@ Configuration description:
|
|||
<min>
|
||||
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.
|
||||
|
||||
<max>
|
||||
|
||||
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 ):
|
||||
Calculations are made the following way (for both pitch and volume):
|
||||
|
||||
if (scale < 0) {
|
||||
value[i] = offset[n] - abs(scale[n]) * function(property[n])
|
||||
offset[i] = 0;
|
||||
} else
|
||||
value[i] = scale[n] * function(property[n])
|
||||
|
||||
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
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#else
|
||||
# include <math.h>
|
||||
#endif
|
||||
#include STL_STRING
|
||||
#include <string.h>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
if (pitch.factor < 0.0) {
|
||||
pitch.factor = -pitch.factor;
|
||||
pitch.subtract = true;
|
||||
|
||||
if (!pitch.fn)
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Unknown pitch type, default to 'lin'");
|
||||
} else
|
||||
pitch.subtract = false;
|
||||
|
||||
pitch.fn = NULL;
|
||||
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.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?
|
||||
|
|
Loading…
Reference in a new issue